瀏覽代碼

moved all hooks into hooks and hooks-frame

Gildas 7 年之前
父節點
當前提交
df4850ecd2

+ 2 - 1
extension/core/bg/script-loader.js

@@ -23,6 +23,7 @@
 singlefile.scriptLoader = (() => {
 
 	const contentScriptFiles = [
+		"/lib/hooks/hooks.js",
 		"/lib/browser-polyfill/custom-browser-polyfill.js",
 		"/lib/single-file/vendor/css-tree.js",
 		"/lib/single-file/vendor/html-srcset-parser.js",
@@ -38,8 +39,8 @@ singlefile.scriptLoader = (() => {
 	];
 
 	const frameScriptFiles = [
+		"/lib/hooks/hooks-frame.js",
 		"/lib/browser-polyfill/custom-browser-polyfill.js",
-		"/lib/hooks/hooks.js",
 		"/extension/index.js",
 		"/lib/single-file/util/doc-helper.js",
 		"/lib/single-file/util/timeout.js",

+ 1 - 16
extension/core/content/content-bootstrap.js

@@ -18,7 +18,7 @@
  *   along with SingleFile.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/* global singlefile, frameTree, browser, window, history, HTMLDocument, dispatchEvent, CustomEvent, addEventListener, removeEventListener, document, location, docHelper, setTimeout */
+/* global singlefile, frameTree, browser, window, addEventListener, removeEventListener, document, location, docHelper, setTimeout */
 
 this.singlefile.autosave = this.singlefile.autosave || (async () => {
 
@@ -34,12 +34,6 @@ this.singlefile.autosave = this.singlefile.autosave || (async () => {
 			refresh();
 		}
 	});
-	if (location.href.startsWith("http") && document instanceof HTMLDocument) {
-		const scriptElement = document.createElement("script");
-		scriptElement.textContent = `(${hookPushState.toString()})()`;
-		document.documentElement.appendChild(scriptElement);
-		scriptElement.remove();
-	}
 	browser.runtime.sendMessage({ processReset: true });
 	return {};
 
@@ -124,13 +118,4 @@ this.singlefile.autosave = this.singlefile.autosave || (async () => {
 		}
 	}
 
-	function hookPushState() {
-		console.warn("SingleFile is hooking the history.pushState API to detect navigation."); // eslint-disable-line no-console
-		const pushState = history.pushState;
-		history.pushState = function (state, title, url) {
-			dispatchEvent(new CustomEvent("single-file-push-state", { detail: { state, title, url } }));
-			pushState.call(history, state, title, url);
-		};
-	}
-
 })();

+ 128 - 0
lib/hooks/hooks-frame.js

@@ -0,0 +1,128 @@
+/*
+ * Copyright 2018 Gildas Lormeau
+ * contact : gildas.lormeau <at> gmail.com
+ * 
+ * This file is part of SingleFile.
+ *
+ *   SingleFile is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   SingleFile is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with SingleFile.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* global window, addEventListener, dispatchEvent, CustomEvent, document, HTMLDocument */
+
+this.hooksFrame = this.hooksFrame || (() => {
+
+	const NEW_FONT_FACE_EVENT = "single-file-new-font-face";
+	const fontFaces = [];
+
+	if (document instanceof HTMLDocument) {
+		const scriptElement = document.createElement("script");
+		scriptElement.textContent = `(${hook.toString()})()`;
+		document.documentElement.appendChild(scriptElement);
+		scriptElement.remove();
+		addEventListener(NEW_FONT_FACE_EVENT, event => fontFaces.push(event.detail));
+	}
+
+	return {
+		getFontsData: () => fontFaces
+	};
+
+	function hook() {
+		const NEW_FONT_FACE_EVENT = "single-file-new-font-face";
+		const FONT_STYLE_PROPERTIES = {
+			family: "font-family",
+			style: "font-style",
+			weight: "font-weight",
+			stretch: "font-stretch",
+			unicodeRange: "unicode-range",
+			variant: "font-variant",
+			featureSettings: "font-feature-settings"
+		};
+
+		const FontFace = window.FontFace;
+		let warningFontFaceDisplayed;
+		window.__defineGetter__("FontFace", () => new Proxy(FontFace, {
+			construct(FontFace, argumentsList) {
+				if (!warningFontFaceDisplayed) {
+					console.warn("SingleFile is hooking the FontFace constructor to get font URLs."); // eslint-disable-line no-console
+				}
+				const detail = {};
+				detail["font-family"] = argumentsList[0];
+				detail.src = argumentsList[1];
+				const descriptors = argumentsList[2];
+				if (descriptors) {
+					Object.keys(descriptors).forEach(descriptor => detail[FONT_STYLE_PROPERTIES[descriptor]] = descriptors[descriptor]);
+				}
+				dispatchEvent(new CustomEvent(NEW_FONT_FACE_EVENT, { detail }));
+				return new FontFace(...argumentsList);
+			}
+		}));
+
+		const LOAD_OBSERVED_ELEMENTS_EVENT = "single-file-load-observed-elements";
+
+		const IntersectionObserver = window.IntersectionObserver;
+		const observeIntersection = IntersectionObserver.prototype.observe;
+		const unobserveIntersection = IntersectionObserver.prototype.unobserve;
+		const observedElements = new Map();
+		const observers = new Map();
+		let warningIntersectionObserverDisplayed;
+		window.__defineGetter__("IntersectionObserver", () => new Proxy(IntersectionObserver, {
+			construct(IntersectionObserver, argumentsList) {
+				if (!warningIntersectionObserverDisplayed) {
+					console.warn("SingleFile is hooking the IntersectionObserver API to detect and load deferred images."); // eslint-disable-line no-console
+				}
+				const intersectionObserver = new IntersectionObserver(...argumentsList);
+				const callback = argumentsList[0];
+				const options = argumentsList[1];
+				intersectionObserver.observe = function (targetElement) {
+					let targetElements = observedElements.get(intersectionObserver);
+					if (!targetElements) {
+						targetElements = [];
+						observedElements.set(intersectionObserver, targetElements);
+					}
+					targetElements.push(targetElement);
+					return observeIntersection.call(intersectionObserver, targetElement);
+				};
+				intersectionObserver.unobserve = function (targetElement) {
+					let targetElements = observedElements.get(intersectionObserver);
+					if (targetElements) {
+						targetElements = targetElements.filter(element => element <= targetElement);
+						if (targetElements.length) {
+							observedElements.set(intersectionObserver, targetElements);
+						} else {
+							observedElements.delete(intersectionObserver);
+						}
+					}
+					return unobserveIntersection.call(intersectionObserver, targetElement);
+				};
+				observers.set(intersectionObserver, { callback, options });
+				return intersectionObserver;
+			}
+		}));
+		window.__defineSetter__("IntersectionObserver", () => { });
+		addEventListener(LOAD_OBSERVED_ELEMENTS_EVENT, () => {
+			Array.from(observers).forEach(([intersectionObserver, observer]) => {
+				observer.callback(observedElements.get(intersectionObserver).map(target => {
+					const boundingClientRect = target.getBoundingClientRect();
+					const intersectionRect = target.getBoundingClientRect();
+					const isIntersecting = true;
+					const intersectionRatio = 1;
+					const rootBounds = observer.options && observer.options.root ? observer.options.root.getBoundingClientRect() : document.documentElement.getBoundingClientRect();
+					const time = 0;
+					return { target, intersectionRatio, boundingClientRect, intersectionRect, isIntersecting, rootBounds, time };
+				}), intersectionObserver);
+			});
+		}, false);
+	}
+
+})();

+ 13 - 94
lib/hooks/hooks.js

@@ -18,111 +18,30 @@
  *   along with SingleFile.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/* global window, addEventListener, dispatchEvent, CustomEvent, document, HTMLDocument */
+/* global history, dispatchEvent, CustomEvent, document, HTMLDocument */
 
 this.hooks = this.hooks || (() => {
 
-	const NEW_FONT_FACE_EVENT = "single-file-new-font-face";
-	const fontFaces = [];
-
 	if (document instanceof HTMLDocument) {
 		const scriptElement = document.createElement("script");
-		scriptElement.textContent = `(${hook.toString()})()`;
+		scriptElement.textContent = `(${hookPushState.toString()})()`;
 		document.documentElement.appendChild(scriptElement);
 		scriptElement.remove();
-		addEventListener(NEW_FONT_FACE_EVENT, event => fontFaces.push(event.detail));
 	}
 
-	return {
-		getFontsData: () => fontFaces
-	};
-
-	function hook() {
-		const NEW_FONT_FACE_EVENT = "single-file-new-font-face";
-		const FONT_STYLE_PROPERTIES = {
-			family: "font-family",
-			style: "font-style",
-			weight: "font-weight",
-			stretch: "font-stretch",
-			unicodeRange: "unicode-range",
-			variant: "font-variant",
-			featureSettings: "font-feature-settings"
-		};
+	return true;
 
-		const FontFace = window.FontFace;
-		let warningFontFaceDisplayed;
-		window.__defineGetter__("FontFace", () => new Proxy(FontFace, {
-			construct(FontFace, argumentsList) {
-				if (!warningFontFaceDisplayed) {
-					console.warn("SingleFile is hooking the FontFace constructor to get font URLs."); // eslint-disable-line no-console
-				}
-				const detail = {};
-				detail["font-family"] = argumentsList[0];
-				detail.src = argumentsList[1];
-				const descriptors = argumentsList[2];
-				if (descriptors) {
-					Object.keys(descriptors).forEach(descriptor => detail[FONT_STYLE_PROPERTIES[descriptor]] = descriptors[descriptor]);
-				}
-				dispatchEvent(new CustomEvent(NEW_FONT_FACE_EVENT, { detail }));
-				return new FontFace(...argumentsList);
+	function hookPushState() {
+		const pushState = history.pushState;
+		let warningDisplayed;
+		history.pushState = function (state, title, url) {
+			if (!warningDisplayed) {
+				warningDisplayed = true;
+				console.warn("SingleFile is hooking the history.pushState API to detect navigation."); // eslint-disable-line no-console		
 			}
-		}));
-
-		const LOAD_OBSERVED_ELEMENTS_EVENT = "single-file-load-observed-elements";
-
-		const IntersectionObserver = window.IntersectionObserver;
-		const observeIntersection = IntersectionObserver.prototype.observe;
-		const unobserveIntersection = IntersectionObserver.prototype.unobserve;
-		const observedElements = new Map();
-		const observers = new Map();
-		let warningIntersectionObserverDisplayed;
-		window.__defineGetter__("IntersectionObserver", () => new Proxy(IntersectionObserver, {
-			construct(IntersectionObserver, argumentsList) {
-				if (!warningIntersectionObserverDisplayed) {
-					console.warn("SingleFile is hooking the IntersectionObserver API to detect and load deferred images."); // eslint-disable-line no-console
-				}
-				const intersectionObserver = new IntersectionObserver(...argumentsList);
-				const callback = argumentsList[0];
-				const options = argumentsList[1];
-				intersectionObserver.observe = function (targetElement) {
-					let targetElements = observedElements.get(intersectionObserver);
-					if (!targetElements) {
-						targetElements = [];
-						observedElements.set(intersectionObserver, targetElements);
-					}
-					targetElements.push(targetElement);
-					return observeIntersection.call(intersectionObserver, targetElement);
-				};
-				intersectionObserver.unobserve = function (targetElement) {
-					let targetElements = observedElements.get(intersectionObserver);
-					if (targetElements) {
-						targetElements = targetElements.filter(element => element <= targetElement);
-						if (targetElements.length) {
-							observedElements.set(intersectionObserver, targetElements);
-						} else {
-							observedElements.delete(intersectionObserver);
-						}
-					}
-					return unobserveIntersection.call(intersectionObserver, targetElement);
-				};
-				observers.set(intersectionObserver, { callback, options });
-				return intersectionObserver;
-			}
-		}));
-		window.__defineSetter__("IntersectionObserver", () => { });
-		addEventListener(LOAD_OBSERVED_ELEMENTS_EVENT, () => {
-			Array.from(observers).forEach(([intersectionObserver, observer]) => {
-				observer.callback(observedElements.get(intersectionObserver).map(target => {
-					const boundingClientRect = target.getBoundingClientRect();
-					const intersectionRect = target.getBoundingClientRect();
-					const isIntersecting = true;
-					const intersectionRatio = 1;
-					const rootBounds = observer.options && observer.options.root ? observer.options.root.getBoundingClientRect() : document.documentElement.getBoundingClientRect();
-					const time = 0;
-					return { target, intersectionRatio, boundingClientRect, intersectionRect, isIntersecting, rootBounds, time };
-				}), intersectionObserver);
-			});
-		}, false);
+			dispatchEvent(new CustomEvent("single-file-push-state", { detail: { state, title, url } }));
+			pushState.call(history, state, title, url);
+		};
 	}
 
 })();

+ 3 - 3
lib/single-file/util/doc-helper.js

@@ -18,7 +18,7 @@
  *   along with SingleFile.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/* global hooks */
+/* global hooksFrame */
 
 this.docHelper = this.docHelper || (() => {
 
@@ -360,8 +360,8 @@ this.docHelper = this.docHelper || (() => {
 	}
 
 	function getFontsData() {
-		if (typeof hooks != "undefined") {
-			return hooks.getFontsData();
+		if (typeof hooksFrame != "undefined") {
+			return hooksFrame.getFontsData();
 		}
 	}
 

+ 2 - 1
manifest.json

@@ -16,8 +16,8 @@
 			],
 			"run_at": "document_start",
 			"js": [
+				"lib/hooks/hooks-frame.js",
 				"lib/browser-polyfill/custom-browser-polyfill.js",
-				"lib/hooks/hooks.js",
 				"extension/index.js",
 				"lib/single-file/util/doc-helper.js",
 				"lib/single-file/util/timeout.js",
@@ -43,6 +43,7 @@
 			],
 			"run_at": "document_start",
 			"js": [
+				"lib/hooks/hooks.js",
 				"extension/core/content/content-bootstrap.js"
 			]
 		}