single-file-core 1.0.63 → 1.0.65
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/common/content-infobar-web.js +15 -258
- package/common/infobar.js +277 -0
- package/package.json +1 -1
- package/processors/hooks/content/content-hooks-frames-web.js +6 -4
- package/single-file-core.js +27 -17
- package/single-file-helper.js +10 -1
- package/single-file-mini-helper.js +45 -0
- package/single-file-util.js +3 -0
|
@@ -21,111 +21,11 @@
|
|
|
21
21
|
* Source.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
/* global globalThis, window, document
|
|
24
|
+
/* global globalThis, window, document */
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
import { appendInfobar, refreshInfobarInfo, extractInfobarData } from "./infobar.js";
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
const LINK_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAgMAAADXB5lNAAABhmlDQ1BJQ0MgcHJvZmlsZQAAKJF9kj1Iw0AYht+mSkUrDnYQcchQnSyIijqWKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjx4LiH9+59+e67A4RGhalm1wSgapaRisfEbG5VDLyiDwEAvZiVmKkn0osZeI6ve/j4ehfhWd7n/hz9St5kgE8kjjLdsIg3iGc2LZ3zPnGIlSSF+Jx43KACiR+5Lrv8xrnosMAzQ0YmNU8cIhaLHSx3MCsZKvE0cVhRNcoXsi4rnLc4q5Uaa9XJbxjMaytprtMcQRxLSCAJETJqKKMCCxFaNVJMpGg/5uEfdvxJcsnkKoORYwFVqJAcP/gb/O6tWZiadJOCMaD7xbY/RoHALtCs2/b3sW03TwD/M3Cltf3VBjD3SXq9rYWPgIFt4OK6rcl7wOUOMPSkS4bkSH6aQqEAvJ/RM+WAwVv6EGtu31r7OH0AMtSr5Rvg4BAYK1L2use9ezr79u+ZVv9+AFlNcp0UUpiqAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH5AsHAB8H+DhhoQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAJUExURQAAAICHi4qKioTuJAkAAAABdFJOUwBA5thmAAAAAWJLR0QCZgt8ZAAAAJJJREFUOI3t070NRCEMA2CnYAOyDyPwpHj/Va7hJ3FzV7zy3ET5JIwoAF6Jk4wzAJAkzxAYG9YRTgB+24wBgKmfrGAKTcEfAY4KRlRoIeBTgKOCERVaCPgU4Khge2GqKOBTgKOCERVaAEC/4PNcnyoSWHpjqkhwKxbcig0Q6AorXYF/+A6eIYD1lVbwG/jdA6/kA2THRAURVubcAAAAAElFTkSuQmCC";
|
|
30
|
-
const CLOSE_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAgMAAADXB5lNAAABhmlDQ1BJQ0MgcHJvZmlsZQAAKJF9kj1Iw0AYht+mSkUrDnYQcchQnSyIijqWKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjx4LiH9+59+e67A4RGhalm1wSgapaRisfEbG5VDLyiDwEAvZiVmKkn0osZeI6ve/j4ehfhWd7n/hz9St5kgE8kjjLdsIg3iGc2LZ3zPnGIlSSF+Jx43KACiR+5Lrv8xrnosMAzQ0YmNU8cIhaLHSx3MCsZKvE0cVhRNcoXsi4rnLc4q5Uaa9XJbxjMaytprtMcQRxLSCAJETJqKKMCCxFaNVJMpGg/5uEfdvxJcsnkKoORYwFVqJAcP/gb/O6tWZiadJOCMaD7xbY/RoHALtCs2/b3sW03TwD/M3Cltf3VBjD3SXq9rYWPgIFt4OK6rcl7wOUOMPSkS4bkSH6aQqEAvJ/RM+WAwVv6EGtu31r7OH0AMtSr5Rvg4BAYK1L2use9ezr79u+ZVv9+AFlNcp0UUpiqAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH5AsHAB8VC4EQ6QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAJUExURQAAAICHi4qKioTuJAkAAAABdFJOUwBA5thmAAAAAWJLR0QCZgt8ZAAAAJtJREFUOI3NkrsBgCAMRLFwBPdxBArcfxXFkO8rbKWAAJfHJ9faf9vuYX/749T5NmShm3bEwbe2SxeuM4+2oxDL1cDoKtVUjRy+tH78Cv2CS+wIiQNC1AEhk4AQeUTMWUJMfUJMSEJMSEY8kIx4IONroaYAimNxsXp1PA7PxwfVL8QnowwoVC0lig07wDDVUjAdbAnjwtow/z/bDW7eI4M2KruJAAAAAElFTkSuQmCC";
|
|
31
|
-
const IMAGE_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAABhmlDQ1BJQ0MgcHJvZmlsZQAAKJF9kj1Iw0AYht+mSkUrDnYQcchQnSyIijqWKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjx4LiH9+59+e67A4RGhalm1wSgapaRisfEbG5VDLyiDwEAvZiVmKkn0osZeI6ve/j4ehfhWd7n/hz9St5kgE8kjjLdsIg3iGc2LZ3zPnGIlSSF+Jx43KACiR+5Lrv8xrnosMAzQ0YmNU8cIhaLHSx3MCsZKvE0cVhRNcoXsi4rnLc4q5Uaa9XJbxjMaytprtMcQRxLSCAJETJqKKMCCxFaNVJMpGg/5uEfdvxJcsnkKoORYwFVqJAcP/gb/O6tWZiadJOCMaD7xbY/RoHALtCs2/b3sW03TwD/M3Cltf3VBjD3SXq9rYWPgIFt4OK6rcl7wOUOMPSkS4bkSH6aQqEAvJ/RM+WAwVv6EGtu31r7OH0AMtSr5Rvg4BAYK1L2use9ezr79u+ZVv9+AFlNcp0UUpiqAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH5AsHADIRLMaOHwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAPUExURQAAAIqKioyNjY2OjvDw8L2y1DEAAAABdFJOUwBA5thmAAAAAWJLR0QB/wIt3gAAAGNJREFUSMdjYCAJsLi4OBCQx6/CBQwIGIDPCBcXAkYQUsACU+AwlBVQHg6Eg5pgZBGOboIJZugDFwRwoJECJCUOhJI1wZwzqmBUwagCuipgIqTABG9h7YIKaKGAURAFEF/6AQAO4HqSoDP8bgAAAABJRU5ErkJggg==";
|
|
32
|
-
const SINGLEFILE_COMMENT = "SingleFile";
|
|
33
|
-
const SINGLE_FILE_UI_ELEMENT_CLASS = "single-file-ui-element";
|
|
34
|
-
const INFOBAR_STYLES = `
|
|
35
|
-
.infobar {
|
|
36
|
-
background-color: #737373;
|
|
37
|
-
color: white;
|
|
38
|
-
display: flex;
|
|
39
|
-
position: fixed;
|
|
40
|
-
top: 16px;
|
|
41
|
-
right: 16px;
|
|
42
|
-
height: auto;
|
|
43
|
-
width: auto;
|
|
44
|
-
min-height: 24px;
|
|
45
|
-
min-width: 24px;
|
|
46
|
-
background-position: center;
|
|
47
|
-
background-repeat: no-repeat;
|
|
48
|
-
z-index: 2147483647;
|
|
49
|
-
margin: 0 0 0 16px;
|
|
50
|
-
background-image: url(${IMAGE_ICON});
|
|
51
|
-
border-radius: 16px;
|
|
52
|
-
user-select: none;
|
|
53
|
-
-moz-user-select: none;
|
|
54
|
-
opacity: .7;
|
|
55
|
-
cursor: pointer;
|
|
56
|
-
padding-left: 0;
|
|
57
|
-
padding-right: 0;
|
|
58
|
-
padding-top: 0;
|
|
59
|
-
padding-bottom: 0;
|
|
60
|
-
border: 2px solid #eee;
|
|
61
|
-
background-size: 70% 70%;
|
|
62
|
-
transition: all 250ms;
|
|
63
|
-
font-size: 13px;
|
|
64
|
-
}
|
|
65
|
-
.infobar:hover {
|
|
66
|
-
opacity: 1;
|
|
67
|
-
}
|
|
68
|
-
.infobar-open {
|
|
69
|
-
opacity: 1;
|
|
70
|
-
background-color: #f9f9f9;
|
|
71
|
-
cursor: auto;
|
|
72
|
-
color: #2d2d2d;
|
|
73
|
-
padding-top: 2px;
|
|
74
|
-
padding-bottom: 2px;
|
|
75
|
-
border: 2px solid #878787;
|
|
76
|
-
background-image: none;
|
|
77
|
-
border-radius: 8px;
|
|
78
|
-
user-select: initial;
|
|
79
|
-
-moz-user-select: initial;
|
|
80
|
-
}
|
|
81
|
-
.infobar-close-button {
|
|
82
|
-
display: none;
|
|
83
|
-
opacity: .7;
|
|
84
|
-
padding-top: 4px;
|
|
85
|
-
padding-left: 8px;
|
|
86
|
-
padding-right: 8px;
|
|
87
|
-
cursor: pointer;
|
|
88
|
-
transition: opacity 250ms;
|
|
89
|
-
height: 16px;
|
|
90
|
-
}
|
|
91
|
-
.infobar-close-button:hover {
|
|
92
|
-
opacity: 1;
|
|
93
|
-
}
|
|
94
|
-
.infobar-content {
|
|
95
|
-
display: none;
|
|
96
|
-
font-family: Arial;
|
|
97
|
-
font-size: 14px;
|
|
98
|
-
line-height: 22px;
|
|
99
|
-
word-break: break-word;
|
|
100
|
-
white-space: pre-wrap;
|
|
101
|
-
position: relative;
|
|
102
|
-
top: 1px;
|
|
103
|
-
text-align: left;
|
|
104
|
-
}
|
|
105
|
-
.infobar-link {
|
|
106
|
-
display: none;
|
|
107
|
-
padding-left: 8px;
|
|
108
|
-
padding-right: 8px;
|
|
109
|
-
line-height: 11px;
|
|
110
|
-
cursor: pointer;
|
|
111
|
-
user-select: none;
|
|
112
|
-
outline: 0;
|
|
113
|
-
}
|
|
114
|
-
.infobar-link-icon {
|
|
115
|
-
padding-top: 4px;
|
|
116
|
-
padding-left: 2px;
|
|
117
|
-
cursor: pointer;
|
|
118
|
-
opacity: .7;
|
|
119
|
-
transition: opacity 250ms;
|
|
120
|
-
height: 16px;
|
|
121
|
-
}
|
|
122
|
-
.infobar-link-icon:hover {
|
|
123
|
-
opacity: 1;
|
|
124
|
-
}
|
|
125
|
-
.infobar-open .infobar-close-button, .infobar-open .infobar-content, .infobar-open .infobar-link {
|
|
126
|
-
display: inline-block;
|
|
127
|
-
}`;
|
|
128
|
-
let SHADOW_DOM_SUPPORTED = true;
|
|
28
|
+
(globalThis => {
|
|
129
29
|
|
|
130
30
|
const browser = globalThis.browser;
|
|
131
31
|
|
|
@@ -137,169 +37,26 @@
|
|
|
137
37
|
}
|
|
138
38
|
}
|
|
139
39
|
if (globalThis.singlefile) {
|
|
140
|
-
globalThis.singlefile.infobar = {
|
|
40
|
+
globalThis.singlefile.infobar = {
|
|
141
41
|
displayIcon
|
|
142
42
|
};
|
|
143
43
|
}
|
|
144
44
|
|
|
145
45
|
async function displayIcon() {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
let options;
|
|
155
|
-
if (browser && browser.runtime && browser.runtime.sendMessage) {
|
|
156
|
-
try {
|
|
157
|
-
options = await browser.runtime.sendMessage({ method: "tabs.getOptions", url });
|
|
158
|
-
} catch (error) {
|
|
159
|
-
options = { displayInfobar: true };
|
|
160
|
-
}
|
|
161
|
-
} else {
|
|
162
|
-
options = { displayInfobar: true };
|
|
163
|
-
}
|
|
164
|
-
if (options.displayInfobar) {
|
|
165
|
-
await initInfobar(url, optionalData);
|
|
46
|
+
let options = { displayInfobar: true };
|
|
47
|
+
const infoData = extractInfobarData(document);
|
|
48
|
+
if (infoData && infoData.saveUrl) {
|
|
49
|
+
if (browser && browser.runtime && browser.runtime.sendMessage) {
|
|
50
|
+
try {
|
|
51
|
+
options = await browser.runtime.sendMessage({ method: "tabs.getOptions", url: infoData.saveUrl });
|
|
52
|
+
} catch (error) {
|
|
53
|
+
// ignored
|
|
166
54
|
}
|
|
167
55
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
function isSingleFileComment(node) {
|
|
172
|
-
return node.nodeType == Node.COMMENT_NODE && node.textContent.includes(SINGLEFILE_COMMENT);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async function initInfobar(url, optionalData /* saveDate, infoData */) {
|
|
176
|
-
let infobarElement = document.querySelector(INFOBAR_TAGNAME);
|
|
177
|
-
if (!infobarElement) {
|
|
178
|
-
let infoData = "";
|
|
179
|
-
if (optionalData.length) {
|
|
180
|
-
const saveDate = optionalData[0].split("saved date: ")[1];
|
|
181
|
-
if (saveDate) {
|
|
182
|
-
optionalData.shift();
|
|
183
|
-
}
|
|
184
|
-
if (optionalData.length > 1) {
|
|
185
|
-
let content = optionalData[0].split("info: ")[1].trim();
|
|
186
|
-
for (let indexLine = 1; indexLine < optionalData.length - 1; indexLine++) {
|
|
187
|
-
content += "\n" + optionalData[indexLine].trim();
|
|
188
|
-
}
|
|
189
|
-
infoData = content.trim();
|
|
190
|
-
} else {
|
|
191
|
-
infoData = saveDate;
|
|
192
|
-
}
|
|
56
|
+
if (options.displayInfobar) {
|
|
57
|
+
appendInfobar(document, options, true);
|
|
58
|
+
refreshInfobarInfo(document, infoData);
|
|
193
59
|
}
|
|
194
|
-
infoData = infoData || "No info";
|
|
195
|
-
infobarElement = createElement(INFOBAR_TAGNAME, document.body);
|
|
196
|
-
infobarElement.className = SINGLE_FILE_UI_ELEMENT_CLASS;
|
|
197
|
-
const shadowRoot = await getShadowRoot(infobarElement);
|
|
198
|
-
const styleElement = document.createElement("style");
|
|
199
|
-
styleElement.textContent = INFOBAR_STYLES;
|
|
200
|
-
shadowRoot.appendChild(styleElement);
|
|
201
|
-
const infobarContent = document.createElement("div");
|
|
202
|
-
infobarContent.classList.add("infobar");
|
|
203
|
-
shadowRoot.appendChild(infobarContent);
|
|
204
|
-
const closeElement = document.createElement("img");
|
|
205
|
-
closeElement.classList.add("infobar-close-button");
|
|
206
|
-
infobarContent.appendChild(closeElement);
|
|
207
|
-
closeElement.src = CLOSE_ICON;
|
|
208
|
-
closeElement.onclick = event => {
|
|
209
|
-
if (event.button === 0) {
|
|
210
|
-
infobarElement.remove();
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
const infoElement = document.createElement("span");
|
|
214
|
-
infobarContent.appendChild(infoElement);
|
|
215
|
-
infoElement.classList.add("infobar-content");
|
|
216
|
-
infoElement.textContent = infoData;
|
|
217
|
-
const linkElement = document.createElement("a");
|
|
218
|
-
linkElement.classList.add("infobar-link");
|
|
219
|
-
infobarContent.appendChild(linkElement);
|
|
220
|
-
linkElement.target = "_blank";
|
|
221
|
-
linkElement.rel = "noopener noreferrer";
|
|
222
|
-
linkElement.title = "Open source URL: " + url;
|
|
223
|
-
linkElement.href = url;
|
|
224
|
-
const imgElement = document.createElement("img");
|
|
225
|
-
imgElement.classList.add("infobar-link-icon");
|
|
226
|
-
linkElement.appendChild(imgElement);
|
|
227
|
-
imgElement.src = LINK_ICON;
|
|
228
|
-
hideInfobar(infobarContent);
|
|
229
|
-
|
|
230
|
-
document.addEventListener("click", event => {
|
|
231
|
-
if (event.button === 0) {
|
|
232
|
-
let element = event.target;
|
|
233
|
-
while (element && element != infobarElement) {
|
|
234
|
-
element = element.parentElement;
|
|
235
|
-
}
|
|
236
|
-
if (element != infobarElement) {
|
|
237
|
-
hideInfobar(infobarContent);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function displayInfobar(infobarContent) {
|
|
245
|
-
if (!SHADOW_DOM_SUPPORTED) {
|
|
246
|
-
const infobarElement = document.querySelector(INFOBAR_TAGNAME);
|
|
247
|
-
const frameElement = infobarElement.childNodes[0];
|
|
248
|
-
frameElement.contentWindow.getSelection().removeAllRanges();
|
|
249
|
-
}
|
|
250
|
-
infobarContent.classList.add("infobar-open");
|
|
251
|
-
infobarContent.onclick = null;
|
|
252
|
-
infobarContent.onmouseout = null;
|
|
253
|
-
if (!SHADOW_DOM_SUPPORTED) {
|
|
254
|
-
const infobarElement = document.querySelector(INFOBAR_TAGNAME);
|
|
255
|
-
const frameElement = infobarElement.childNodes[0];
|
|
256
|
-
frameElement.style.setProperty("width", "100vw", "important");
|
|
257
|
-
frameElement.style.setProperty("height", "100vh", "important");
|
|
258
|
-
frameElement.style.setProperty("width", (infobarContent.getBoundingClientRect().width + 33) + "px", "important");
|
|
259
|
-
frameElement.style.setProperty("height", (infobarContent.getBoundingClientRect().height + 21) + "px", "important");
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function hideInfobar(infobarContent) {
|
|
264
|
-
infobarContent.classList.remove("infobar-open");
|
|
265
|
-
infobarContent.onclick = event => {
|
|
266
|
-
if (event.button === 0) {
|
|
267
|
-
displayInfobar(infobarContent);
|
|
268
|
-
return false;
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
if (!SHADOW_DOM_SUPPORTED) {
|
|
272
|
-
const infobarElement = document.querySelector(INFOBAR_TAGNAME);
|
|
273
|
-
const frameElement = infobarElement.childNodes[0];
|
|
274
|
-
frameElement.style.setProperty("width", "44px", "important");
|
|
275
|
-
frameElement.style.setProperty("height", "48px", "important");
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function createElement(tagName, parentElement) {
|
|
280
|
-
const element = document.createElement(tagName);
|
|
281
|
-
parentElement.appendChild(element);
|
|
282
|
-
Array.from(getComputedStyle(element)).forEach(property => element.style.setProperty(property, "initial", "important"));
|
|
283
|
-
return element;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
async function getShadowRoot(element) {
|
|
287
|
-
if (element.attachShadow) {
|
|
288
|
-
return element.attachShadow({ mode: "open" });
|
|
289
|
-
} else {
|
|
290
|
-
SHADOW_DOM_SUPPORTED = false;
|
|
291
|
-
const iframe = createElement("iframe", element);
|
|
292
|
-
iframe.style.setProperty("background-color", "transparent", "important");
|
|
293
|
-
iframe.style.setProperty("position", "fixed", "important");
|
|
294
|
-
iframe.style.setProperty("top", 0, "important");
|
|
295
|
-
iframe.style.setProperty("right", 0, "important");
|
|
296
|
-
iframe.style.setProperty("width", "44px", "important");
|
|
297
|
-
iframe.style.setProperty("height", "48px", "important");
|
|
298
|
-
iframe.style.setProperty("z-index", 2147483647, "important");
|
|
299
|
-
return new Promise(resolve => {
|
|
300
|
-
iframe.contentDocument.body.style.setProperty("margin", 0);
|
|
301
|
-
iframe.onload = () => resolve(iframe.contentDocument.body);
|
|
302
|
-
});
|
|
303
60
|
}
|
|
304
61
|
}
|
|
305
62
|
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2010-2022 Gildas Lormeau
|
|
3
|
+
* contact : gildas.lormeau <at> gmail.com
|
|
4
|
+
*
|
|
5
|
+
* This file is part of SingleFile.
|
|
6
|
+
*
|
|
7
|
+
* The code in this file is free software: you can redistribute it and/or
|
|
8
|
+
* modify it under the terms of the GNU Affero General Public License
|
|
9
|
+
* (GNU AGPL) as published by the Free Software Foundation, either version 3
|
|
10
|
+
* of the License, or (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* The code in this file is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
|
|
15
|
+
* General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* As additional permission under GNU AGPL version 3 section 7, you may
|
|
18
|
+
* distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
|
|
19
|
+
* AGPL normally required by section 4, provided you include this license
|
|
20
|
+
* notice and a URL through which recipients can access the Corresponding
|
|
21
|
+
* Source.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/* global getComputedStyle, XPathResult, Node */
|
|
25
|
+
|
|
26
|
+
const INFOBAR_TAGNAME = "single-file-infobar";
|
|
27
|
+
const INFOBAR_STYLES = `
|
|
28
|
+
.infobar,
|
|
29
|
+
.infobar .infobar-icon,
|
|
30
|
+
.infobar .infobar-link-icon {
|
|
31
|
+
min-inline-size: 28px;
|
|
32
|
+
min-block-size: 28px;
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.infobar,
|
|
37
|
+
.infobar .infobar-close-icon,
|
|
38
|
+
.infobar .infobar-link-icon {
|
|
39
|
+
opacity: 0.7;
|
|
40
|
+
transition: opacity 250ms;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.infobar:hover,
|
|
44
|
+
.infobar .infobar-close-icon:hover,
|
|
45
|
+
.infobar .infobar-link-icon:hover {
|
|
46
|
+
opacity: 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.infobar,
|
|
50
|
+
.infobar-content {
|
|
51
|
+
display: flex;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.infobar {
|
|
55
|
+
position: fixed;
|
|
56
|
+
top: 16px;
|
|
57
|
+
right: 16px;
|
|
58
|
+
margin-inline-start: 16px;
|
|
59
|
+
margin-block-end: 16px;
|
|
60
|
+
color: #2d2d2d;
|
|
61
|
+
background-color: #737373;
|
|
62
|
+
border: 2px solid;
|
|
63
|
+
border-color: #eee;
|
|
64
|
+
border-radius: 16px;
|
|
65
|
+
z-index: 2147483647;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.infobar:valid, .infobar:not(:focus-within) .infobar-content {
|
|
69
|
+
display: none;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.infobar:focus-within {
|
|
73
|
+
background-color: #f9f9f9;
|
|
74
|
+
border-color: #878787;
|
|
75
|
+
border-radius: 8px;
|
|
76
|
+
opacity: 1;
|
|
77
|
+
transition-property: opacity, background-color, border-color, border-radius,
|
|
78
|
+
color;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.infobar-content {
|
|
82
|
+
align-items: center;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.infobar-content span {
|
|
86
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
87
|
+
font-size: 14px;
|
|
88
|
+
line-height: 18px;
|
|
89
|
+
word-break: break-word;
|
|
90
|
+
white-space: pre-wrap;
|
|
91
|
+
margin-inline: 4px;
|
|
92
|
+
margin-block: 4px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.infobar .infobar-icon,
|
|
96
|
+
.infobar .infobar-close-icon,
|
|
97
|
+
.infobar .infobar-link-icon {
|
|
98
|
+
cursor: pointer;
|
|
99
|
+
background-position: center;
|
|
100
|
+
background-repeat: no-repeat;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.infobar .infobar-close-icon,
|
|
104
|
+
.infobar .infobar-link-icon {
|
|
105
|
+
align-self: flex-start;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.infobar .infobar-icon {
|
|
109
|
+
position: absolute;
|
|
110
|
+
min-inline-size: 24px;
|
|
111
|
+
min-block-size: 24px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.infobar:focus-within .infobar-icon {
|
|
115
|
+
z-index: -1;
|
|
116
|
+
background-image: none;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.infobar .infobar-close-icon {
|
|
120
|
+
min-inline-size: 22px;
|
|
121
|
+
min-block-size: 22px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.infobar .infobar-icon {
|
|
125
|
+
background-color: transparent;
|
|
126
|
+
background-size: 70%;
|
|
127
|
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAABhmlDQ1BJQ0MgcHJvZmlsZQAAKJF9kj1Iw0AYht+mSkUrDnYQcchQnSyIijqWKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjx4LiH9+59+e67A4RGhalm1wSgapaRisfEbG5VDLyiDwEAvZiVmKkn0osZeI6ve/j4ehfhWd7n/hz9St5kgE8kjjLdsIg3iGc2LZ3zPnGIlSSF+Jx43KACiR+5Lrv8xrnosMAzQ0YmNU8cIhaLHSx3MCsZKvE0cVhRNcoXsi4rnLc4q5Uaa9XJbxjMaytprtMcQRxLSCAJETJqKKMCCxFaNVJMpGg/5uEfdvxJcsnkKoORYwFVqJAcP/gb/O6tWZiadJOCMaD7xbY/RoHALtCs2/b3sW03TwD/M3Cltf3VBjD3SXq9rYWPgIFt4OK6rcl7wOUOMPSkS4bkSH6aQqEAvJ/RM+WAwVv6EGtu31r7OH0AMtSr5Rvg4BAYK1L2use9ezr79u+ZVv9+AFlNcp0UUpiqAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH5AsHADIRLMaOHwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAPUExURQAAAIqKioyNjY2OjvDw8L2y1DEAAAABdFJOUwBA5thmAAAAAWJLR0QB/wIt3gAAAGNJREFUSMdjYCAJsLi4OBCQx6/CBQwIGIDPCBcXAkYQUsACU+AwlBVQHg6Eg5pgZBGOboIJZugDFwRwoJECJCUOhJI1wZwzqmBUwagCuipgIqTABG9h7YIKaKGAURAFEF/6AQAO4HqSoDP8bgAAAABJRU5ErkJggg==);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.infobar .infobar-link-icon {
|
|
131
|
+
background-size: 60%;
|
|
132
|
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAgMAAADXB5lNAAABhmlDQ1BJQ0MgcHJvZmlsZQAAKJF9kj1Iw0AYht+mSkUrDnYQcchQnSyIijqWKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjx4LiH9+59+e67A4RGhalm1wSgapaRisfEbG5VDLyiDwEAvZiVmKkn0osZeI6ve/j4ehfhWd7n/hz9St5kgE8kjjLdsIg3iGc2LZ3zPnGIlSSF+Jx43KACiR+5Lrv8xrnosMAzQ0YmNU8cIhaLHSx3MCsZKvE0cVhRNcoXsi4rnLc4q5Uaa9XJbxjMaytprtMcQRxLSCAJETJqKKMCCxFaNVJMpGg/5uEfdvxJcsnkKoORYwFVqJAcP/gb/O6tWZiadJOCMaD7xbY/RoHALtCs2/b3sW03TwD/M3Cltf3VBjD3SXq9rYWPgIFt4OK6rcl7wOUOMPSkS4bkSH6aQqEAvJ/RM+WAwVv6EGtu31r7OH0AMtSr5Rvg4BAYK1L2use9ezr79u+ZVv9+AFlNcp0UUpiqAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH5AsHAB8H+DhhoQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAJUExURQAAAICHi4qKioTuJAkAAAABdFJOUwBA5thmAAAAAWJLR0QCZgt8ZAAAAJJJREFUOI3t070NRCEMA2CnYAOyDyPwpHj/Va7hJ3FzV7zy3ET5JIwoAF6Jk4wzAJAkzxAYG9YRTgB+24wBgKmfrGAKTcEfAY4KRlRoIeBTgKOCERVaCPgU4Khge2GqKOBTgKOCERVaAEC/4PNcnyoSWHpjqkhwKxbcig0Q6AorXYF/+A6eIYD1lVbwG/jdA6/kA2THRAURVubcAAAAAElFTkSuQmCC);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.infobar .infobar-close-icon {
|
|
136
|
+
appearance: none;
|
|
137
|
+
background-size: 80%;
|
|
138
|
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAgMAAADXB5lNAAABhmlDQ1BJQ0MgcHJvZmlsZQAAKJF9kj1Iw0AYht+mSkUrDnYQcchQnSyIijqWKhbBQmkrtOpgcukfNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ0UVK/C4ptIjx4LiH9+59+e67A4RGhalm1wSgapaRisfEbG5VDLyiDwEAvZiVmKkn0osZeI6ve/j4ehfhWd7n/hz9St5kgE8kjjLdsIg3iGc2LZ3zPnGIlSSF+Jx43KACiR+5Lrv8xrnosMAzQ0YmNU8cIhaLHSx3MCsZKvE0cVhRNcoXsi4rnLc4q5Uaa9XJbxjMaytprtMcQRxLSCAJETJqKKMCCxFaNVJMpGg/5uEfdvxJcsnkKoORYwFVqJAcP/gb/O6tWZiadJOCMaD7xbY/RoHALtCs2/b3sW03TwD/M3Cltf3VBjD3SXq9rYWPgIFt4OK6rcl7wOUOMPSkS4bkSH6aQqEAvJ/RM+WAwVv6EGtu31r7OH0AMtSr5Rvg4BAYK1L2use9ezr79u+ZVv9+AFlNcp0UUpiqAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH5AsHAB8VC4EQ6QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAJUExURQAAAICHi4qKioTuJAkAAAABdFJOUwBA5thmAAAAAWJLR0QCZgt8ZAAAAJtJREFUOI3NkrsBgCAMRLFwBPdxBArcfxXFkO8rbKWAAJfHJ9faf9vuYX/749T5NmShm3bEwbe2SxeuM4+2oxDL1cDoKtVUjRy+tH78Cv2CS+wIiQNC1AEhk4AQeUTMWUJMfUJMSEJMSEY8kIx4IONroaYAimNxsXp1PA7PxwfVL8QnowwoVC0lig07wDDVUjAdbAnjwtow/z/bDW7eI4M2KruJAAAAAElFTkSuQmCC);
|
|
139
|
+
}
|
|
140
|
+
`;
|
|
141
|
+
|
|
142
|
+
export { displayIcon, appendInfobar, refreshInfobarInfo, extractInfobarData, INFOBAR_TAGNAME };
|
|
143
|
+
|
|
144
|
+
function appendInfobar(doc, options, useShadowRoot) {
|
|
145
|
+
if (!doc.querySelector(INFOBAR_TAGNAME)) {
|
|
146
|
+
let infoData = options.infobarContent ? options.infobarContent : options.saveDate;
|
|
147
|
+
infoData = infoData || "No info";
|
|
148
|
+
const infobarElement = createElement(doc, INFOBAR_TAGNAME, doc.body);
|
|
149
|
+
let infobarContainer;
|
|
150
|
+
if (useShadowRoot) {
|
|
151
|
+
infobarContainer = infobarElement.attachShadow({ mode: "open" });
|
|
152
|
+
} else {
|
|
153
|
+
const shadowRootTemplate = doc.createElement("template");
|
|
154
|
+
shadowRootTemplate.setAttribute("shadowroot", "open");
|
|
155
|
+
infobarElement.appendChild(shadowRootTemplate);
|
|
156
|
+
infobarContainer = shadowRootTemplate;
|
|
157
|
+
}
|
|
158
|
+
const shadowRootContent = doc.createElement("div");
|
|
159
|
+
const styleElement = doc.createElement("style");
|
|
160
|
+
styleElement.textContent = INFOBAR_STYLES
|
|
161
|
+
.replace(/ {2}/g, "")
|
|
162
|
+
.replace(/\n/g, "")
|
|
163
|
+
.replace(/: /g, ":")
|
|
164
|
+
.replace(/, /g, ",");
|
|
165
|
+
shadowRootContent.appendChild(styleElement);
|
|
166
|
+
const infobarContent = doc.createElement("form");
|
|
167
|
+
infobarContent.classList.add("infobar");
|
|
168
|
+
shadowRootContent.appendChild(infobarContent);
|
|
169
|
+
const iconElement = doc.createElement("span");
|
|
170
|
+
iconElement.tabIndex = -1;
|
|
171
|
+
iconElement.classList.add("infobar-icon");
|
|
172
|
+
infobarContent.appendChild(iconElement);
|
|
173
|
+
const contentElement = doc.createElement("span");
|
|
174
|
+
contentElement.tabIndex = -1;
|
|
175
|
+
contentElement.classList.add("infobar-content");
|
|
176
|
+
const closeButtonElement = doc.createElement("input");
|
|
177
|
+
closeButtonElement.type = "checkbox";
|
|
178
|
+
closeButtonElement.required = true;
|
|
179
|
+
closeButtonElement.classList.add("infobar-close-icon");
|
|
180
|
+
contentElement.appendChild(closeButtonElement);
|
|
181
|
+
const textElement = doc.createElement("span");
|
|
182
|
+
textElement.textContent = infoData;
|
|
183
|
+
contentElement.appendChild(textElement);
|
|
184
|
+
const linkElement = doc.createElement("a");
|
|
185
|
+
linkElement.classList.add("infobar-link-icon");
|
|
186
|
+
linkElement.target = "_blank";
|
|
187
|
+
linkElement.rel = "noopener noreferrer";
|
|
188
|
+
linkElement.title = "Open source URL: " + options.saveUrl;
|
|
189
|
+
linkElement.href = options.saveUrl;
|
|
190
|
+
contentElement.appendChild(linkElement);
|
|
191
|
+
infobarContent.appendChild(contentElement);
|
|
192
|
+
if (useShadowRoot) {
|
|
193
|
+
infobarContainer.appendChild(shadowRootContent);
|
|
194
|
+
} else {
|
|
195
|
+
const scriptElement = doc.createElement("script");
|
|
196
|
+
let scriptContent = (refreshInfobarInfo.toString());
|
|
197
|
+
scriptContent += (extractInfobarData.toString());
|
|
198
|
+
scriptContent += "refreshInfobarInfo(document, extractInfobarData(document))";
|
|
199
|
+
scriptContent = scriptContent
|
|
200
|
+
.replace(/ == /g, "==")
|
|
201
|
+
.replace(/ > /g, ">")
|
|
202
|
+
.replace(/ < /g, "<")
|
|
203
|
+
.replace(/ \+ /g, "+")
|
|
204
|
+
.replace(/ - /g, "-")
|
|
205
|
+
.replace(/ = /g, "=")
|
|
206
|
+
.replace(/ \+= /g, "+=")
|
|
207
|
+
.replace(/ && /g, "&&")
|
|
208
|
+
.replace(/ \|\| /g, "||")
|
|
209
|
+
.replace(/{ /g, "{")
|
|
210
|
+
.replace(/ }/g, "}")
|
|
211
|
+
.replace(/, /g, ",")
|
|
212
|
+
.replace(/; /g, ";")
|
|
213
|
+
.replace(/ \(/g, "(")
|
|
214
|
+
.replace(/ \)/g, ")")
|
|
215
|
+
.replace(/\t/g, "")
|
|
216
|
+
.replace(/\n/g, "");
|
|
217
|
+
scriptElement.textContent = scriptContent;
|
|
218
|
+
shadowRootContent.appendChild(scriptElement);
|
|
219
|
+
infobarContainer.innerHTML = shadowRootContent.outerHTML;
|
|
220
|
+
}
|
|
221
|
+
doc.body.appendChild(infobarElement);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function extractInfobarData(doc) {
|
|
226
|
+
const result = doc.evaluate("//comment()", doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
|
227
|
+
let singleFileComment = result && result.singleNodeValue;
|
|
228
|
+
if (singleFileComment && singleFileComment.nodeType == Node.COMMENT_NODE && singleFileComment.textContent.includes("SingleFile")) {
|
|
229
|
+
const info = singleFileComment.textContent.split("\n");
|
|
230
|
+
const [, , urlData, ...optionalData] = info;
|
|
231
|
+
const urlMatch = urlData.match(/^ url: (.*) ?$/);
|
|
232
|
+
const saveUrl = urlMatch && urlMatch[1];
|
|
233
|
+
if (saveUrl) {
|
|
234
|
+
let infobarContent, saveDate;
|
|
235
|
+
if (optionalData.length) {
|
|
236
|
+
saveDate = optionalData[0].split("saved date: ")[1];
|
|
237
|
+
if (saveDate) {
|
|
238
|
+
optionalData.shift();
|
|
239
|
+
}
|
|
240
|
+
if (optionalData.length > 1) {
|
|
241
|
+
let content = optionalData[0].split("info: ")[1].trim();
|
|
242
|
+
for (let indexLine = 1; indexLine < optionalData.length - 1; indexLine++) {
|
|
243
|
+
content += "\n" + optionalData[indexLine].trim();
|
|
244
|
+
}
|
|
245
|
+
infobarContent = content.trim();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return { saveUrl, infobarContent, saveDate };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function refreshInfobarInfo(doc, { saveUrl, infobarContent, saveDate }) {
|
|
254
|
+
if (saveUrl) {
|
|
255
|
+
const infobarElement = doc.querySelector("single-file-infobar");
|
|
256
|
+
const shadowRootFragment = infobarElement.shadowRoot;
|
|
257
|
+
const infobarContentElement = shadowRootFragment.querySelector(".infobar-content span");
|
|
258
|
+
infobarContentElement.textContent = infobarContent || saveDate;
|
|
259
|
+
const linkElement = shadowRootFragment.querySelector(".infobar-content .infobar-link-icon");
|
|
260
|
+
linkElement.href = saveUrl;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function displayIcon(doc, useShadowRoot) {
|
|
265
|
+
const infoData = extractInfobarData(doc);
|
|
266
|
+
if (infoData.saveUrl) {
|
|
267
|
+
appendInfobar(doc, infoData, useShadowRoot);
|
|
268
|
+
refreshInfobarInfo(doc, infoData);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function createElement(doc, tagName, parentElement) {
|
|
273
|
+
const element = doc.createElement(tagName);
|
|
274
|
+
parentElement.appendChild(element);
|
|
275
|
+
Array.from(getComputedStyle(element)).forEach(property => element.style.setProperty(property, "initial", "important"));
|
|
276
|
+
return element;
|
|
277
|
+
}
|
package/package.json
CHANGED
|
@@ -314,10 +314,12 @@
|
|
|
314
314
|
|
|
315
315
|
addEventListener(GET_ADOPTED_STYLESHEETS_REQUEST_EVENT, event => {
|
|
316
316
|
const shadowRoot = event.target.shadowRoot;
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
317
|
+
if (shadowRoot) {
|
|
318
|
+
const adoptedStyleSheets = Array.from(shadowRoot.adoptedStyleSheets).map(stylesheet => Array.from(stylesheet.cssRules).map(cssRule => cssRule.cssText).join("\n"));
|
|
319
|
+
if (adoptedStyleSheets.length) {
|
|
320
|
+
event.target.dispatchEvent(new CustomEvent(GET_ADOPTED_STYLESHEETS_RESPONSE_EVENT, { detail: { adoptedStyleSheets } }));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
321
323
|
}, { capture: true });
|
|
322
324
|
|
|
323
325
|
if (globalThis.FontFace) {
|
package/single-file-core.js
CHANGED
|
@@ -494,6 +494,18 @@ class Processor {
|
|
|
494
494
|
);
|
|
495
495
|
this.doc.documentElement.insertBefore(commentNode, this.doc.documentElement.firstChild);
|
|
496
496
|
}
|
|
497
|
+
if (this.options.includeInfobar) {
|
|
498
|
+
util.appendInfobar(this.doc, this.options);
|
|
499
|
+
}
|
|
500
|
+
if (this.doc.querySelector("template[" + SHADOWROOT_ATTRIBUTE_NAME + "]") || (this.options.shadowRoots && this.options.shadowRoots.length)) {
|
|
501
|
+
if (this.options.blockScripts) {
|
|
502
|
+
this.doc.querySelectorAll("script[" + SCRIPT_TEMPLATE_SHADOW_ROOT + "]").forEach(element => element.remove());
|
|
503
|
+
}
|
|
504
|
+
const scriptElement = this.doc.createElement("script");
|
|
505
|
+
scriptElement.setAttribute(SCRIPT_TEMPLATE_SHADOW_ROOT, "");
|
|
506
|
+
scriptElement.textContent = `(()=>{document.currentScript.remove();processNode(document);function processNode(node){node.querySelectorAll("template[${SHADOWROOT_ATTRIBUTE_NAME}]").forEach(element=>{let shadowRoot = element.parentElement.shadowRoot;if (!shadowRoot) {try {shadowRoot=element.parentElement.attachShadow({mode:element.getAttribute("${SHADOWROOT_ATTRIBUTE_NAME}")});shadowRoot.innerHTML=element.innerHTML;element.remove()} catch (error) {} if (shadowRoot) {processNode(shadowRoot)}}})}})()`;
|
|
507
|
+
this.doc.body.appendChild(scriptElement);
|
|
508
|
+
}
|
|
497
509
|
if (this.options.insertCanonicalLink && this.options.saveUrl.match(HTTP_URI_PREFIX)) {
|
|
498
510
|
let canonicalLink = this.doc.querySelector("link[rel=canonical]");
|
|
499
511
|
if (!canonicalLink) {
|
|
@@ -724,15 +736,16 @@ class Processor {
|
|
|
724
736
|
|
|
725
737
|
removeEmbedScripts() {
|
|
726
738
|
const JAVASCRIPT_URI_PREFIX = "javascript:";
|
|
739
|
+
const DISABLED_SCRIPT = "javascript:void(0)";
|
|
727
740
|
this.onEventAttributeNames.forEach(attributeName => this.doc.querySelectorAll("[" + attributeName + "]").forEach(element => element.removeAttribute(attributeName)));
|
|
728
741
|
this.doc.querySelectorAll("[href]").forEach(element => {
|
|
729
742
|
if (element.href && element.href.match && element.href.trim().startsWith(JAVASCRIPT_URI_PREFIX)) {
|
|
730
|
-
element.
|
|
743
|
+
element.setAttribute("href", DISABLED_SCRIPT);
|
|
731
744
|
}
|
|
732
745
|
});
|
|
733
746
|
this.doc.querySelectorAll("[src]").forEach(element => {
|
|
734
747
|
if (element.src && element.src.trim().startsWith(JAVASCRIPT_URI_PREFIX)) {
|
|
735
|
-
element.
|
|
748
|
+
element.setAttribute("src", DISABLED_SCRIPT);
|
|
736
749
|
}
|
|
737
750
|
});
|
|
738
751
|
const scriptElements = this.doc.querySelectorAll("script:not([type=\"application/ld+json\"]):not([" + SCRIPT_TEMPLATE_SHADOW_ROOT + "])");
|
|
@@ -874,7 +887,11 @@ class Processor {
|
|
|
874
887
|
if (attributeValue) {
|
|
875
888
|
const canvasData = this.options.canvases[Number(attributeValue)];
|
|
876
889
|
if (canvasData) {
|
|
877
|
-
|
|
890
|
+
const backgroundStyle = {};
|
|
891
|
+
if (canvasData.backgroundColor) {
|
|
892
|
+
backgroundStyle["background-color"] = canvasData.backgroundColor;
|
|
893
|
+
}
|
|
894
|
+
ProcessorHelper.setBackgroundImage(canvasElement, "url(" + canvasData.dataURI + ")", backgroundStyle);
|
|
878
895
|
this.stats.add("processed", "canvas", 1);
|
|
879
896
|
}
|
|
880
897
|
}
|
|
@@ -1139,13 +1156,6 @@ class Processor {
|
|
|
1139
1156
|
const options = this.options;
|
|
1140
1157
|
if (options.shadowRoots && options.shadowRoots.length) {
|
|
1141
1158
|
processElement(this.doc);
|
|
1142
|
-
if (options.blockScripts) {
|
|
1143
|
-
this.doc.querySelectorAll("script[" + SCRIPT_TEMPLATE_SHADOW_ROOT + "]").forEach(element => element.remove());
|
|
1144
|
-
}
|
|
1145
|
-
const scriptElement = doc.createElement("script");
|
|
1146
|
-
scriptElement.setAttribute(SCRIPT_TEMPLATE_SHADOW_ROOT, "");
|
|
1147
|
-
scriptElement.textContent = `(()=>{document.currentScript.remove();processNode(document);function processNode(node){node.querySelectorAll("template[${SHADOWROOT_ATTRIBUTE_NAME}]").forEach(element=>{let shadowRoot = element.parentElement.shadowRoot;if (!shadowRoot) {try {shadowRoot=element.parentElement.attachShadow({mode:element.getAttribute("${SHADOWROOT_ATTRIBUTE_NAME}")});shadowRoot.innerHTML=element.innerHTML;element.remove()} catch (error) {} if (shadowRoot) {processNode(shadowRoot)}}})}})()`;
|
|
1148
|
-
doc.body.appendChild(scriptElement);
|
|
1149
1159
|
}
|
|
1150
1160
|
|
|
1151
1161
|
function processElement(element) {
|
|
@@ -1157,13 +1167,6 @@ class Processor {
|
|
|
1157
1167
|
if (shadowRootData) {
|
|
1158
1168
|
const templateElement = doc.createElement("template");
|
|
1159
1169
|
templateElement.setAttribute(SHADOWROOT_ATTRIBUTE_NAME, shadowRootData.mode);
|
|
1160
|
-
if (shadowRootData.adoptedStyleSheets) {
|
|
1161
|
-
shadowRootData.adoptedStyleSheets.forEach(stylesheetContent => {
|
|
1162
|
-
const styleElement = doc.createElement("style");
|
|
1163
|
-
styleElement.textContent = stylesheetContent;
|
|
1164
|
-
templateElement.appendChild(styleElement);
|
|
1165
|
-
});
|
|
1166
|
-
}
|
|
1167
1170
|
const shadowDoc = util.parseDocContent(shadowRootData.content);
|
|
1168
1171
|
if (shadowDoc.head) {
|
|
1169
1172
|
const metaCharset = shadowDoc.head.querySelector("meta[charset]");
|
|
@@ -1181,6 +1184,13 @@ class Processor {
|
|
|
1181
1184
|
} else {
|
|
1182
1185
|
element.appendChild(templateElement);
|
|
1183
1186
|
}
|
|
1187
|
+
if (shadowRootData.adoptedStyleSheets) {
|
|
1188
|
+
shadowRootData.adoptedStyleSheets.forEach(stylesheetContent => {
|
|
1189
|
+
const styleElement = doc.createElement("style");
|
|
1190
|
+
styleElement.textContent = stylesheetContent;
|
|
1191
|
+
templateElement.appendChild(styleElement);
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1184
1194
|
}
|
|
1185
1195
|
}
|
|
1186
1196
|
});
|
package/single-file-helper.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
import * as cssUnescape from "./vendor/css-unescape.js";
|
|
27
27
|
import * as hooksFrames from "./processors/hooks/content/content-hooks-frames.js";
|
|
28
|
+
import * as infobar from "./common/infobar.js";
|
|
28
29
|
|
|
29
30
|
const ON_BEFORE_CAPTURE_EVENT_NAME = "single-file-on-before-capture";
|
|
30
31
|
const ON_AFTER_CAPTURE_EVENT_NAME = "single-file-on-after-capture";
|
|
@@ -79,6 +80,7 @@ export {
|
|
|
79
80
|
getFontWeight,
|
|
80
81
|
normalizeFontFamily,
|
|
81
82
|
getShadowRoot,
|
|
83
|
+
appendInfobar,
|
|
82
84
|
ON_BEFORE_CAPTURE_EVENT_NAME,
|
|
83
85
|
ON_AFTER_CAPTURE_EVENT_NAME,
|
|
84
86
|
WIN_ID_ATTRIBUTE_NAME,
|
|
@@ -265,7 +267,10 @@ function getResourcesInfo(win, doc, element, options, data, elementHidden, compu
|
|
|
265
267
|
const tagName = element.tagName && element.tagName.toUpperCase();
|
|
266
268
|
if (tagName == "CANVAS") {
|
|
267
269
|
try {
|
|
268
|
-
data.canvases.push({
|
|
270
|
+
data.canvases.push({
|
|
271
|
+
dataURI: element.toDataURL("image/png", ""),
|
|
272
|
+
backgroundColor: computedStyle.getPropertyValue("background-color")
|
|
273
|
+
});
|
|
269
274
|
element.setAttribute(CANVAS_ATTRIBUTE_NAME, data.canvases.length - 1);
|
|
270
275
|
data.markedElements.push(element);
|
|
271
276
|
} catch (error) {
|
|
@@ -395,6 +400,10 @@ function getShadowRoot(element) {
|
|
|
395
400
|
}
|
|
396
401
|
}
|
|
397
402
|
|
|
403
|
+
function appendInfobar(doc, options, useShadowRoot) {
|
|
404
|
+
return infobar.appendInfobar(doc, options, useShadowRoot);
|
|
405
|
+
}
|
|
406
|
+
|
|
398
407
|
function normalizeFontFamily(fontFamilyName = "") {
|
|
399
408
|
return removeQuotes(cssUnescape.process(fontFamilyName.trim())).toLowerCase();
|
|
400
409
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2010-2020 Gildas Lormeau
|
|
3
|
+
* contact : gildas.lormeau <at> gmail.com
|
|
4
|
+
*
|
|
5
|
+
* This file is part of SingleFile.
|
|
6
|
+
*
|
|
7
|
+
* The code in this file is free software: you can redistribute it and/or
|
|
8
|
+
* modify it under the terms of the GNU Affero General Public License
|
|
9
|
+
* (GNU AGPL) as published by the Free Software Foundation, either version 3
|
|
10
|
+
* of the License, or (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* The code in this file is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
|
|
15
|
+
* General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* As additional permission under GNU AGPL version 3 section 7, you may
|
|
18
|
+
* distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
|
|
19
|
+
* AGPL normally required by section 4, provided you include this license
|
|
20
|
+
* notice and a URL through which recipients can access the Corresponding
|
|
21
|
+
* Source.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import * as serializer from "./modules/html-serializer.js";
|
|
25
|
+
import * as infobar from "./common/infobar.js";
|
|
26
|
+
|
|
27
|
+
const helper = {
|
|
28
|
+
serialize(doc, compressHTML) {
|
|
29
|
+
return serializer.process(doc, compressHTML);
|
|
30
|
+
},
|
|
31
|
+
appendInfobar(doc, options, useShadowRoot) {
|
|
32
|
+
return infobar.appendInfobar(doc, options, useShadowRoot);
|
|
33
|
+
},
|
|
34
|
+
extractInfobarData(doc) {
|
|
35
|
+
return infobar.extractInfobarData(doc);
|
|
36
|
+
},
|
|
37
|
+
displayIcon(doc, useShadowRoot) {
|
|
38
|
+
return infobar.displayIcon(doc, useShadowRoot);
|
|
39
|
+
},
|
|
40
|
+
INFOBAR_TAGNAME: infobar.INFOBAR_TAGNAME
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
helper
|
|
45
|
+
};
|
package/single-file-util.js
CHANGED
|
@@ -160,6 +160,9 @@ function getInstance(utilOptions) {
|
|
|
160
160
|
removeQuotes(string) {
|
|
161
161
|
return helper.removeQuotes(string);
|
|
162
162
|
},
|
|
163
|
+
appendInfobar(doc, options) {
|
|
164
|
+
return helper.appendInfobar(doc, options);
|
|
165
|
+
},
|
|
163
166
|
ON_BEFORE_CAPTURE_EVENT_NAME: helper.ON_BEFORE_CAPTURE_EVENT_NAME,
|
|
164
167
|
ON_AFTER_CAPTURE_EVENT_NAME: helper.ON_AFTER_CAPTURE_EVENT_NAME,
|
|
165
168
|
WIN_ID_ATTRIBUTE_NAME: helper.WIN_ID_ATTRIBUTE_NAME,
|