From 8f0cc21067cda6dcd8c9b5e072d4bee5916b44a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Fri, 19 Jan 2018 09:55:41 +0100 Subject: [PATCH 01/18] es: remove all comments --- _locales/es/messages.json | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 3af1de4..48cd929 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -85,7 +85,6 @@ }, "titleRuleReplace": { "message": "El texto de reemplazo para la expresión regular coincide. Se pueden usar símbolos como $$& o $$1 para referirse a la coincidencia o un contenido de corchete. Los textos especiales \\L$$& y \\U$$& significan una versión en mayúsculas y minúsculas de las coincidencias, respectivamente..", - // "message": "El texto de reemplazo para la expresión regular coincide. Symbols like $$& or $$1 can be used to refer to the match or a brace content. The special texts \\L$$& and \\U$$& mean a lower and upper case version of the matches, respectively.", "description": "Explain that the text will be used as replacement text for the regular expression matches" }, "buttonRuleAdd": { @@ -110,42 +109,34 @@ }, "buttonRulesDefault": { "message": "Restaurar reglas por defecto", - //"message": "Restore default rules", "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { "message": "Restaurar las reglas por defecto. Cualquier cambio se perderá", - //"message": "Restore the default rules. Any changes will be lost", "description": "Explain that default rules will be restored" }, "buttonRulesStore": { "message": "Guardar reglas", - //"message": "Store rules", "description": "Button for putting current rules to local storage. The text should be short" }, "titleButtonRulesStore": { "message": "Las reglas actuales se colocarán en el área de almacenamiento local del navegador.", - // "message": "The current rules will be put to the browser's local storage area.", "description": "Explain that current rules will be put to local storage" }, "buttonRulesRestore": { "message": "Restaurar reglas", - // "message": "Restore rules", "description": "Button for fetching rules from local storage. The text should be short" }, "titleButtonRulesRestore": { "message": "Las reglas serán reemplazadas por aquellas almacenadas en el área de almacenamiento local del navegador. Cualquier cambio se perderá.", - // "message": "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost.", "description": "Explain that rules will be fetched from local storage" }, "buttonRulesClean": { "message": "Limpiar almacenamiento local", - // "message": "Cleanup storage", "description": "Button for cleaning local storage from stored rules. The text should be short" }, "titleButtonRulesClean": { "message": "Se limpiarán las reglas almacenadas dentro del área de almacenamiento local del navegador. Las reglas almacenadas se perderán.", - // "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", "description": "Explain that the local storage will be cleaned from stored rules" }, "buttonListDupes": { @@ -154,7 +145,6 @@ }, "titleButtonListDupes": { "message": "(Re)calcule la lista de duplicados de marcadores. Dos marcadores se consideran duplicados si sus URL coinciden. En modo experto, las reglas de preprocesamiento (sustitución) de URL seleccionadas se aplican antes de comparar las URL.", - // "message": "(Re)calcule la lista de duplicados de marcadores. Dos marcadores se consideran duplicados si sus URL coinciden. In expert mode, the selected URL preprocessing (substitution) rules are applied before the URLs are compared.", "description": "Explain that the list of bookmark dupes will be (re)calculated, and how bookmark dupes are defined" }, "buttonListEmpty": { @@ -403,7 +393,6 @@ }, "titleMessageMatches": { "message": "Dos marcadores se consideran duplicados si sus URL coinciden. En modo experto, las reglas de preprocesamiento (sustitución) de URL seleccionadas se aplican antes de comparar las URL.", - // "message": "Dos marcadores se consideran duplicados si sus URL coinciden. In expert mode, the selected URL preprocessing (substitution) rules are applied before the URLs are compared.", "description": "Explain how bookmark dupes are defined" }, "messageEmpty": { From c532ee5f32aa6eecb5377964c93bb90f7ca96d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Fri, 19 Jan 2018 11:26:35 +0100 Subject: [PATCH 02/18] Versionize storage. Insert checkboxRules manually. Improve default rules --- data/tab/dupes.js | 58 +++++++++++++++++++++++++++------------------ data/tab/index.html | 2 +- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/data/tab/dupes.js b/data/tab/dupes.js index f599edb..5cc3742 100644 --- a/data/tab/dupes.js +++ b/data/tab/dupes.js @@ -70,12 +70,8 @@ function getCheckboxRules() { return isChecked("checkboxRules"); } -function setCheckboxRulesTitle(title) { - document.getElementById("titleCheckboxRules").title = title; -} - -function setCheckboxRulesText(text) { - document.getElementById("checkboxRulesText").textContent = text; +function getTableCheckboxRules() { + return document.getElementById("tableCheckboxRules"); } function getCheckboxFullUrl() { @@ -202,7 +198,7 @@ function appendCheckbox(parent, id, title, checked, enabled) { function appendCheckboxCol(row, id, title, checked, enabled) { const col = document.createElement("TD"); - appendCheckbox(col, id, title, checked); + appendCheckbox(col, id, title, checked, enabled); row.appendChild(col); } @@ -384,13 +380,21 @@ function addRules(rules) { } } +function addCheckboxRules() { + const row = document.createElement("TR"); + appendCheckboxCol(row, "checkboxRules", + browser.i18n.getMessage("titleCheckboxRules"), false, true); + appendTextNodeCol(row, browser.i18n.getMessage("CheckboxRules")); + const parent = getTableCheckboxRules(); + parent.appendChild(row); +} + function addButtonsBase() { const parent = getButtonsBase(); if (parent.hasChildNodes()) { // Already done return; } - setCheckboxRulesTitle(browser.i18n.getMessage("titleCheckboxRules")); - setCheckboxRulesText(browser.i18n.getMessage("checkboxRules")); + addCheckboxRules(); const row = document.createElement("TR"); appendButtonCol(row, "buttonListDupes", "titleButtonListDupes"); appendButtonCol(row, "buttonListEmpty", "titleButtonListEmpty"); @@ -723,7 +727,7 @@ function buttonRule(action) { function buttonsRules() { browser.storage.local.get().then(function (storage) { - const haveStorage = (storage && storage.rules); + const haveStorage = (storage && storage.rulesV1); addButtonsRules(haveStorage, haveStorage); }, function () { addButtonsRules(false, true); @@ -1794,7 +1798,7 @@ function processMarked(stopPressed, callback, bookmarkMap) { function rulesStore() { const storage = { - rules: getRules() + rulesV1: getRules() }; browser.storage.local.set(storage).then(buttonsRules, buttonsRules); } @@ -1805,8 +1809,8 @@ function rulesClean() { function rulesRestore() { browser.storage.local.get().then(function (storage) { - if (storage && storage.rules) { - redisplayRules(storage.rules); + if (storage && storage.rulesV1) { + redisplayRules(storage.rulesV1); addButtonsRules(true, true); } else { addButtonsRules(false, false); @@ -1821,16 +1825,17 @@ function rulesRestore() { let state = {}; let rules; const rulesDefault = [ - { radio: "url", search: "^\\w*://[^\/]*/", replace: "\\L$&" }, - { radio: "url", urlNegation: "\\b(e?mail|bugs|youtube|translate)\\b", - search: "\\?.*" }, - { radio: "off", search: "^http:", replace: "https:" }, + { radio: "url", search: "^\\w+://[^\/]*/", replace: "\\L$&" }, { radio: "filter", name: "\\0(" + browser.i18n.getMessage("regExpFrequent") + ")\\0" }, + { radio: "off", name: "^[^\\0]*\\0[^\\0]*$" }, + { radio: "off", urlNegation: "\\b(e?mail|bugs|youtube|translat)\\b", + search: "\\?.*" }, + { radio: "off", search: "/[^/]*$" }, { radio: "url", search: "/+(index.html)?$" }, + { radio: "url", search: "^http:", replace: "https:" }, { radio: "url", search: "^([^:]*://)www?\\d*\.", replace: "$1" }, - { radio: "url", search: "\.htm$", replace: ".html" }, - { radio: "off", search: "/[^/]*$" } + { radio: "url", search: "\.htm$", replace: ".html" } ]; function startLock() { @@ -1904,11 +1909,18 @@ function rulesRestore() { return; } browser.storage.local.get().then(function (storage) { - if (storage && storage.rules) { - rules = toggleRules(storage.rules); - } else { - initRulesDefault(); + if (storage) { + if (storage.rulesV1) { + rules = toggleRules(storage.rulesV1); + return; + } + for (let attribute in storage) { + browser.storage.local.clear().then(initRulesDefault, + initRulesDefault); + return; + } } + initRulesDefault(); }, initRulesDefault); } diff --git a/data/tab/index.html b/data/tab/index.html index be2a17d..5877c0a 100644 --- a/data/tab/index.html +++ b/data/tab/index.html @@ -5,7 +5,7 @@ -
+
From 96993ee1e6b27b3aaf74c405f2c1bb189e845aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Fri, 19 Jan 2018 11:40:14 +0100 Subject: [PATCH 03/18] Drop tab permission --- ChangeLog | 2 ++ README.md | 3 +-- background.js | 28 +++++++--------------------- manifest.json | 3 +-- 4 files changed, 11 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 09a1e2d..96527dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,8 @@ This replaces the previous unsatisfactory "Similar Dupes" button and implements also https://github.com/vaeth/bookmarkdupes/issues/45 - Default regexp rules deal with much more than \? tails + - Remove tabs permissions. + The price is that several tabs open when clicked several times - bugfix: increase minimal gecko version to 48.0 to reflect that manifest.json itself apparently requires that version, see https://github.com/vaeth/bookmarkdupes/issues/44 diff --git a/README.md b/README.md index 1001022..446e87d 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,7 @@ the corresponding bookmarks to their previous location in the bookmark menu! The extension requires the following permissions for these reasons: 1. "bookmarks" to read/modify bookmarks -2. "tabs" to let the extension symbol activate the correct tab if it open. -3. "storage" to store/restore the customized rules in expert mode. +2. "storage" to store/restore the customized rules in expert mode. Unfortunately, "storage" is not one of the optional_permissions which might be required only if that feature is actually requested by the user, see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/optional_permissions diff --git a/background.js b/background.js index cb293c6..bdf6edd 100644 --- a/background.js +++ b/background.js @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Nartin Väth +/* Copyright (C) 2017-2018 Nartin Väth * This project is under the GNU public license 2.0 */ @@ -7,26 +7,12 @@ // For documentation on the tab API see e.g. // https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs -function bookmarkdupesTab() { - const url = browser.extension.getURL("data/tab/index.html") - - function selectOrCreate(tabs) { - const properties = { - active: true - }; - if (tabs.length) { // switch to tab - const tab = tabs[0]; - browser.tabs.update(tab.id, properties); - return; - } - properties.url = url; - browser.tabs.create(properties); - } - - const queryInfo = { - url: url +function onClickedListener() { + const properties = { + url: browser.extension.getURL("data/tab/index.html"), + active: true }; - browser.tabs.query(queryInfo).then(selectOrCreate); + browser.tabs.create(properties); } -browser.browserAction.onClicked.addListener(bookmarkdupesTab); +browser.browserAction.onClicked.addListener(onClickedListener); diff --git a/manifest.json b/manifest.json index 8ce0c50..14dcf85 100644 --- a/manifest.json +++ b/manifest.json @@ -10,8 +10,7 @@ "permissions": [ "bookmarks", - "storage", - "tabs" + "storage" ], "background": { From f6b0f746536fbf86d0ece34c01c04d4f971516f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Fri, 19 Jan 2018 13:58:12 +0100 Subject: [PATCH 04/18] Add up/down button. Prefer pics. Fix regExpFrequent[es] and description typos --- _locales/de/messages.json | 34 ++++++++++++++----- _locales/en/messages.json | 32 +++++++++++++----- _locales/es/messages.json | 39 +++++++++++++++++----- _locales/ru/messages.json | 34 ++++++++++++++----- _locales/uk/messages.json | 34 ++++++++++++++----- _locales/zh_CN/messages.json | 34 ++++++++++++++----- data/tab/dupes.js | 65 +++++++++++++++++++++++++++--------- 7 files changed, 207 insertions(+), 65 deletions(-) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 790e1ee..2b56033 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -61,7 +61,7 @@ }, "titleRuleUrl": { "message": "Die Regel trifft auf ein Lesezeichen zu, wenn dessen URL auf den regulären Ausdruck passt.", - "description": "Explain that bookmarks whose URL matches the regular expression" + "description": "Explain that bookmarks whose URL matches the regular expression will be selected" }, "ruleUrlNegation": { "message": "URL passt nicht", @@ -69,7 +69,7 @@ }, "titleRuleUrlNegation": { "message": "Die Regel trifft auf ein Lesezeichen zu, wenn dessen URL nicht auf den regulären Ausdruck passt.", - "description": "Explain that bookmarks whose URL does not match the regular expression" + "description": "Explain that bookmarks whose URL does not match the regular expression will be selected" }, "ruleSearch": { "message": "Ersetze URL-Teil", @@ -87,22 +87,38 @@ "message": "Der Ersetzungstext für den passenden Teil des regulären Ausdrucks. Symbole wie $$& oder $$1 können benutzt werden, um auf Treffer oder Klammern zu verweisen. Die speziellen Texte \\L$$& und \\U$$& bedeuten eine klein- bzw. großgeschriebene Version der Treffer.", "description": "Explain that the text will be used as replacement text for the regular expression matches" }, - "buttonRuleAdd": { - "message": "Neu", - "description": "Button for inserting a new rule. The text should be short" + "buttonRuleUp": { + "message": "⇧", + "description": "Button for moving a rule up. The text should be short" }, - "titleButtonRuleAdd": { - "message": "Einfügen einer neuen Regel.", - "description": "Explain that a new rule will be inserted" + "titleButtonRuleUp": { + "message": "Die Regel wird nach oben verschoben.", + "description": "Explain that the rule will be moved up" + }, + "buttonRuleDown": { + "message": "⇩", + "description": "Button for moving a rule down. The text should be short" + }, + "titleButtonRuleDown": { + "message": "Die Regel wird nach unten verschoben.", + "description": "Explain that the rule will be moved down" }, "buttonRuleSub": { - "message": "Löschen", + "message": "❌", "description": "Button for removing a rule. The text should be short" }, "titleButtonRuleSub": { "message": "Löschen dieser Regel.", "description": "Explain that the rule will be removed" }, + "buttonRuleAdd": { + "message": "❎", + "description": "Button for inserting a new rule. The text should be short" + }, + "titleButtonRuleAdd": { + "message": "Einfügen einer neuen Regel.", + "description": "Explain that a new rule will be inserted" + }, "regExpFrequent": { "message": "[hH]äufig.*|[oO]ft|[dD]uplikate", "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 240d03d..6a4c03f 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -69,7 +69,7 @@ }, "titleRuleUrlNegation": { "message": "The rule applies to a bookmark if its URL does not match the regular expression.", - "description": "Explain that bookmarks whose URL does not matche the regular expression will be selected" + "description": "Explain that bookmarks whose URL does not match the regular expression will be selected" }, "ruleSearch": { "message": "Replace URL matches", @@ -87,22 +87,38 @@ "message": "The replacement text for the regular expresssion matches. Symbols like $$& or $$1 can be used to refer to the match or a brace content. The special texts \\L$$& and \\U$$& mean a lower and upper case version of the matches, respectively.", "description": "Explain that the text will be used as replacement text for the regular expression matches" }, - "buttonRuleAdd": { - "message": "New", - "description": "Button for inserting a new rule. The text should be short" + "buttonRuleUp": { + "message": "⇧", + "description": "Button for moving a rule up. The text should be short" }, - "titleButtonRuleAdd": { - "message": "Insert a new rule.", - "description": "Explain that a new rule will be inserted" + "titleButtonRuleUp": { + "message": "The rule will be moved up.", + "description": "Explain that the rule will be moved up" + }, + "buttonRuleDown": { + "message": "⇩", + "description": "Button for moving a rule down. The text should be short" + }, + "titleButtonRuleDown": { + "message": "The rule will be moved down.", + "description": "Explain that the rule will be moved down" }, "buttonRuleSub": { - "message": "Remove", + "message": "❌", "description": "Button for removing a rule. The text should be short" }, "titleButtonRuleSub": { "message": "Remove this rule.", "description": "Explain that the rule will be removed" }, + "buttonRuleAdd": { + "message": "❎", + "description": "Button for inserting a new rule. The text should be short" + }, + "titleButtonRuleAdd": { + "message": "Insert a new rule.", + "description": "Explain that a new rule will be inserted" + }, "regExpFrequent": { "message": "[fF]requent.*|[oO]ften|[dD]upes", "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 48cd929..783af04 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -69,7 +69,7 @@ }, "titleRuleUrlNegation": { "message": "La regla se aplica a un marcador si su URL no coincide con la expresión regular.", - "description": "Explain that bookmarks whose URL does not matche the regular expression will be selected" + "description": "Explain that bookmarks whose URL does not match the regular expression will be selected" }, "ruleSearch": { "message": "Reemplazo de coincidencias de URL", @@ -87,24 +87,45 @@ "message": "El texto de reemplazo para la expresión regular coincide. Se pueden usar símbolos como $$& o $$1 para referirse a la coincidencia o un contenido de corchete. Los textos especiales \\L$$& y \\U$$& significan una versión en mayúsculas y minúsculas de las coincidencias, respectivamente..", "description": "Explain that the text will be used as replacement text for the regular expression matches" }, - "buttonRuleAdd": { - "message": "Nuevo", - "description": "Button for inserting a new rule. The text should be short" + "buttonRuleUp": { + "message": "⇧", // new + "description": "Button for moving a rule up. The text should be short" }, - "titleButtonRuleAdd": { - "message": "Intertar una nueva regla.", - "description": "Explain that a new rule will be inserted" + "titleButtonRuleUp": { + "message": "⇧", // new (until it is translated the symbol is perhaps better than English) +// "message": "The rule will be moved up.", + "description": "Explain that the rule will be moved up" + }, + "buttonRuleDown": { + "message": "⇩", // new + "description": "Button for moving a rule down. The text should be short" + }, + "titleButtonRuleDown": { + "message": "⇩", // new (until it is translated the symbol is perhaps better than English) +// "message": "The rule will be moved down.", + "description": "Explain that the rule will be moved down" }, "buttonRuleSub": { - "message": "Eliminar", + "message": "❌", // new +// changed "Eliminar", "description": "Button for removing a rule. The text should be short" }, "titleButtonRuleSub": { "message": "Eliminar esta regla.", "description": "Explain that the rule will be removed" }, + "buttonRuleAdd": { + "message": "❎", // new +// changed "Nuevo", + "description": "Button for inserting a new rule. The text should be short" + }, + "titleButtonRuleAdd": { + "message": "Intertar una nueva regla.", + "description": "Explain that a new rule will be inserted" + }, "regExpFrequent": { - "message": "[fF]recuente. * | [oO] a menudo | [dD]uplicado", + "message": "[fF]recuente.*|.*\\b[mM]enudo\\b.*|[dD]uplicado\\b.*", // new +// changed "[fF]recuente. * | [oO] a menudo | [dD]uplicado", "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index f15540c..1f3060b 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -69,7 +69,7 @@ }, "titleRuleUrlNegation": { "message": "The rule applies to a bookmark if its URL does not match the regular expression.", // new - "description": "Explain that bookmarks whose URL does not matche the regular expression will be selected" + "description": "Explain that bookmarks whose URL does not match the regular expression will be selected" }, "ruleSearch": { "message": "Replace URL matches", // new @@ -87,22 +87,40 @@ "message": "The replacement text for the regular expresssion matches. Symbols like $$& or $$1 can be used to refer to the match or a brace content. The special texts \\L$$& and \\U$$& mean a lower and upper case version of the matches, respectively.", // new "description": "Explain that the text will be used as replacement text for the regular expression matches" }, - "buttonRuleAdd": { - "message": "New", // new - "description": "Button for inserting a new rule. The text should be short" + "buttonRuleUp": { + "message": "⇧", // new + "description": "Button for moving a rule up. The text should be short" }, - "titleButtonRuleAdd": { - "message": "Insert a new rule.", // new - "description": "Explain that a new rule will be inserted" + "titleButtonRuleUp": { + "message": "⇧", // new (until it is translated the symbol is perhaps better than English) +// "message": "The rule will be moved up.", + "description": "Explain that the rule will be moved up" + }, + "buttonRuleDown": { + "message": "⇩", // new + "description": "Button for moving a rule down. The text should be short" + }, + "titleButtonRuleDown": { + "message": "⇩", // new (until it is translated the symbol is perhaps better than English) +// "message": "The rule will be moved down.", + "description": "Explain that the rule will be moved down" }, "buttonRuleSub": { - "message": "Remove", // new + "message": "❌", // new "description": "Button for removing a rule. The text should be short" }, "titleButtonRuleSub": { "message": "Remove this rule.", // new "description": "Explain that the rule will be removed" }, + "buttonRuleAdd": { + "message": "❎", // new + "description": "Button for inserting a new rule. The text should be short" + }, + "titleButtonRuleAdd": { + "message": "Insert a new rule.", // new + "description": "Explain that a new rule will be inserted" + }, "regExpFrequent": { "message": "[fF]requent.*|[oO]ften|[dD]upes", // new "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index ca122b3..7e8007c 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -69,7 +69,7 @@ }, "titleRuleUrlNegation": { "message": "The rule applies to a bookmark if its URL does not match the regular expression.", // new - "description": "Explain that bookmarks whose URL does not matche the regular expression will be selected" + "description": "Explain that bookmarks whose URL does not match the regular expression will be selected" }, "ruleSearch": { "message": "Replace URL matches", // new @@ -87,22 +87,40 @@ "message": "The replacement text for the regular expresssion matches. Symbols like $$& or $$1 can be used to refer to the match or a brace content. The special texts \\L$$& and \\U$$& mean a lower and upper case version of the matches, respectively.", // new "description": "Explain that the text will be used as replacement text for the regular expression matches" }, - "buttonRuleAdd": { - "message": "New", // new - "description": "Button for inserting a new rule. The text should be short" + "buttonRuleUp": { + "message": "⇧", // new + "description": "Button for moving a rule up. The text should be short" }, - "titleButtonRuleAdd": { - "message": "Insert a new rule.", // new - "description": "Explain that a new rule will be inserted" + "titleButtonRuleUp": { + "message": "⇧", // new (until it is translated the symbol is perhaps better than English) +// "message": "The rule will be moved up.", + "description": "Explain that the rule will be moved up" + }, + "buttonRuleDown": { + "message": "⇩", // new + "description": "Button for moving a rule down. The text should be short" + }, + "titleButtonRuleDown": { + "message": "⇩", // new (until it is translated the symbol is perhaps better than English) +// "message": "The rule will be moved down.", + "description": "Explain that the rule will be moved down" }, "buttonRuleSub": { - "message": "Remove", // new + "message": "❌", // new "description": "Button for removing a rule. The text should be short" }, "titleButtonRuleSub": { "message": "Remove this rule.", // new "description": "Explain that the rule will be removed" }, + "buttonRuleAdd": { + "message": "❎", // new + "description": "Button for inserting a new rule. The text should be short" + }, + "titleButtonRuleAdd": { + "message": "Insert a new rule.", // new + "description": "Explain that a new rule will be inserted" + }, "regExpFrequent": { "message": "[fF]requent.*|[oO]ften|[dD]upes", // new "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index 7fee96f..f14ecc9 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -69,7 +69,7 @@ }, "titleRuleUrlNegation": { "message": "The rule applies to a bookmark if its URL does not match the regular expression.", // new - "description": "Explain that bookmarks whose URL does not matche the regular expression will be selected" + "description": "Explain that bookmarks whose URL does not match the regular expression will be selected" }, "ruleSearch": { "message": "Replace URL matches", // new @@ -87,22 +87,40 @@ "message": "The replacement text for the regular expresssion matches. Symbols like $$& or $$1 can be used to refer to the match or a brace content. The special texts \\L$$& and \\U$$& mean a lower and upper case version of the matches, respectively.", // new "description": "Explain that the text will be used as replacement text for the regular expression matches" }, - "buttonRuleAdd": { - "message": "New", // new - "description": "Button for inserting a new rule. The text should be short" + "buttonRuleUp": { + "message": "⇧", // new + "description": "Button for moving a rule up. The text should be short" }, - "titleButtonRuleAdd": { - "message": "Insert a new rule.", // new - "description": "Explain that a new rule will be inserted" + "titleButtonRuleUp": { + "message": "⇧", // new (until it is translated the symbol is perhaps better than English) +// "message": "The rule will be moved up.", + "description": "Explain that the rule will be moved up" + }, + "buttonRuleDown": { + "message": "⇩", // new + "description": "Button for moving a rule down. The text should be short" + }, + "titleButtonRuleDown": { + "message": "⇩", // new (until it is translated the symbol is perhaps better than English) +// "message": "The rule will be moved down.", + "description": "Explain that the rule will be moved down" }, "buttonRuleSub": { - "message": "Remove", // new + "message": "❌", // new "description": "Button for removing a rule. The text should be short" }, "titleButtonRuleSub": { "message": "Remove this rule.", // new "description": "Explain that the rule will be removed" }, + "buttonRuleAdd": { + "message": "❎", // new + "description": "Button for inserting a new rule. The text should be short" + }, + "titleButtonRuleAdd": { + "message": "Insert a new rule.", // new + "description": "Explain that a new rule will be inserted" + }, "regExpFrequent": { "message": "[fF]requent.*|[oO]ften|[dD]upes", // new "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" diff --git a/data/tab/dupes.js b/data/tab/dupes.js index 5cc3742..b8e3173 100644 --- a/data/tab/dupes.js +++ b/data/tab/dupes.js @@ -125,6 +125,11 @@ function getName(folders, parent, name, separator) { return name; } +function appendCol(row) { + const col = document.createElement("TD"); + row.appendChild(col); +} + function appendTextNodeCol(row, text, title, id) { const col = document.createElement("TD"); const textNode = document.createTextNode(text); @@ -274,7 +279,7 @@ function getRule(row) { return rule; } -function addRule(parent, count, rule) { +function addRule(parent, count, total, rule) { if (!rule) { rule = {}; } @@ -296,9 +301,22 @@ function addRule(parent, count, rule) { appendInputCol(row, "titleRuleUrlNegation", rule.urlNegation, off); appendInputCol(row, "titleRuleSearch", rule.search, filterOrOff); appendInputCol(row, "titleRuleReplace", rule.replace, filterOrOff); - appendButtonCol(row, "regexpButton=sub" + stringCount, "titleButtonRuleSub", + const colUp = document.createElement("TD"); + if ((count > 1) && (total > 1)) { + appendButton(colUp, "regexpButton=/" + stringCount, "titleButtonRuleUp", + browser.i18n.getMessage("buttonRuleUp"), null, true); + } + row.appendChild(colUp); + const colDown = document.createElement("TD"); + if (count < total) { + appendButton(colDown, "regexpButton=*" + stringCount, + "titleButtonRuleDown", browser.i18n.getMessage("buttonRuleDown"), + null, true); + } + row.appendChild(colDown); + appendButtonCol(row, "regexpButton=-" + stringCount, "titleButtonRuleSub", browser.i18n.getMessage("buttonRuleSub"), null, true); - appendButtonCol(row, "regexpButton=add" + stringCount, "titleButtonRuleAdd", + appendButtonCol(row, "regexpButton=+" + stringCount, "titleButtonRuleAdd", browser.i18n.getMessage("buttonRuleAdd"), null, true); parent.appendChild(row); } @@ -370,13 +388,16 @@ function addRules(rules) { browser.i18n.getMessage("titleRuleSearch")); appendTextNodeCol(row, browser.i18n.getMessage("ruleReplace"), browser.i18n.getMessage("titleRuleReplace")); - row.appendChild(document.createElement("TD")); - appendButtonCol(row, "regexpButton=add0", "titleButtonRuleAdd", + for (let i = 0; i < 3; ++i) { + appendCol(row); + } + appendButtonCol(row, "regexpButton=+0", "titleButtonRuleAdd", browser.i18n.getMessage("buttonRuleAdd"), null, true); parent.appendChild(row); + const total = rules.length; let count = 0; for (let rule of rules) { - addRule(parent, ++count, rule); + addRule(parent, ++count, total, rule); } } @@ -663,12 +684,11 @@ function addBookmark(bookmark, folders, id) { appendCheckboxCol(row, "bookmark=" + bookmark.id); if (bookmark.order !== undefined) { appendTextNodeCol(row, String(bookmark.order)); - const dummy = document.createElement("TD"); // A dummy column for space - row.appendChild(dummy); + appendCol(row); } const name = getName(folders, bookmark.parent, bookmark.text); - const col = document.createElement("TD"); if (bookmark.url) { + const col = document.createElement("TD"); const url = bookmark.url; row.title = url; const link = document.createElement("A"); @@ -715,12 +735,27 @@ function redisplayRules(rules) { function buttonRule(action) { const rules = getRules(); - const number = Number(action.substr(3)); // 3 = "add".length = "sub".length - if (action.startsWith("add")) { - const rule = {}; - rules.splice(number, 0, rule); - } else { - rules.splice(number - 1, 1); + let number = Number(action.substr(1)); + const type = action.substr(0, 1); + switch(type) { + case '+': { + const rule = {}; + rules.splice(number, 0, rule); + } + break; + case '-': + rules.splice(number - 1, 1); + break; + case '/': + --number; + case '*': { + const rule = rules[number - 1]; + rules[number - 1] = rules[number]; + rules[number] = rule; + } + break; + default: // should not happen + return; // it is a bug if we get here } redisplayRules(rules); } From 3c2b39bb5578769c5897cca785b462f7bc46dd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Sat, 20 Jan 2018 08:38:47 +0100 Subject: [PATCH 05/18] avoid arguments array when simple args passing will do --- ChangeLog | 3 ++- data/tab/dupes.js | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 96527dc..a200b31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,8 +14,9 @@ manifest.json itself apparently requires that version, see https://github.com/vaeth/bookmarkdupes/issues/44 - bugfix: calculation error messages are now displayed correctly - - bugfix: use safe ids for bookmarks + - bugfix: use safe (guaranteed non-duplicate) ids for bookmarks - internal: remove redundant SplitNumber + - internal: avoid arguments array when simple args passing will do Juan Salvador Aleixandre Talens: - Update es locales diff --git a/data/tab/dupes.js b/data/tab/dupes.js index b8e3173..0224584 100644 --- a/data/tab/dupes.js +++ b/data/tab/dupes.js @@ -2047,14 +2047,11 @@ function rulesRestore() { }) } - function markWrapper(func, funcargs) { + function markWrapper(mainFunction, arg1, arg2) { startLock(); enableBookmarks(false); - const thisArg = this; - const args = Array.prototype.slice.call(arguments); - args.splice(0, 1); setTimeout(function () { - func.apply(thisArg, args); + mainFunction(arg1, arg2); endLockAll(); }) } From fb8e7f76699accd0e0e1bd685b77768a4ae0f73a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Sat, 20 Jan 2018 08:46:42 +0100 Subject: [PATCH 06/18] bugfix: add some forgotten semicolons --- ChangeLog | 1 + data/options/options.js | 4 ++-- data/tab/dupes.js | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index a200b31..7f1950c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ https://github.com/vaeth/bookmarkdupes/issues/44 - bugfix: calculation error messages are now displayed correctly - bugfix: use safe (guaranteed non-duplicate) ids for bookmarks + - bugfix: add some forgotten semicolons - internal: remove redundant SplitNumber - internal: avoid arguments array when simple args passing will do diff --git a/data/options/options.js b/data/options/options.js index 9ad860a..630f1ce 100644 --- a/data/options/options.js +++ b/data/options/options.js @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Nartin Väth +/* Copyright (C) 2017-2018 Nartin Väth * This project is under the GNU public license 2.0 */ @@ -16,7 +16,7 @@ function createLink(title) { return; } const link = document.createElement("A"); - const url = browser.extension.getURL("data/tab/index.html") + const url = browser.extension.getURL("data/tab/index.html"); link.href = url; link.target = "_blank"; link.textContent = title; diff --git a/data/tab/dupes.js b/data/tab/dupes.js index 0224584..4b8c61b 100644 --- a/data/tab/dupes.js +++ b/data/tab/dupes.js @@ -159,7 +159,7 @@ function appendRadio(parent, id, name, title, checked) { function appendRadioCol(row, id, name, title, checked) { const col = document.createElement("TD"); - appendRadio(col, id, name, title, checked) + appendRadio(col, id, name, title, checked); row.appendChild(col); } @@ -1168,7 +1168,7 @@ function displayProgress(textId, buttonTextId, total, todo) { const percentage = (100 * total) / todo; addProgressButton(buttonTextId, percentage); displayMessage(browser.i18n.getMessage(textId, - [String(total), String(todo), String(Math.round(percentage))])) + [String(total), String(todo), String(Math.round(percentage))])); } function displayEndProgress(textId, total, error) { @@ -2044,7 +2044,7 @@ function rulesRestore() { startLock(); setTimeout(function () { processMarked(stopPressed, endLockReset, bookmarkMap); - }) + }); } function markWrapper(mainFunction, arg1, arg2) { @@ -2053,7 +2053,7 @@ function rulesRestore() { setTimeout(function () { mainFunction(arg1, arg2); endLockAll(); - }) + }); } function clickListener(event) { From a27b67eceb7c2dadb216844b8b8d2f0a14e6a8b3 Mon Sep 17 00:00:00 2001 From: perdolka Date: Sun, 21 Jan 2018 00:56:49 +0200 Subject: [PATCH 07/18] Update messages.json not finished yet --- _locales/uk/messages.json | 94 +++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 53 deletions(-) diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index 7e8007c..eacac7a 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -8,117 +8,115 @@ "description": "Description of the extension" }, "checkboxRules": { - "message": "Expert mode: use customized rules to match similar bookmarks or to ignore bookmarks when searching.", // new + "message": "Експертний режим: використовуйте власні правила, щоб знаходити або ігнорувати закладки під час пошуку.", "description": "Checkbox text for switching on/off regexp rules" }, "titleCheckboxRules": { - "message": "With this option bookmarks can be ignored or similar bookmarks can be found. The details are specified in terms of regular expressions.", // new + "message": "З допомогою цієї опції закладки можна ігнорувати чи знаходити подібні, відповідно до правил. Подробиці вказано у термінах регулярних виразів.", "description": "Explain what regular expresssions are used for" }, "radioFilter": { - "message": "Filter", // new + "message": "Фільтр", "description": "Radio button for filtering a bookmark. The text should be short" }, "titleRadioFilter": { - "message": "Bookmarks matching the criteria will be ignored.", // new + "message": "Закладки, що відповідають критеріям будуть ігноруватися.", "description": "Explain that by choosing that button the corresponding bookmark will be ignored" }, "radioUrl": { - "message": "Modify", // new + "message": "Змінити", "description": "Radio button for preprocessing a URL. The text should be short" }, "titleRadioUrl": { - "message": "Before checking URLs to find bookmark dupes, the URL of matching bookmarks will be preprocessed according to the specified rule.", // new + "message": "Перед перевіркою URL, щоб знайти дублі закладок, URL-адреси відповідних закладок будуть попередньо оброблені згідно із зазначеним правилом.", "description": "Explain that by choosing that button the url of matching bookmarks will be preprocessed" }, "radioOff": { - "message": "Off", // new + "message": "Вимк.", "description": "Radio button for ignoring the rule. The text should be short" }, "titleRadioOff": { - "message": "This rule has no effect.", // new + "message": "Це правило не діє.", "description": "Explain that by choosing that button the rule has no effect" }, "ruleName": { - "message": "Name matches", // new + "message": "Відповідність імен", "description": "Input field for matching the name. The text should be short" }, "titleRuleName": { - "message": "The rule applies to a bookmark if the bookmark path (folders + name) matches the regular expression. The separator for folders is \\0 or \\x00.", // new + "message": "Правило застосовується до закладок, якщо шлях до них (папки + ім'я) відповідають регулярному виразу. Роздільник для папок це \\0 чи \\x00.", "description": "Explain that bookmarks whose name matches the regular expression will be selected and that folders names are separated by \\0 or \\x00" }, "ruleNameNegation": { - "message": "Name does not match", // new + "message": "Невідповідність імен", "description": "Input field for not matching the name. The text should be short" }, "titleRuleNameNegation": { - "message": "The rule applies to a bookmark if the bookmark path (folders + name) does not match the regular expression. The separator for folders is \\0 or \\x00.", // new + "message": "Правило застосовується до закладок, якщо шлях до них (папки + ім'я) не відповідають регулярному виразу. Роздільник для папок це \\0 чи \\x00.", "description": "Explain that bookmarks whose names does not match the regular expression will be selected and that folders names are separated by \\0 or \\x00" }, "ruleUrl": { - "message": "URL matches", // new + "message": "Відповідність URL-ів", "description": "Input field for matching the URL. The text should be short" }, "titleRuleUrl": { - "message": "The rule applies to a bookmark if its URL matches the regular expression.", // new + "message": "Правило застосовується до закладок, якщо їх адреси збігаються з регулярним виразом.", "description": "Explain that bookmarks whose URL matches the regular expression will be selected" }, "ruleUrlNegation": { - "message": "URL does not match", // new + "message": "Невідповідність URL-ів", "description": "Input field for matching the URL. The text should be short" }, "titleRuleUrlNegation": { - "message": "The rule applies to a bookmark if its URL does not match the regular expression.", // new + "message": "Правило застосовується до закладок, якщо їх адреси не збігаються з регулярним виразом.", "description": "Explain that bookmarks whose URL does not match the regular expression will be selected" }, "ruleSearch": { - "message": "Replace URL matches", // new + "message": "Замін.URL-відповідн.", "description": "Input field for the search part of the URL. The text should be short" }, "titleRuleSearch": { - "message": "When comparing URLs the parts matching the regular expression will be replaced by the subsequent text.", // new + "message": "Якщо порівнювані URL-и містять частини, відповідні до регулярного виразу, їх буде замінено вказаним у правилі текстом.", "description": "Explain that the corresponding parts of the URL will be replaced for comparison" }, "ruleReplace": { - "message": "by", // new + "message": "на", "description": "Input field for the replacement text for the regular expression matches. The text should be short" }, "titleRuleReplace": { - "message": "The replacement text for the regular expresssion matches. Symbols like $$& or $$1 can be used to refer to the match or a brace content. The special texts \\L$$& and \\U$$& mean a lower and upper case version of the matches, respectively.", // new + "message": "Текст заміни по відповідності регулярному виразу. Символи на зразок $$& чи $$1 can be used to refer to the match or a brace content. Спеціальні тексти \\L$$& та \\U$$& означають нижній та верхній регістр відповідно.", // new "description": "Explain that the text will be used as replacement text for the regular expression matches" }, "buttonRuleUp": { - "message": "⇧", // new + "message": "Правило вгору", "description": "Button for moving a rule up. The text should be short" }, "titleButtonRuleUp": { - "message": "⇧", // new (until it is translated the symbol is perhaps better than English) -// "message": "The rule will be moved up.", + "message": "Правило буде переміщено вгору.", "description": "Explain that the rule will be moved up" }, "buttonRuleDown": { - "message": "⇩", // new + "message": "Правило вниз", "description": "Button for moving a rule down. The text should be short" }, "titleButtonRuleDown": { - "message": "⇩", // new (until it is translated the symbol is perhaps better than English) -// "message": "The rule will be moved down.", + "message": "Правило буде переміщено вниз.", "description": "Explain that the rule will be moved down" }, "buttonRuleSub": { - "message": "❌", // new + "message": "Видал.правило", "description": "Button for removing a rule. The text should be short" }, "titleButtonRuleSub": { - "message": "Remove this rule.", // new + "message": "Видалити це правило.", "description": "Explain that the rule will be removed" }, "buttonRuleAdd": { - "message": "❎", // new + "message": "Дод.правило", "description": "Button for inserting a new rule. The text should be short" }, "titleButtonRuleAdd": { - "message": "Insert a new rule.", // new + "message": "Додати нове правило.", "description": "Explain that a new rule will be inserted" }, "regExpFrequent": { @@ -126,47 +124,43 @@ "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "Restore default rules", // new + "message": "Відн. правила за замовч.", "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Restore the default rules. Any changes will be lost", // new + "message": "Відновити правила за замовчуванням. Будь-які зміни буде втрачено.", "description": "Explain that default rules will be restored" }, "buttonRulesStore": { - "message": "Store rules", // new + "message": "Збер.правила", "description": "Button for putting current rules to local storage. The text should be short" }, "titleButtonRulesStore": { - "message": "The current rules will be put to the browser's local storage area.", // new + "message": "Поточні правила буде збережено в локальному сховищі браузера.", "description": "Explain that current rules will be put to local storage" }, "buttonRulesRestore": { - "message": "Restore rules", // new + "message": "Відн.правила", "description": "Button for fetching rules from local storage. The text should be short" }, "titleButtonRulesRestore": { - "message": "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost.", // new + "message": "Правила буде замінено тими, що зберігаються в локальному сховищі браузера. Будь-які зміни буде втрачено.", "description": "Explain that rules will be fetched from local storage" }, "buttonRulesClean": { - "message": "Cleanup storage", // new + "message": "Очистити сховище", "description": "Button for cleaning local storage from stored rules. The text should be short" }, "titleButtonRulesClean": { - "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "message": "Локальне сховище браузера буде очищено від збережених правил. Збережені правила буде втрачено.", "description": "Explain that the local storage will be cleaned from stored rules" }, "buttonListDupes": { - "message": "Dupes", // new -// changed "Exact dupes" -// "message": "Точні дублі", + "message": "Дублі", "description": "Button for listing dupes" }, "titleButtonListDupes": { - "message": "(Re)calculate the list of bookmark dupes. Two bookmarks are considered to be dupes if their URLs coincide. In expert mode, the selected URL preprocessing (substitution) rules are applied before the URLs are compared.", // new -// changed "(Re)calculate the list of exact bookmark dupes. Two bookmarks are considered to be exact dupes if their URLs are identical." -// "message": "(Пере)визначити список точних дублів. Дві закладки вважаються точними дублями, якщо їх URL-и однакові.", + "message": "(Пере)визначити список дублів. Дві закладки вважаються дублями, якщо їх URL-и однакові. В Експертному режимі, обрані правила попередньої обробки (заміни) застосовуються перед порівнянням URL-ів .", "description": "Explain that the list of bookmark dupes will be (re)calculated, and how bookmark dupes are defined" }, "buttonListEmpty": { @@ -378,9 +372,7 @@ "description": "Checkbox for displaying URL in listing. Explain that the URL will appear as title anyway" }, "checkboxExtra": { - "message": "Display replaced URL content in listing", // new -// changed "Display URL tail (following “?”) in listing" -// "message": "Відображати кінцівку URL-адреси (все після “?”) у списку", + "message": "Відображати замінений URL-вміст у списку", "description": "Checkbox for displaying the replaced URL content in listing" }, "messageCount": { @@ -398,9 +390,7 @@ "description": "Report that marks are not counted for speed reasons" }, "messageMatches": { - "message": "$TOTAL$ (of $ALL$) dupes in $GROUPS$ groups", // new -// changed "$TOTAL$ (of $ALL$) exact dupes in $GROUPS$ groups" -// "message": "$TOTAL$ (із $ALL$) точних дублів у $GROUPS$ групах", + "message": "$TOTAL$ (із $ALL$) дублів у $GROUPS$ групах", "description": "Report specified numbers of matches and groups of all", "placeholders": { "total": { @@ -418,9 +408,7 @@ } }, "titleMessageMatches": { - "message": "Two bookmarks are considered to be dupes if their URLs coincide. In expert mode, the selected URL preprocessing (substitution) rules are applied before the URLs are compared.", // new -// changed "Two bookmarks are considered to be exact dupes if their URLs are identical." -// "message": "Дві закладки вважаються точними дублями, якщо їх URL-и однакові.", + "message": "Дві закладки вважаються дублями, якщо їх URL-и однакові. У Експертному режимі, правила попередньої обробки (заміни) застосовуються до URL-ів ще до їх порівняння.", "description": "Explain how bookmark dupes are defined" }, "messageEmpty": { From 79d7d42a3523f8a4784c2402b6c8d18465118569 Mon Sep 17 00:00:00 2001 From: perdolka Date: Sun, 21 Jan 2018 01:42:52 +0200 Subject: [PATCH 08/18] Update messages.json same as UK (87, 123) --- _locales/ru/messages.json | 90 ++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index 1f3060b..fde2da2 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -8,117 +8,115 @@ "description": "Description of the extension" }, "checkboxRules": { - "message": "Expert mode: use customized rules to match similar bookmarks or to ignore bookmarks when searching.", // new + "message": "Экспертный режим: используйте собственные правила, чтобы находить или игнорировать закладки во время поиска.", "description": "Checkbox text for switching on/off regexp rules" }, "titleCheckboxRules": { - "message": "With this option bookmarks can be ignored or similar bookmarks can be found. The details are specified in terms of regular expressions.", // new + "message": "С помощью этой опции можно игнорировать или находить подобные закладки, в соответствии с правилами. Подробности указано в терминах регулярных выражений.", "description": "Explain what regular expresssions are used for" }, "radioFilter": { - "message": "Filter", // new + "message": "Фильтр", "description": "Radio button for filtering a bookmark. The text should be short" }, "titleRadioFilter": { - "message": "Bookmarks matching the criteria will be ignored.", // new + "message": "Закладки, соответствующие критериям будут игнорироваться.", "description": "Explain that by choosing that button the corresponding bookmark will be ignored" }, "radioUrl": { - "message": "Modify", // new + "message": "Изменить", "description": "Radio button for preprocessing a URL. The text should be short" }, "titleRadioUrl": { - "message": "Before checking URLs to find bookmark dupes, the URL of matching bookmarks will be preprocessed according to the specified rule.", // new + "message": "Перед проверкой URL, чтобы найти дубли закладок, URL-ы соответствующих закладок будут предварительно обработанны в соответствии с указанным правилом.", "description": "Explain that by choosing that button the url of matching bookmarks will be preprocessed" }, "radioOff": { - "message": "Off", // new + "message": "Выкл.", "description": "Radio button for ignoring the rule. The text should be short" }, "titleRadioOff": { - "message": "This rule has no effect.", // new + "message": "Это правило не действует.", "description": "Explain that by choosing that button the rule has no effect" }, "ruleName": { - "message": "Name matches", // new + "message": "Соответствие имен", "description": "Input field for matching the name. The text should be short" }, "titleRuleName": { - "message": "The rule applies to a bookmark if the bookmark path (folders + name) matches the regular expression. The separator for folders is \\0 or \\x00.", // new + "message": "Правило применяется к закладкам, если путь к ним (папки + имя) соответствует регулярному выражению. Разделитель для папок это \\0 или \\x00.", "description": "Explain that bookmarks whose name matches the regular expression will be selected and that folders names are separated by \\0 or \\x00" }, "ruleNameNegation": { - "message": "Name does not match", // new + "message": "Несоответствие имен", "description": "Input field for not matching the name. The text should be short" }, "titleRuleNameNegation": { - "message": "The rule applies to a bookmark if the bookmark path (folders + name) does not match the regular expression. The separator for folders is \\0 or \\x00.", // new + "message": "Правило применяется к закладкам, если путь к ним (папки + имя) несоответствует регулярному выражению. Разделитель для папок это \\0 или \\x00.", "description": "Explain that bookmarks whose names does not match the regular expression will be selected and that folders names are separated by \\0 or \\x00" }, "ruleUrl": { - "message": "URL matches", // new + "message": "Соответствие URL-ов", "description": "Input field for matching the URL. The text should be short" }, "titleRuleUrl": { - "message": "The rule applies to a bookmark if its URL matches the regular expression.", // new + "message": "Правило применяется к закладкам, если их адреса совпадают с регулярным выражением.", "description": "Explain that bookmarks whose URL matches the regular expression will be selected" }, "ruleUrlNegation": { - "message": "URL does not match", // new + "message": "Несоответствие URL-ов", "description": "Input field for matching the URL. The text should be short" }, "titleRuleUrlNegation": { - "message": "The rule applies to a bookmark if its URL does not match the regular expression.", // new + "message": "Правило применяется к закладкам, если их адреса несовпадают с регулярным выражением.", "description": "Explain that bookmarks whose URL does not match the regular expression will be selected" }, "ruleSearch": { - "message": "Replace URL matches", // new + "message": "Замен.URL соотв.", "description": "Input field for the search part of the URL. The text should be short" }, "titleRuleSearch": { - "message": "When comparing URLs the parts matching the regular expression will be replaced by the subsequent text.", // new + "message": "Если сравниваемые URL-ы содержат части, соответствующие регулярному выражению, они будут заменены указанным в правиле текстом.", "description": "Explain that the corresponding parts of the URL will be replaced for comparison" }, "ruleReplace": { - "message": "by", // new + "message": "на", "description": "Input field for the replacement text for the regular expression matches. The text should be short" }, "titleRuleReplace": { - "message": "The replacement text for the regular expresssion matches. Symbols like $$& or $$1 can be used to refer to the match or a brace content. The special texts \\L$$& and \\U$$& mean a lower and upper case version of the matches, respectively.", // new + "message": "Текст замены по соответствию регулярному выражению. Символы вроде $$& или $$1 can be used to refer to the match or a brace content. Специальные тексты \\L$$& и \\U$$& означают нижний и верхний регистр соответствий.", // new "description": "Explain that the text will be used as replacement text for the regular expression matches" }, "buttonRuleUp": { - "message": "⇧", // new + "message": "Правило вверх", "description": "Button for moving a rule up. The text should be short" }, "titleButtonRuleUp": { - "message": "⇧", // new (until it is translated the symbol is perhaps better than English) -// "message": "The rule will be moved up.", + "message": "Правило будет перемещено вверх.", "description": "Explain that the rule will be moved up" }, "buttonRuleDown": { - "message": "⇩", // new + "message": "Правило вниз", "description": "Button for moving a rule down. The text should be short" }, "titleButtonRuleDown": { - "message": "⇩", // new (until it is translated the symbol is perhaps better than English) -// "message": "The rule will be moved down.", + "message": "Правило будет перемещено вниз.", "description": "Explain that the rule will be moved down" }, "buttonRuleSub": { - "message": "❌", // new + "message": "Удал.правило", "description": "Button for removing a rule. The text should be short" }, "titleButtonRuleSub": { - "message": "Remove this rule.", // new + "message": "Удалить это правило.", "description": "Explain that the rule will be removed" }, "buttonRuleAdd": { - "message": "❎", // new + "message": "Доб.правило", "description": "Button for inserting a new rule. The text should be short" }, "titleButtonRuleAdd": { - "message": "Insert a new rule.", // new + "message": "Добавить новое правило.", "description": "Explain that a new rule will be inserted" }, "regExpFrequent": { @@ -126,45 +124,43 @@ "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "Restore default rules", // new + "message": "Вост.правила по умолч.", "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Restore the default rules. Any changes will be lost", // new + "message": "Восстановить правила по умолчанию. Любые изменения будут потеряны.", "description": "Explain that default rules will be restored" }, "buttonRulesStore": { - "message": "Store rules", // new + "message": "Сохр.правила", "description": "Button for putting current rules to local storage. The text should be short" }, "titleButtonRulesStore": { - "message": "The current rules will be put to the browser's local storage area.", // new + "message": "Текущие правила будут сохранены в локальном хранилище браузера.", "description": "Explain that current rules will be put to local storage" }, "buttonRulesRestore": { - "message": "Restore rules", // new + "message": "Возобн.правила", "description": "Button for fetching rules from local storage. The text should be short" }, "titleButtonRulesRestore": { - "message": "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost.", // new + "message": "Правила будут заменены теми, что хранятся в локальном хранилище браузера. Любые изменения будут потеряны.", "description": "Explain that rules will be fetched from local storage" }, "buttonRulesClean": { - "message": "Cleanup storage", // new + "message": "Очистить хранилищe", "description": "Button for cleaning local storage from stored rules. The text should be short" }, "titleButtonRulesClean": { - "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "message": "Локальное хранилище браузера будет очищено от сохраненных правил. Сохранены правила будут потеряны.", "description": "Explain that the local storage will be cleaned from stored rules" }, "buttonListDupes": { - "message": "Dupes", // new -// changed "Exact dupes" -// "message": "Точные дубли", + "message": "Дубли", "description": "Button for listing dupes" }, "titleButtonListDupes": { - "message": "(Re)calculate the list of bookmark dupes. Two bookmarks are considered to be dupes if their URLs coincide. In expert mode, the selected URL preprocessing (substitution) rules are applied before the URLs are compared.", // new + "message": "(Пере)определить список дублей. Две закладки считаются дублями, если их URL-ы одинаковы. В Экспертном режиме, выбранные правила предварительной обработки (замены) применяются перед сравнением URL-ов.", // changed "(Re)calculate the list of exact bookmark dupes. Two bookmarks are considered to be exact dupes if their URLs are identical." // "message": "(Пере)определить список точных дублей. Закладки считаются точными дублями, если их URL-ы идентичны.", "description": "Explain that the list of bookmark dupes will be (re)calculated, and how bookmark dupes are defined" @@ -378,7 +374,7 @@ "description": "Checkbox for displaying URL in listing. Explain that the URL will appear as title anyway" }, "checkboxExtra": { - "message": "Display replaced URL content in listing", // new + "message": "Отображать заменённое содержание URL-ов в списке", // changed "Display URL tail (following “?”) in listing" // "message": "Отображать концовку URL-адреса (всё после “?”) в списке", "description": "Checkbox for displaying the replaced URL content in listing" @@ -398,9 +394,7 @@ "description": "Report that marks are not counted for speed reasons" }, "messageMatches": { - "message": "$TOTAL$ (of $ALL$) dupes in $GROUPS$ groups", // new -// changed "$TOTAL$ (of $ALL$) exact dupes in $GROUPS$ groups" -// "message": "$TOTAL$ (из $ALL$) точных дублей в $GROUPS$ группах", + "message": "$TOTAL$ (из $ALL$) дублей в $GROUPS$ группах", "description": "Report specified numbers of matches and groups of all", "placeholders": { "total": { @@ -418,9 +412,7 @@ } }, "titleMessageMatches": { - "message": "Two bookmarks are considered to be dupes if their URLs coincide. In expert mode, the selected URL preprocessing (substitution) rules are applied before the URLs are compared.", // new -// changed "Two bookmarks are considered to be exact dupes if their URLs are identical." -// "message": "Две закладки считаются точными дублями, если их URL-ы одинаковы.", + "message": "Две закладки считаются дублями, если их URL-ы одинаковы. В Экспертном режиме, выбранные правила предварительной обработки (замены) применяются к URL-ам до их сравнения.", "description": "Explain how bookmark dupes are defined" }, "messageEmpty": { From 5888a3a7d87e1184ea55adc4d044cb213a45684d Mon Sep 17 00:00:00 2001 From: perdolka Date: Sun, 21 Jan 2018 10:24:34 +0200 Subject: [PATCH 09/18] fix --- _locales/uk/messages.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index eacac7a..273a8bd 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -44,7 +44,7 @@ "description": "Input field for matching the name. The text should be short" }, "titleRuleName": { - "message": "Правило застосовується до закладок, якщо шлях до них (папки + ім'я) відповідають регулярному виразу. Роздільник для папок це \\0 чи \\x00.", + "message": "Правило застосовується до закладок, якщо шлях до них (папки + ім'я) відповідає регулярному виразу. Роздільник для папок це \\0 чи \\x00.", "description": "Explain that bookmarks whose name matches the regular expression will be selected and that folders names are separated by \\0 or \\x00" }, "ruleNameNegation": { @@ -52,7 +52,7 @@ "description": "Input field for not matching the name. The text should be short" }, "titleRuleNameNegation": { - "message": "Правило застосовується до закладок, якщо шлях до них (папки + ім'я) не відповідають регулярному виразу. Роздільник для папок це \\0 чи \\x00.", + "message": "Правило застосовується до закладок, якщо шлях до них (папки + ім'я) не відповідає регулярному виразу. Роздільник для папок це \\0 чи \\x00.", "description": "Explain that bookmarks whose names does not match the regular expression will be selected and that folders names are separated by \\0 or \\x00" }, "ruleUrl": { From 0f10289a910dcd46f5cc81aff08af44bfc528959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Sun, 21 Jan 2018 09:39:52 +0100 Subject: [PATCH 10/18] Support sync storage. Use storage change listener. Fix possible race --- _locales/de/messages.json | 56 ++++++++++ _locales/en/messages.json | 68 ++++++++---- _locales/es/messages.json | 122 ++++++++++++++++----- _locales/ru/messages.json | 64 +++++++---- _locales/uk/messages.json | 64 +++++++---- _locales/zh_CN/messages.json | 64 +++++++---- data/tab/dupes.js | 200 +++++++++++++++++++++++++---------- data/tab/index.html | 2 +- 8 files changed, 473 insertions(+), 167 deletions(-) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 2b56033..2c28c8f 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -123,6 +123,62 @@ "message": "[hH]äufig.*|[oO]ft|[dD]uplikate", "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, + "buttonRulesDefault": { + "message": "⇇ voreingestellte Regeln", + "description": "Button for restoring default rules. The text should be short" + }, + "titleButtonRulesDefault": { + "message": "Ersetzen der angezeigten Regeln durch die fest voreingestellten", + "description": "Explain that current rules will be replaced by default rules" + }, + "buttonRulesStoreLocal": { + "message": "⇉ lokaler Speicher", + "description": "Button for putting rules to local storage. The text should be short" + }, + "titleButtonRulesStoreLocal": { + "message": "Kopieren der angezeigten Regeln in die des lokalen Browser-Speichers. Frühere Speicherungen werden dabei ggf. verworfen.", + "description": "Explain that current rules will replace those in the browser's local storage area" + }, + "buttonRulesRestoreLocal": { + "message": "⇇ lokaler Speicher", + "description": "Button for restoring rules from local storage. The text should be short" + }, + "titleButtonRulesRestoreLocal": { + "message": "Ersetzen der angezeigten Regeln durch die des lokalen Browser-Speichers", + "description": "Explain that current rules will be replaced by those from the browser's local storage area" + }, + "buttonRulesCleanLocal": { + "message": "❌ lokaler Speicher", + "description": "Button for cleaning local storage. The text should be short" + }, + "titleButtonRulesCleanLocal": { + "message": "Der lokale Browser-Speicher wird von allen gespeicherten Regeln befreit", + "description": "Explain that the browser's local storage area will be cleaned from stored rules" + }, + "buttonRulesStoreSync": { + "message": "⇉ Sync-Speicher", + "description": "Button for putting rules to sync storage. The text should be short" + }, + "titleButtonRulesStoreSync": { + "message": "Kopieren der angezeigten Regeln in die des Sync-Speichers des Browsers. Frühere Speicherungen werden dabei ggf. verworfen.", + "description": "Explain that current rules will replace those in the browser's sync storage area" + }, + "buttonRulesRestoreSync": { + "message": "⇇ Sync-Speicher", + "description": "Button for restoring rules from sync storage. The text should be short" + }, + "titleButtonRulesRestoreSync": { + "message": "Ersetzen der angezeigten Regeln durch die des Sync-Speichers des Browsers", + "description": "Explain that current rules will be replaced by those from the browser's sync storage area" + }, + "buttonRulesCleanSync": { + "message": "❌ Sync-Speicher", + "description": "Button for cleaning sync storage. The text should be short" + }, + "titleButtonRulesCleanSync": { + "message": "Der Sync-Speicher des Browsers wird von allen gespeicherten Regeln befreit", + "description": "Explain that the sync browser's storage area will be cleaned from stored rules" + }, "buttonRulesDefault": { "message": "Voreingestelle Regeln zurückholen", "description": "Button for restoring default rules. The text should be short" diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 6a4c03f..f411d2c 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -124,36 +124,60 @@ "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "Restore default rules", // news + "message": "⇇ default rules", "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Restore the default rules. Any changes will be lost", // new - "description": "Explain that default rules will be restored" + "message": "Replace the currently displayed rules by default rules.", + "description": "Explain that current rules will be replaced by default rules" }, - "buttonRulesStore": { - "message": "Store rules", // news - "description": "Button for putting current rules to local storage. The text should be short" + "buttonRulesStoreLocal": { + "message": "⇉ local storage", + "description": "Button for putting rules to local storage. The text should be short" }, - "titleButtonRulesStore": { - "message": "The current rules will be put to the browser's local storage area.", // new - "description": "Explain that current rules will be put to local storage" + "titleButtonRulesStoreLocal": { + "message": "Put the current rules to the browser's local storage area, possibly replacing earlier stored rules.", + "description": "Explain that current rules will replace those in the browser's local storage area" }, - "buttonRulesRestore": { - "message": "Restore rules", // news - "description": "Button for fetching rules from local storage. The text should be short" + "buttonRulesRestoreLocal": { + "message": "⇇ local storage", + "description": "Button for restoring rules from local storage. The text should be short" }, - "titleButtonRulesRestore": { - "message": "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost.", // new - "description": "Explain that rules will be fetched from local storage" + "titleButtonRulesRestoreLocal": { + "message": "Replace the currently displayed rules by those from the browser's local storage area.", + "description": "Explain that current rules will be replaced by those from the browser's local storage area" }, - "buttonRulesClean": { - "message": "Cleanup storage", // news - "description": "Button for cleaning local storage from stored rules. The text should be short" + "buttonRulesCleanLocal": { + "message": "❌ local storage", + "description": "Button for cleaning local storage. The text should be short" }, - "titleButtonRulesClean": { - "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", // new - "description": "Explain that the local storage will be cleaned from stored rules" + "titleButtonRulesCleanLocal": { + "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", + "description": "Explain that the browser's local storage area will be cleaned from stored rules" + }, + "buttonRulesStoreSync": { + "message": "⇉ sync storage", + "description": "Button for putting rules to sync storage. The text should be short" + }, + "titleButtonRulesStoreSync": { + "message": "Put the current rules to the browser's sync storage area, possibly replacing earlier stored rules.", + "description": "Explain that current rules will replace those in the browser's sync storage area" + }, + "buttonRulesRestoreSync": { + "message": "⇇ sync storage", + "description": "Button for restoring rules from sync storage. The text should be short" + }, + "titleButtonRulesRestoreSync": { + "message": "Replace the currently displayed rules by those from the browser's sync storage area.", + "description": "Explain that current rules will be replaced by those from the browser's sync storage area" + }, + "buttonRulesCleanSync": { + "message": "❌ sync storage", + "description": "Button for cleaning sync storage. The text should be short" + }, + "titleButtonRulesCleanSync": { + "message": "The browser's sync storage area will be cleaned from stored rules. The stored rules will be lost.", + "description": "Explain that the sync browser's storage area will be cleaned from stored rules" }, "buttonListDupes": { "message": "Dupes", @@ -408,7 +432,7 @@ } }, "titleMessageMatches": { - "message": "Two bookmarks are considered to be dupes if their URLs coincide. In expert mode, the selected URL preprocessing (substitution) rules are applied before the URLs are compared.", // new + "message": "Two bookmarks are considered to be dupes if their URLs coincide. In expert mode, the selected URL preprocessing (substitution) rules are applied before the URLs are compared.", "description": "Explain how bookmark dupes are defined" }, "messageEmpty": { diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 783af04..8b4efe5 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -124,41 +124,109 @@ "description": "Explain that a new rule will be inserted" }, "regExpFrequent": { - "message": "[fF]recuente.*|.*\\b[mM]enudo\\b.*|[dD]uplicado\\b.*", // new + "message": "[fF]recuente.*|.*\\b[mM]enudo\\b.*|[dD]uplicado\\b.*", // new (translation attempt; remove the comments if you agree) // changed "[fF]recuente. * | [oO] a menudo | [dD]uplicado", +// reason for the change: I suppose spaces are not meant. Also " *" means to match an arbitrary number of spaces; better use \\b if you mean end of the word (likely) or \\s+ (if you really mean that a space _must_ follow) "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "Restaurar reglas por defecto", + "message": "⇇ reglas por defecto", // new (translation attempt; remove the comments if you agree) +// "message": "⇇ default rules", +// changed "Restaurar reglas por defecto", +// changed "Restore default rules", "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Restaurar las reglas por defecto. Cualquier cambio se perderá", - "description": "Explain that default rules will be restored" - }, - "buttonRulesStore": { - "message": "Guardar reglas", - "description": "Button for putting current rules to local storage. The text should be short" - }, - "titleButtonRulesStore": { - "message": "Las reglas actuales se colocarán en el área de almacenamiento local del navegador.", - "description": "Explain that current rules will be put to local storage" - }, - "buttonRulesRestore": { - "message": "Restaurar reglas", - "description": "Button for fetching rules from local storage. The text should be short" - }, - "titleButtonRulesRestore": { - "message": "Las reglas serán reemplazadas por aquellas almacenadas en el área de almacenamiento local del navegador. Cualquier cambio se perderá.", - "description": "Explain that rules will be fetched from local storage" - }, - "buttonRulesClean": { - "message": "Limpiar almacenamiento local", - "description": "Button for cleaning local storage from stored rules. The text should be short" - }, - "titleButtonRulesClean": { + "message": "Restaurar las reglas por defecto. Cualquier cambio se perderá", // new +// I left the translation unchanged, but it would probably be better to make it +// consistent with the changes in similar messages. +// "message": "Replace the currently displayed rules by default rules.", // new +// changed "Restore the default rules. Any changes will be lost", + "description": "Explain that current rules will be replaced by default rules" + }, + "buttonRulesStoreLocal": { + "message": "⇉ almacenamiento local", // new (translation attempt; remove the comments if you agree) +// changed "Guardar reglas", +// changed "Store rules", + "description": "Button for putting rules to local storage. The text should be short" + }, + "titleButtonRulesStoreLocal": { + "message": "Las reglas actuales se colocarán en el área de almacenamiento local del navegador.", // new +// I left the translation unchanged, but it would probably be better to make it +// more verbose and consistent with the changes in similar messages. +// "message": "Put the current rules to the browser's local storage area, possibly replacing earlier stored rules.", // new +// changed "The current rules will be put to the browser's local storage area.", + "description": "Explain that current rules will replace those in the browser's local storage area" + }, + "buttonRulesRestoreLocal": { + "message": "⇇ almacenamiento local", // new (translation attempt; remove the comments if you agree) +// "message": "⇇ local storage", // new +// changed "Restaurar reglas", +// changed "Restore rules", + "description": "Button for restoring rules from local storage. The text should be short" + }, + "titleButtonRulesRestoreLocal": { + "message": "Las reglas serán reemplazadas por aquellas almacenadas en el área de almacenamiento local del navegador. Cualquier cambio se perderá.", // new +// I left the translation unchanged, but it would probably be better to make it +// consistent with the changes in similar messages. +// "message": "Replace the currently displayed rules by those from the browser's local storage area.", // new +// changed "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost." + "description": "Explain that current rules will be replaced by those from the browser's local storage area" + }, + "buttonRulesCleanLocal": { + "message": "❌ almacenamiento local", // new (translation attempt; remove the comments if you agree) +// "message": "❌ local storage", // new +// changed "Limpiar almacenamiento local", +// changed "Cleanup storage", + "description": "Button for cleaning local storage. The text should be short" + }, + "titleButtonRulesCleanLocal": { "message": "Se limpiarán las reglas almacenadas dentro del área de almacenamiento local del navegador. Las reglas almacenadas se perderán.", - "description": "Explain that the local storage will be cleaned from stored rules" + "description": "Explain that the browser's local storage area will be cleaned from stored rules" + }, + "buttonRulesStoreSync": { + "message": "⇉ almacenamiento sync", // new (translation attempt; remove the comments if you agree) +// "message": "⇉ sync storage", // new +// changed "Guardar reglas", +// changed "Store rules", + "description": "Button for putting rules to sync storage. The text should be short" + }, + "titleButtonRulesStoreSync": { + "message": "Las reglas actuales se colocarán en el área de almacenamiento sync del navegador.", // new +// I left the translation unchanged (up to the word sync), but it would probably +// be better to make it more verbose and consistent with the changes in +// similar messages. +// "message": "Put the current rules to the browser's sync storage area, possibly replacing earlier stored rules.", // new +// changed "The current rules will be put to the browser's local storage area.", + "description": "Explain that current rules will replace those in the browser's sync storage area" + }, + "buttonRulesRestoreSync": { + "message": "⇇ almacenamiento sync", // new (translation attempt; remove the comments if you agree) +// "message": "⇇ sync storage", // new +// changed "Restaurar reglas", +// changed "Restore rules", + "description": "Button for restoring rules from sync storage. The text should be short" + }, + "titleButtonRulesRestoreSync": { + "message": "Las reglas serán reemplazadas por aquellas almacenadas en el área de almacenamiento sync del navegador. Cualquier cambio se perderá.", // new +// I left the translation unchanged (up to the word sync), but it would probably +// be better to make it consistent with the changes in similar messages. +// "message": "Replace the currently displayed rules by those from the browser's sync storage area.", // new +// changed "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost." + "description": "Explain that current rules will be replaced by those from the browser's sync storage area" + }, + "buttonRulesCleanSync": { + "message": "❌ almacenamiento sync", // new (translation attempt; remove the comments if you agree) +// "message": "❌ sync storage", // new +// changed "Limpiar almacenamiento local", +// changed "Cleanup storage", + "description": "Button for cleaning sync storage. The text should be short" + }, + "titleButtonRulesCleanSync": { + "message": "Se limpiarán las reglas almacenadas dentro del área de almacenamiento sync del navegador. Las reglas almacenadas se perderán.", // new (translation attempt; remove the comments if you agree) +// I took the text from "titleButtonRulesCleanLocal" and changed local->sync +// "message": "The browser's sync storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "description": "Explain that the browser's sync storage area will be cleaned from stored rules" }, "buttonListDupes": { "message": "Duplicados", diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index 1f3060b..0cb22d9 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -126,36 +126,60 @@ "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "Restore default rules", // new + "message": "⇇ default rules", // new "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Restore the default rules. Any changes will be lost", // new - "description": "Explain that default rules will be restored" + "message": "Replace the currently displayed rules by default rules.", // new + "description": "Explain that current rules will be replaced by default rules" }, - "buttonRulesStore": { - "message": "Store rules", // new - "description": "Button for putting current rules to local storage. The text should be short" + "buttonRulesStoreLocal": { + "message": "⇉ local storage", // new + "description": "Button for putting rules to local storage. The text should be short" }, - "titleButtonRulesStore": { - "message": "The current rules will be put to the browser's local storage area.", // new - "description": "Explain that current rules will be put to local storage" + "titleButtonRulesStoreLocal": { + "message": "Put the current rules to the browser's local storage area, possibly replacing earlier stored rules.", // new + "description": "Explain that current rules will replace those in the browser's local storage area" }, - "buttonRulesRestore": { - "message": "Restore rules", // new - "description": "Button for fetching rules from local storage. The text should be short" + "buttonRulesRestoreLocal": { + "message": "⇇ local storage", // new + "description": "Button for restoring rules from local storage. The text should be short" }, - "titleButtonRulesRestore": { - "message": "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost.", // new - "description": "Explain that rules will be fetched from local storage" + "titleButtonRulesRestoreLocal": { + "message": "Replace the currently displayed rules by those from the browser's local storage area.", // new + "description": "Explain that current rules will be replaced by those from the browser's local storage area" }, - "buttonRulesClean": { - "message": "Cleanup storage", // new - "description": "Button for cleaning local storage from stored rules. The text should be short" + "buttonRulesCleanLocal": { + "message": "❌ local storage", // new + "description": "Button for cleaning local storage. The text should be short" }, - "titleButtonRulesClean": { + "titleButtonRulesCleanLocal": { "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", // new - "description": "Explain that the local storage will be cleaned from stored rules" + "description": "Explain that the browser's local storage area will be cleaned from stored rules" + }, + "buttonRulesStoreSync": { + "message": "⇉ sync storage", // new + "description": "Button for putting rules to sync storage. The text should be short" + }, + "titleButtonRulesStoreSync": { + "message": "Put the current rules to the browser's sync storage area, possibly replacing earlier stored rules.", // new + "description": "Explain that current rules will replace those in the browser's sync storage area" + }, + "buttonRulesRestoreSync": { + "message": "⇇ sync storage", // new + "description": "Button for restoring rules from sync storage. The text should be short" + }, + "titleButtonRulesRestoreSync": { + "message": "Replace the currently displayed rules by those from the browser's sync storage area.", // new + "description": "Explain that current rules will be replaced by those from the browser's sync storage area" + }, + "buttonRulesCleanSync": { + "message": "❌ sync storage", // new + "description": "Button for cleaning sync storage. The text should be short" + }, + "titleButtonRulesCleanSync": { + "message": "The browser's sync storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "description": "Explain that the sync browser's storage area will be cleaned from stored rules" }, "buttonListDupes": { "message": "Dupes", // new diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index 7e8007c..060cde5 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -126,36 +126,60 @@ "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "Restore default rules", // new + "message": "⇇ default rules", // new "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Restore the default rules. Any changes will be lost", // new - "description": "Explain that default rules will be restored" + "message": "Replace the currently displayed rules by default rules.", // new + "description": "Explain that current rules will be replaced by default rules" }, - "buttonRulesStore": { - "message": "Store rules", // new - "description": "Button for putting current rules to local storage. The text should be short" + "buttonRulesStoreLocal": { + "message": "⇉ local storage", // new + "description": "Button for putting rules to local storage. The text should be short" }, - "titleButtonRulesStore": { - "message": "The current rules will be put to the browser's local storage area.", // new - "description": "Explain that current rules will be put to local storage" + "titleButtonRulesStoreLocal": { + "message": "Put the current rules to the browser's local storage area, possibly replacing earlier stored rules.", // new + "description": "Explain that current rules will replace those in the browser's local storage area" }, - "buttonRulesRestore": { - "message": "Restore rules", // new - "description": "Button for fetching rules from local storage. The text should be short" + "buttonRulesRestoreLocal": { + "message": "⇇ local storage", // new + "description": "Button for restoring rules from local storage. The text should be short" }, - "titleButtonRulesRestore": { - "message": "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost.", // new - "description": "Explain that rules will be fetched from local storage" + "titleButtonRulesRestoreLocal": { + "message": "Replace the currently displayed rules by those from the browser's local storage area.", // new + "description": "Explain that current rules will be replaced by those from the browser's local storage area" }, - "buttonRulesClean": { - "message": "Cleanup storage", // new - "description": "Button for cleaning local storage from stored rules. The text should be short" + "buttonRulesCleanLocal": { + "message": "❌ local storage", // new + "description": "Button for cleaning local storage. The text should be short" }, - "titleButtonRulesClean": { + "titleButtonRulesCleanLocal": { "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", // new - "description": "Explain that the local storage will be cleaned from stored rules" + "description": "Explain that the browser's local storage area will be cleaned from stored rules" + }, + "buttonRulesStoreSync": { + "message": "⇉ sync storage", // new + "description": "Button for putting rules to sync storage. The text should be short" + }, + "titleButtonRulesStoreSync": { + "message": "Put the current rules to the browser's sync storage area, possibly replacing earlier stored rules.", // new + "description": "Explain that current rules will replace those in the browser's sync storage area" + }, + "buttonRulesRestoreSync": { + "message": "⇇ sync storage", // new + "description": "Button for restoring rules from sync storage. The text should be short" + }, + "titleButtonRulesRestoreSync": { + "message": "Replace the currently displayed rules by those from the browser's sync storage area.", // new + "description": "Explain that current rules will be replaced by those from the browser's sync storage area" + }, + "buttonRulesCleanSync": { + "message": "❌ sync storage", // new + "description": "Button for cleaning sync storage. The text should be short" + }, + "titleButtonRulesCleanSync": { + "message": "The browser's sync storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "description": "Explain that the sync browser's storage area will be cleaned from stored rules" }, "buttonListDupes": { "message": "Dupes", // new diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index f14ecc9..11a4c47 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -126,36 +126,60 @@ "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "Restore default rules", // new + "message": "⇇ default rules", // new "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Restore the default rules. Any changes will be lost", // new - "description": "Explain that default rules will be restored" + "message": "Replace the currently displayed rules by default rules.", // new + "description": "Explain that current rules will be replaced by default rules" }, - "buttonRulesStore": { - "message": "Store rules", // new - "description": "Button for putting current rules to local storage. The text should be short" + "buttonRulesStoreLocal": { + "message": "⇉ local storage", // new + "description": "Button for putting rules to local storage. The text should be short" }, - "titleButtonRulesStore": { - "message": "The current rules will be put to the browser's local storage area.", // new - "description": "Explain that current rules will be put to local storage" + "titleButtonRulesStoreLocal": { + "message": "Put the current rules to the browser's local storage area, possibly replacing earlier stored rules.", // new + "description": "Explain that current rules will replace those in the browser's local storage area" }, - "buttonRulesRestore": { - "message": "Restore rules", // new - "description": "Button for fetching rules from local storage. The text should be short" + "buttonRulesRestoreLocal": { + "message": "⇇ local storage", // new + "description": "Button for restoring rules from local storage. The text should be short" }, - "titleButtonRulesRestore": { - "message": "The rules will be replaced by those stored in the browser's local storage area. Any changes will be lost.", // new - "description": "Explain that rules will be fetched from local storage" + "titleButtonRulesRestoreLocal": { + "message": "Replace the currently displayed rules by those from the browser's local storage area.", // new + "description": "Explain that current rules will be replaced by those from the browser's local storage area" }, - "buttonRulesClean": { - "message": "Cleanup storage", // new - "description": "Button for cleaning local storage from stored rules. The text should be short" + "buttonRulesCleanLocal": { + "message": "❌ local storage", // new + "description": "Button for cleaning local storage. The text should be short" }, - "titleButtonRulesClean": { + "titleButtonRulesCleanLocal": { "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", // new - "description": "Explain that the local storage will be cleaned from stored rules" + "description": "Explain that the browser's local storage area will be cleaned from stored rules" + }, + "buttonRulesStoreSync": { + "message": "⇉ sync storage", // new + "description": "Button for putting rules to sync storage. The text should be short" + }, + "titleButtonRulesStoreSync": { + "message": "Put the current rules to the browser's sync storage area, possibly replacing earlier stored rules.", // new + "description": "Explain that current rules will replace those in the browser's sync storage area" + }, + "buttonRulesRestoreSync": { + "message": "⇇ sync storage", // new + "description": "Button for restoring rules from sync storage. The text should be short" + }, + "titleButtonRulesRestoreSync": { + "message": "Replace the currently displayed rules by those from the browser's sync storage area.", // new + "description": "Explain that current rules will be replaced by those from the browser's sync storage area" + }, + "buttonRulesCleanSync": { + "message": "❌ sync storage", // new + "description": "Button for cleaning sync storage. The text should be short" + }, + "titleButtonRulesCleanSync": { + "message": "The browser's sync storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "description": "Explain that the sync browser's storage area will be cleaned from stored rules" }, "buttonListDupes": { "message": "Dupes", // new diff --git a/data/tab/dupes.js b/data/tab/dupes.js index 4b8c61b..e5c3e37 100644 --- a/data/tab/dupes.js +++ b/data/tab/dupes.js @@ -58,8 +58,12 @@ function getMessageNode() { return document.getElementById("textMessage"); } -function getButtonsRules() { - return document.getElementById("buttonsRules"); +function getButtonsRulesLocal() { + return document.getElementById("buttonsRulesLocal"); +} + +function getButtonsRulesSync() { + return document.getElementById("buttonsRulesSync"); } function getTableRules() { @@ -343,24 +347,39 @@ function changeRule(id) { children[9].firstChild.disabled = filterOrOff; } -function addButtonsRules(restore, clean) { - const parent = getButtonsRules(); - if (parent.hasChildNodes()) { // Already done - const children = parent.firstChild.children; +function addButtonsRulesLocal(restore, clean) { + const row = getButtonsRulesLocal(); + if (row.hasChildNodes()) { // Already done + const children = row.children; children[2].firstChild.disabled = !restore; children[3].firstChild.disabled = !clean; return; } - const row = document.createElement("TR"); appendButtonCol(row, "buttonRulesDefault", "titleButtonRulesDefault", null, null, true); - appendButtonCol(row, "buttonRulesStore", "titleButtonRulesStore", + appendButtonCol(row, "buttonRulesStoreLocal", "titleButtonRulesStoreLocal", null, null, true); - appendButtonCol(row, "buttonRulesRestore", "titleButtonRulesRestore", - null, null, restore); - appendButtonCol(row, "buttonRulesClean", "titleButtonRulesClean", + appendButtonCol(row, "buttonRulesRestoreLocal", + "titleButtonRulesRestoreLocal", null, null, restore); + appendButtonCol(row, "buttonRulesCleanLocal", "titleButtonRulesCleanLocal", + null, null, clean); +} + +function addButtonsRulesSync(restore, clean) { + const row = getButtonsRulesSync(); + if (row.hasChildNodes()) { // Already done + const children = row.children; + children[2].firstChild.disabled = !restore; + children[3].firstChild.disabled = !clean; + return; + } + appendCol(row); + appendButtonCol(row, "buttonRulesStoreSync", "titleButtonRulesStoreSync", + null, null, true); + appendButtonCol(row, "buttonRulesRestoreSync", + "titleButtonRulesRestoreSync", null, null, restore); + appendButtonCol(row, "buttonRulesCleanSync", "titleButtonRulesCleanSync", null, null, clean); - parent.appendChild(row); } function addRules(rules) { @@ -738,17 +757,17 @@ function buttonRule(action) { let number = Number(action.substr(1)); const type = action.substr(0, 1); switch(type) { - case '+': { + case "+": { const rule = {}; rules.splice(number, 0, rule); } break; - case '-': + case "-": rules.splice(number - 1, 1); break; - case '/': + case "/": --number; - case '*': { + case "*": { const rule = rules[number - 1]; rules[number - 1] = rules[number]; rules[number] = rule; @@ -760,19 +779,59 @@ function buttonRule(action) { redisplayRules(rules); } -function buttonsRules() { - browser.storage.local.get().then(function (storage) { - const haveStorage = (storage && storage.rulesV1); - addButtonsRules(haveStorage, haveStorage); +function haveStorageSync() { // check if supported by browser + return (browser.storage.sync && browser.storage.sync.get && + (typeof(browser.storage.sync.get) == "function")); +} + +function haveProperties(object) { + for (let attribute in object) { + return true; + } + return false; +} + +function buttonsRulesQuick(storageArea, restoreRules) { + const addButtonsRules = ((storageArea === "sync") ? + addButtonsRulesSync : addButtonsRulesLocal); + browser.storage[storageArea].get().then(function (storage) { + if (!getCheckboxRules()) { // async race: user might have changed + return; + } + if (!storage) { + addButtonsRules(false, false); + return; + } + const clean = haveProperties(storage); + if (!storage.rulesV1) { + addButtonsRules(false, clean); + return; + } + if (restoreRules) { + redisplayRules(storage.rulesV1); + } + addButtonsRules(true, clean); }, function () { + if (!getCheckboxRules()) { // async race: user might have changed + return; + } addButtonsRules(false, true); }); } +function buttonsRules(storageArea, restoreRules) { + if (getCheckboxRules()) { + buttonsRulesQuick(storageArea, restoreRules); + } +} + function toggleRules(rules) { if (getCheckboxRules()) { addRules(rules); - buttonsRules(); + buttonsRulesQuick("local"); + if (haveStorageSync()) { + buttonsRulesQuick("sync"); + } return null; } if (rules) { // checkboxRules was already unchecked @@ -780,7 +839,8 @@ function toggleRules(rules) { } const newRules = getRules(); clearItem(getTableRules()); - clearItem(getButtonsRules()); + clearItem(getButtonsRulesLocal()); + clearItem(getButtonsRulesSync()); return newRules; } @@ -1831,28 +1891,19 @@ function processMarked(stopPressed, callback, bookmarkMap) { recurse(); } -function rulesStore() { +function rulesStore(storageArea) { const storage = { rulesV1: getRules() }; - browser.storage.local.set(storage).then(buttonsRules, buttonsRules); + browser.storage[storageArea].set(storage); } -function rulesClean() { - browser.storage.local.clear().then(buttonsRules, buttonsRules); +function rulesClean(storageArea) { + browser.storage[storageArea].clear(); } -function rulesRestore() { - browser.storage.local.get().then(function (storage) { - if (storage && storage.rulesV1) { - redisplayRules(storage.rulesV1); - addButtonsRules(true, true); - } else { - addButtonsRules(false, false); - } - }, function () { - addButtonsRules(false, true); - }); +function rulesRestore(storageArea) { + buttonsRules(storageArea, true); } { @@ -1938,25 +1989,50 @@ function rulesRestore() { rules = toggleRules(rulesDefault); } + function initRulesStorage(storageArea, callback) { + browser.storage[storageArea].get().then(function (storage) { + if (storage && storage.rulesV1) { + rules = toggleRules(storage.rulesV1); + return; + } + callback(); + }, callback); + } + + function initRulesSync() { + const callback = initRulesDefault; + if (!haveStorageSync()) { + callback(); + return; + } + initRulesStorage("sync", callback); + } + + function initRulesLocal() { + initRulesStorage("local", initRulesSync); + } + function checkboxRules() { - if (rules !== undefined) { + if (rules === undefined) { // first call + initRulesLocal(); + } else { rules = toggleRules(rules); - return; } - browser.storage.local.get().then(function (storage) { - if (storage) { - if (storage.rulesV1) { - rules = toggleRules(storage.rulesV1); - return; - } - for (let attribute in storage) { - browser.storage.local.clear().then(initRulesDefault, - initRulesDefault); + } + + function storageListener(changes, storageArea) { + switch(storageArea) { + case "sync": + if (!haveStorageSync()) { // only if supported by browser return; } - } - initRulesDefault(); - }, initRulesDefault); + break; + case "local": + break; + default: // unsupported storageArea (e.g. "managed") + return; + } + buttonsRules(storageArea); } function checkboxListener(event) { @@ -2145,14 +2221,23 @@ function rulesRestore() { case "buttonRulesDefault": redisplayRules(rulesDefault); return; - case "buttonRulesStore": - rulesStore(); + case "buttonRulesStoreLocal": + rulesStore("local"); + return; + case "buttonRulesRestoreLocal": + rulesRestore("local"); + return; + case "buttonRulesCleanLocal": + rulesClean("local"); + return; + case "buttonRulesStoreSync": + rulesStore("sync"); return; - case "buttonRulesRestore": - rulesRestore(); + case "buttonRulesRestoreSync": + rulesRestore("sync"); return; - case "buttonRulesClean": - rulesClean(); + case "buttonRulesCleanSync": + rulesClean("sync"); return; default: if (id.startsWith("regexpButton=")) { @@ -2169,5 +2254,6 @@ function rulesRestore() { document.addEventListener("CheckboxStateChange", checkboxListener); document.addEventListener("click", clickListener); document.addEventListener("change", changeListener); + browser.storage.onChanged.addListener(storageListener); endLock(); } diff --git a/data/tab/index.html b/data/tab/index.html index 5877c0a..62a2b39 100644 --- a/data/tab/index.html +++ b/data/tab/index.html @@ -7,7 +7,7 @@
-
+
From b11819c9edacb114fb0b7c81df7e76239845306d Mon Sep 17 00:00:00 2001 From: perdolka Date: Sun, 21 Jan 2018 12:09:15 +0200 Subject: [PATCH 11/18] update --- _locales/ru/messages.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index e9ec2c4..89110ef 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -124,59 +124,59 @@ "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "⇇ default rules", // new + "message": "Вост.правила по умолч.", "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Replace the currently displayed rules by default rules.", // new + "message": "Заменить текущие правила правилами по умолчанию.", "description": "Explain that current rules will be replaced by default rules" }, "buttonRulesStoreLocal": { - "message": "⇉ local storage", // new + "message": "Сохр.правила", "description": "Button for putting rules to local storage. The text should be short" }, "titleButtonRulesStoreLocal": { - "message": "Put the current rules to the browser's local storage area, possibly replacing earlier stored rules.", // new + "message": "Текущие правила будут сохранены в локальном хранилище браузера, возможно перезапишутся ранее сохраненные правила.", "description": "Explain that current rules will replace those in the browser's local storage area" }, "buttonRulesRestoreLocal": { - "message": "⇇ local storage", // new + "message": "Вост.правила", "description": "Button for restoring rules from local storage. The text should be short" }, "titleButtonRulesRestoreLocal": { - "message": "Replace the currently displayed rules by those from the browser's local storage area.", // new + "message": "Правила будут заменены теми, что хранятся в локальном хранилище браузера.", "description": "Explain that current rules will be replaced by those from the browser's local storage area" }, "buttonRulesCleanLocal": { - "message": "❌ local storage", // new + "message": "Очистка хранилища", "description": "Button for cleaning local storage. The text should be short" }, "titleButtonRulesCleanLocal": { - "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "message": "Локальное хранилище браузера будет очищено от сохраненных правил. Сохранены правила будут утеряны.", "description": "Explain that the browser's local storage area will be cleaned from stored rules" }, "buttonRulesStoreSync": { - "message": "⇉ sync storage", // new + "message": "Сохр.синхр.хранилище", "description": "Button for putting rules to sync storage. The text should be short" }, "titleButtonRulesStoreSync": { - "message": "Put the current rules to the browser's sync storage area, possibly replacing earlier stored rules.", // new + "message": "Текущие правила будут сохранены в хранилище синхронизации браузера, возможно перезапишутся ранее сохраненные правила.", "description": "Explain that current rules will replace those in the browser's sync storage area" }, "buttonRulesRestoreSync": { - "message": "⇇ sync storage", // new + "message": "Вост.синхр.хранилище", "description": "Button for restoring rules from sync storage. The text should be short" }, "titleButtonRulesRestoreSync": { - "message": "Replace the currently displayed rules by those from the browser's sync storage area.", // new + "message": "Заменить текущие правила теми, которые находятся в хранилище синхронизации браузера.", "description": "Explain that current rules will be replaced by those from the browser's sync storage area" }, "buttonRulesCleanSync": { - "message": "❌ sync storage", // new + "message": "Оч.Синхр.хранилище", "description": "Button for cleaning sync storage. The text should be short" }, "titleButtonRulesCleanSync": { - "message": "The browser's sync storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "message": "Хранилище синхронизации браузера будет очищено от сохранённых правил. Сохраненные правила будут утеряны.", "description": "Explain that the sync browser's storage area will be cleaned from stored rules" }, "buttonListDupes": { From 22bce22c48e494f011d87dcab7dfb14d50af56f4 Mon Sep 17 00:00:00 2001 From: perdolka Date: Sun, 21 Jan 2018 12:12:39 +0200 Subject: [PATCH 12/18] update --- _locales/ru/messages.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index 89110ef..ede4cf8 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -136,7 +136,7 @@ "description": "Button for putting rules to local storage. The text should be short" }, "titleButtonRulesStoreLocal": { - "message": "Текущие правила будут сохранены в локальном хранилище браузера, возможно перезапишутся ранее сохраненные правила.", + "message": "Текущие правила будут сохранены в локальном хранилище браузера, возможно перезапишутся ранее сохранённые правила.", "description": "Explain that current rules will replace those in the browser's local storage area" }, "buttonRulesRestoreLocal": { @@ -152,7 +152,7 @@ "description": "Button for cleaning local storage. The text should be short" }, "titleButtonRulesCleanLocal": { - "message": "Локальное хранилище браузера будет очищено от сохраненных правил. Сохранены правила будут утеряны.", + "message": "Локальное хранилище браузера будет очищено от сохраненных правил. Сохранённые правила будут утеряны.", "description": "Explain that the browser's local storage area will be cleaned from stored rules" }, "buttonRulesStoreSync": { @@ -160,7 +160,7 @@ "description": "Button for putting rules to sync storage. The text should be short" }, "titleButtonRulesStoreSync": { - "message": "Текущие правила будут сохранены в хранилище синхронизации браузера, возможно перезапишутся ранее сохраненные правила.", + "message": "Текущие правила будут сохранены в хранилище синхронизации браузера, возможно перезапишутся ранее сохранённые правила.", "description": "Explain that current rules will replace those in the browser's sync storage area" }, "buttonRulesRestoreSync": { @@ -176,7 +176,7 @@ "description": "Button for cleaning sync storage. The text should be short" }, "titleButtonRulesCleanSync": { - "message": "Хранилище синхронизации браузера будет очищено от сохранённых правил. Сохраненные правила будут утеряны.", + "message": "Хранилище синхронизации браузера будет очищено от сохранённых правил. Сохранённые правила будут утеряны.", "description": "Explain that the sync browser's storage area will be cleaned from stored rules" }, "buttonListDupes": { From 909a4fd734899cb1fc5584d094e71baefc122c18 Mon Sep 17 00:00:00 2001 From: perdolka Date: Sun, 21 Jan 2018 22:26:53 +0200 Subject: [PATCH 13/18] Update messages.json --- _locales/uk/messages.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index e467616..b38c3a8 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -124,59 +124,59 @@ "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { - "message": "⇇ default rules", // new + "message": "Відн.стандарт.правила", "description": "Button for restoring default rules. The text should be short" }, "titleButtonRulesDefault": { - "message": "Replace the currently displayed rules by default rules.", // new + "message": "Замінити поточні правила правилами за замовчуванням.", "description": "Explain that current rules will be replaced by default rules" }, "buttonRulesStoreLocal": { - "message": "⇉ local storage", // new + "message": "Збер.правила", "description": "Button for putting rules to local storage. The text should be short" }, "titleButtonRulesStoreLocal": { - "message": "Put the current rules to the browser's local storage area, possibly replacing earlier stored rules.", // new + "message": "Поточні правила буде збережено в локальному сховищі браузера, можливо ця дія перезапише раніше збережені правила.", "description": "Explain that current rules will replace those in the browser's local storage area" }, "buttonRulesRestoreLocal": { - "message": "⇇ local storage", // new + "message": "Відн.правила", "description": "Button for restoring rules from local storage. The text should be short" }, "titleButtonRulesRestoreLocal": { - "message": "Replace the currently displayed rules by those from the browser's local storage area.", // new + "message": "Правила буде замінено тими, що зберігаються в локальному сховищі браузера.", "description": "Explain that current rules will be replaced by those from the browser's local storage area" }, "buttonRulesCleanLocal": { - "message": "❌ local storage", // new + "message": "Очищення сховища", "description": "Button for cleaning local storage. The text should be short" }, "titleButtonRulesCleanLocal": { - "message": "The browser's local storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "message": "Локальну пам'ять браузера буде очищено від збережених правил. Збережені правила буде втрачено.", "description": "Explain that the browser's local storage area will be cleaned from stored rules" }, "buttonRulesStoreSync": { - "message": "⇉ sync storage", // new + "message": "Збер.синхр.сховище", "description": "Button for putting rules to sync storage. The text should be short" }, "titleButtonRulesStoreSync": { - "message": "Put the current rules to the browser's sync storage area, possibly replacing earlier stored rules.", // new + "message": "Поточні правила буде збережено в сховище синхронізації браузера, можливо ця дія перезапише раніше збережені правила.", "description": "Explain that current rules will replace those in the browser's sync storage area" }, "buttonRulesRestoreSync": { - "message": "⇇ sync storage", // new + "message": "Відн.синхр.сховище", "description": "Button for restoring rules from sync storage. The text should be short" }, "titleButtonRulesRestoreSync": { - "message": "Replace the currently displayed rules by those from the browser's sync storage area.", // new + "message": "Замінити поточні правила тими, що знаходяться в сховищі синхронізації браузера.", "description": "Explain that current rules will be replaced by those from the browser's sync storage area" }, "buttonRulesCleanSync": { - "message": "❌ sync storage", // new + "message": "Оч.синхр.сховище", "description": "Button for cleaning sync storage. The text should be short" }, "titleButtonRulesCleanSync": { - "message": "The browser's sync storage area will be cleaned from stored rules. The stored rules will be lost.", // new + "message": "Сховище синхронізації браузера буде очищено від збережених правил. Збережені правила буде втрачено.", "description": "Explain that the sync browser's storage area will be cleaned from stored rules" }, "buttonListDupes": { From 04fd7b299310bf2592a44aa495f5b74d33ff6894 Mon Sep 17 00:00:00 2001 From: perdolka Date: Sun, 21 Jan 2018 23:12:39 +0200 Subject: [PATCH 14/18] Update messages.json --- _locales/ru/messages.json | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index ede4cf8..0adb818 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -84,7 +84,7 @@ "description": "Input field for the replacement text for the regular expression matches. The text should be short" }, "titleRuleReplace": { - "message": "Текст замены по соответствию регулярному выражению. Символы вроде $$& или $$1 can be used to refer to the match or a brace content. Специальные тексты \\L$$& и \\U$$& означают нижний и верхний регистр соответствий.", // new + "message": "Текст замены по соответствию регулярному выражению. Символы типа $$& или $$1 могут использоваться для обозначения соответствий или содержимого скобок (). Специальные тексты \\L$$& и \\U$$& означают нижний и верхний регистр соответствий.", "description": "Explain that the text will be used as replacement text for the regular expression matches" }, "buttonRuleUp": { @@ -120,7 +120,7 @@ "description": "Explain that a new rule will be inserted" }, "regExpFrequent": { - "message": "[fF]requent.*|[oO]ften|[dD]upes", // new + "message": "[чЧ]асто.*|[иИ]спользуемые|[зЗ]акладки", "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { @@ -185,8 +185,6 @@ }, "titleButtonListDupes": { "message": "(Пере)определить список дублей. Две закладки считаются дублями, если их URL-ы одинаковы. В Экспертном режиме, выбранные правила предварительной обработки (замены) применяются перед сравнением URL-ов.", -// changed "(Re)calculate the list of exact bookmark dupes. Two bookmarks are considered to be exact dupes if their URLs are identical." -// "message": "(Пере)определить список точных дублей. Закладки считаются точными дублями, если их URL-ы идентичны.", "description": "Explain that the list of bookmark dupes will be (re)calculated, and how bookmark dupes are defined" }, "buttonListEmpty": { @@ -398,9 +396,7 @@ "description": "Checkbox for displaying URL in listing. Explain that the URL will appear as title anyway" }, "checkboxExtra": { - "message": "Отображать заменённое содержание URL-ов в списке", -// changed "Display URL tail (following “?”) in listing" -// "message": "Отображать концовку URL-адреса (всё после “?”) в списке", + "message": "Отображать заменённое содержимое URL-ов в списке", "description": "Checkbox for displaying the replaced URL content in listing" }, "messageCount": { From 4090f67d9823cd2625fa4384c2a0b5fbc50f2f5d Mon Sep 17 00:00:00 2001 From: perdolka Date: Sun, 21 Jan 2018 23:18:20 +0200 Subject: [PATCH 15/18] Update messages.json --- _locales/uk/messages.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index b38c3a8..1aee57d 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -84,7 +84,7 @@ "description": "Input field for the replacement text for the regular expression matches. The text should be short" }, "titleRuleReplace": { - "message": "Текст заміни по відповідності регулярному виразу. Символи на зразок $$& чи $$1 can be used to refer to the match or a brace content. Спеціальні тексти \\L$$& та \\U$$& означають нижній та верхній регістр відповідно.", // new + "message": "Текст заміни по відповідності регулярному виразу. Символи типу $$& чи $$1 можуть використовуватися для позначення відповідностей чи вмісту дужок (). Спеціальні тексти \\L$$& та \\U$$& означають нижній та верхній регістр відповідно.", "description": "Explain that the text will be used as replacement text for the regular expression matches" }, "buttonRuleUp": { @@ -120,7 +120,7 @@ "description": "Explain that a new rule will be inserted" }, "regExpFrequent": { - "message": "[fF]requent.*|[oO]ften|[dD]upes", // new + "message": "[чЧ]асто.*|[вВ]икористовувані|[зЗ]акладки", "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" }, "buttonRulesDefault": { From 911ea7ed15610ae9620b0214ac1733221e88c640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Mon, 22 Jan 2018 06:12:11 +0100 Subject: [PATCH 16/18] Update ChangeLog. Improve some function names. es: less aggressive RegExp --- ChangeLog | 24 +++++++++++++++++++----- _locales/es/messages.json | 2 +- data/tab/dupes.js | 34 +++++++++++++++++----------------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7f1950c..46f3e4a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,12 +2,17 @@ *bookmarkdupes-5.0: Martin Väth : - - Add expert rules to ignore certain bookmarks. - Storage permissions are required to store these expert rules locally. - - Use expert rules to define when bookmarks are considered to be dupes. + - Add expert rules to ignore ("filter") certain bookmarks. + Storage permissions are required to store these expert rules in + the local or sync storage. + - Expert rules can define when bookmarks are considered as dupes. This replaces the previous unsatisfactory "Similar Dupes" button and implements also https://github.com/vaeth/bookmarkdupes/issues/45 - - Default regexp rules deal with much more than \? tails + - Default expert rules deal with much more than \? tails. + Actually, the \? tails rule is now by default deactivated because it + has too many false positives: only relatively safe rules are active + in the defaults, and in addition one locale-specific example of a + filter rule. - Remove tabs permissions. The price is that several tabs open when clicked several times - bugfix: increase minimal gecko version to 48.0 to reflect that @@ -15,9 +20,18 @@ https://github.com/vaeth/bookmarkdupes/issues/44 - bugfix: calculation error messages are now displayed correctly - bugfix: use safe (guaranteed non-duplicate) ids for bookmarks - - bugfix: add some forgotten semicolons + - bugfix: add some forgotten semicolons. Another missing semicolon + (in menwhile changed code) might also have been a reason for + https://github.com/vaeth/bookmarkdupes/issues/38 + However, currently the options page is not removed: some users might + find it convenient. - internal: remove redundant SplitNumber - internal: avoid arguments array when simple args passing will do + - internal: improve some function names + + Henaro aka Ironwool: + - Update uk locales + - Update ru locales Juan Salvador Aleixandre Talens: - Update es locales diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 8b4efe5..513009d 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -124,7 +124,7 @@ "description": "Explain that a new rule will be inserted" }, "regExpFrequent": { - "message": "[fF]recuente.*|.*\\b[mM]enudo\\b.*|[dD]uplicado\\b.*", // new (translation attempt; remove the comments if you agree) + "message": "[fF]recuente.*|.*\\b[mM]enudo|[dD]uplicado", // new (translation attempt; remove the comments if you agree) // changed "[fF]recuente. * | [oO] a menudo | [dD]uplicado", // reason for the change: I suppose spaces are not meant. Also " *" means to match an arbitrary number of spaces; better use \\b if you mean end of the word (likely) or \\s+ (if you really mean that a space _must_ follow) "description": "A regular expression for folder names which intentionally might contain duplicate bookmarks (e.g. \"Frequently used\"). The expression is enclosed into \\0(...)\\0" diff --git a/data/tab/dupes.js b/data/tab/dupes.js index e5c3e37..5f4c084 100644 --- a/data/tab/dupes.js +++ b/data/tab/dupes.js @@ -70,7 +70,7 @@ function getTableRules() { return document.getElementById("tableRules"); } -function getCheckboxRules() { +function isCheckedRules() { return isChecked("checkboxRules"); } @@ -78,15 +78,15 @@ function getTableCheckboxRules() { return document.getElementById("tableCheckboxRules"); } -function getCheckboxFullUrl() { +function isCheckedFullUrl() { return isChecked("checkboxFullUrl"); } -function getCheckboxExtra() { +function isCheckedExtra() { return isChecked("checkboxExtra"); } -function getSelectedFolder() { +function getValueSelectedFolder() { const value = document.getElementById("selectedFolder").value; return ((!value || (value === "@")) ? null : value); } @@ -99,7 +99,7 @@ function getTextCount() { return document.getElementById("textCount"); } -function getCheckboxCount() { +function isCheckedCount() { return isChecked("checkboxCount"); } @@ -747,7 +747,7 @@ function getRules() { function redisplayRules(rules) { clearItem(getTableRules()); - if (getCheckboxRules()) { + if (isCheckedRules()) { addRules(rules); } } @@ -795,7 +795,7 @@ function buttonsRulesQuick(storageArea, restoreRules) { const addButtonsRules = ((storageArea === "sync") ? addButtonsRulesSync : addButtonsRulesLocal); browser.storage[storageArea].get().then(function (storage) { - if (!getCheckboxRules()) { // async race: user might have changed + if (!isCheckedRules()) { // async race: user might have changed return; } if (!storage) { @@ -812,7 +812,7 @@ function buttonsRulesQuick(storageArea, restoreRules) { } addButtonsRules(true, clean); }, function () { - if (!getCheckboxRules()) { // async race: user might have changed + if (!isCheckedRules()) { // async race: user might have changed return; } addButtonsRules(false, true); @@ -820,13 +820,13 @@ function buttonsRulesQuick(storageArea, restoreRules) { } function buttonsRules(storageArea, restoreRules) { - if (getCheckboxRules()) { + if (isCheckedRules()) { buttonsRulesQuick(storageArea, restoreRules); } } function toggleRules(rules) { - if (getCheckboxRules()) { + if (isCheckedRules()) { addRules(rules); buttonsRulesQuick("local"); if (haveStorageSync()) { @@ -848,7 +848,7 @@ function toggleExtra(entryList, rulerList) { if (!entryList && !rulerList) { return; } - const fullUrl = getCheckboxFullUrl(); + const fullUrl = isCheckedFullUrl(); if (rulerList) { for (let i = 0; i < rulerList.length; ++i) { const col = document.getElementById("rulerExtra=" + String(i)); @@ -858,7 +858,7 @@ function toggleExtra(entryList, rulerList) { if (!entryList) { return; } - let extra = getCheckboxExtra(); + let extra = isCheckedExtra(); for (let i = 0; i < entryList.length; ++i) { const col = document.getElementById("entryExtra=" + String(i)); const entry = entryList[i]; @@ -985,7 +985,7 @@ function markButNewest() { } function getSelectedIds(folderIds) { - const value = getSelectedFolder(); + const value = getValueSelectedFolder(); if ((!value) || (value === "=")) { return null; } @@ -1315,7 +1315,7 @@ function textToUpperCase(text) { function compileRules(mode) { const compiledRules = {}; - if (!getCheckboxRules()) { + if (!isCheckedRules()) { return compiledRules; } const rules = getRules(); @@ -1953,7 +1953,7 @@ function rulesRestore(storageArea) { return; } if (id) { - if (!getCheckboxCount()) { + if (!isCheckedCount()) { return; } if (isChecked(id)) { @@ -1962,7 +1962,7 @@ function rulesRestore(storageArea) { state.marked.delete(getBookmarkId(id)); } } else { - if (!getCheckboxCount()) { + if (!isCheckedCount()) { if (state.hasOwnProperty("lastCount")) { delete state.lastCount; displayCount(browser.i18n.getMessage("messageNoCount")); @@ -2063,7 +2063,7 @@ function rulesRestore(storageArea) { let haveSelected = state.hasOwnProperty("markFolders"); let sameFolders = false; if (haveSelected) { - const name = getSelectedFolder(); + const name = getValueSelectedFolder(); if (name) { if (name === "=") { sameFolders = true; From 79d9703c6741d5cfee8901331b081ebc71145b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Mon, 22 Jan 2018 20:04:13 +0100 Subject: [PATCH 17/18] Fix . in default rules --- data/tab/dupes.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/tab/dupes.js b/data/tab/dupes.js index 5f4c084..af8c2b6 100644 --- a/data/tab/dupes.js +++ b/data/tab/dupes.js @@ -1918,10 +1918,10 @@ function rulesRestore(storageArea) { { radio: "off", urlNegation: "\\b(e?mail|bugs|youtube|translat)\\b", search: "\\?.*" }, { radio: "off", search: "/[^/]*$" }, - { radio: "url", search: "/+(index.html)?$" }, + { radio: "url", search: "/+(index\\.html)?$" }, { radio: "url", search: "^http:", replace: "https:" }, - { radio: "url", search: "^([^:]*://)www?\\d*\.", replace: "$1" }, - { radio: "url", search: "\.htm$", replace: ".html" } + { radio: "url", search: "^([^:]*://)www?\\d*\\.", replace: "$1" }, + { radio: "url", search: "\\.htm$", replace: ".html" } ]; function startLock() { From 544c84d63d685bc7697d3d79371164892c4474e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Tue, 23 Jan 2018 06:01:19 +0100 Subject: [PATCH 18/18] Simplify default rule for filtering top-level bookmarks --- data/tab/dupes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/tab/dupes.js b/data/tab/dupes.js index af8c2b6..0b36f26 100644 --- a/data/tab/dupes.js +++ b/data/tab/dupes.js @@ -1914,7 +1914,7 @@ function rulesRestore(storageArea) { { radio: "url", search: "^\\w+://[^\/]*/", replace: "\\L$&" }, { radio: "filter", name: "\\0(" + browser.i18n.getMessage("regExpFrequent") + ")\\0" }, - { radio: "off", name: "^[^\\0]*\\0[^\\0]*$" }, + { radio: "off", nameNegation: "\\0.*\\0" }, { radio: "off", urlNegation: "\\b(e?mail|bugs|youtube|translat)\\b", search: "\\?.*" }, { radio: "off", search: "/[^/]*$" },