From 50e19ef594eafc01f5ece1c501909113c4e51257 Mon Sep 17 00:00:00 2001 From: Chris White Date: Sun, 2 Sep 2018 14:06:06 -0400 Subject: [PATCH 01/17] settings: Ignore #open= on settings-load complete Also, bump version number to 0.1.18-pre.1 --- package-lock.json | 2 +- package.json | 2 +- tabfern/manifest.json | 4 +- tabfern/src/common/common.js | 2 +- tabfern/src/settings/main.js | 69 ++++++-------------------------- tabfern/src/settings/manifest.js | 9 +++++ 6 files changed, 27 insertions(+), 61 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9250ee52..7f7495a1 100755 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tabfern", - "version": "0.1.17.1337", + "version": "0.1.18.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 254c6653..6cd4be6f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tabfern", - "version": "0.1.17.1337", + "version": "0.1.18.1", "description": "Google Chrome extension for displaying, saving, and managing tabs", "main": "src/view/main.js", "directories": { diff --git a/tabfern/manifest.json b/tabfern/manifest.json index 6d9bacdc..ea53bfb4 100755 --- a/tabfern/manifest.json +++ b/tabfern/manifest.json @@ -1,8 +1,8 @@ { "name": "__MSG_wsLongName__", "short_name": "__MSG_wsShortName__", - "version": "0.1.17.1337", - "version_name": "0.1.17", + "version": "0.1.18.1", + "version_name": "0.1.18-pre.1", "offline_enabled": true, "manifest_version": 2, "minimum_chrome_version": "54", diff --git a/tabfern/src/common/common.js b/tabfern/src/common/common.js index 9e6c98c8..8188c835 100755 --- a/tabfern/src/common/common.js +++ b/tabfern/src/common/common.js @@ -11,7 +11,7 @@ console.log('TabFern common.js loading'); /// The TabFern extension friendly version number. Displayed in the /// title bar of the popup window, so lowercase (no shouting!). -const TABFERN_VERSION='0.1.17'; +const TABFERN_VERSION='0.1.18-pre.1'; // When you change this, also update: // - manifest.json: both the version and version_name // - package.json diff --git a/tabfern/src/settings/main.js b/tabfern/src/settings/main.js index 6cb993db..fc5e1c7e 100755 --- a/tabfern/src/settings/main.js +++ b/tabfern/src/settings/main.js @@ -1,3 +1,6 @@ +/// main.js: Main file for TabFern settings page +/// Copyright (c) 2017--2018 Chris White + /// An object to hold the settings for later programmatic access let settingsobj; @@ -193,9 +196,6 @@ function main() $$('#settings-label').text(_T('wsSettings')); settingsobj = settings; - //settings.manifest.myButton.addEvent("action", function () { - // alert("You clicked me!"); - //}); // ---------------------------- // Finish creating the page @@ -206,18 +206,26 @@ function main() $$('#import-settings').on('click', importSettings); $$('#export-settings').on('click', exportSettings); + let is_settings_load = false; if(getBoolSetting(SETTINGS_LOADED_OK)) { + is_settings_load = true; let elem = $$('
').text("Settings loaded"); $$('#import-settings').after(elem); setSetting(SETTINGS_LOADED_OK, false); } + // ---------------------------- // open tab specified in a query parm, if known. // See https://stackoverflow.com/a/12151322/2877364 // Use location.hash instead of location.search since Chrome doesn't // seem to navigate to chrome-extension://...&... . + // + // Note: if we have come from a settings-load event, don't change + // tabs. Load-settings is on the first tab, which is the + // one activated by default. + let searchParams = new URLSearchParams(window.location.hash.slice(1)); - if(searchParams.has('open')) { + if(!is_settings_load && searchParams.has('open')) { let whichtab = -1; // If other than -1, select that tab let openval = String(searchParams.get('open')); // Do we need the explicit String()? @@ -240,60 +248,9 @@ function main() settingsobj.tabs[tabNames[whichtab]].bundle.activate(); } - } //endif &open=... parameter specified - }); - - // Option 2: Do everything manually: - /* - var settings = new FancySettings("My Extension", "icon.png"); - - var username = settings.create({ - "tab": i18n.get("information"), - "group": i18n.get("login"), - "name": "username", - "type": "text", - "label": i18n.get("username"), - "text": i18n.get("x-characters") - }); - - var password = settings.create({ - "tab": i18n.get("information"), - "group": i18n.get("login"), - "name": "password", - "type": "text", - "label": i18n.get("password"), - "text": i18n.get("x-characters-pw"), - "masked": true - }); - - var myDescription = settings.create({ - "tab": i18n.get("information"), - "group": i18n.get("login"), - "name": "myDescription", - "type": "description", - "text": i18n.get("description") - }); - - var myButton = settings.create({ - "tab": "Information", - "group": "Logout", - "name": "myButton", - "type": "button", - "label": "Disconnect:", - "text": "Logout" - }); - - // ... - - myButton.addEvent("action", function () { - alert("You clicked me!"); + } //endif #open=... parameter specified }); - settings.align([ - username, - password - ]); - */ } //main() window.addEvent("domready", main); diff --git a/tabfern/src/settings/manifest.js b/tabfern/src/settings/manifest.js index f3c07646..792fcc18 100755 --- a/tabfern/src/settings/manifest.js +++ b/tabfern/src/settings/manifest.js @@ -343,6 +343,15 @@ order.` // }}}2 // Changelog {{{1 + { + "tab": i18n.get("What's new?"), + "group": `Version 0.1.18${brplain('2018-xx-xx')}`, + 'group_html':true, + "type": "description", + "text": +``, + }, { "tab": i18n.get("What's new?"), "group": `Version 0.1.17${brplain('2018-09-02')}`, From 01408f28acf17c7b80d633b802254f42e8ea796d Mon Sep 17 00:00:00 2001 From: Chris White Date: Mon, 3 Sep 2018 09:43:00 -0400 Subject: [PATCH 02/17] Modularization cleanup - Switch back to the non-ES6 UMD for the sake of tooling - make view/main into a module --- tabfern/js/asq-helpers.js | 16 ++------- tabfern/js/buffer.js | 2 +- tabfern/js/export-file.js | 5 ++- tabfern/js/import-file.js | 3 +- tabfern/js/jstree-multitype.js | 2 +- tabfern/js/justhtmlescape.js | 4 +-- tabfern/js/spin-packed.js | 2 +- tabfern/src/common/common.js | 2 +- tabfern/src/common/validation.js | 17 +++------ tabfern/src/settings/main.js | 4 +-- tabfern/src/view/bundle_tree.js | 30 +++++----------- tabfern/src/view/const.js | 24 ++++++------- tabfern/src/view/item_details.js | 23 ++++++------ tabfern/src/view/item_tree.js | 32 ++++++++--------- tabfern/src/view/main.html | 6 +--- tabfern/src/view/main.js | 60 ++++++++++++++++---------------- tabfern/src/view/model.js | 28 +++++++-------- tabfern/src/view/sorts.js | 25 ++++++------- tabfern/src/view/template.js | 2 ++ tabfern/src/view/tree.html | 4 +-- tabfern/src/view/tree.js | 6 +++- 21 files changed, 127 insertions(+), 170 deletions(-) diff --git a/tabfern/js/asq-helpers.js b/tabfern/js/asq-helpers.js index 7f7b667b..970ec07d 100755 --- a/tabfern/js/asq-helpers.js +++ b/tabfern/js/asq-helpers.js @@ -1,25 +1,15 @@ // asq-helpers.js: Helpers for asynquence and Chrome callbacks. (function (root, factory) { - let imports=['asynquence-contrib']; - if (typeof define === 'function' && define.amd) { // AMD - define('asq-helpers',imports, factory); + define('asq-helpers', ['asynquence-contrib'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory(require('asynquence-contrib')); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.ASQH = factory(...requirements); + root.ASQH = factory(root.ASQ); } }(this, function (ASQ) { "use strict"; diff --git a/tabfern/js/buffer.js b/tabfern/js/buffer.js index b84e1e22..c709bcee 100755 --- a/tabfern/js/buffer.js +++ b/tabfern/js/buffer.js @@ -2121,4 +2121,4 @@ module.exports = Array.isArray || function (arr) { /***/ }) -/******/ ]); \ No newline at end of file +/******/ ]); diff --git a/tabfern/js/export-file.js b/tabfern/js/export-file.js index f6fc3fa0..63f700e0 100644 --- a/tabfern/js/export-file.js +++ b/tabfern/js/export-file.js @@ -11,10 +11,9 @@ module.exports = factory(); } else { // Browser globals (root is window) - root.Fileops = root.Fileops || {}; - root.Fileops.Export = factory(); + root.ExportFile = factory(); } -}(this, function ($) { +}(this, function () { /// Save the given text to the given filename. This is what is returned /// by the module loader. diff --git a/tabfern/js/import-file.js b/tabfern/js/import-file.js index ed33bcaa..fc8f2129 100644 --- a/tabfern/js/import-file.js +++ b/tabfern/js/import-file.js @@ -11,8 +11,7 @@ module.exports = factory(); } else { // Browser globals (root is window) - root.Fileops = root.Fileops || {}; - root.Fileops.Importer = factory(); + root.ImportFile = factory(); } }(this, function () { diff --git a/tabfern/js/jstree-multitype.js b/tabfern/js/jstree-multitype.js index 8f76af8a..b0c968f6 100644 --- a/tabfern/js/jstree-multitype.js +++ b/tabfern/js/jstree-multitype.js @@ -20,7 +20,7 @@ else { factory(jQuery, jQuery.jstree); } -}(function ($, jstree, undefined) { +}(function ($, _jstree_unused, undefined) { "use strict"; if($.jstree.plugins.multitype) { return; } diff --git a/tabfern/js/justhtmlescape.js b/tabfern/js/justhtmlescape.js index 72fd9b2c..c6fc455c 100644 --- a/tabfern/js/justhtmlescape.js +++ b/tabfern/js/justhtmlescape.js @@ -3,7 +3,7 @@ /// Adapted from https://github.com/janl/mustache.js/blob/master/mustache.js /// MIT license --- see end of file -// Defines HTMLEscaper, which has escape(text) and unescape(text) functions. +// Returns { escape(text), unescape(text) }. (function (root, factory) { if (typeof define === 'function' && define.amd) { @@ -14,7 +14,7 @@ module.exports = factory(); } else { // Browser globals (root is window) - root.HTMLEscaper = factory(); + root.JustHTMLEscape = factory(); } }(this, function () { diff --git a/tabfern/js/spin-packed.js b/tabfern/js/spin-packed.js index 8a5c2d05..846afe62 100644 --- a/tabfern/js/spin-packed.js +++ b/tabfern/js/spin-packed.js @@ -292,4 +292,4 @@ function convertOffset(x, y, degrees) { /***/ }) -/******/ ]); \ No newline at end of file +/******/ ]); diff --git a/tabfern/src/common/common.js b/tabfern/src/common/common.js index 8188c835..1302288f 100755 --- a/tabfern/src/common/common.js +++ b/tabfern/src/common/common.js @@ -2,7 +2,7 @@ // in this file. // ** Not currently a require.js module so that it can be used in contexts // ** where require.js is not available (e.g., background.js). -// ** TODO make this a UMD module? +// ** TODO extract at least the settings portion into a UMD module. console.log('TabFern common.js loading'); diff --git a/tabfern/src/common/validation.js b/tabfern/src/common/validation.js index 1f3fb53e..a8081c2c 100755 --- a/tabfern/src/common/validation.js +++ b/tabfern/src/common/validation.js @@ -1,26 +1,17 @@ /// validation.js: Data-validation routines. +/// Copyright (c) cxw42, 2017--2018. /// NOTE: does NOT use common.js routines, so that common.js can use it. (function (root, factory) { - let imports=[]; - if (typeof define === 'function' && define.amd) { // AMD - define(imports, factory); + define([], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory(); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.Validation = factory(...requirements); + root.Validation = factory(); } }(this, function () { "use strict"; diff --git a/tabfern/src/settings/main.js b/tabfern/src/settings/main.js index fc5e1c7e..7ca30f85 100755 --- a/tabfern/src/settings/main.js +++ b/tabfern/src/settings/main.js @@ -77,7 +77,7 @@ function exportSettings(evt_unused) let filename = 'TabFern settings backup ' + date_tag + '.tabfern_settings'; let saved_info = saveSettingsToObject(); - Fileops.Export(document, JSON.stringify(saved_info), filename); + ExportFile(document, JSON.stringify(saved_info), filename); } //exportSettings() /// Assign settings from an object we have loaded. @@ -182,7 +182,7 @@ function importSettings(evt_unused) } //processFile() setSetting(SETTINGS_LOADED_OK, false); - let importer = Fileops.Importer(document, '.tabfern_settings'); + let importer = ImportFile(document, '.tabfern_settings'); importer.getFileAsString(processFile); } //importSettings() diff --git a/tabfern/src/view/bundle_tree.js b/tabfern/src/view/bundle_tree.js index aa932014..5cd73fbb 100644 --- a/tabfern/src/view/bundle_tree.js +++ b/tabfern/src/view/bundle_tree.js @@ -9183,7 +9183,7 @@ else { factory(jQuery, jQuery.jstree); } -}(function ($, jstree, undefined) { +}(function ($, _jstree_unused, undefined) { "use strict"; if($.jstree.plugins.multitype) { return; } @@ -10092,7 +10092,7 @@ /// Adapted from https://github.com/janl/mustache.js/blob/master/mustache.js /// MIT license --- see end of file -// Defines HTMLEscaper, which has escape(text) and unescape(text) functions. +// Returns { escape(text), unescape(text) }. (function (root, factory) { if (typeof define === 'function' && define.amd) { @@ -10103,7 +10103,7 @@ module.exports = factory(); } else { // Browser globals (root is window) - root.HTMLEscaper = factory(); + root.JustHTMLEscape = factory(); } }(this, function () { @@ -13907,25 +13907,15 @@ ASQ.wrap = function $$wrap(fn, opts) { // asq-helpers.js: Helpers for asynquence and Chrome callbacks. (function (root, factory) { - let imports=['asynquence-contrib']; - if (typeof define === 'function' && define.amd) { // AMD - define('asq-helpers',imports, factory); + define('asq-helpers', ['asynquence-contrib'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory(require('asynquence-contrib')); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.ASQH = factory(...requirements); + root.ASQH = factory(root.ASQ); } }(this, function (ASQ) { "use strict"; @@ -16737,8 +16727,7 @@ Combo options available and their defaults: module.exports = factory(); } else { // Browser globals (root is window) - root.Fileops = root.Fileops || {}; - root.Fileops.Importer = factory(); + root.ImportFile = factory(); } }(this, function () { @@ -16825,10 +16814,9 @@ Combo options available and their defaults: module.exports = factory(); } else { // Browser globals (root is window) - root.Fileops = root.Fileops || {}; - root.Fileops.Export = factory(); + root.ExportFile = factory(); } -}(this, function ($) { +}(this, function () { /// Save the given text to the given filename. This is what is returned /// by the module loader. diff --git a/tabfern/src/view/const.js b/tabfern/src/view/const.js index 3b5fd0e3..ad3dd342 100755 --- a/tabfern/src/view/const.js +++ b/tabfern/src/view/const.js @@ -2,26 +2,22 @@ // Copyright (c) 2017 Chris White, Jasmine Hegman. (function (root, factory) { - let imports=['jquery','jstree','loglevel','asynquence-contrib', - 'asq-helpers' ]; - if (typeof define === 'function' && define.amd) { // AMD - define(imports, factory); + define([ 'jquery', 'jstree', 'loglevel', 'asynquence-contrib', + 'asq-helpers' ], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory( + require('jquery'), require('jstree'), require('loglevel'), + require('asynquence-contrib'), require('asq-helpers') + ); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.tabfern_const = factory(...requirements); + root.K = factory( + root.$, root.$.jstree, root.log, + root.ASQ, root.ASQH + ); } }(this, function ($, _unused_jstree_placeholder_, log_orig, ASQ, ASQH ) { "use strict"; diff --git a/tabfern/src/view/item_details.js b/tabfern/src/view/item_details.js index 76eb37c3..e45ac222 100755 --- a/tabfern/src/view/item_details.js +++ b/tabfern/src/view/item_details.js @@ -6,25 +6,22 @@ // Copyright (c) 2017 Chris White, Jasmine Hegman. (function (root, factory) { - let imports=['jquery','jstree','loglevel', 'multidex', 'view/const' ]; - if (typeof define === 'function' && define.amd) { // AMD - define(imports, factory); + define([ 'jquery','jstree','loglevel', 'multidex', 'view/const' ], + factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory( + require('jquery'), require('jstree'), require('loglevel'), + require('multidex'), require('view/const') + ); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.tabfern_item_details = factory(...requirements); + root.D = factory( + root.$, root.$.jstree, root.log, + root.multidex, root.K + ); } }(this, function ($, _unused_jstree_placeholder_, log, multidex, K ) { "use strict"; diff --git a/tabfern/src/view/item_tree.js b/tabfern/src/view/item_tree.js index d5da5421..121426a0 100755 --- a/tabfern/src/view/item_tree.js +++ b/tabfern/src/view/item_tree.js @@ -2,29 +2,29 @@ // Copyright (c) 2017 Chris White, Jasmine Hegman. (function (root, factory) { - let imports=['jquery','jstree','jstree-actions', 'jstree-flagnode', - 'jstree-because', 'loglevel', 'view/const', - 'jstree-multitype', 'jstree-redraw-event' ]; - if (typeof define === 'function' && define.amd) { // AMD - define(imports, factory); + define([ 'jquery','jstree','jstree-actions', 'jstree-flagnode', + 'jstree-because', 'loglevel', 'view/const', + 'jstree-multitype', 'jstree-redraw-event' ], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory( + require('jquery'), require('jstree'), require('jstree-actions'), + require('jstree-flagnode'), require('jstree-because'), + require('loglevel'), require('view/const'), + require('jstree-multitype'), require('jstree-redraw-event') + ); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.tabfern_item_tree = factory(...requirements); + root.T = factory( + root.$, root.$.jstree, root.jstree.plugins.actions, + root.jstree.plugins.flagnode, root.jstree.plugins.because, + root.log, root.K, + root.jstree.plugins.multitype, root.jstree.plugins.redraw_event + ); } -}(this, function ($, _jstree, _actions, _flagnode, _because, log_orig, K, multitype ) { +}(this, function ($, _jstree, _actions, _flagnode, _because, log_orig, K, _multitype, _redraw_event ) { "use strict"; function loginfo(...args) { log_orig.info('TabFern view/item_tree.js: ', ...args); }; diff --git a/tabfern/src/view/main.html b/tabfern/src/view/main.html index 1e1c3e03..99772492 100644 --- a/tabfern/src/view/main.html +++ b/tabfern/src/view/main.html @@ -17,7 +17,7 @@ - + @@ -42,10 +42,6 @@
Dummy content!
- - - - diff --git a/tabfern/src/view/main.js b/tabfern/src/view/main.js index a07404a3..b08b6e67 100755 --- a/tabfern/src/view/main.js +++ b/tabfern/src/view/main.js @@ -1,19 +1,29 @@ // main.js: main script for src/view/index.html. // Part of TabFern. Copyright (c) cxw42, r4j4h, 2017. +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD + define([ 'jquery', 'split', 'loglevel' ],factory); + } else if (typeof exports === 'object') { + // Node, CommonJS-like + module.exports = factory(require('jquery'), require('split'), + require('loglevel')); + } else { + // Browser globals (root is window) + root.Multidex = factory(root.$, root.split, root.log); + } +}(this, main)); + +function main($, split, log) { + /// Modules loaded via requirejs let Modules = {}; -/// HACK - a global for loglevel because typing `Modules.log` everywhere is a pain. -let log; - /// The tree window itself. REMINDER: Don't access window.frames until the /// document is fully loaded (after onload) let W; -/// A variable that tree.html can access via window.parent (`var`, not `let`) -var hello='world'; - ////////////////////////////////////////////////////////////////////////// // PLUGINS // @@ -32,20 +42,21 @@ function testCrossLoad() ////////////////////////////////////////////////////////////////////////// // SPLIT // -let split; +let the_split; function doSplit() { - if(!!split) { - split.collapse(1); // close #plugin-container - split.destroy(); - split = undefined; + if(!!the_split) { // Close the split + the_split.collapse(1); // close #plugin-container + the_split.destroy(); + the_split = undefined; //$('#tabfern-container').css('padding-top','0'); - } else { + + } else { // Open the split let tree=$('#tree-container'); let plugin=$('#plugin-container'); - split = Modules['split']( + the_split = split( [tree[0], plugin[0]], { direction: 'vertical', } @@ -65,29 +76,18 @@ function initMain() // Thanks to https://stackoverflow.com/a/13913943/2877364 by // https://stackoverflow.com/users/1105384/shank document.title = `${_T('wsShortName')} (v${TABFERN_VERSION})`; + + window.doSplit = doSplit; // export doSplit so tree.js can call it } //initMain ////////////////////////////////////////////////////////////////////////// // MAIN // -/// require.js modules used by this file -let dependencies = [ - 'jquery', 'split', 'loglevel' -]; - -function main(...args) -{ - // Hack: Copy the loaded modules into our Modules global - for(let depidx = 0; depidx < args.length; ++depidx) { - Modules[dependencies[depidx]] = args[depidx]; - } - - log = Modules.loglevel; - log.setDefaultLevel(log.levels.DEBUG); // TODO set to WARN for production +log.setDefaultLevel(log.levels.WARN); +callbackOnLoad(initMain); - callbackOnLoad(initMain); -} // main() +return {}; // main doesn't provide access to any functions currently -require(dependencies, main); +} //main // vi: set ts=4 sts=4 sw=4 et ai fo-=o fo-=r: // diff --git a/tabfern/src/view/model.js b/tabfern/src/view/model.js index b512556d..70d5da55 100755 --- a/tabfern/src/view/model.js +++ b/tabfern/src/view/model.js @@ -17,27 +17,25 @@ // Boilerplate {{{1 (function (root, factory) { - let imports=['jquery','jstree','loglevel', 'view/const', - 'view/item_details', 'view/item_tree', 'justhtmlescape', - 'buffer', 'blake2s']; - if (typeof define === 'function' && define.amd) { // AMD - define(imports, factory); + define(['jquery','jstree','loglevel', 'view/const', + 'view/item_details', 'view/item_tree', 'justhtmlescape', + 'buffer', 'blake2s'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory( + require('jquery'), require('jstree'), require('loglevel'), + require('view/const'), require('view/item_details'), + require('view/item_tree'), require('justhtmlescape'), + require('buffer'), require('blake2s') + ); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.tabfern_item = factory(...requirements); + root.M = factory( + root.$, root.$.jstree, root.log, root.K, + root.D, root.T, root.JustHTMLEscape, root.Buffer, root.BLAKE2s + ); } }(this, function ($, _unused_jstree_placeholder_, log, K, D, T, Esc, Buffer, BLAKE2s) { diff --git a/tabfern/src/view/sorts.js b/tabfern/src/view/sorts.js index f25890fc..346cee02 100755 --- a/tabfern/src/view/sorts.js +++ b/tabfern/src/view/sorts.js @@ -2,26 +2,23 @@ // Copyright (c) 2017 Chris White, Jasmine Hegman. (function (root, factory) { - let imports=['jquery','jstree','loglevel', 'view/const', 'view/item_tree', - 'view/item_details']; - if (typeof define === 'function' && define.amd) { // AMD - define(imports, factory); + define(['jquery', 'jstree','loglevel', 'view/const', 'view/item_tree', + 'view/item_details'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory( + require('jquery'), require('jstree'), require('loglevel'), + require('view/const'), require('view/item_tree'), + require('view/item_details'), + ); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.tabfern_sorts = factory(...requirements); + root.sorts = factory( + root.$, root.$.jstree, root.log, + root.K, root.T, root.D + ); } }(this, function ($, _unused_jstree_placeholder_, log_orig, K, T, D ) { "use strict"; diff --git a/tabfern/src/view/template.js b/tabfern/src/view/template.js index 7ad19a69..886f1ece 100755 --- a/tabfern/src/view/template.js +++ b/tabfern/src/view/template.js @@ -1,3 +1,5 @@ +// Template for less-repetitive UMD module using spread operator. +// Not sure if all the tooling can handle it, though. // TODO.js: // Copyright (c) 2017 Chris White, Jasmine Hegman. diff --git a/tabfern/src/view/tree.html b/tabfern/src/view/tree.html index 2961c124..54824ae2 100644 --- a/tabfern/src/view/tree.html +++ b/tabfern/src/view/tree.html @@ -1,8 +1,7 @@ - + TabFern tree @@ -94,6 +93,7 @@ + diff --git a/tabfern/src/view/tree.js b/tabfern/src/view/tree.js index 21659db7..e5c314e8 100755 --- a/tabfern/src/view/tree.js +++ b/tabfern/src/view/tree.js @@ -2,7 +2,9 @@ // Copyright (c) cxw42, 2017--2018 // See /doc/design.md for information about notation and organization. -// TODO break more of this into separate modules +// This is not a module. That is so that its internals are available for +// console inspection and debugging. That may change in the future. +// TODO break more of this into separate modules. console.log(`============================================================= Loading TabFern ${TABFERN_VERSION}`); @@ -4188,6 +4190,8 @@ function initIncompleteWarning() //////////////////////////////////////////////////////////////////////// }}}1 // MAIN // {{{1 +/// The main function. Called once RequireJS has loaded all the +/// dependencies. function main(...args) { // Hack: Copy the loaded modules into our Modules global From b36d55f1074c13269dba5e34b337caab64117d49 Mon Sep 17 00:00:00 2001 From: Chris White Date: Mon, 3 Sep 2018 13:39:08 -0400 Subject: [PATCH 03/17] First version of URL-substitution (#132) Still needs flags and some thought re. escaping. However, basic functionality is present. --- tabfern/_locales/en/messages.json | 16 ++++++ tabfern/assets/css/icons.css | 13 +++-- tabfern/assets/icons/arrow_switch.png | Bin 0 -> 683 bytes tabfern/src/view/model.js | 2 +- tabfern/src/view/tree.js | 78 ++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 tabfern/assets/icons/arrow_switch.png diff --git a/tabfern/_locales/en/messages.json b/tabfern/_locales/en/messages.json index fc30c4a2..442f926c 100755 --- a/tabfern/_locales/en/messages.json +++ b/tabfern/_locales/en/messages.json @@ -84,6 +84,14 @@ } } } + , "dlgpTextToReplace": { + "message": "Text to replace? (/.../ for regex)" + ,"description":"Prompt for the user to enter text to replace" + } + , "dlgpReplacementText": { + "message": "Replacement text?" + ,"description":"Prompt for the user to enter text to replace" + } , "dlgYesHTML": { "message": "Yes" @@ -243,6 +251,14 @@ "message": "Delete" ,"description":"The context-menu item to delete a window or tab's tree item" } + , "menuURLSubstitute": { + "message": "Replace in URLs" + ,"description":"The context-menu item to make a replacement in the URL of each tab in the window" + } + , "menuttURLSubstitute": { + "message": "Make a text replacement in all of the URLs in this window" + ,"description":"The context-menu tooltip for menuURLSubstitute" + } , "error_text": { "message": "--------------------------------------------" ,"description": "Text for error messages" } diff --git a/tabfern/assets/css/icons.css b/tabfern/assets/css/icons.css index 6c54a6aa..7331aa75 100755 --- a/tabfern/assets/css/icons.css +++ b/tabfern/assets/css/icons.css @@ -60,6 +60,10 @@ background-image: url("/assets/icons/text_padding_top.png"); } +.jstree-themeicon-custom.arrow-switch, .vakata-context .arrow-switch { + background-image: url("/assets/icons/arrow_switch.png"); +} + /* Class for icons with no content. Used in jstree.set_icon() when the * icon is actually being set using CSS. */ @@ -91,12 +95,9 @@ content: url("/assets/icons/cross.png"); } -/* Background sizes in context menu are different. TODO fix this --- it is - * an ugly hack. */ -.vakata-context .fff-pencil, -.vakata-context .fff-cross, -.vakata-context .fff-picture-delete, -.vakata-context .fff-text-padding-top { +/* Background sizes of icons in context menu are different. Note: Need the + * `li a` to make it specific enough. */ +.vakata-context li a i { background-repeat: no-repeat; background-position: center center; } diff --git a/tabfern/assets/icons/arrow_switch.png b/tabfern/assets/icons/arrow_switch.png new file mode 100644 index 0000000000000000000000000000000000000000..258c16c63a20f7474764507475af7961ecf4263a GIT binary patch literal 683 zcmV;c0#yBpP)A3WJ2dfsV78ToP)wU4~UJxT^#Yl8pW;T)B2y+W_BqqmW z&#t|w0SE!KR$a#7aL!?!V{G>0(f7&GF0n$i_yAiovkXpE$M|c8KDe}2*w(W8jK3Y2*x)V03j=u2XF48q6F<0_UD&z zFmi~T?K=p$491faq~>RsPR$VB89_xzOpK2V+=|x$1lD3~x!;g2Mz5ELE831k>xd528II@{FM*4t5cwMI2$KMmfFm;RN43xW+e;$tzEyd|PV<@i4gUfKh|U-I$hymfQ} zt?kWDj37pE;wZ>1WHG%+SvbnRqEaTN#u*-slSm{u7_C6WGBh|el4$>24G=QE;Y9f< z)G2BOvC3T5Jn;{4ig%R|E{ITA5W$|ds8uW$Z^f(HeLnnp>dACn(D>^wEGjH6Et2~F zjpx1H%%|rOCx{iqDPk27MT{DNK*OCgPK;oDLHt!jVx&(zZS&Lq>Ld9Y&Ck!LvbvJw zmn1{|Z(}o^vo(KE_?L 1 && old_text[0]==='/' && + old_text[old_text.length-1]==='/') { // Regex + findregex = new RegExp(old_text.slice(1, -1)); // drop the slashes + // TODO support flags as well + } else { // Literal + findregex = new RegExp(escapeRegExp(old_text)); + } + + for(let tab_node_id of node.children) { + let tab_val = D.tabs.by_node_id(tab_node_id); + if(!tab_val || !tab_val.tab_id) continue; + let new_url = tab_val.raw_url.replace(findregex, new_text); + // TODO URL escaping? + if(new_url === tab_val.raw_url) continue; + + if(win_val.isOpen) { + // Make the change and let tabOnUpdated update the model. + ASQH.NowCC((cc)=>{ // ASQ for error reporting + chrome.tabs.update(tab_val.tab_id, {url: new_url}, cc); + }); + } else { + tab_val.raw_url = new_url; + M.refresh_label(tab_val); // do what tabOnUpdated() would + M.refresh_icon(tab_val); + M.refresh_tooltip(tab_val); + } + } // foreach child + + // If the window is closed, update the hash. Otherwise, tabOnUpdated() + // handled it. + if(!win_val.isOpen) { + M.updateOrderedURLHash(win_val); + } +} //actionURLSubstitute + ////////////////////////////////////////////////////////////////////////// }}}1 // jstree-action callbacks // {{{1 @@ -2373,6 +2437,11 @@ function tabOnUpdated(tabid, changeinfo, ctab) // Caution: changeinfo doesn't always have all the changed information. // Therefore, we check changeinfo and ctab. + // TODO refactor the following into a separate routine that can be + // used to update closed or open tabs' tree items. Maybe move it + // to model.js as well. This will reduce code duplication, e.g., in + // actionURLSubstitute. + // URL let new_raw_url = changeinfo.url || ctab.url || 'about:blank'; if(new_raw_url !== tab_node_val.raw_url) { @@ -3099,6 +3168,15 @@ function getMainContextMenuItems(node, _unused_proxyfunc, e) function(){actionDeleteWindow(node.id, node, null, null);} }; + winItems.urlSubstituteItem = { + label: _T('menuURLSubstitute'), + title: _T('menuttURLSubstitute'), + icon: 'arrow-switch', + separator_before: true, + action: + function(){actionURLSubstitute(node.id, node, null, null);} + }; + return winItems; } //endif K.IT_WIN From 8799c605f9cdb8c2641addd675ce691defe1413a Mon Sep 17 00:00:00 2001 From: Chris White Date: Thu, 6 Sep 2018 13:31:06 -0400 Subject: [PATCH 04/17] i18n of background.js extension-menu item (#135) --- tabfern/_locales/de/messages.json | 4 ++++ tabfern/_locales/en/messages.json | 4 ++++ tabfern/src/bg/background.js | 10 +--------- tabfern/src/view/tree.js | 1 + 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tabfern/_locales/de/messages.json b/tabfern/_locales/de/messages.json index 8609f660..88f4146a 100755 --- a/tabfern/_locales/de/messages.json +++ b/tabfern/_locales/de/messages.json @@ -214,6 +214,10 @@ "message": "Notiz hinzufügen oder bearbeiten" ,"description":"The context-menu item to add or edit a tab's note" } + , "menuAddEditNoteThisTab": { + "message": "Notiz für den aktuellen Tab hinzufügen oder bearbeiten" + ,"description":"The extension-menu item to add or edit the current tab's note" + } , "menuRename": { "message": "Umbenennen" ,"description":"The context-menu item to rename a window's tree entry" diff --git a/tabfern/_locales/en/messages.json b/tabfern/_locales/en/messages.json index 442f926c..c713dc7b 100755 --- a/tabfern/_locales/en/messages.json +++ b/tabfern/_locales/en/messages.json @@ -223,6 +223,10 @@ "message": "Add/edit a note" ,"description":"The context-menu item to add or edit a tab's note" } + , "menuAddEditNoteThisTab": { + "message": "Add/edit a note for the current tab" + ,"description":"The extension-menu item to add or edit the current tab's note" + } , "menuRename": { "message": "Rename" ,"description":"The context-menu item to rename a window's tree entry" diff --git a/tabfern/src/bg/background.js b/tabfern/src/bg/background.js index 1ef6e284..4f8d482c 100755 --- a/tabfern/src/bg/background.js +++ b/tabfern/src/bg/background.js @@ -133,7 +133,7 @@ function editNoteOnClick(info, tab) } //editNoteOnClick chrome.contextMenus.create({ - id: 'editNote', title: 'Add/edit a note for the current tab', + id: 'editNote', title: _T('menuAddEditNoteThisTab'), contexts: ['browser_action'], onclick: editNoteOnClick }); @@ -166,14 +166,6 @@ chrome.runtime.onMessage.addListener(messageListener); // 'sample_setting': 'This is how you use Store.js to remember values' //}); - -////example of using a message handler from the inject scripts -//chrome.extension.onMessage.addListener( -// function(request, sender, sendResponse) { -// chrome.pageAction.show(sender.tab.id); -// sendResponse(); -// }); - ////////////////////////////////////////////////////////////////////////// // MAIN // diff --git a/tabfern/src/view/tree.js b/tabfern/src/view/tree.js index 04f32f2e..9ed6d6a8 100755 --- a/tabfern/src/view/tree.js +++ b/tabfern/src/view/tree.js @@ -636,6 +636,7 @@ function actionURLSubstitute(node_id, node, unused_action_id, unused_action_el) if(!tab_val || !tab_val.tab_id) continue; let new_url = tab_val.raw_url.replace(findregex, new_text); // TODO URL escaping? + // TODO also replace in favicon URL? if(new_url === tab_val.raw_url) continue; if(win_val.isOpen) { From 17fc4527a450676eafe51bc1288877c3624d40bd Mon Sep 17 00:00:00 2001 From: Chris White Date: Thu, 6 Sep 2018 18:15:36 -0400 Subject: [PATCH 05/17] Remove unused management.js and rjs async plugin The RequireJS async plugin is not currently used. Plus, removing it keeps us closer to the node model and therefore gives us more flexibility to use build tools later. --- tabfern/conf/require-config.js | 4 --- tabfern/js/async.js | 46 --------------------------- tabfern/js/management.js | 57 ---------------------------------- 3 files changed, 107 deletions(-) delete mode 100644 tabfern/js/async.js delete mode 100755 tabfern/js/management.js diff --git a/tabfern/conf/require-config.js b/tabfern/conf/require-config.js index a042a965..105623c9 100755 --- a/tabfern/conf/require-config.js +++ b/tabfern/conf/require-config.js @@ -50,10 +50,6 @@ var require = { exports: 'BLAKE2s' } }, - async: { - useHash: true // #callback=x rather than ?callback=x since Chrome - // won't load files with ? - }, }; // vi: set ts=4 sts=4 sw=4 et ai fo-=o fo-=r: // diff --git a/tabfern/js/async.js b/tabfern/js/async.js deleted file mode 100644 index 4786c106..00000000 --- a/tabfern/js/async.js +++ /dev/null @@ -1,46 +0,0 @@ -/** @license - * RequireJS plugin for async dependency load like JSONP and Google Maps - * Author: Miller Medeiros - * Version: 0.1.2 (2014/02/24) - * Released under the MIT license - */ -define(function(){ - - var DEFAULT_PARAM_NAME = 'callback', - _uid = 0; - - function injectScript(src){ - var s, t; - s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = src; - t = document.getElementsByTagName('script')[0]; t.parentNode.insertBefore(s,t); - } - - function formatUrl(name, id, useHash){ - var separ = (useHash ? '#' : '?'), - paramRegex = /!(.+)/, - url = name.replace(paramRegex, ''), - param = (paramRegex.test(name)) ? name.replace(/.+!/, '') : DEFAULT_PARAM_NAME; - url += (url.indexOf(separ) < 0) ? separ : '&'; - return url + param +'='+ id; - } - - function uid() { - _uid += 1; - return '__async_req_'+ _uid +'__'; - } - - return{ - load : function(name, req, onLoad, config){ - if(config.isBuild){ - onLoad(null); //avoid errors on the optimizer - }else{ - var id = uid(); - //create a global variable that stores onLoad so callback - //function can define new module after async load - window[id] = onLoad; - injectScript(formatUrl(req.toUrl(name), id, config.async.useHash)); - } - } - }; -}); -// vi: set ts=4 sts=4 sw=4 et ai fo-=o fo-=r: // diff --git a/tabfern/js/management.js b/tabfern/js/management.js deleted file mode 100755 index cafdd8e9..00000000 --- a/tabfern/js/management.js +++ /dev/null @@ -1,57 +0,0 @@ -// management.js: Test of a management module. -// Copyright (c) Chris White 2017. CC-BY-SA 4.0 International. -// Load this using the async plugin, -// https://github.com/millermedeiros/requirejs-plugins/blob/master/src/async.js - -// Code to check development status thanks to -// https://stackoverflow.com/a/12833511/2877364 by -// https://stackoverflow.com/users/1143495/konrad-dzwinel and -// https://stackoverflow.com/users/934239/xan - -(function(root){ - - /// The completion callback - call when the module is fully loaded - let callback; - - /// Our worker function - function with_info(info) - { - let obj = info; - obj.isDevelMode = (info.installType === 'development'); - console.log({'Got info': obj}); - callback(obj); //complete module loading - } //with_info - - // Stash the onload callback for later, when we are done loading - // Thanks to https://stackoverflow.com/a/22745553/2877364 by - // https://stackoverflow.com/users/140264/brice for - // info about document.currentScript. - if(!document.currentScript) - throw new Error("Can't load --- I don't know what script I'm in"); - - // VVV code from here to "^^^" is also available as CC-BY 4.0 International - - let script_url = document.currentScript.src; - - let url = new URL(script_url); - let searchParams = new URLSearchParams(url.hash.slice(1)); - // Using the hash, not the query string, because Chrome won't load - // chrome-extension resources with query strings. - - if(searchParams.has('callback')) { - let cbk_name = searchParams.get('callback'); - callback = root[cbk_name]; - if(!callback) throw new Error( - `Can't load --- I can't find the ${cbk_name} callback`); - - } else { - throw new Error("Can't load --- I can't find a #callback=... param"); - } - - // ^^^ - - // Fire off the loading - chrome.management.getSelf(with_info); - -})(this); -// vi: set ts=4 sts=4 sw=4 et ai fo-=o: // From e3dc4d06670cb316648ab0888941f6070a57bf55 Mon Sep 17 00:00:00 2001 From: Chris White Date: Thu, 6 Sep 2018 18:25:30 -0400 Subject: [PATCH 06/17] Remove a minor race condition in is_devel_mode --- tabfern/src/view/tree.js | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/tabfern/src/view/tree.js b/tabfern/src/view/tree.js index 9ed6d6a8..016ce010 100755 --- a/tabfern/src/view/tree.js +++ b/tabfern/src/view/tree.js @@ -183,15 +183,6 @@ function local_init() M = Modules['view/model']; ASQ = Modules['asynquence-contrib']; ASQH = Modules['asq-helpers']; - - // Check development status. Thanks to - // https://stackoverflow.com/a/12833511/2877364 by - // https://stackoverflow.com/users/1143495/konrad-dzwinel and - // https://stackoverflow.com/users/934239/xan - chrome.management.getSelf(function(info){ - if(info.installType === 'development') is_devel_mode = true; - }); - } //init() /// Copy properties named #property_names from #source to #dest. @@ -3935,7 +3926,22 @@ function preLoadInit() } //preLoadInit -/// Beginning of the onload initialization. +// Beginning of the onload initialization. + +/// Check development status in an ASQ step. Thanks to +/// https://stackoverflow.com/a/12833511/2877364 by +/// https://stackoverflow.com/users/1143495/konrad-dzwinel and +/// https://stackoverflow.com/users/934239/xan +function determine_devel_mode(done) +{ + ASQH.NowCC((cc)=>{ chrome.management.getSelf(cc); }) + .val((info)=>{ + is_devel_mode = (info.installType === 'development'); + }) + .pipe(done); +} //determine_devel_mode() + +/// Initialization we can do before we have our window ID function basicInit(done) { next_init_step('basic initialization'); @@ -4302,11 +4308,12 @@ function main(...args) // Run the main init steps once the page has loaded let s = ASQ(); - callbackOnLoad(s.errfcb()); + callbackOnLoad(s.errfcb()); // Just using errfcb() to kick off s. // Note: on one test on Firefox, the rest of the chain never fired. // Not sure why. - s.then(basicInit) + s.then(determine_devel_mode) + .then(basicInit) .try((done)=>{ // Get our Chrome-extensions-API window ID from the background page. From 0f52cda25c4a06f22fdf499ec24b5feb05c8b368 Mon Sep 17 00:00:00 2001 From: Chris White Date: Thu, 6 Sep 2018 18:38:30 -0400 Subject: [PATCH 07/17] Added spinner during the popup load sequence --- tabfern/src/view/tree.html | 1 + tabfern/src/view/tree.js | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tabfern/src/view/tree.html b/tabfern/src/view/tree.html index 54824ae2..ccf33662 100644 --- a/tabfern/src/view/tree.html +++ b/tabfern/src/view/tree.html @@ -13,6 +13,7 @@ + diff --git a/tabfern/src/view/tree.js b/tabfern/src/view/tree.js index 016ce010..0a6df1bd 100755 --- a/tabfern/src/view/tree.js +++ b/tabfern/src/view/tree.js @@ -49,7 +49,7 @@ let Module_dependencies = [ 'loglevel', 'hamburger', 'bypasser', 'multidex', 'justhtmlescape', 'signals', 'export-file', 'import-file', 'asynquence-contrib', 'asq-helpers', 'rmodal', - 'tinycolor', + 'tinycolor', 'spin-packed', // Shimmed modules. Refer to these via Modules or *without* the // `window.` prefix so it will be easier to refactor references @@ -4312,9 +4312,19 @@ function main(...args) // Note: on one test on Firefox, the rest of the chain never fired. // Not sure why. + // Start a spinner if loading takes more than 1 s + let spinner = new Spinner(); + let spin_starter = function() { + if(spinner) spinner.spin($('#tabfern-container')[0]); + }; + //let spin_timer = window.setTimeout(spin_starter, 1000); + s.then(determine_devel_mode) .then(basicInit) + .val(spin_starter) + // for now, always start --- loadSavedWindowsIntoTree is synchronous + .try((done)=>{ // Get our Chrome-extensions-API window ID from the background page. // I don't know a way to get this directly from the JS window object. @@ -4342,6 +4352,13 @@ function main(...args) .val(check_init_step_count) + // Stop the spinner, if it started + .val(()=>{ + spinner.stop(); + spinner = null; + //clearTimeout(spin_timer); + }) + .or((err)=>{ $(K.INIT_MSG_SEL).text( $(K.INIT_MSG_SEL).text() + "\n" + err From a2deaf29f42611507f24d9f6ad6ab39191e4be86 Mon Sep 17 00:00:00 2001 From: Chris White Date: Fri, 7 Sep 2018 09:56:31 -0400 Subject: [PATCH 08/17] Clean up settings code - UMDify, remove old i18n - manifest, lib/store are now UMD modules - consolidated CSS into css/ - removed references to `i18n.get` - removed fancy-settings i18n routines --- tabfern/src/settings/{ => css}/custom.css | 0 tabfern/src/settings/{lib => css}/default.css | 0 tabfern/src/settings/i18n.js | 71 ------ tabfern/src/settings/index.html | 21 +- .../src/settings/js/classes/fancy-settings.js | 15 +- tabfern/src/settings/js/classes/search.js | 4 +- tabfern/src/settings/js/i18n.js | 27 --- tabfern/src/settings/lib/store.js | 48 ++-- tabfern/src/settings/main.js | 4 +- tabfern/src/settings/manifest.js | 220 ++++++++++-------- 10 files changed, 174 insertions(+), 236 deletions(-) rename tabfern/src/settings/{ => css}/custom.css (100%) rename tabfern/src/settings/{lib => css}/default.css (100%) delete mode 100755 tabfern/src/settings/i18n.js delete mode 100755 tabfern/src/settings/js/i18n.js diff --git a/tabfern/src/settings/custom.css b/tabfern/src/settings/css/custom.css similarity index 100% rename from tabfern/src/settings/custom.css rename to tabfern/src/settings/css/custom.css diff --git a/tabfern/src/settings/lib/default.css b/tabfern/src/settings/css/default.css similarity index 100% rename from tabfern/src/settings/lib/default.css rename to tabfern/src/settings/css/default.css diff --git a/tabfern/src/settings/i18n.js b/tabfern/src/settings/i18n.js deleted file mode 100755 index 13d7ebbc..00000000 --- a/tabfern/src/settings/i18n.js +++ /dev/null @@ -1,71 +0,0 @@ -// SAMPLE -this.i18n = { - "settings": { - "en": "Settings", - "de": "Optionen" - }, - "search": { - "en": "Search", - "de": "Suche" - }, - "nothing-found": { - "en": "No matches were found.", - "de": "Keine Übereinstimmungen gefunden." - }, - - - - "information": { - "en": "Information", - "de": "Information" - }, - "login": { - "en": "Login", - "de": "Anmeldung" - }, - "username": { - "en": "Username:", - "de": "Benutzername:" - }, - "password": { - "en": "Password:", - "de": "Passwort:" - }, - "x-characters": { - "en": "6 - 12 characters", - "de": "6 - 12 Zeichen" - }, - "x-characters-pw": { - "en": "10 - 18 characters", - "de": "10 - 18 Zeichen" - }, - "description": { - "en": "This is a description. You can write any text inside of this.
\ - Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut\ - labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores\ - et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem\ - ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et\ - dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.\ - Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.", - - "de": "Das ist eine Beschreibung. Du kannst hier beliebigen Text einfügen.
\ - Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut\ - labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores\ - et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem\ - ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et\ - dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.\ - Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." - }, - "logout": { - "en": "Logout", - "de": "Abmeldung" - }, - "enable": { - "en": "Enable", - "de": "Aktivieren" - }, - "disconnect": { - "en": "Disconnect:", - "de": "Trennen:" - } -}; diff --git a/tabfern/src/settings/index.html b/tabfern/src/settings/index.html index 78796d2b..1d0a84f4 100755 --- a/tabfern/src/settings/index.html +++ b/tabfern/src/settings/index.html @@ -12,10 +12,10 @@ - + - + @@ -30,23 +30,22 @@ - + + + + + + + - - - - - - - - + - - - - diff --git a/webstore/src/view/main.js b/webstore/src/view/main.js index a07404a3..b08b6e67 100755 --- a/webstore/src/view/main.js +++ b/webstore/src/view/main.js @@ -1,19 +1,29 @@ // main.js: main script for src/view/index.html. // Part of TabFern. Copyright (c) cxw42, r4j4h, 2017. +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD + define([ 'jquery', 'split', 'loglevel' ],factory); + } else if (typeof exports === 'object') { + // Node, CommonJS-like + module.exports = factory(require('jquery'), require('split'), + require('loglevel')); + } else { + // Browser globals (root is window) + root.Multidex = factory(root.$, root.split, root.log); + } +}(this, main)); + +function main($, split, log) { + /// Modules loaded via requirejs let Modules = {}; -/// HACK - a global for loglevel because typing `Modules.log` everywhere is a pain. -let log; - /// The tree window itself. REMINDER: Don't access window.frames until the /// document is fully loaded (after onload) let W; -/// A variable that tree.html can access via window.parent (`var`, not `let`) -var hello='world'; - ////////////////////////////////////////////////////////////////////////// // PLUGINS // @@ -32,20 +42,21 @@ function testCrossLoad() ////////////////////////////////////////////////////////////////////////// // SPLIT // -let split; +let the_split; function doSplit() { - if(!!split) { - split.collapse(1); // close #plugin-container - split.destroy(); - split = undefined; + if(!!the_split) { // Close the split + the_split.collapse(1); // close #plugin-container + the_split.destroy(); + the_split = undefined; //$('#tabfern-container').css('padding-top','0'); - } else { + + } else { // Open the split let tree=$('#tree-container'); let plugin=$('#plugin-container'); - split = Modules['split']( + the_split = split( [tree[0], plugin[0]], { direction: 'vertical', } @@ -65,29 +76,18 @@ function initMain() // Thanks to https://stackoverflow.com/a/13913943/2877364 by // https://stackoverflow.com/users/1105384/shank document.title = `${_T('wsShortName')} (v${TABFERN_VERSION})`; + + window.doSplit = doSplit; // export doSplit so tree.js can call it } //initMain ////////////////////////////////////////////////////////////////////////// // MAIN // -/// require.js modules used by this file -let dependencies = [ - 'jquery', 'split', 'loglevel' -]; - -function main(...args) -{ - // Hack: Copy the loaded modules into our Modules global - for(let depidx = 0; depidx < args.length; ++depidx) { - Modules[dependencies[depidx]] = args[depidx]; - } - - log = Modules.loglevel; - log.setDefaultLevel(log.levels.DEBUG); // TODO set to WARN for production +log.setDefaultLevel(log.levels.WARN); +callbackOnLoad(initMain); - callbackOnLoad(initMain); -} // main() +return {}; // main doesn't provide access to any functions currently -require(dependencies, main); +} //main // vi: set ts=4 sts=4 sw=4 et ai fo-=o fo-=r: // diff --git a/webstore/src/view/model.js b/webstore/src/view/model.js index b512556d..dd14ca88 100755 --- a/webstore/src/view/model.js +++ b/webstore/src/view/model.js @@ -17,27 +17,25 @@ // Boilerplate {{{1 (function (root, factory) { - let imports=['jquery','jstree','loglevel', 'view/const', - 'view/item_details', 'view/item_tree', 'justhtmlescape', - 'buffer', 'blake2s']; - if (typeof define === 'function' && define.amd) { // AMD - define(imports, factory); + define(['jquery','jstree','loglevel', 'view/const', + 'view/item_details', 'view/item_tree', 'justhtmlescape', + 'buffer', 'blake2s'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory( + require('jquery'), require('jstree'), require('loglevel'), + require('view/const'), require('view/item_details'), + require('view/item_tree'), require('justhtmlescape'), + require('buffer'), require('blake2s') + ); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.tabfern_item = factory(...requirements); + root.M = factory( + root.$, root.$.jstree, root.log, root.K, + root.D, root.T, root.JustHTMLEscape, root.Buffer, root.BLAKE2s + ); } }(this, function ($, _unused_jstree_placeholder_, log, K, D, T, Esc, Buffer, BLAKE2s) { @@ -147,7 +145,7 @@ } else if(val.ty === K.IT_WIN) { // def. title for ephem. win. return _T('labelUnsaved'); } else { // e.g., tabs with no raw_title. - // TODO see if this makes sense. + // TODO see if this makes sense. Maybe show the URL instead? return "** no title **"; } }; //get_raw_text() diff --git a/webstore/src/view/sorts.js b/webstore/src/view/sorts.js index f25890fc..346cee02 100755 --- a/webstore/src/view/sorts.js +++ b/webstore/src/view/sorts.js @@ -2,26 +2,23 @@ // Copyright (c) 2017 Chris White, Jasmine Hegman. (function (root, factory) { - let imports=['jquery','jstree','loglevel', 'view/const', 'view/item_tree', - 'view/item_details']; - if (typeof define === 'function' && define.amd) { // AMD - define(imports, factory); + define(['jquery', 'jstree','loglevel', 'view/const', 'view/item_tree', + 'view/item_details'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like - let requirements = []; - for(let modulename of imports) { - requirements.push(require(modulename)); - } - module.exports = factory(...requirements); + module.exports = factory( + require('jquery'), require('jstree'), require('loglevel'), + require('view/const'), require('view/item_tree'), + require('view/item_details'), + ); } else { // Browser globals (root is `window`) - let requirements = []; - for(let modulename of imports) { - requirements.push(root[modulename]); - } - root.tabfern_sorts = factory(...requirements); + root.sorts = factory( + root.$, root.$.jstree, root.log, + root.K, root.T, root.D + ); } }(this, function ($, _unused_jstree_placeholder_, log_orig, K, T, D ) { "use strict"; diff --git a/webstore/src/view/template.js b/webstore/src/view/template.js index 7ad19a69..886f1ece 100755 --- a/webstore/src/view/template.js +++ b/webstore/src/view/template.js @@ -1,3 +1,5 @@ +// Template for less-repetitive UMD module using spread operator. +// Not sure if all the tooling can handle it, though. // TODO.js: // Copyright (c) 2017 Chris White, Jasmine Hegman. diff --git a/webstore/src/view/tree.html b/webstore/src/view/tree.html index 2961c124..ccf33662 100644 --- a/webstore/src/view/tree.html +++ b/webstore/src/view/tree.html @@ -1,8 +1,7 @@ - + TabFern tree @@ -14,6 +13,7 @@ + @@ -94,6 +94,7 @@ + diff --git a/webstore/src/view/tree.js b/webstore/src/view/tree.js index 21659db7..dae5eb0f 100755 --- a/webstore/src/view/tree.js +++ b/webstore/src/view/tree.js @@ -2,7 +2,9 @@ // Copyright (c) cxw42, 2017--2018 // See /doc/design.md for information about notation and organization. -// TODO break more of this into separate modules +// This is not a module. That is so that its internals are available for +// console inspection and debugging. That may change in the future. +// TODO break more of this into separate modules. console.log(`============================================================= Loading TabFern ${TABFERN_VERSION}`); @@ -47,7 +49,7 @@ let Module_dependencies = [ 'loglevel', 'hamburger', 'bypasser', 'multidex', 'justhtmlescape', 'signals', 'export-file', 'import-file', 'asynquence-contrib', 'asq-helpers', 'rmodal', - 'tinycolor', + 'tinycolor', 'spin-packed', // Shimmed modules. Refer to these via Modules or *without* the // `window.` prefix so it will be easier to refactor references @@ -181,15 +183,6 @@ function local_init() M = Modules['view/model']; ASQ = Modules['asynquence-contrib']; ASQH = Modules['asq-helpers']; - - // Check development status. Thanks to - // https://stackoverflow.com/a/12833511/2877364 by - // https://stackoverflow.com/users/1143495/konrad-dzwinel and - // https://stackoverflow.com/users/934239/xan - chrome.management.getSelf(function(info){ - if(info.installType === 'development') is_devel_mode = true; - }); - } //init() /// Copy properties named #property_names from #source to #dest. @@ -207,6 +200,12 @@ function copyTruthyProperties(dest, source, property_names, modifier) return dest; } //copyTruthyProperties +/// Escape text for use in a regex. By Mozilla Contributors (CC-BY-SA 2.5+), from +/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} //escapeRegExp + ////////////////////////////////////////////////////////////////////////// }}}1 // DOM Manipulation // {{{1 @@ -424,6 +423,7 @@ function showConfirmationModalDialog(message_html) { afterOpen: function() { $('#confirm-dialog .btn-primary').focus(); + // Note: focus is set but not visible in Chrome 69 - #142 //console.log('opened'); }, @@ -513,7 +513,7 @@ function saveTree(save_ephemeral_windows = true, cbk = undefined) // Get the raw data for the whole tree. Can't use $(...) because closed // tree nodes aren't in the DOM. - let root_node = T.treeobj.get_node($.jstree.root); //from get_json() src + let root_node = T.root_node(); if(!root_node || !root_node.children) { if(typeof cbk === 'function') cbk(new Error("Can't get root node")); return; @@ -592,6 +592,65 @@ function saveTree(save_ephemeral_windows = true, cbk = undefined) ); //storage.local.set } //saveTree() +////////////////////////////////////////////////////////////////////////// }}}1 +// Other actions // {{{1 + +/// Make a string replacement on the URLs of all the tabs in a window +/// @param node_id {string} the ID of the window's node +/// @param node {Object} the window's node +function actionURLSubstitute(node_id, node, unused_action_id, unused_action_el) +{ + let win_val = D.windows.by_node_id(node_id); + if(!win_val) return; + + // TODO replace window.prompt with an in-DOM GUI. + let old_text = window.prompt(_T('dlgpTextToReplace')); + if(old_text === null) return; // user cancelled + + let new_text = window.prompt(_T('dlgpReplacementText')); + if(new_text === null) return; // user cancelled + + if(!old_text) return; // search pattern is required + + // TODO URL escaping of new_text? + + let findregex; + if(old_text.length > 1 && old_text[0]==='/' && + old_text[old_text.length-1]==='/') { // Regex + findregex = new RegExp(old_text.slice(1, -1)); // drop the slashes + // TODO support flags as well + } else { // Literal + findregex = new RegExp(escapeRegExp(old_text)); + } + + for(let tab_node_id of node.children) { + let tab_val = D.tabs.by_node_id(tab_node_id); + if(!tab_val || !tab_val.tab_id) continue; + let new_url = tab_val.raw_url.replace(findregex, new_text); + // TODO URL escaping? + // TODO also replace in favicon URL? + if(new_url === tab_val.raw_url) continue; + + if(win_val.isOpen) { + // Make the change and let tabOnUpdated update the model. + ASQH.NowCC((cc)=>{ // ASQ for error reporting + chrome.tabs.update(tab_val.tab_id, {url: new_url}, cc); + }); + } else { + tab_val.raw_url = new_url; + M.refresh_label(tab_val); // do what tabOnUpdated() would + M.refresh_icon(tab_val); + M.refresh_tooltip(tab_val); + } + } // foreach child + + // If the window is closed, update the hash. Otherwise, tabOnUpdated() + // handled it. + if(!win_val.isOpen) { + M.updateOrderedURLHash(win_val); + } +} //actionURLSubstitute + ////////////////////////////////////////////////////////////////////////// }}}1 // jstree-action callbacks // {{{1 @@ -832,6 +891,14 @@ function actionDeleteWindow(node_id, node, unused_action_id, unused_action_el, } //endif confirmation required } //actionDeleteWindow +/// Move a window to the top of the tree. +function actionMoveWinToTop(node_id, node, unused_action_id, unused_action_el) +{ + if(!node) return; + T.treeobj.move_node(node, T.root_node(), 1); + // 1 => after the holding pen +} //actionMoveWinToTop + /// Toggle the top border on a node. This is a hack until I can add /// dividers. function actionToggleTabTopBorder(node_id, node, unused_action_id, unused_action_el) @@ -1502,11 +1569,32 @@ var loadSavedWindowsFromData = (function(){ // Load it if(vernum in versionLoaders) { - loader_retval = versionLoaders[vernum](data); - } else { + + try { +/* // TEMPORARILY REMOVED + T.treeobj.suppress_redraw(true); // EXPERIMENTAL +*/ + loader_retval = versionLoaders[vernum](data); + + } catch(e) { + log.error( + `Error loading version-${vernum} save data: ${e}`); + loader_retval = false; + // Continue out of the catch block so the + // suppress_redraw(false) will be called. + } + +/* // TEMPORARILY REMOVED + T.treeobj.suppress_redraw(false); // EXPERIMENTAL + T.treeobj.redraw(true); // Just in case the experiment + // had different results than + // we expected! +*/ + + } else { // unknown version log.error("I don't know how to load save data from version " + vernum); break READIT; - } + } //endif known version else if(loader_retval === false) { log.error("There was a problem loading save data of version " + vernum); @@ -2060,8 +2148,8 @@ function initFocusHandler() else if(old_win_id === WINID_NONE) change_from = FC_FROM_NONE; else change_from = FC_FROM_OPEN; - // Uncomment if you are debugging focus-change behaviour - //log.info({change_from, old_win_id, change_to, win_id}); + // Uncomment if you are debugging focus-change behaviour TODO RESUME HERE + log.info({change_from, old_win_id, change_to, win_id}); let same_window = (old_win_id === win_id); previously_focused_winid = win_id; @@ -2371,6 +2459,11 @@ function tabOnUpdated(tabid, changeinfo, ctab) // Caution: changeinfo doesn't always have all the changed information. // Therefore, we check changeinfo and ctab. + // TODO refactor the following into a separate routine that can be + // used to update closed or open tabs' tree items. Maybe move it + // to model.js as well. This will reduce code duplication, e.g., in + // actionURLSubstitute. + // URL let new_raw_url = changeinfo.url || ctab.url || 'about:blank'; if(new_raw_url !== tab_node_val.raw_url) { @@ -2810,7 +2903,7 @@ function hamRestoreLastDeleted() if(typeof wins_loaded === 'number' && wins_loaded > 0) { // We loaded the window successfully. Open it, if the user wishes. if(getBoolSetting(CFG_RESTORE_ON_LAST_DELETED, false)) { - let root = T.treeobj.get_node($.jstree.root); + let root = T.root_node(); let node_id = root.children[root.children.length-1]; T.treeobj.select_node(node_id); } @@ -2833,7 +2926,7 @@ function hamCollapseAll() function hamSorter(compare_fn) { return function() { - let arr = T.treeobj.get_node($.jstree.root).children; + let arr = T.root_node().children; Modules['view/sorts'].stable_sort(arr, compare_fn); // children[] holds node IDs, so compare_fn will always get strings. T.treeobj.redraw(true); // true => full redraw @@ -3043,7 +3136,6 @@ function getMainContextMenuItems(node, _unused_proxyfunc, e) // }; // } - return tabItems; } //endif K.IT_TAB @@ -3089,6 +3181,18 @@ function getMainContextMenuItems(node, _unused_proxyfunc, e) }; } + { // If not the first item, add "Move to top" + let parent_node = T.treeobj.get_node(node.parent); + if(parent_node.children[1] !== node.id) { + // children[1], not [0], because [0] is the holding pen. + winItems.toTopItem = { + label: _T('menuMoveToTop'), + icon: 'fff-text-padding-top', + action: ()=>{actionMoveWinToTop(node.id,node,null,null);}, + }; + } + } + winItems.deleteItem = { label: _T('menuDelete'), icon: 'fff-cross', @@ -3097,6 +3201,17 @@ function getMainContextMenuItems(node, _unused_proxyfunc, e) function(){actionDeleteWindow(node.id, node, null, null);} }; +/* // TEMPORARILY REMOVED + winItems.urlSubstituteItem = { + label: _T('menuURLSubstitute'), + title: _T('menuttURLSubstitute'), + icon: 'arrow-switch', + separator_before: true, + action: + function(){actionURLSubstitute(node.id, node, null, null);} + }; +*/ + return winItems; } //endif K.IT_WIN @@ -3755,7 +3870,7 @@ function delete_all_closed_nodes(are_you_sure) { if(!are_you_sure) return; - let root = T.treeobj.get_node($.jstree.root); + let root = T.root_node(); if(!root) return for(let i=root.children.length-1; i>0; --i) { @@ -3854,7 +3969,22 @@ function preLoadInit() } //preLoadInit -/// Beginning of the onload initialization. +// Beginning of the onload initialization. + +/// Check development status in an ASQ step. Thanks to +/// https://stackoverflow.com/a/12833511/2877364 by +/// https://stackoverflow.com/users/1143495/konrad-dzwinel and +/// https://stackoverflow.com/users/934239/xan +function determine_devel_mode(done) +{ + ASQH.NowCC((cc)=>{ chrome.management.getSelf(cc); }) + .val((info)=>{ + is_devel_mode = (info.installType === 'development'); + }) + .pipe(done); +} //determine_devel_mode() + +/// Initialization we can do before we have our window ID function basicInit(done) { next_init_step('basic initialization'); @@ -4188,6 +4318,8 @@ function initIncompleteWarning() //////////////////////////////////////////////////////////////////////// }}}1 // MAIN // {{{1 +/// The main function. Called once RequireJS has loaded all the +/// dependencies. function main(...args) { // Hack: Copy the loaded modules into our Modules global @@ -4219,11 +4351,22 @@ function main(...args) // Run the main init steps once the page has loaded let s = ASQ(); - callbackOnLoad(s.errfcb()); + callbackOnLoad(s.errfcb()); // Just using errfcb() to kick off s. // Note: on one test on Firefox, the rest of the chain never fired. // Not sure why. - s.then(basicInit) + // Start a spinner if loading takes more than 1 s + let spinner = new Spinner(); + let spin_starter = function() { + if(spinner) spinner.spin($('#tabfern-container')[0]); + }; + //let spin_timer = window.setTimeout(spin_starter, 1000); + + s.then(determine_devel_mode) + .then(basicInit) + + .val(spin_starter) + // for now, always start --- loadSavedWindowsIntoTree is synchronous .try((done)=>{ // Get our Chrome-extensions-API window ID from the background page. @@ -4252,6 +4395,13 @@ function main(...args) .val(check_init_step_count) + // Stop the spinner, if it started + .val(()=>{ + spinner.stop(); + spinner = null; + //clearTimeout(spin_timer); + }) + .or((err)=>{ $(K.INIT_MSG_SEL).text( $(K.INIT_MSG_SEL).text() + "\n" + err From a76295aaf13c2a0758bad39ec5d105a9fd9fbcab Mon Sep 17 00:00:00 2001 From: Chris White Date: Fri, 14 Sep 2018 09:10:59 -0400 Subject: [PATCH 15/17] Hide Settings | Features | Key Mapping [minor] Since we're not using it yet. --- tabfern/src/settings/manifest.js | 2 +- webstore/src/settings/manifest.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tabfern/src/settings/manifest.js b/tabfern/src/settings/manifest.js index 986e82b7..becd7cf8 100755 --- a/tabfern/src/settings/manifest.js +++ b/tabfern/src/settings/manifest.js @@ -293,6 +293,7 @@ bar (it will start with "file://") "type": "checkbox", "label": "Enable right-click menus" + refresh_message, }, +/* { "tab": "Features", "group": "Key Mapping", @@ -301,7 +302,6 @@ bar (it will start with "file://") "label": "Enable key mapping" + refresh_message, }, -/* { "tab": "Key Mappings", "group": "Persistence Control", diff --git a/webstore/src/settings/manifest.js b/webstore/src/settings/manifest.js index 986e82b7..becd7cf8 100755 --- a/webstore/src/settings/manifest.js +++ b/webstore/src/settings/manifest.js @@ -293,6 +293,7 @@ bar (it will start with "file://") "type": "checkbox", "label": "Enable right-click menus" + refresh_message, }, +/* { "tab": "Features", "group": "Key Mapping", @@ -301,7 +302,6 @@ bar (it will start with "file://") "label": "Enable key mapping" + refresh_message, }, -/* { "tab": "Key Mappings", "group": "Persistence Control", From 7a69ddfa3a34f5d06b3e06c84d2ec78b2a6a383a Mon Sep 17 00:00:00 2001 From: Chris White Date: Mon, 17 Sep 2018 09:21:23 -0400 Subject: [PATCH 16/17] Add consolidated version-reporting script This way it's easier to find or edit all the files that have version information. Updating version numbers across the project should be automated as part of #4. --- Makefile | 1 + check-version.sh | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100755 check-version.sh diff --git a/Makefile b/Makefile index 260a7572..955fb47c 100644 --- a/Makefile +++ b/Makefile @@ -34,6 +34,7 @@ DEST_BUNDLE_2 = tabfern/src/view/bundle_tree.js .PHONY: all bundle clean all: bundle + ./check-version.sh ./check-webstore.sh bundle: $(DEST_BUNDLE_1) $(DEST_BUNDLE_2) diff --git a/check-version.sh b/check-version.sh new file mode 100755 index 00000000..bc1155cd --- /dev/null +++ b/check-version.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# check-version.sh: report version numbers in TabFern +function check() { + ack_opts=( -m 1 --nocolor --nopager --output '$line_no: $line' ) + # $filename is also available + echo -n "$1: " + ack "${ack_opts[@]}" VERSION "$1" || + ack "${ack_opts[@]}" version "$1" +} + +files=(package.json package-lock.json) + +for tree in tabfern webstore ; do + files+=(${tree}/manifest.json ${tree}/src/common/common.js) +done + +for f in "${files[@]}" ; do + check "$f" +done + +if [[ $1 = '-e' ]]; then + vi "${files[@]}" +fi +# vi: set ts=4 sts=4 sw=4 et ai: # From 9e2730170d1dbc9b7df7f349b441f7afd883e2b5 Mon Sep 17 00:00:00 2001 From: Chris White Date: Mon, 17 Sep 2018 09:23:12 -0400 Subject: [PATCH 17/17] Bumped version number to 0.1.18 --- package-lock.json | 2 +- package.json | 2 +- tabfern/manifest.json | 4 ++-- tabfern/src/common/common.js | 4 ++-- tabfern/src/settings/manifest.js | 2 +- webstore/manifest.json | 4 ++-- webstore/src/common/common.js | 4 ++-- webstore/src/settings/manifest.js | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f7495a1..470f2dbd 100755 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tabfern", - "version": "0.1.18.1", + "version": "0.1.18.1337", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6cd4be6f..2c158fb8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tabfern", - "version": "0.1.18.1", + "version": "0.1.18.1337", "description": "Google Chrome extension for displaying, saving, and managing tabs", "main": "src/view/main.js", "directories": { diff --git a/tabfern/manifest.json b/tabfern/manifest.json index ea53bfb4..1a8f695a 100755 --- a/tabfern/manifest.json +++ b/tabfern/manifest.json @@ -1,8 +1,8 @@ { "name": "__MSG_wsLongName__", "short_name": "__MSG_wsShortName__", - "version": "0.1.18.1", - "version_name": "0.1.18-pre.1", + "version": "0.1.18.1337", + "version_name": "0.1.18", "offline_enabled": true, "manifest_version": 2, "minimum_chrome_version": "54", diff --git a/tabfern/src/common/common.js b/tabfern/src/common/common.js index 9c33ae89..8e56cd11 100755 --- a/tabfern/src/common/common.js +++ b/tabfern/src/common/common.js @@ -12,7 +12,7 @@ console.log('TabFern common.js loading'); /// The TabFern extension friendly version number. Displayed in the /// title bar of the popup window, so lowercase (no shouting!). -const TABFERN_VERSION='0.1.18-pre.1'; +const TABFERN_VERSION='0.1.18'; // When you change this, also update: // - manifest.json: both the version and version_name // - package.json @@ -21,7 +21,7 @@ const TABFERN_VERSION='0.1.18-pre.1'; // Design decision: version numbers follow semver.org. // In the Chrome manifest, the version_name attribute tracks the above. // The version attribute, `x.y.z.w`, which is compared in numeric order L-R, -// is as follows: x.y.z track the above. w is the "-pre." number. +// is as follows: x.y.z track the above. w is the "-pre." or "-rc." number. // A release to the Chrome Web Store has w=1337. // E.g., 1.2.3-pre.4 is `version='1.2.3.4'`, and 1.2.3 (release) is // `version='1.2.3.1337'`. diff --git a/tabfern/src/settings/manifest.js b/tabfern/src/settings/manifest.js index becd7cf8..b14bd7b3 100755 --- a/tabfern/src/settings/manifest.js +++ b/tabfern/src/settings/manifest.js @@ -388,7 +388,7 @@ order.` // Changelog {{{1 { "tab": future_i18n("What's new?"), - "group": `Version 0.1.18${brplain('2018-xx-xx')}`, + "group": `Version 0.1.18${brplain('2018-09-17')}`, 'group_html':true, "type": "description", "text": diff --git a/webstore/manifest.json b/webstore/manifest.json index ea53bfb4..1a8f695a 100755 --- a/webstore/manifest.json +++ b/webstore/manifest.json @@ -1,8 +1,8 @@ { "name": "__MSG_wsLongName__", "short_name": "__MSG_wsShortName__", - "version": "0.1.18.1", - "version_name": "0.1.18-pre.1", + "version": "0.1.18.1337", + "version_name": "0.1.18", "offline_enabled": true, "manifest_version": 2, "minimum_chrome_version": "54", diff --git a/webstore/src/common/common.js b/webstore/src/common/common.js index 9c33ae89..8e56cd11 100755 --- a/webstore/src/common/common.js +++ b/webstore/src/common/common.js @@ -12,7 +12,7 @@ console.log('TabFern common.js loading'); /// The TabFern extension friendly version number. Displayed in the /// title bar of the popup window, so lowercase (no shouting!). -const TABFERN_VERSION='0.1.18-pre.1'; +const TABFERN_VERSION='0.1.18'; // When you change this, also update: // - manifest.json: both the version and version_name // - package.json @@ -21,7 +21,7 @@ const TABFERN_VERSION='0.1.18-pre.1'; // Design decision: version numbers follow semver.org. // In the Chrome manifest, the version_name attribute tracks the above. // The version attribute, `x.y.z.w`, which is compared in numeric order L-R, -// is as follows: x.y.z track the above. w is the "-pre." number. +// is as follows: x.y.z track the above. w is the "-pre." or "-rc." number. // A release to the Chrome Web Store has w=1337. // E.g., 1.2.3-pre.4 is `version='1.2.3.4'`, and 1.2.3 (release) is // `version='1.2.3.1337'`. diff --git a/webstore/src/settings/manifest.js b/webstore/src/settings/manifest.js index becd7cf8..b14bd7b3 100755 --- a/webstore/src/settings/manifest.js +++ b/webstore/src/settings/manifest.js @@ -388,7 +388,7 @@ order.` // Changelog {{{1 { "tab": future_i18n("What's new?"), - "group": `Version 0.1.18${brplain('2018-xx-xx')}`, + "group": `Version 0.1.18${brplain('2018-09-17')}`, 'group_html':true, "type": "description", "text":