simplify exports
This commit is contained in:
parent
e74a349a88
commit
f8269c7424
|
@ -18,12 +18,7 @@ define(require => {
|
|||
const ICON_SIZES = FIREFOX || CHROME >= 55 && !VIVALDI ? [16, 32] : [19, 38];
|
||||
const staleBadges = new Set();
|
||||
|
||||
let exports;
|
||||
const {
|
||||
|
||||
updateIconBadge,
|
||||
|
||||
} = exports = /** @namespace API */ {
|
||||
const iconManager = /** @namespace API */ {
|
||||
/**
|
||||
* @param {(number|string)[]} styleIds
|
||||
* @param {boolean} [lazyBadge=false] preventing flicker during page load
|
||||
|
@ -72,7 +67,7 @@ define(require => {
|
|||
|
||||
function onPortDisconnected({sender}) {
|
||||
if (tabManager.get(sender.tab.id, 'styleIds')) {
|
||||
updateIconBadge.call({sender}, [], {lazyBadge: true});
|
||||
iconManager.updateIconBadge.call({sender}, [], {lazyBadge: true});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,5 +148,5 @@ define(require => {
|
|||
staleBadges.clear();
|
||||
}
|
||||
|
||||
return exports;
|
||||
return iconManager;
|
||||
});
|
||||
|
|
|
@ -28,13 +28,11 @@ define(require => {
|
|||
|
||||
//#region Declarations
|
||||
|
||||
const ready = init();
|
||||
/**
|
||||
* @typedef StyleMapData
|
||||
* @property {StyleObj} style
|
||||
* @property {?StyleObj} [preview]
|
||||
* @property {Set<string>} appliesTo - urls
|
||||
*/
|
||||
/** @typedef {{
|
||||
style: StyleObj
|
||||
preview?: StyleObj
|
||||
appliesTo: Set<string>
|
||||
}} StyleMapData */
|
||||
/** @type {Map<number,StyleMapData>} */
|
||||
const dataMap = new Map();
|
||||
const uuidIndex = new Map();
|
||||
|
@ -59,13 +57,33 @@ define(require => {
|
|||
};
|
||||
const DELETE_IF_NULL = ['id', 'customName'];
|
||||
|
||||
let ready = false;
|
||||
const init = db.exec('getAll').then(async res => {
|
||||
const styles = res || [];
|
||||
const updated = styles.filter(style =>
|
||||
addMissingProps(style) +
|
||||
addCustomName(style));
|
||||
if (updated.length) {
|
||||
await db.exec('putMany', updated);
|
||||
}
|
||||
for (const style of styles) {
|
||||
fixUsoMd5Issue(style);
|
||||
storeInMap(style);
|
||||
uuidIndex.set(style._id, style.id);
|
||||
}
|
||||
ready = true;
|
||||
});
|
||||
|
||||
chrome.runtime.onConnect.addListener(handleLivePreview);
|
||||
|
||||
//#endregion
|
||||
//#region Exports
|
||||
|
||||
/** @type {StyleManager} */
|
||||
const styleManager = /** @namespace StyleManager */ {
|
||||
/**
|
||||
* @type StyleManager
|
||||
* @namespace StyleManager
|
||||
*/
|
||||
const styleManager = {
|
||||
|
||||
/* props first,
|
||||
then method shorthands if any,
|
||||
|
@ -79,7 +97,7 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<number>} style id */
|
||||
async delete(id, reason) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
const data = id2data(id);
|
||||
await db.exec('delete', id);
|
||||
if (reason !== 'sync') {
|
||||
|
@ -100,7 +118,7 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<number>} style id */
|
||||
async deleteByUUID(_id, rev) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
const id = uuidIndex.get(_id);
|
||||
const oldDoc = id && id2style(id);
|
||||
if (oldDoc && styleManager.compareRevision(oldDoc._rev, rev) <= 0) {
|
||||
|
@ -111,7 +129,7 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<StyleObj>} */
|
||||
async editSave(style) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
style = mergeWithMapped(style);
|
||||
style.updateDate = Date.now();
|
||||
return handleSave(await saveStyle(style), 'editSave');
|
||||
|
@ -119,7 +137,7 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<?StyleObj>} */
|
||||
async find(filter) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
const filterEntries = Object.entries(filter);
|
||||
for (const {style} of dataMap.values()) {
|
||||
if (filterEntries.every(([key, val]) => style[key] === val)) {
|
||||
|
@ -131,19 +149,19 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<StyleObj[]>} */
|
||||
async getAll() {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
return Array.from(dataMap.values(), data2style);
|
||||
},
|
||||
|
||||
/** @returns {Promise<StyleObj>} */
|
||||
async getByUUID(uuid) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
return id2style(uuidIndex.get(uuid));
|
||||
},
|
||||
|
||||
/** @returns {Promise<StyleSectionsToApply>} */
|
||||
async getSectionsByUrl(url, id, isInitialApply) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
/* Chrome hides text frament from location.href of the page e.g. #:~:text=foo
|
||||
so we'll use the real URL reported by webNavigation API */
|
||||
const {tab, frameId} = this && this.sender || {};
|
||||
|
@ -170,13 +188,13 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<StyleObj>} */
|
||||
async get(id) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
return id2style(id);
|
||||
},
|
||||
|
||||
/** @returns {Promise<StylesByUrlResult[]>} */
|
||||
async getByUrl(url, id = null) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
// FIXME: do we want to cache this? Who would like to open popup rapidly
|
||||
// or search the DB with the same URL?
|
||||
const result = [];
|
||||
|
@ -218,7 +236,7 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<StyleObj[]>} */
|
||||
async importMany(items) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
items.forEach(beforeSave);
|
||||
const events = await db.exec('putMany', items);
|
||||
return Promise.all(items.map((item, i) => {
|
||||
|
@ -229,13 +247,13 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<StyleObj>} */
|
||||
async import(data) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
return handleSave(await saveStyle(data), 'import');
|
||||
},
|
||||
|
||||
/** @returns {Promise<StyleObj>} */
|
||||
async install(style, reason = null) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
reason = reason || dataMap.has(style.id) ? 'update' : 'install';
|
||||
style = mergeWithMapped(style);
|
||||
const url = !style.url && style.updateUrl && (
|
||||
|
@ -250,7 +268,7 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<?StyleObj>} */
|
||||
async putByUUID(doc) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
const id = uuidIndex.get(doc._id);
|
||||
if (id) {
|
||||
doc.id = id;
|
||||
|
@ -275,7 +293,7 @@ define(require => {
|
|||
|
||||
/** @returns {Promise<number>} style id */
|
||||
async toggle(id, enabled) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
const style = Object.assign({}, id2style(id), {enabled});
|
||||
handleSave(await saveStyle(style), 'toggle', false);
|
||||
return id;
|
||||
|
@ -362,7 +380,7 @@ define(require => {
|
|||
}
|
||||
|
||||
async function addIncludeExclude(type, id, rule) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
const style = Object.assign({}, id2style(id));
|
||||
const list = style[type] || (style[type] = []);
|
||||
if (list.includes(rule)) {
|
||||
|
@ -373,7 +391,7 @@ define(require => {
|
|||
}
|
||||
|
||||
async function removeIncludeExclude(type, id, rule) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
const style = Object.assign({}, id2style(id));
|
||||
const list = style[type];
|
||||
if (!list || !list.includes(rule)) {
|
||||
|
@ -472,21 +490,6 @@ define(require => {
|
|||
return code.length && code;
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const styles = await db.exec('getAll') || [];
|
||||
const updated = styles.filter(style =>
|
||||
addMissingProps(style) +
|
||||
addCustomName(style));
|
||||
if (updated.length) {
|
||||
await db.exec('putMany', updated);
|
||||
}
|
||||
for (const style of styles) {
|
||||
fixUsoMd5Issue(style);
|
||||
storeInMap(style);
|
||||
uuidIndex.set(style._id, style.id);
|
||||
}
|
||||
}
|
||||
|
||||
function addMissingProps(style) {
|
||||
let res = 0;
|
||||
for (const key in MISSING_PROPS) {
|
||||
|
|
|
@ -7,9 +7,6 @@ define(require => {
|
|||
const {compareRevision} = require('./style-manager');
|
||||
const tokenManager = require('./token-manager');
|
||||
|
||||
/** @type Sync */
|
||||
let sync;
|
||||
|
||||
//#region Init
|
||||
|
||||
const SYNC_DELAY = 1; // minutes
|
||||
|
@ -32,30 +29,23 @@ define(require => {
|
|||
};
|
||||
let currentDrive;
|
||||
let ctrl;
|
||||
|
||||
const ready = prefs.initializing.then(() => {
|
||||
prefs.subscribe('sync.enabled',
|
||||
(_, val) => val === 'none'
|
||||
? sync.stop()
|
||||
: sync.start(val, true),
|
||||
{runNow: true});
|
||||
});
|
||||
|
||||
chrome.alarms.onAlarm.addListener(info => {
|
||||
if (info.name === 'syncNow') {
|
||||
sync.syncNow();
|
||||
}
|
||||
});
|
||||
let ready = false;
|
||||
const init = prefs.initializing.then(onPrefsReady);
|
||||
chrome.alarms.onAlarm.addListener(onAlarm);
|
||||
|
||||
//#endregion
|
||||
//#region Exports
|
||||
|
||||
sync = /** @namespace Sync */ {
|
||||
/**
|
||||
* @type Sync
|
||||
* @namespace Sync
|
||||
*/
|
||||
const sync = {
|
||||
|
||||
// sorted alphabetically
|
||||
|
||||
async delete(...args) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
if (!currentDrive) return;
|
||||
schedule();
|
||||
return ctrl.delete(...args);
|
||||
|
@ -67,7 +57,7 @@ define(require => {
|
|||
},
|
||||
|
||||
async login(name = prefs.get('sync.enabled')) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
try {
|
||||
await tokenManager.getToken(name, true);
|
||||
} catch (err) {
|
||||
|
@ -82,14 +72,14 @@ define(require => {
|
|||
},
|
||||
|
||||
async put(...args) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
if (!currentDrive) return;
|
||||
schedule();
|
||||
return ctrl.put(...args);
|
||||
},
|
||||
|
||||
async start(name, fromPref = false) {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
if (currentDrive) {
|
||||
return;
|
||||
}
|
||||
|
@ -121,7 +111,7 @@ define(require => {
|
|||
},
|
||||
|
||||
async stop() {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
if (!currentDrive) {
|
||||
return;
|
||||
}
|
||||
|
@ -142,7 +132,7 @@ define(require => {
|
|||
},
|
||||
|
||||
async syncNow() {
|
||||
await ready;
|
||||
if (!ready) await init;
|
||||
if (!currentDrive) {
|
||||
return Promise.reject(new Error('cannot sync when disconnected'));
|
||||
}
|
||||
|
@ -197,13 +187,6 @@ define(require => {
|
|||
});
|
||||
}
|
||||
|
||||
function schedule(delay = SYNC_DELAY) {
|
||||
chrome.alarms.create('syncNow', {
|
||||
delayInMinutes: delay,
|
||||
periodInMinutes: SYNC_INTERVAL,
|
||||
});
|
||||
}
|
||||
|
||||
async function handle401Error(err) {
|
||||
let emit;
|
||||
if (err.code === 401) {
|
||||
|
@ -232,6 +215,28 @@ define(require => {
|
|||
throw new Error(`unknown cloud name: ${name}`);
|
||||
}
|
||||
|
||||
function onAlarm(info) {
|
||||
if (info.name === 'syncNow') {
|
||||
sync.syncNow();
|
||||
}
|
||||
}
|
||||
|
||||
function onPrefsReady() {
|
||||
ready = true;
|
||||
prefs.subscribe('sync.enabled',
|
||||
(_, val) => val === 'none'
|
||||
? sync.stop()
|
||||
: sync.start(val, true),
|
||||
{runNow: true});
|
||||
}
|
||||
|
||||
function schedule(delay = SYNC_DELAY) {
|
||||
chrome.alarms.create('syncNow', {
|
||||
delayInMinutes: delay,
|
||||
periodInMinutes: SYNC_INTERVAL,
|
||||
});
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
return sync;
|
||||
|
|
|
@ -7,12 +7,7 @@ define(require => {
|
|||
const AUTH = createAuth();
|
||||
const NETWORK_LATENCY = 30; // seconds
|
||||
|
||||
let exports;
|
||||
const {
|
||||
|
||||
buildKeys,
|
||||
|
||||
} = exports = {
|
||||
const tokenManager = {
|
||||
|
||||
buildKeys(name) {
|
||||
const k = {
|
||||
|
@ -29,7 +24,7 @@ define(require => {
|
|||
},
|
||||
|
||||
getToken(name, interactive) {
|
||||
const k = buildKeys(name);
|
||||
const k = tokenManager.buildKeys(name);
|
||||
return chromeLocal.get(k.LIST)
|
||||
.then(obj => {
|
||||
if (!obj[k.TOKEN]) {
|
||||
|
@ -53,7 +48,7 @@ define(require => {
|
|||
|
||||
async revokeToken(name) {
|
||||
const provider = AUTH[name];
|
||||
const k = buildKeys(name);
|
||||
const k = tokenManager.buildKeys(name);
|
||||
if (provider.revoke) {
|
||||
try {
|
||||
const token = await chromeLocal.getValue(k.TOKEN);
|
||||
|
@ -222,5 +217,5 @@ define(require => {
|
|||
throw err;
|
||||
}
|
||||
|
||||
return exports;
|
||||
return tokenManager;
|
||||
});
|
||||
|
|
|
@ -47,8 +47,11 @@ define(require => {
|
|||
chrome.alarms.onAlarm.addListener(onAlarm);
|
||||
});
|
||||
|
||||
/** @type {StyleUpdater} */
|
||||
const updater = /** @namespace StyleUpdater */ {
|
||||
/**
|
||||
* @type StyleUpdater
|
||||
* @namespace StyleUpdater
|
||||
*/
|
||||
const updater = {
|
||||
|
||||
async checkAllStyles({
|
||||
save = true,
|
||||
|
|
|
@ -16,7 +16,11 @@ define(require => {
|
|||
'missingChar',
|
||||
];
|
||||
|
||||
const usercss = /** @namespace UsercssHelper */ {
|
||||
/**
|
||||
* @type UsercssHelper
|
||||
* @namespace UsercssHelper
|
||||
*/
|
||||
const usercss = {
|
||||
|
||||
rxMETA: /\/\*!?\s*==userstyle==[\s\S]*?==\/userstyle==\s*\*\//i,
|
||||
|
||||
|
|
|
@ -2,6 +2,39 @@
|
|||
|
||||
define(require => { // define and require use `importScripts` which is synchronous
|
||||
|
||||
/** @namespace EditorWorker */
|
||||
require('/js/worker-util').createAPI({
|
||||
|
||||
async csslint(code, config) {
|
||||
return require('/js/csslint/csslint')
|
||||
.verify(code, config).messages
|
||||
.map(m => Object.assign(m, {rule: {id: m.rule.id}}));
|
||||
},
|
||||
|
||||
getRules(linter) {
|
||||
return ruleRetriever[linter](); // eslint-disable-line no-use-before-define
|
||||
},
|
||||
|
||||
metalint(code) {
|
||||
const result = require('/js/meta-parser').lint(code);
|
||||
// extract needed info
|
||||
result.errors = result.errors.map(err => ({
|
||||
code: err.code,
|
||||
args: err.args,
|
||||
message: err.message,
|
||||
index: err.index,
|
||||
}));
|
||||
return result;
|
||||
},
|
||||
|
||||
async stylelint(code, config) {
|
||||
require('/vendor/stylelint-bundle/stylelint-bundle.min');
|
||||
const {results: [res]} = await self.require('stylelint').lint({code, config});
|
||||
delete res._postcssResult; // huge and unused
|
||||
return res;
|
||||
},
|
||||
});
|
||||
|
||||
const ruleRetriever = {
|
||||
|
||||
csslint() {
|
||||
|
@ -54,37 +87,4 @@ define(require => { // define and require use `importScripts` which is synchrono
|
|||
return options;
|
||||
},
|
||||
};
|
||||
|
||||
/** @namespace EditorWorker */
|
||||
require('/js/worker-util').createAPI({
|
||||
|
||||
async csslint(code, config) {
|
||||
return require('/js/csslint/csslint')
|
||||
.verify(code, config).messages
|
||||
.map(m => Object.assign(m, {rule: {id: m.rule.id}}));
|
||||
},
|
||||
|
||||
getRules(linter) {
|
||||
return ruleRetriever[linter]();
|
||||
},
|
||||
|
||||
metalint(code) {
|
||||
const result = require('/js/meta-parser').lint(code);
|
||||
// extract needed info
|
||||
result.errors = result.errors.map(err => ({
|
||||
code: err.code,
|
||||
args: err.args,
|
||||
message: err.message,
|
||||
index: err.index,
|
||||
}));
|
||||
return result;
|
||||
},
|
||||
|
||||
async stylelint(code, config) {
|
||||
require('/vendor/stylelint-bundle/stylelint-bundle.min');
|
||||
const {results: [res]} = await self.require('stylelint').lint({code, config});
|
||||
delete res._postcssResult; // huge and unused
|
||||
return res;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,9 +11,9 @@ define(require => {
|
|||
const {clipString} = require('./util');
|
||||
|
||||
const dirty = DirtyReporter();
|
||||
const toc = [];
|
||||
let style;
|
||||
let wasDirty = false;
|
||||
const toc = [];
|
||||
|
||||
/**
|
||||
* @mixes SectionsEditor
|
||||
|
|
115
js/cache.js
115
js/cache.js
|
@ -4,63 +4,62 @@
|
|||
* Creates a FIFO limit-size map.
|
||||
*/
|
||||
|
||||
define(require =>
|
||||
function createCache({size = 1000, onDeleted} = {}) {
|
||||
const map = new Map();
|
||||
const buffer = Array(size);
|
||||
let index = 0;
|
||||
let lastIndex = 0;
|
||||
return {
|
||||
get(id) {
|
||||
const item = map.get(id);
|
||||
return item && item.data;
|
||||
},
|
||||
set(id, data) {
|
||||
if (map.size === size) {
|
||||
// full
|
||||
map.delete(buffer[lastIndex].id);
|
||||
if (onDeleted) {
|
||||
onDeleted(buffer[lastIndex].id, buffer[lastIndex].data);
|
||||
}
|
||||
lastIndex = (lastIndex + 1) % size;
|
||||
}
|
||||
const item = {id, data, index};
|
||||
map.set(id, item);
|
||||
buffer[index] = item;
|
||||
index = (index + 1) % size;
|
||||
},
|
||||
delete(id) {
|
||||
const item = map.get(id);
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
map.delete(item.id);
|
||||
const lastItem = buffer[lastIndex];
|
||||
lastItem.index = item.index;
|
||||
buffer[item.index] = lastItem;
|
||||
lastIndex = (lastIndex + 1) % size;
|
||||
define(require => function createCache({size = 1000, onDeleted} = {}) {
|
||||
const map = new Map();
|
||||
const buffer = Array(size);
|
||||
let index = 0;
|
||||
let lastIndex = 0;
|
||||
return {
|
||||
get(id) {
|
||||
const item = map.get(id);
|
||||
return item && item.data;
|
||||
},
|
||||
set(id, data) {
|
||||
if (map.size === size) {
|
||||
// full
|
||||
map.delete(buffer[lastIndex].id);
|
||||
if (onDeleted) {
|
||||
onDeleted(item.id, item.data);
|
||||
onDeleted(buffer[lastIndex].id, buffer[lastIndex].data);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
clear() {
|
||||
map.clear();
|
||||
index = lastIndex = 0;
|
||||
},
|
||||
has: id => map.has(id),
|
||||
*entries() {
|
||||
for (const [id, item] of map) {
|
||||
yield [id, item.data];
|
||||
}
|
||||
},
|
||||
*values() {
|
||||
for (const item of map.values()) {
|
||||
yield item.data;
|
||||
}
|
||||
},
|
||||
get size() {
|
||||
return map.size;
|
||||
},
|
||||
};
|
||||
});
|
||||
lastIndex = (lastIndex + 1) % size;
|
||||
}
|
||||
const item = {id, data, index};
|
||||
map.set(id, item);
|
||||
buffer[index] = item;
|
||||
index = (index + 1) % size;
|
||||
},
|
||||
delete(id) {
|
||||
const item = map.get(id);
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
map.delete(item.id);
|
||||
const lastItem = buffer[lastIndex];
|
||||
lastItem.index = item.index;
|
||||
buffer[item.index] = lastItem;
|
||||
lastIndex = (lastIndex + 1) % size;
|
||||
if (onDeleted) {
|
||||
onDeleted(item.id, item.data);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
clear() {
|
||||
map.clear();
|
||||
index = lastIndex = 0;
|
||||
},
|
||||
has: id => map.has(id),
|
||||
*entries() {
|
||||
for (const [id, item] of map) {
|
||||
yield [id, item.data];
|
||||
}
|
||||
},
|
||||
*values() {
|
||||
for (const item of map.values()) {
|
||||
yield item.data;
|
||||
}
|
||||
},
|
||||
get size() {
|
||||
return map.size;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
15
js/dom.js
15
js/dom.js
|
@ -9,18 +9,11 @@ define(require => {
|
|||
|
||||
/** @type {Prefs} */
|
||||
let prefs;
|
||||
let $, $$;
|
||||
|
||||
//#region Exports
|
||||
|
||||
/** @type {DOM} */
|
||||
let dom;
|
||||
const {
|
||||
|
||||
$,
|
||||
$$,
|
||||
$create,
|
||||
|
||||
} = dom = /** @namespace DOM */ {
|
||||
const dom = {
|
||||
|
||||
$(selector, base = document) {
|
||||
// we have ids with . like #manage.onlyEnabled which looks like #id.class
|
||||
|
@ -351,6 +344,8 @@ define(require => {
|
|||
//#endregion
|
||||
//#region Init
|
||||
|
||||
({$, $$} = dom);
|
||||
|
||||
const Collapsible = {
|
||||
bindEvents(_, elems) {
|
||||
const prefKeys = [];
|
||||
|
@ -413,7 +408,7 @@ define(require => {
|
|||
function addFaviconFF() {
|
||||
const iconset = ['', 'light/'][prefs.get('iconset')] || '';
|
||||
for (const size of [38, 32, 19, 16]) {
|
||||
document.head.appendChild($create('link', {
|
||||
document.head.appendChild(dom.$create('link', {
|
||||
rel: 'icon',
|
||||
href: `/images/icon/${iconset}${size}.png`,
|
||||
sizes: size + 'x' + size,
|
||||
|
|
12
js/prefs.js
12
js/prefs.js
|
@ -10,8 +10,11 @@ define(require => {
|
|||
|
||||
const STORAGE_KEY = 'settings';
|
||||
const clone = deepCopy || (val => JSON.parse(JSON.stringify(val)));
|
||||
/** @type {PrefsValues} */
|
||||
const defaults = /** @namespace PrefsValues */ {
|
||||
/**
|
||||
* @type PrefsValues
|
||||
* @namespace PrefsValues
|
||||
*/
|
||||
const defaults = {
|
||||
'openEditInWindow': false, // new editor opens in a own browser window
|
||||
'openEditInWindow.popup': false, // new editor opens in a simplified browser window without omnibox
|
||||
'windowPosition': {}, // detached window position
|
||||
|
@ -138,7 +141,10 @@ define(require => {
|
|||
}
|
||||
});
|
||||
|
||||
/** @namespace Prefs */
|
||||
/**
|
||||
* @type Prefs
|
||||
* @namespace Prefs
|
||||
*/
|
||||
const prefs = {
|
||||
|
||||
STORAGE_KEY,
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
define(require => {
|
||||
/** @type {Toolbox} */
|
||||
let toolbox;
|
||||
|
||||
const ua = navigator.userAgent;
|
||||
const chromeApp = Boolean(chrome.app);
|
||||
const CHROME = chromeApp && parseInt(ua.match(/Chrom\w+\/(\d+)|$/)[1]);
|
||||
|
@ -14,14 +11,9 @@ define(require => {
|
|||
// (detecting FF57 by the feature it added, not navigator.ua which may be spoofed in about:config)
|
||||
const openerTabIdSupported = (!FIREFOX || window.AbortController) && chrome.windows != null;
|
||||
const debounceTimers = new Map();
|
||||
const {
|
||||
let URLS, deepCopy, deepEqual, deepMerge;
|
||||
|
||||
URLS,
|
||||
deepCopy,
|
||||
deepEqual,
|
||||
deepMerge,
|
||||
|
||||
} = toolbox = /** @namespace Toolbox */ {
|
||||
const toolbox = {
|
||||
|
||||
CHROME,
|
||||
FIREFOX,
|
||||
|
@ -384,6 +376,8 @@ define(require => {
|
|||
},
|
||||
};
|
||||
|
||||
({URLS, deepCopy, deepEqual, deepMerge} = toolbox);
|
||||
|
||||
// see PR #781
|
||||
if (!CHROME && !chrome.browserAction.openPopup) {
|
||||
// in FF pre-57 legacy addons can override useragent so we assume the worst
|
||||
|
|
|
@ -5,6 +5,10 @@ define(require => {
|
|||
const t = require('/js/localization');
|
||||
const prefs = require('/js/prefs');
|
||||
|
||||
/**
|
||||
* @type NewUI
|
||||
* @namespace NewUI
|
||||
*/
|
||||
const newUI = {
|
||||
enabled: null, // the global option should come first
|
||||
favicons: null,
|
||||
|
@ -14,7 +18,7 @@ define(require => {
|
|||
};
|
||||
|
||||
// ...add utility functions
|
||||
Object.assign(newUI, {
|
||||
Object.assign(newUI, /** @namespace NewUI */ {
|
||||
|
||||
ids: Object.keys(newUI),
|
||||
|
||||
|
|
|
@ -336,8 +336,6 @@ define(require => {
|
|||
},
|
||||
};
|
||||
|
||||
const {$entry} = render;
|
||||
|
||||
function createAgeText(el, style) {
|
||||
let val = style.updateDate || style.installDate;
|
||||
if (val) {
|
||||
|
@ -359,7 +357,7 @@ define(require => {
|
|||
|
||||
function highlightEditedStyle() {
|
||||
if (!sessionStore.justEditedStyleId) return;
|
||||
const entry = $entry(sessionStore.justEditedStyleId);
|
||||
const entry = render.$entry(sessionStore.justEditedStyleId);
|
||||
delete sessionStore.justEditedStyleId;
|
||||
if (entry) {
|
||||
animateElement(entry);
|
||||
|
|
|
@ -15,26 +15,9 @@ define(require => {
|
|||
|
||||
const MODAL_SHOWN = 'data-display'; // attribute name
|
||||
|
||||
/** @type {PopupEvents} */
|
||||
let exports;
|
||||
const {
|
||||
const Events = {
|
||||
|
||||
closeExplanation,
|
||||
getClickedStyleElement,
|
||||
getClickedStyleId,
|
||||
getExcludeRule,
|
||||
hideModal,
|
||||
openURLandHide,
|
||||
showModal,
|
||||
thisTab,
|
||||
|
||||
} = exports = /** @namespace PopupEvents */ {
|
||||
|
||||
thisTab: {url: ''},
|
||||
|
||||
closeExplanation() {
|
||||
$('#regexp-explanation').remove();
|
||||
},
|
||||
tabURL: '',
|
||||
|
||||
async configure(event) {
|
||||
const {styleId, styleIsUsercss} = getClickedStyleElement(event);
|
||||
|
@ -46,7 +29,7 @@ define(require => {
|
|||
await configDialog(style);
|
||||
hotkeys.setState(true);
|
||||
} else {
|
||||
openURLandHide.call(this, event);
|
||||
Events.openURLandHide.call(this, event);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -68,19 +51,11 @@ define(require => {
|
|||
const box = $('#confirm');
|
||||
box.dataset.id = entry.styleId;
|
||||
$('b', box).textContent = $('.style-name', entry).textContent;
|
||||
showModal(box, '[data-cmd=cancel]');
|
||||
},
|
||||
|
||||
getClickedStyleId(event) {
|
||||
return (getClickedStyleElement(event) || {}).styleId;
|
||||
},
|
||||
|
||||
getClickedStyleElement(event) {
|
||||
return event.target.closest('.entry');
|
||||
Events.showModal(box, '[data-cmd=cancel]');
|
||||
},
|
||||
|
||||
getExcludeRule(type) {
|
||||
const u = new URL(thisTab.url);
|
||||
const u = new URL(Events.tabURL);
|
||||
return type === 'domain'
|
||||
? u.origin + '/*'
|
||||
: escapeGlob(u.origin + u.pathname); // current page
|
||||
|
@ -100,7 +75,7 @@ define(require => {
|
|||
const entry = getClickedStyleElement(event);
|
||||
const info = t.template.regexpProblemExplanation.cloneNode(true);
|
||||
$remove('#' + info.id);
|
||||
$$('a', info).forEach(el => (el.onclick = openURLandHide));
|
||||
$$('a', info).forEach(el => (el.onclick = Events.openURLandHide));
|
||||
$$('button', info).forEach(el => (el.onclick = closeExplanation));
|
||||
entry.appendChild(info);
|
||||
},
|
||||
|
@ -109,7 +84,7 @@ define(require => {
|
|||
if (!exclusions) {
|
||||
return false;
|
||||
}
|
||||
const rule = getExcludeRule(type);
|
||||
const rule = Events.getExcludeRule(type);
|
||||
return exclusions.includes(rule);
|
||||
},
|
||||
|
||||
|
@ -149,8 +124,8 @@ define(require => {
|
|||
|
||||
async openManager(event) {
|
||||
event.preventDefault();
|
||||
const isSearch = thisTab.url && (event.shiftKey || event.button === 2);
|
||||
await API.openManage(isSearch ? {search: thisTab.url, searchMode: 'url'} : {});
|
||||
const isSearch = Events.tabURL && (event.shiftKey || event.button === 2);
|
||||
await API.openManage(isSearch ? {search: Events.tabURL, searchMode: 'url'} : {});
|
||||
window.close();
|
||||
},
|
||||
|
||||
|
@ -187,7 +162,7 @@ define(require => {
|
|||
};
|
||||
window.on('keydown', box._onkeydown);
|
||||
moveFocus(box, 0);
|
||||
hideModal(oldBox);
|
||||
Events.hideModal(oldBox);
|
||||
},
|
||||
|
||||
async toggleState(event) {
|
||||
|
@ -200,9 +175,9 @@ define(require => {
|
|||
toggleExclude(event, type) {
|
||||
const entry = getClickedStyleElement(event);
|
||||
if (event.target.checked) {
|
||||
API.styles.addExclusion(entry.styleMeta.id, getExcludeRule(type));
|
||||
API.styles.addExclusion(entry.styleMeta.id, Events.getExcludeRule(type));
|
||||
} else {
|
||||
API.styles.removeExclusion(entry.styleMeta.id, getExcludeRule(type));
|
||||
API.styles.removeExclusion(entry.styleMeta.id, Events.getExcludeRule(type));
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -210,17 +185,29 @@ define(require => {
|
|||
const entry = getClickedStyleElement(event);
|
||||
const menu = $('.menu', entry);
|
||||
if (menu.hasAttribute(MODAL_SHOWN)) {
|
||||
hideModal(menu, {animate: true});
|
||||
Events.hideModal(menu, {animate: true});
|
||||
} else {
|
||||
$('.menu-title', entry).textContent = $('.style-name', entry).textContent;
|
||||
showModal(menu, '.menu-close');
|
||||
Events.showModal(menu, '.menu-close');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function closeExplanation() {
|
||||
$('#regexp-explanation').remove();
|
||||
}
|
||||
|
||||
function escapeGlob(text) {
|
||||
return text.replace(/\*/g, '\\*');
|
||||
}
|
||||
|
||||
return exports;
|
||||
function getClickedStyleElement(event) {
|
||||
return event.target.closest('.entry');
|
||||
}
|
||||
|
||||
function getClickedStyleId(event) {
|
||||
return (getClickedStyleElement(event) || {}).styleId;
|
||||
}
|
||||
|
||||
return Events;
|
||||
});
|
||||
|
|
|
@ -31,8 +31,7 @@ define(require => {
|
|||
const ENTRY_ID_PREFIX_RAW = 'style-';
|
||||
|
||||
initializing.then(({frames, styles, url}) => {
|
||||
tabURL = url;
|
||||
Events.thisTab.url = url;
|
||||
tabURL = Events.tabURL = url;
|
||||
toggleUiSliders();
|
||||
initPopup(frames);
|
||||
if (styles[0]) {
|
||||
|
|
|
@ -444,7 +444,7 @@ define(require => {
|
|||
* @returns {boolean} true if the category has actually changed
|
||||
*/
|
||||
function calcCategory({retry} = {}) {
|
||||
const u = tryCatch(() => new URL(Events.thisTab.url));
|
||||
const u = tryCatch(() => new URL(Events.tabURL));
|
||||
const old = category;
|
||||
if (!u) {
|
||||
// Invalid URL
|
||||
|
|
Loading…
Reference in New Issue
Block a user