Просмотр исходного кода

Merge pull request #14 from gildas-lormeau/master

upd
solokot 5 лет назад
Родитель
Сommit
a382e5513a

+ 1 - 1
README.MD

@@ -85,7 +85,7 @@ See https://addons.mozilla.org/firefox/addon/single-file/versions/
   - The "File name > file name conflict resolution" option does not work if set to "prompt for a name"
   - Sometimes, SingleFile is unable to save the contents of  sandboxed iframes because of [this bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1411641).
   - When processing a page from the filesystem, external resources (e.g. images, stylesheets, fonts etc.) will not be embedded into the saved page. You can find more info about this bug [here](https://bugzilla.mozilla.org/show_bug.cgi?id=1644488). This bug has been closed by Mozilla as "WontFix".
-- Waterfox
+- Waterfox Classic
   - When opening pages saved with the option "Images > group duplicate images together" enabled, some duplicate images might not displayed. It is recommended to disable this option.  
 
 ## Troubleshooting unknown issues

+ 15 - 11
_locales/de/messages.json

@@ -3,14 +3,14 @@
 		"message": "Speichern einer kompletten Webseite in eine einzige HTML-Datei",
 		"description": "Description of the extension."
 	},
-    "commandSaveTab": {
-        "message": "Speichern der aktuellen Tab oder des ausgewählten Inhalts",
-        "description": "Command (Ctrl+Shift+Y): 'Save the current tab or the selected content'"
-    },
-    "commandSaveAllTabs": {
-        "message": "Speichern aller Tabs",
-        "description": "Command (Ctrl+Shift+U): 'Save all tabs'"
-    },
+	"commandSaveTab": {
+		"message": "Speichern der aktuellen Tab oder des ausgewählten Inhalts",
+		"description": "Command (Ctrl+Shift+Y): 'Save the current tab or the selected content'"
+	},
+	"commandSaveAllTabs": {
+		"message": "Speichern aller Tabs",
+		"description": "Command (Ctrl+Shift+U): 'Save all tabs'"
+	},
 	"menuSavePage": {
 		"message": "Speichern der Webseite mit SingleFile",
 		"description": "Menu entry: 'Save page with SingleFile'"
@@ -615,9 +615,13 @@
 		"message": "Die Seite zur besseren Lesbarkeit formatieren",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "Aktivieren/Deaktivieren des Entfernens des Dokument-Elements auf Klick",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "Aktivieren/Deaktivieren der Entfernung interner Elemente",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "Aktivieren/Deaktivieren der Entfernung externer Elemente",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
 		"message": "Wiederherstellen des zuletzt entfernten Elements",

+ 7 - 3
_locales/en/messages.json

@@ -615,9 +615,13 @@
 		"message": "Format the page for better readability",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "Enable/disable removing document's element on click",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "Enable/disable removing of internal elements",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "Enable/disable removing of external elements",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
 		"message": "Restore last removed element",

+ 7 - 3
_locales/es/messages.json

@@ -615,9 +615,13 @@
 		"message": "Format the page for better readability",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "Enable/disable removing document's element on click",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "Enable/disable removing of internal elements",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "Enable/disable removing of external elements",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
 		"message": "Restore last removed element",

+ 7 - 3
_locales/fr/messages.json

@@ -615,9 +615,13 @@
 		"message": "Formater la  page pour une meilleure lisibilité",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "Activer/désactiver la supression des éléments du document au click",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "Activer/désactiver la supression des éléments internes",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "Activer/désactiver la supression des éléments externes",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
 		"message": "Restaurer le dernier élement supprimé",

+ 7 - 3
_locales/ja/messages.json

@@ -615,9 +615,13 @@
 		"message": "Format the page for better readability",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "クリック時にドキュメントの要素を削除することを有効/無効にする",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "Enable/disable removing of internal elements",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "Enable/disable removing of external elements",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
 		"message": "最後に削除された要素を復元する",

+ 7 - 3
_locales/pl/messages.json

@@ -615,9 +615,13 @@
 		"message": "Sformatuj stronę dla lepszej czytelności",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "Włącz/wyłącz usuwanie elementu dokumentu po kliknięciu",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "Włącz/wyłącz usuwanie elementów wewnętrznych",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "Włącz/wyłącz usuwanie elementów zewnętrznych",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
 		"message": "Przywróć ostatni usunięty element",

+ 7 - 3
_locales/ru/messages.json

@@ -615,9 +615,13 @@
 		"message": "Форматировать страницу для лучшей читаемости",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "Включить/отключить удаление элемента документа щелчком мыши",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "Enable/disable removing of internal elements",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "Enable/disable removing of external elements",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
 		"message": "Восстановить последний удалённый элемент",

+ 7 - 3
_locales/uk/messages.json

@@ -615,9 +615,13 @@
 		"message": "Format the page for better readability",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "Enable/disable removing document's element on click",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "Enable/disable removing of internal elements",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "Enable/disable removing of external elements",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
 		"message": "Restore last removed element",

+ 19 - 15
_locales/zh_CN/messages.json

@@ -4,7 +4,7 @@
 		"description": "Description of the extension."
 	},
 	"commandSaveTab": {
-		"message": "保存所选标签页或选中部分",
+		"message": "保存当前标签页或选中部分",
 		"description": "Command (Ctrl+Shift+Y): 'Save the current tab or the selected content'"
 	},
 	"commandSaveAllTabs": {
@@ -60,7 +60,7 @@
 		"description": "Menu entry (SingleFile button only): 'Save tabs'"
 	},
 	"menuSaveSelectedTabs": {
-		"message": "保存所选标签页",
+		"message": "保存当前标签页",
 		"description": "Menu entry: 'Save selected tabs'"
 	},
 	"menuSaveUnpinnedTabs": {
@@ -396,23 +396,23 @@
 		"description": "Options page label: 'open pages saved with SingleFile in the annotation editor'"
 	},
 	"optionDefaultEditorMode": {
-		"message": "default mode",
+		"message": "默认模式",
 		"description": "Options page label: 'default mode'"
 	},
 	"optionDefaultEditorModeNormal": {
-		"message": "normal",
+		"message": "常规",
 		"description": "Options page label: 'default mode > normal'"
 	},
 	"optionDefaultEditorModeEdit": {
-		"message": "edit the page",
+		"message": "编辑模式",
 		"description": "Options page label: 'default mode > edit the page'"
 	},
 	"optionDefaultEditorModeFormat": {
-		"message": "format the page",
+		"message": "格式化页面",
 		"description": "Options page label: 'default mode > format the page'"
 	},
 	"optionDefaultEditorModeCut": {
-		"message": "remove elements",
+		"message": "删除文档元素",
 		"description": "Options page label: 'default mode > remove elements'"
 	},
 	"optionApplySystemTheme": {
@@ -608,27 +608,31 @@
 		"description": "Title of the button 'Remove the selected highlighted text' in the editor"
 	},
 	"editorEditPage": {
-		"message": "启用/禁用 只读模式",
+		"message": "启用/禁用 编辑模式",
 		"description": "Title of the button 'Enable/disable read-only' in the editor"
 	},
 	"editorFormatPage": {
-		"message": "格式化页面以提升可读性",
+		"message": "格式化页面以提升可读性",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "启用/禁用 点击时删除文档元素",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "启用/禁用 点击时删除内部文档元素",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "启用/禁用 点击时删除外部文档元素",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
-		"message": "还原上次被移除的元素",
+		"message": "撤销上次移除元素的操作",
 		"description": "Title of the button 'Restore last removed element' in the editor"
 	},
 	"editorUndoAllCutPage": {
-		"message": "还原所有被移除的元素",
+		"message": "撤销所有移除元素的操作",
 		"description": "Title of the button 'Restore all removed elements' in the editor"
 	},
 	"editorRedoCutPage": {
-		"message": "Remove last restored element",
+		"message": "恢复上次移除元素的操作",
 		"description": "Title of the button 'Remove last restored element' in the editor"
 	},
 	"editorSavePage": {

+ 19 - 15
_locales/zh_TW/messages.json

@@ -4,7 +4,7 @@
 		"description": "Description of the extension."
 	},
 	"commandSaveTab": {
-		"message": "保存所選標籤頁或選中部分",
+		"message": "保存當前標籤頁或選中部分",
 		"description": "Command (Ctrl+Shift+Y): 'Save the current tab or the selected content'"
 	},
 	"commandSaveAllTabs": {
@@ -60,7 +60,7 @@
 		"description": "Menu entry (SingleFile button only): 'Save tabs'"
 	},
 	"menuSaveSelectedTabs": {
-		"message": "保存所選標籤頁",
+		"message": "保存當前標籤頁",
 		"description": "Menu entry: 'Save selected tabs'"
 	},
 	"menuSaveUnpinnedTabs": {
@@ -396,23 +396,23 @@
 		"description": "Options page label: 'open pages saved with SingleFile in the annotation editor'"
 	},
 	"optionDefaultEditorMode": {
-		"message": "default mode",
+		"message": "默認模式",
 		"description": "Options page label: 'default mode'"
 	},
 	"optionDefaultEditorModeNormal": {
-		"message": "normal",
+		"message": "常規",
 		"description": "Options page label: 'default mode > normal'"
 	},
 	"optionDefaultEditorModeEdit": {
-		"message": "edit the page",
+		"message": "編輯模式",
 		"description": "Options page label: 'default mode > edit the page'"
 	},
 	"optionDefaultEditorModeFormat": {
-		"message": "format the page",
+		"message": "格式化頁面",
 		"description": "Options page label: 'default mode > format the page'"
 	},
 	"optionDefaultEditorModeCut": {
-		"message": "remove elements",
+		"message": "刪除文檔元素",
 		"description": "Options page label: 'default mode > remove elements'"
 	},
 	"optionApplySystemTheme": {
@@ -608,27 +608,31 @@
 		"description": "Title of the button 'Remove the selected highlighted text' in the editor"
 	},
 	"editorEditPage": {
-		"message": "啟用/禁用 只讀模式",
+		"message": "啟用/禁用 編輯模式",
 		"description": "Title of the button 'Enable/disable read-only' in the editor"
 	},
 	"editorFormatPage": {
-		"message": "格式化頁面以提升可讀性",
+		"message": "格式化頁面以提升可讀性",
 		"description": "Title of the button 'Format the page for better readability' in the editor"
 	},
-	"editorCutPage": {
-		"message": "啟用/禁用 點擊時刪除文檔元素",
-		"description": "Title of the button 'Enable/disable removing document's element on click' in the editor"
+	"editorCutInnerPage": {
+		"message": "啟用/禁用 點擊時刪除內部文檔元素",
+		"description": "Title of the button 'Enable/disable removing of internal elements' in the editor"
+	},
+	"editorCutOuterPage": {
+		"message": "啟用/禁用 點擊時刪除外部文檔元素",
+		"description": "Title of the button 'Enable/disable removing of external elements' in the editor"
 	},
 	"editorUndoCutPage": {
-		"message": "還原上次被移除的元素",
+		"message": "撤銷上次移除元素的操作",
 		"description": "Title of the button 'Restore last removed element' in the editor"
 	},
 	"editorUndoAllCutPage": {
-		"message": "還原所有被移除的元素",
+		"message": "撤銷所有移除元素的操作",
 		"description": "Title of the button 'Restore all removed elements' in the editor"
 	},
 	"editorRedoCutPage": {
-		"message": "Remove last restored element",
+		"message": "恢復上次移除元素的操作",
 		"description": "Title of the button 'Remove last restored element' in the editor"
 	},
 	"editorSavePage": {

+ 63 - 21
extension/ui/bg/ui-editor.js

@@ -41,7 +41,8 @@ singlefile.extension.ui.bg.editor = (() => {
 	const addGreenNoteButton = document.querySelector(".add-note-green-button");
 	const editPageButton = document.querySelector(".edit-page-button");
 	const formatPageButton = document.querySelector(".format-page-button");
-	const cutPageButton = document.querySelector(".cut-page-button");
+	const cutInnerPageButton = document.querySelector(".cut-inner-page-button");
+	const cutOuterPageButton = document.querySelector(".cut-outer-page-button");
 	const undoCutPageButton = document.querySelector(".undo-cut-page-button");
 	const undoAllCutPageButton = document.querySelector(".undo-all-cut-page-button");
 	const redoCutPageButton = document.querySelector(".redo-cut-page-button");
@@ -62,7 +63,8 @@ singlefile.extension.ui.bg.editor = (() => {
 	removeHighlightButton.title = browser.i18n.getMessage("editorRemoveHighlight");
 	editPageButton.title = browser.i18n.getMessage("editorEditPage");
 	formatPageButton.title = browser.i18n.getMessage("editorFormatPage");
-	cutPageButton.title = browser.i18n.getMessage("editorCutPage");
+	cutInnerPageButton.title = browser.i18n.getMessage("editorCutInnerPage");
+	cutOuterPageButton.title = browser.i18n.getMessage("editorCutOuterPage");
 	undoCutPageButton.title = browser.i18n.getMessage("editorUndoCutPage");
 	undoAllCutPageButton.title = browser.i18n.getMessage("editorUndoAllCutPage");
 	redoCutPageButton.title = browser.i18n.getMessage("editorRedoCutPage");
@@ -74,8 +76,11 @@ singlefile.extension.ui.bg.editor = (() => {
 	addGreenNoteButton.onclick = () => editorElement.contentWindow.postMessage(JSON.stringify({ method: "addNote", color: "note-green" }), "*");
 	highlightButtons.forEach(highlightButton => {
 		highlightButton.onclick = () => {
-			if (toolbarElement.classList.contains("cut-mode")) {
-				disableCutPage();
+			if (toolbarElement.classList.contains("cut-inner-mode")) {
+				disableCutInnerPage();
+			}
+			if (toolbarElement.classList.contains("cut-outer-mode")) {
+				disableCutOuterPage();
 			}
 			if (toolbarElement.classList.contains("remove-highlight-mode")) {
 				disableRemoveHighlights();
@@ -108,8 +113,11 @@ singlefile.extension.ui.bg.editor = (() => {
 		}
 	};
 	removeHighlightButton.onclick = () => {
-		if (toolbarElement.classList.contains("cut-mode")) {
-			disableCutPage();
+		if (toolbarElement.classList.contains("cut-inner-mode")) {
+			disableCutInnerPage();
+		}
+		if (toolbarElement.classList.contains("cut-outer-mode")) {
+			disableCutOuterPage();
 		}
 		if (removeHighlightButton.classList.contains("remove-highlight-disabled")) {
 			removeHighlightButton.classList.remove("remove-highlight-disabled");
@@ -123,8 +131,11 @@ singlefile.extension.ui.bg.editor = (() => {
 		}
 	};
 	editPageButton.onclick = () => {
-		if (toolbarElement.classList.contains("cut-mode")) {
-			disableCutPage();
+		if (toolbarElement.classList.contains("cut-inner-mode")) {
+			disableCutInnerPage();
+		}
+		if (toolbarElement.classList.contains("cut-outer-mode")) {
+			disableCutOuterPage();
 		}
 		if (editPageButton.classList.contains("edit-disabled")) {
 			enableEditPage();
@@ -135,15 +146,32 @@ singlefile.extension.ui.bg.editor = (() => {
 	formatPageButton.onclick = () => {
 		enableFormatPage();
 	};
-	cutPageButton.onclick = () => {
+	cutInnerPageButton.onclick = () => {
+		if (toolbarElement.classList.contains("edit-mode")) {
+			disableEditPage();
+		}
+		if (toolbarElement.classList.contains("cut-outer-mode")) {
+			disableCutOuterPage();
+		}
+		if (cutInnerPageButton.classList.contains("cut-disabled")) {
+			enableCutInnerPage();
+			editorElement.contentWindow.focus();
+		} else {
+			disableCutInnerPage();
+		}
+	};
+	cutOuterPageButton.onclick = () => {
 		if (toolbarElement.classList.contains("edit-mode")) {
 			disableEditPage();
 		}
-		if (cutPageButton.classList.contains("cut-disabled")) {
-			enableCutPage();
+		if (toolbarElement.classList.contains("cut-inner-mode")) {
+			disableCutInnerPage();
+		}
+		if (cutOuterPageButton.classList.contains("cut-disabled")) {
+			enableCutOuterPage();
 			editorElement.contentWindow.focus();
 		} else {
-			disableCutPage();
+			disableCutOuterPage();
 		}
 	};
 	undoCutPageButton.onclick = () => {
@@ -195,7 +223,7 @@ singlefile.extension.ui.bg.editor = (() => {
 			} else if (tabData.options.defaultEditorMode == "format" && !tabData.options.disableFormatPage) {
 				enableFormatPage();
 			} else if (tabData.options.defaultEditorMode == "cut") {
-				enableCutPage();
+				enableCutInnerPage();
 			}
 		}
 	};
@@ -248,10 +276,16 @@ singlefile.extension.ui.bg.editor = (() => {
 		editorElement.contentWindow.postMessage(JSON.stringify({ method: "disableEditPage" }), "*");
 	}
 
-	function disableCutPage() {
-		cutPageButton.classList.add("cut-disabled");
-		toolbarElement.classList.remove("cut-mode");
-		editorElement.contentWindow.postMessage(JSON.stringify({ method: "disableCutPage" }), "*");
+	function disableCutInnerPage() {
+		cutInnerPageButton.classList.add("cut-disabled");
+		toolbarElement.classList.remove("cut-inner-mode");
+		editorElement.contentWindow.postMessage(JSON.stringify({ method: "disableCutInnerPage" }), "*");
+	}
+
+	function disableCutOuterPage() {
+		cutOuterPageButton.classList.add("cut-disabled");
+		toolbarElement.classList.remove("cut-outer-mode");
+		editorElement.contentWindow.postMessage(JSON.stringify({ method: "disableCutOuterPage" }), "*");
 	}
 
 	function resetHighlightButtons() {
@@ -284,12 +318,20 @@ singlefile.extension.ui.bg.editor = (() => {
 		}
 	}
 
-	function enableCutPage() {
-		cutPageButton.classList.remove("cut-disabled");
-		toolbarElement.classList.add("cut-mode");
+	function enableCutInnerPage() {
+		cutInnerPageButton.classList.remove("cut-disabled");
+		toolbarElement.classList.add("cut-inner-mode");
+		resetHighlightButtons();
+		disableRemoveHighlights();
+		editorElement.contentWindow.postMessage(JSON.stringify({ method: "enableCutInnerPage" }), "*");
+	}
+
+	function enableCutOuterPage() {
+		cutOuterPageButton.classList.remove("cut-disabled");
+		toolbarElement.classList.add("cut-outer-mode");
 		resetHighlightButtons();
 		disableRemoveHighlights();
-		editorElement.contentWindow.postMessage(JSON.stringify({ method: "enableCutPage" }), "*");
+		editorElement.contentWindow.postMessage(JSON.stringify({ method: "enableCutOuterPage" }), "*");
 	}
 
 	function savePage() {

+ 54 - 36
extension/ui/content/content-ui-editor-web.js

@@ -46,8 +46,8 @@
 	const REMOVED_CONTENT_CLASS = "single-file-removed";
 	const HIGHLIGHT_HIDDEN_CLASS = "single-file-highlight-hidden";
 	const PAGE_MASK_ACTIVE_CLASS = "page-mask-active";
-	const CUT_HOVER_CLASS = "single-file-hover";
-	const CUT_CONTAINER_HOVER_CLASS = "single-file-container-hover";
+	const CUT_HOVER_CLASS = "single-file-cut-hover";
+	const CUT_OUTER_HOVER_CLASS = "single-file-cut-outer-hover";
 	const NOTE_INITIAL_POSITION_X = 20;
 	const NOTE_INITIAL_POSITION_Y = 20;
 	const NOTE_INITIAL_WIDTH = 150;
@@ -810,7 +810,7 @@ table {
 }`;
 
 	let NOTES_WEB_STYLESHEET, MASK_WEB_STYLESHEET, HIGHLIGHTS_WEB_STYLESHEET;
-	let selectedNote, anchorElement, maskNoteElement, maskPageElement, highlightSelectionMode, removeHighlightMode, resizingNoteMode, movingNoteMode, highlightColor, collapseNoteTimeout, cuttingMode, cuttingPath, cuttingPathIndex, cuttingElementContainer;
+	let selectedNote, anchorElement, maskNoteElement, maskPageElement, highlightSelectionMode, removeHighlightMode, resizingNoteMode, movingNoteMode, highlightColor, collapseNoteTimeout, cuttingOuterMode, cuttingMode, cuttingPath, cuttingPathIndex;
 	let removedElements = [], removedElementIndex = 0;
 
 	window.onmessage = async event => {
@@ -862,22 +862,32 @@ table {
 		if (message.method == "disableEditPage") {
 			document.body.contentEditable = false;
 		}
-		if (message.method == "enableCutPage") {
+		if (message.method == "enableCutInnerPage") {
 			cuttingMode = true;
 		}
-		if (message.method == "disableCutPage") {
+		if (message.method == "enableCutOuterPage") {
+			cuttingOuterMode = true;
+		}
+		if (message.method == "disableCutInnerPage") {
 			cuttingMode = false;
 			if (cuttingPath) {
 				unhighlightCutElement();
 				cuttingPath = null;
 			}
 		}
+		if (message.method == "disableCutOuterPage") {
+			cuttingOuterMode = false;
+			if (cuttingPath) {
+				unhighlightCutElement();
+				cuttingPath = null;
+			}
+		}
 		if (message.method == "undoCutPage") {
 			undoCutPage();
 		}
 		if (message.method == "undoAllCutPage") {
 			while (removedElementIndex) {
-				removedElements[removedElementIndex - 1].classList.remove(REMOVED_CONTENT_CLASS);
+				removedElements[removedElementIndex - 1].forEach(element => element.classList.remove(REMOVED_CONTENT_CLASS));
 				removedElementIndex--;
 			}
 		}
@@ -1104,7 +1114,7 @@ table {
 		}
 
 		function getTarget(clientX, clientY) {
-			const targets = Array.from(document.elementsFromPoint(clientX, clientY)).filter(element => element.tagName.toLowerCase() != NOTE_TAGNAME && !element.classList.contains(MASK_CLASS));
+			const targets = Array.from(document.elementsFromPoint(clientX, clientY)).filter(element => element.matches("html *"));
 			if (!targets.includes(document.documentElement)) {
 				targets.push(document.documentElement);
 			}
@@ -1190,13 +1200,13 @@ table {
 			clearTimeout(collapseNoteTimeout);
 			collapseNoteTimeout = null;
 		}
-		if (cuttingMode) {
+		if (cuttingMode || cuttingOuterMode) {
 			validateCutElement();
 		}
 	}
 
 	function onMouseOver(event) {
-		if (cuttingMode) {
+		if (cuttingMode || cuttingOuterMode) {
 			const target = event.target;
 			if (target.classList) {
 				cuttingPath = getEventPath(event);
@@ -1207,7 +1217,7 @@ table {
 	}
 
 	function onMouseOut() {
-		if (cuttingMode) {
+		if (cuttingMode || cuttingOuterMode) {
 			if (cuttingPath) {
 				unhighlightCutElement();
 				cuttingPath = null;
@@ -1216,7 +1226,7 @@ table {
 	}
 
 	function onKeyDown(event) {
-		if (cuttingMode) {
+		if (cuttingMode || cuttingOuterMode) {
 			if (event.code == "Tab") {
 				if (cuttingPath) {
 					const delta = event.shiftKey ? -1 : 1;
@@ -1262,52 +1272,56 @@ table {
 
 	function highlightCutElement() {
 		const element = cuttingPath[cuttingPathIndex];
-		element.classList.add(CUT_HOVER_CLASS);
-		let parentElement = element.parentElement;
-		while (parentElement && getComputedStyle(parentElement).getPropertyValue("overflow") != "hidden") {
-			parentElement = parentElement.parentElement;
-		}
-		if (parentElement) {
-			cuttingElementContainer = parentElement;
-			cuttingElementContainer.classList.add(CUT_CONTAINER_HOVER_CLASS);
-		} else {
-			cuttingElementContainer = null;
-		}
+		element.classList.add(cuttingMode ? CUT_HOVER_CLASS : CUT_OUTER_HOVER_CLASS);
 	}
 
 	function unhighlightCutElement() {
 		if (cuttingPath) {
 			const element = cuttingPath[cuttingPathIndex];
-			element.classList.remove(CUT_HOVER_CLASS);
-			if (cuttingElementContainer) {
-				cuttingElementContainer.classList.remove(CUT_CONTAINER_HOVER_CLASS);
-			}
+			element.classList.remove(cuttingMode ? CUT_HOVER_CLASS : CUT_OUTER_HOVER_CLASS);
 		}
 	}
 
 	function undoCutPage() {
 		if (removedElementIndex) {
-			removedElements[removedElementIndex - 1].classList.remove(REMOVED_CONTENT_CLASS);
+			removedElements[removedElementIndex - 1].forEach(element => element.classList.remove(REMOVED_CONTENT_CLASS));
 			removedElementIndex--;
 		}
 	}
 
 	function redoCutPage() {
 		if (removedElementIndex < removedElements.length) {
-			removedElements[removedElementIndex].classList.add(REMOVED_CONTENT_CLASS);
+			removedElements[removedElementIndex].forEach(element => element.classList.add(REMOVED_CONTENT_CLASS));
 			removedElementIndex++;
 		}
 	}
 
 	function validateCutElement() {
 		if (cuttingPath) {
-			const element = cuttingPath[cuttingPathIndex];
-			if (document.documentElement != element && element.tagName.toLowerCase() != NOTE_TAGNAME) {
-				element.classList.add(REMOVED_CONTENT_CLASS);
-				removedElements[removedElementIndex] = element;
-				removedElementIndex++;
-				removedElements.length = removedElementIndex;
-				onUpdate(false);
+			if (cuttingMode) {
+				const element = cuttingPath[cuttingPathIndex];
+				if (document.documentElement != element && element.tagName.toLowerCase() != NOTE_TAGNAME) {
+					element.classList.add(REMOVED_CONTENT_CLASS);
+					removedElements[removedElementIndex] = [element];
+					removedElementIndex++;
+					removedElements.length = removedElementIndex;
+					onUpdate(false);
+				}
+			}
+			if (cuttingOuterMode) {
+				const elementKept = cuttingPath[cuttingPathIndex];
+				if (document.documentElement != elementKept && elementKept.tagName.toLowerCase() != NOTE_TAGNAME) {
+					const elements = [];
+					document.body.querySelectorAll("*:not(style):not(meta):not(." + REMOVED_CONTENT_CLASS + ")").forEach(element => {
+						if (elementKept != element && !isAncestor(elementKept, element) && !isAncestor(element, elementKept)) {
+							element.classList.add(REMOVED_CONTENT_CLASS);
+							elements.push(element);
+						}
+					});
+					removedElements[removedElementIndex] = elements;
+					removedElementIndex++;
+					removedElements.length = removedElementIndex;
+				}
 			}
 		}
 	}
@@ -1682,7 +1696,7 @@ table {
 			const onMouseUp = ${minifyText(onMouseUp.toString())};
 			const maskNoteElement = getMaskElement(${JSON.stringify(NOTE_MASK_CLASS)});
 			const maskPageElement = getMaskElement(${JSON.stringify(PAGE_MASK_CLASS)}, ${JSON.stringify(PAGE_MASK_CONTAINER_CLASS)});
-			let selectedNote, highlightSelectionMode, removeHighlightMode, resizingNoteMode, movingNoteMode, collapseNoteTimeout, cuttingMode;
+			let selectedNote, highlightSelectionMode, removeHighlightMode, resizingNoteMode, movingNoteMode, collapseNoteTimeout, cuttingMode, cuttingOuterMode;
 			window.onresize = reflowNotes;
 			window.onUpdate = () => {};
 			document.documentElement.onmouseup = document.documentElement.ontouchend = onMouseUp;
@@ -1732,4 +1746,8 @@ table {
 		return text.replace(/[\n\t\s]+/g, " ");
 	}
 
+	function isAncestor(element, otherElement) {
+		return otherElement.parentElement && (element == otherElement.parentElement || isAncestor(element, otherElement.parentElement));
+	}
+
 })();

+ 13 - 7
extension/ui/pages/editor-frame-web.css

@@ -53,17 +53,23 @@ single-file-note {
     display: contents !important;
 }
 
-.single-file-hover {
-    outline: 4px dotted red !important;
-    transition: outline-width 125ms;
+.single-file-cut-hover, .single-file-cut-outer-hover {
+    transition: outline-width 125ms !important;
+    outline-offset: -4px !important;
+    outline-width: 4px !important;
+    outline-style: dotted !important;
 }
 
-.single-file-hover, .single-file-remove-highlights-mode .single-file-highlight:hover {
-    cursor: crosshair !important;
+.single-file-cut-hover {
+    outline-color: red !important;
+}
+
+.single-file-cut-outer-hover {
+    outline-color: green !important;
 }
 
-.single-file-container-hover {
-    overflow: visible !important;
+.single-file-cut-hover, .single-file-cut-outer-hover, .single-file-remove-highlights-mode .single-file-highlight:hover {
+    cursor: crosshair !important;
 }
 
 .single-file-removed {

+ 2 - 2
extension/ui/pages/editor.css

@@ -50,8 +50,8 @@ img[type=button].remove-highlight-disabled {
 
 img[type=button].edit-disabled:hover,
 img[type=button].cut-disabled:hover,
-.toolbar:not(.cut-mode):not(.remove-highlight-mode) img[type=button].highlight-disabled:hover,
-.toolbar:not(.cut-mode) img[type=button].remove-highlight-disabled:hover {
+.toolbar:not(.cut-inner-mode):not(.remove-highlight-mode) img[type=button].highlight-disabled:hover,
+.toolbar:not(.cut-inner-mode) img[type=button].remove-highlight-disabled:hover {
     filter: brightness(0.875);
 }
 

+ 2 - 1
extension/ui/pages/editor.html

@@ -41,7 +41,8 @@
 			<div class="separator"></div>
 		</div>
 		<div class="buttons">
-			<img type="button" class="cut-page-button cut-disabled" src="/extension/ui/resources/button_cut.png">
+			<img type="button" class="cut-inner-page-button cut-disabled" src="/extension/ui/resources/button_cut_inner.png">
+			<img type="button" class="cut-outer-page-button cut-disabled" src="/extension/ui/resources/button_cut_outer.png">
 			<img type="button" class="undo-cut-page-button" src="/extension/ui/resources/button_undo_cut.png">
 			<img type="button" class="undo-all-cut-page-button" src="/extension/ui/resources/button_undo_all_cut.png">
 			<img type="button" class="redo-cut-page-button" src="/extension/ui/resources/button_redo_cut.png">

+ 11 - 0
extension/ui/pages/help.css

@@ -68,6 +68,13 @@ ol>li>ul>li>ul {
     height: 1em;
 }
 
+.button {
+    height: .9em;
+    background-color: #8e8e8e;
+    padding: 3px;
+    border-radius: 4px;
+}
+
 #titleIcon {
     width: 1.2em;
     height: 1.2em;
@@ -197,4 +204,8 @@ kbd.light, .light-keys kbd, .key.light, .light-keys .key {
     .option {
         color: #afafaf;
     }
+    .button {
+        height: .9em;
+        background-color: #484848;
+    }
 }

+ 34 - 28
extension/ui/pages/help.html

@@ -14,7 +14,7 @@
 			<h2>SingleFile</h2>
 			<h4>Save a complete page into a single HTML file</h4>
 		</div> <span id="index"> <a href="#getting-started">Getting started</a> - <a href="#general-notes">Additional
-				notes</a> - <a href="#options">Options description</a> - <a href="#annotation-editor">Anootation
+				notes</a> - <a href="#options">Options description</a> - <a href="#annotation-editor">Annotation
 				editor</a> - <a href="#notes">Technical notes</a> - <a href="#template-variables">Template variables</a>
 			- <a href="#known-issues">Known issues</a> - <a href="#unknown-issues">Troubleshooting unknown issues</a> -
 			<a href="#contributors">Contributors</a>
@@ -175,7 +175,7 @@
 					</li>
 					<li data-options-label="filenameConflictActionLabel"> <span class="option">Option: file name
 							conflict resolution</span>
-						<p>Choose the most appropriate action when a the filename of the saved page is conflicting with
+						<p>Choose the most appropriate action when the filename of the saved page is conflicting with
 							existing ones on the filesystem. The "skip duplicate files" action only detects duplicates
 							among files downloaded during the current browsing session.</p>
 					</li>
@@ -350,12 +350,12 @@
 						<ul>
 							<li><code>normal</code>: default value</li>
 							<li><code>edit the page</code>: enable the button <img
-									src="../resources/button_note_edit.png" class="icon"></li>
+									src="../resources/button_note_edit.png" class="icon button"></li>
 							<li><code>format the page</code>: enable the button <img
-									src="../resources/button_note_format.png" class="icon"> if the page can be
+									src="../resources/button_note_format.png" class="icon button"> if the page can be
 								formatted</li>
-							<li><code>remove elements</code>: enable the button <img src="../resources/button_cut.png"
-									class="icon"></li>
+							<li><code>remove elements</code>: enable the button <img
+									src="../resources/button_cut_inner.png" class="icon button"></li>
 						</ul>
 						</p>
 					</li>
@@ -368,7 +368,7 @@
 					<li data-options-label="warnUnsavedPageLabel"> <span class="option">Option: warn if leaving page
 							with unsaved changes</span>
 						<p>Check this option to display a blocking popup when you leave the annotation editor (e.g.
-							close the tab) without saving the cahnges.</p>
+							close the tab) without saving the changes.</p>
 						<p class="notice">It is recommended to <u>check</u> this option</p>
 					</li>
 					<li data-options-label="openEditorLabel"> <span class="option">Option: edit page before
@@ -509,30 +509,35 @@
 					by enabling the option "Annotation editor &gt; edit page before saving". It allows you to:
 				<ul>
 					<li>add notes by clicking one of these buttons: <img src="../resources/button_note_yellow.png"
-							class="icon">
-						<img src="../resources/button_note_pink.png" class="icon"> <img
-							src="../resources/button_note_blue.png" class="icon">
-						<img src="../resources/button_note_green.png" class="icon"></li>
+							class="icon button">
+						<img src="../resources/button_note_pink.png" class="icon button"> <img
+							src="../resources/button_note_blue.png" class="icon button">
+						<img src="../resources/button_note_green.png" class="icon button"></li>
 					<li>hide or show notes by clicking the button <img src="../resources/button_note_visible.png"
-							class="icon"></li>
+							class="icon button"></li>
 					<li>highlight text by clicking one of these buttons: <img
-							src="../resources/button_highlighter_yellow.png" class="icon"> <img
-							src="../resources/button_highlighter_pink.png" class="icon"> <img
-							src="../resources/button_highlighter_blue.png" class="icon"> <img
-							src="../resources/button_highlighter_green.png" class="icon"></li>
-					<li>hide or show highligted text by clicking the button <img
-							src="../resources/button_highlighter_visible.png" class="icon"></li>
+							src="../resources/button_highlighter_yellow.png" class="icon button"> <img
+							src="../resources/button_highlighter_pink.png" class="icon button"> <img
+							src="../resources/button_highlighter_blue.png" class="icon button"> <img
+							src="../resources/button_highlighter_green.png" class="icon button"></li>
+					<li>hide or show highlighted text by clicking the button <img
+							src="../resources/button_highlighter_visible.png" class="icon button"></li>
 					<li>remove text highlighting by clicking the button <img
-							src="../resources/button_highlighter_delete.png" class="icon"></li>
-					<li>edit the page by clicking the button <img src="../resources/button_note_edit.png" class="icon">
+							src="../resources/button_highlighter_delete.png" class="icon button"></li>
+					<li>edit the page by clicking the button <img src="../resources/button_note_edit.png"
+							class="icon button">
 					</li>
 					<li>format the page to improve readability (when possible) by clicking the button <img
-							src="../resources/button_note_format.png" class="icon">
-					</li>
-					<li>remove contents by clicking the button <img src="../resources/button_cut.png" class="icon">,
-						undo removes by clicking the button <img src="../resources/button_undo_cut.png" class="icon"> or
-						the button <img src="../resources/button_undo_all_cut.png" class="icon">, and redo removes by
-						clicking the button <img src="../resources/button_redo_cut.png" class="icon">.
+							src="../resources/button_note_format.png" class="icon button">
+					</li>
+					<li>remove contents by clicking the button <img src="../resources/button_cut_inner.png"
+							class="icon button"> (inner elements) or <img src="../resources/button_cut_outer.png"
+							class="icon button"> (outer elements),
+						undo removes by clicking the button <img src="../resources/button_undo_cut.png"
+							class="icon button"> or
+						the button <img src="../resources/button_undo_all_cut.png" class="icon button"> (undo all), and
+						redo removes by clicking the button <img src="../resources/button_redo_cut.png"
+							class="icon button">.
 						<br>
 						You can also use the following keyboard shortcuts when removing contents:
 						<ul>
@@ -543,7 +548,8 @@
 							<li><code>Ctrl-Shift-Z</code>: redo the last removal</li>
 						</ul>
 					</li>
-					<li>save the page by clicking the button <img src="../resources/button_download.png" class="icon">.
+					<li>save the page by clicking the button <img src="../resources/button_download.png"
+							class="icon button">.
 				</ul>
 				</p>
 			</li>
@@ -707,4 +713,4 @@
 	</div>
 </body>
 
-</html>
+</html>

BIN
extension/ui/resources/button_cut.png


BIN
extension/ui/resources/button_cut_inner.png


BIN
extension/ui/resources/button_cut_outer.png


BIN
extension/ui/resources/button_redo_cut.png


+ 1 - 1
lib/single-file/modules/css-matched-rules.js

@@ -26,7 +26,7 @@ this.singlefile.lib.modules.matchedRules = this.singlefile.lib.modules.matchedRu
 	const singlefile = this.singlefile;
 
 	const MEDIA_ALL = "all";
-	const IGNORED_PSEUDO_ELEMENTS = ["after", "before", "first-letter", "first-line", "placeholder", "selection", "part"];
+	const IGNORED_PSEUDO_ELEMENTS = ["after", "before", "first-letter", "first-line", "placeholder", "selection", "part", "marker"];
 	const SINGLE_FILE_HIDDEN_CLASS_NAME = "sf-hidden";
 	const DISPLAY_STYLE = "display";
 	const REGEXP_VENDOR_IDENTIFIER = /-(ms|webkit|moz|o)-/;

+ 1 - 1
manifest.json

@@ -8,7 +8,7 @@
 		"64": "extension/ui/resources/icon_64.png",
 		"128": "extension/ui/resources/icon_128.png"
 	},
-	"version": "1.18.12",
+	"version": "1.18.14",
 	"description": "__MSG_extensionDescription__",
 	"content_scripts": [
 		{

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "single-file",
-	"version": "0.1.16",
+	"version": "0.1.17",
 	"description": "SingleFile",
 	"author": "Gildas Lormeau",
 	"license": "AGPL-3.0-or-later",