Przeglądaj źródła

make sure DOM content exists before inserting it (fix issue #209)

Gildas 6 lat temu
rodzic
commit
12ccf00147
1 zmienionych plików z 58 dodań i 48 usunięć
  1. 58 48
      lib/single-file/single-file-core.js

+ 58 - 48
lib/single-file/single-file-core.js

@@ -475,24 +475,27 @@ this.singlefile.lib.core = this.singlefile.lib.core || (() => {
 				this.doc.body.querySelectorAll(":not(svg) title, meta, link[href][rel*=\"icon\"]").forEach(element => element instanceof this.options.win.HTMLElement && this.doc.head.appendChild(element));
 			}
 			if (this.options.images && !this.options.saveRawPage) {
-				const dataAttributeName = util.IMAGE_ATTRIBUTE_NAME;
-				this.doc.querySelectorAll("img").forEach(imgElement => {
-					const imageData = this.options.images[Number(imgElement.getAttribute(dataAttributeName))];
-					if (this.options.removeHiddenElements && imageData.size && !imageData.size.pxWidth && !imageData.size.pxHeight) {
-						imgElement.setAttribute("src", EMPTY_IMAGE);
-					} else if (imageData.currentSrc) {
-						imgElement.setAttribute("src", imageData.currentSrc);
+				this.doc.querySelectorAll("img[" + util.IMAGE_ATTRIBUTE_NAME + "]").forEach(imgElement => {
+					const attributeValue = imgElement.getAttribute(util.IMAGE_ATTRIBUTE_NAME);
+					if (attributeValue) {
+						const imageData = this.options.images[Number(attributeValue)];
+						if (imageData) {
+							if (this.options.removeHiddenElements && imageData.size && !imageData.size.pxWidth && !imageData.size.pxHeight) {
+								imgElement.setAttribute("src", EMPTY_IMAGE);
+							} else if (imageData.currentSrc) {
+								imgElement.setAttribute("src", imageData.currentSrc);
+							}
+							if (this.options.loadDeferredImages) {
+								if ((!imgElement.getAttribute("src") || imgElement.getAttribute("src") == EMPTY_IMAGE) && imgElement.getAttribute("data-src")) {
+									imageData.src = imgElement.dataset.src;
+									imgElement.setAttribute("src", imgElement.dataset.src);
+									imgElement.removeAttribute("data-src");
+								}
+							}
+						}
 					}
 				});
 				if (this.options.loadDeferredImages) {
-					this.doc.querySelectorAll("img[data-src]").forEach(imgElement => {
-						const imageData = this.options.images[Number(imgElement.getAttribute(dataAttributeName))];
-						if ((!imgElement.getAttribute("src") || imgElement.getAttribute("src") == EMPTY_IMAGE) && imgElement.getAttribute("data-src")) {
-							imageData.src = imgElement.dataset.src;
-							imgElement.setAttribute("src", imgElement.dataset.src);
-							imgElement.removeAttribute("data-src");
-						}
-					});
 					this.doc.querySelectorAll("img[data-srcset]").forEach(imgElement => {
 						if (!imgElement.getAttribute("srcset") && imgElement.getAttribute("data-srcset")) {
 							imgElement.setAttribute("srcset", imgElement.dataset.srcset);
@@ -561,9 +564,12 @@ this.singlefile.lib.core = this.singlefile.lib.core || (() => {
 					} else {
 						videoElement = element.parentElement;
 					}
-					const videoIndex = Number(element.getAttribute(util.POSTER_ATTRIBUTE_NAME));
-					if (!videoElement.poster && this.options.posters[videoIndex]) {
-						videoElement.setAttribute("poster", this.options.posters[videoIndex]);
+					const attributeValue = element.getAttribute(util.POSTER_ATTRIBUTE_NAME);
+					if (attributeValue) {
+						const posterURL = this.options.posters[Number(attributeValue)];
+						if (!videoElement.poster && posterURL) {
+							videoElement.setAttribute("poster", posterURL);
+						}
 					}
 				});
 			}
@@ -713,11 +719,13 @@ this.singlefile.lib.core = this.singlefile.lib.core || (() => {
 		replaceCanvasElements() {
 			if (this.options.canvases) {
 				this.doc.querySelectorAll("canvas").forEach(canvasElement => {
-					const canvasIndex = Number(canvasElement.getAttribute(util.CANVAS_ATTRIBUTE_NAME));
-					const canvasData = this.options.canvases[canvasIndex];
-					if (canvasData) {
-						ProcessorHelper.setBackgroundImage(canvasElement, "url(" + canvasData.dataURI + ")");
-						this.stats.add("processed", "canvas", 1);
+					const attributeValue = canvasElement.getAttribute(util.CANVAS_ATTRIBUTE_NAME);
+					if (attributeValue) {
+						const canvasData = this.options.canvases[Number(attributeValue)];
+						if (canvasData) {
+							ProcessorHelper.setBackgroundImage(canvasElement, "url(" + canvasData.dataURI + ")");
+							this.stats.add("processed", "canvas", 1);
+						}
 					}
 				});
 			}
@@ -892,27 +900,29 @@ this.singlefile.lib.core = this.singlefile.lib.core || (() => {
 			function processElement(element) {
 				const shadowRootElements = Array.from((element.querySelectorAll("[" + util.SHADOW_ROOT_ATTRIBUTE_NAME + "]")));
 				shadowRootElements.forEach(element => {
-					const id = element.getAttribute(util.SHADOW_ROOT_ATTRIBUTE_NAME);
-					const shadowRootData = options.shadowRoots[Number(id)];
-					if (shadowRootData) {
-						const templateElement = doc.createElement("template");
-						templateElement.setAttribute(WC_ATTRIBUTE_NAME, "");
-						const shadowDoc = util.parseDocContent(shadowRootData.content);
-						if (shadowDoc.head) {
-							const metaCharset = shadowDoc.head.querySelector("meta[charset]");
-							if (metaCharset) {
-								metaCharset.remove();
+					const attributeValue = element.getAttribute(util.SHADOW_ROOT_ATTRIBUTE_NAME);
+					if (attributeValue) {
+						const shadowRootData = options.shadowRoots[Number(attributeValue)];
+						if (shadowRootData) {
+							const templateElement = doc.createElement("template");
+							templateElement.setAttribute(WC_ATTRIBUTE_NAME, "");
+							const shadowDoc = util.parseDocContent(shadowRootData.content);
+							if (shadowDoc.head) {
+								const metaCharset = shadowDoc.head.querySelector("meta[charset]");
+								if (metaCharset) {
+									metaCharset.remove();
+								}
+								shadowDoc.head.childNodes.forEach(node => templateElement.appendChild(shadowDoc.importNode(node, true)));
+							}
+							if (shadowDoc.body) {
+								shadowDoc.body.childNodes.forEach(node => templateElement.appendChild(shadowDoc.importNode(node, true)));
+							}
+							processElement(templateElement);
+							if (element.firstChild) {
+								element.insertBefore(templateElement, element.firstChild);
+							} else {
+								element.appendChild(templateElement);
 							}
-							shadowDoc.head.childNodes.forEach(node => templateElement.appendChild(shadowDoc.importNode(node, true)));
-						}
-						if (shadowDoc.body) {
-							shadowDoc.body.childNodes.forEach(node => templateElement.appendChild(shadowDoc.importNode(node, true)));
-						}
-						processElement(templateElement);
-						if (element.firstChild) {
-							element.insertBefore(templateElement, element.firstChild);
-						} else {
-							element.appendChild(templateElement);
 						}
 					}
 				});
@@ -1568,10 +1578,10 @@ this.singlefile.lib.core = this.singlefile.lib.core || (() => {
 		}
 
 		static replaceImageSource(imgElement, variableName, options) {
-			const dataAttributeName = util.IMAGE_ATTRIBUTE_NAME;
-			if (imgElement.getAttribute(dataAttributeName) != null) {
-				const imageData = options.images[Number(imgElement.getAttribute(dataAttributeName))];
-				if (imageData.replaceable) {
+			const attributeValue = imgElement.getAttribute(util.IMAGE_ATTRIBUTE_NAME);
+			if (attributeValue) {
+				const imageData = options.images[Number(imgElement.getAttribute(util.IMAGE_ATTRIBUTE_NAME))];
+				if (imageData && imageData.replaceable) {
 					imgElement.setAttribute("src", `${PREFIX_DATA_URI_IMAGE_SVG},<svg xmlns="http://www.w3.org/2000/svg" width="${imageData.size.pxWidth}" height="${imageData.size.pxHeight}"><rect fill-opacity="0"/></svg>`);
 					const backgroundStyle = {};
 					const backgroundSize = (imageData.objectFit == "content" || imageData.objectFit == "cover") && imageData.objectFit;
@@ -1585,7 +1595,7 @@ this.singlefile.lib.core = this.singlefile.lib.core || (() => {
 						backgroundStyle["background-color"] = imageData.backgroundColor;
 					}
 					ProcessorHelper.setBackgroundImage(imgElement, "var(" + variableName + ")", backgroundStyle);
-					imgElement.removeAttribute(dataAttributeName);
+					imgElement.removeAttribute(util.IMAGE_ATTRIBUTE_NAME);
 					return true;
 				}
 			}