diff --git a/.eslintrc b/.eslintrc index 37c2ae81..20603487 100644 --- a/.eslintrc +++ b/.eslintrc @@ -8,64 +8,6 @@ env: es6: true webextensions: true -globals: - # messaging.js - KEEP_CHANNEL_OPEN: false - CHROME: false - FIREFOX: false - VIVALDI: false - OPERA: false - URLS: false - BG: false - API: false - notifyAllTabs: false - sendMessage: false - queryTabs: false - getTab: false - getOwnTab: false - getActiveTab: false - getActiveTabRealURL: false - getTabRealURL: false - openURL: false - activateTab: false - stringAsRegExp: false - ignoreChromeError: false - tryCatch: false - tryRegExp: false - tryJSONparse: false - debounce: false - deepCopy: false - sessionStorageHash: false - download: false - invokeOrPostpone: false - # localization.js - template: false - t: false - o: false - tE: false - tHTML: false - tNodeList: false - tDocLoader: false - tWordBreak: false - formatDate: false - # dom.js - onDOMready: false - onDOMscriptReady: false - scrollElementIntoView: false - enforceInputRange: false - animateElement: false - $: false - $$: false - $create: false - $createLink: false - # prefs.js - prefs: false - setupLivePrefs: false - # storage-util.js - chromeLocal: false - chromeSync: false - LZString: false - rules: accessor-pairs: [2] array-bracket-spacing: [2, never] @@ -214,7 +156,6 @@ rules: no-trailing-spaces: [2] no-undef-init: [2] no-undef: [2] - no-undefined: [0] no-underscore-dangle: [0] no-unexpected-multiline: [2] no-unmodified-loop-condition: [0] @@ -224,7 +165,7 @@ rules: no-unsafe-negation: [2] no-unused-expressions: [1] no-unused-labels: [0] - no-unused-vars: [1, {args: after-used, vars: local, argsIgnorePattern: ^_}] + no-unused-vars: [2, {args: after-used}] no-use-before-define: [2, nofunc] no-useless-call: [2] no-useless-computed-key: [2] diff --git a/background/background.js b/background/background.js index 7e242e2e..e4d958c1 100644 --- a/background/background.js +++ b/background/background.js @@ -329,11 +329,15 @@ function webNavIframeHelperFF({tabId, frameId}) { .catch(() => false) .then(pong => { if (pong) return; - chrome.tabs.executeScript(tabId, { - frameId, - file: '/content/apply.js', - matchAboutBlank: true, - }, ignoreChromeError); + // insert apply.js to iframe + const files = chrome.runtime.getManifest().content_scripts[0].js; + for (const file of files) { + chrome.tabs.executeScript(tabId, { + frameId, + file, + matchAboutBlank: true, + }, ignoreChromeError); + } }); } diff --git a/background/db.js b/background/db.js index 081e9642..6d38a9fb 100644 --- a/background/db.js +++ b/background/db.js @@ -74,10 +74,14 @@ const db = (() => { } else { const transaction = database.transaction(['styles'], 'readwrite'); const store = transaction.objectStore('styles'); - Object.assign(store[method](...args), { - onsuccess: event => resolve(event, store, transaction, database), - onerror: reject, - }); + try { + Object.assign(store[method](...args), { + onsuccess: event => resolve(event, store, transaction, database), + onerror: reject, + }); + } catch (err) { + reject(err); + } } }, onerror(event) { diff --git a/background/style-manager.js b/background/style-manager.js index ce8fe20f..66a176d9 100644 --- a/background/style-manager.js +++ b/background/style-manager.js @@ -43,6 +43,7 @@ const styleManager = (() => { } let id; port.onMessage.addListener(data => { + console.log(data); if (!id) { id = data.id; } @@ -167,7 +168,7 @@ const styleManager = (() => { } function setStyleExclusions(id, exclusions) { - const data = Object.assign({}, styles.get(id), {exclusions}); + const data = Object.assign({}, styles.get(id).data, {exclusions}); return saveStyle(data) .then(newData => handleSave(newData, 'exclusions', 'styleUpdated')); } @@ -257,6 +258,9 @@ const styleManager = (() => { if (!style.name) { throw new Error('style name is empty'); } + if (style.id == null) { + delete style.id; + } return db.exec('put', style) .then(event => { if (style.id == null) { diff --git a/background/usercss-helper.js b/background/usercss-helper.js index e4c66d84..3f058b0d 100644 --- a/background/usercss-helper.js +++ b/background/usercss-helper.js @@ -82,7 +82,7 @@ metaOnly, vars, }) { - return usercss.buildMeta(sourceCode) + return Promise.resolve(usercss.buildMeta(sourceCode)) .then(style => Promise.all([ metaOnly ? style : doBuild(style), @@ -150,7 +150,7 @@ return styleManager.get(styleOrData.id); } const {name, namespace} = styleOrData.usercssData || styleOrData; - return styleManager.getAllStyles(styleList => { + return styleManager.getAllStyles().then(styleList => { for (const dup of styleList) { const data = dup.usercssData; if (!data) continue; diff --git a/content/apply.js b/content/apply.js index 6e174959..8a229661 100644 --- a/content/apply.js +++ b/content/apply.js @@ -134,21 +134,11 @@ applyStyles(request.styles); break; - case 'styleReplaceAll': - replaceAll(request.styles); - break; - - case 'prefChanged': - if ('disableAll' in request.prefs) { - doDisableAll(request.prefs.disableAll); - } - if ('exposeIframes' in request.prefs) { - doExposeIframes(request.prefs.exposeIframes); - } - break; - case 'urlChanged': - // TODO + console.log('url changed', location.href); + API.getSectionsByUrl(getMatchUrl(), {enabled: true}) + .then(buildSections) + .then(replaceAll); break; case 'ping': @@ -384,15 +374,6 @@ } function replaceAll(newStyles) { - if ('disableAll' in newStyles && - disableAll === newStyles.disableAll && - styleElements.size === countStylesInHash(newStyles) && - [...styleElements.values()].every(el => - el.disabled === disableAll && - el.parentNode === ROOT && - el.textContent === (newStyles[getStyleId(el)] || []).map(({code}) => code).join('\n'))) { - return; - } const oldStyles = Array.prototype.slice.call( document.querySelectorAll(`style.stylus[id^="${ID_PREFIX}"]`)); oldStyles.forEach(el => (el.id += '-ghost')); @@ -401,8 +382,10 @@ [...retiredStyleTimers.values()].forEach(clearTimeout); retiredStyleTimers.clear(); applyStyles(newStyles); - docRootObserver.evade(() => - oldStyles.forEach(el => el.remove())); + if (docRewriteObserver) { + docRootObserver.evade(() => + oldStyles.forEach(el => el.remove())); + } } function applyTransitionPatch() { diff --git a/edit/codemirror-factory.js b/edit/codemirror-factory.js index a19979b7..0773d0f9 100644 --- a/edit/codemirror-factory.js +++ b/edit/codemirror-factory.js @@ -11,8 +11,6 @@ const cmFactory = (() => { const INSERT_TAB_COMMAND = CodeMirror.commands.insertTab; const INSERT_SOFT_TAB_COMMAND = CodeMirror.commands.insertSoftTab; - console.log(INSERT_SOFT_TAB_COMMAND, INSERT_TAB_COMMAND); - CodeMirror.defineOption('tabSize', prefs.get('editor.tabSize'), (cm, value) => { cm.setOption('indentUnit', Number(value)); }); diff --git a/edit/edit.js b/edit/edit.js index 6744edb2..13d8daee 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -407,7 +407,6 @@ function initStyleData() { const params = new URLSearchParams(location.search.replace(/^\?/, '')); const id = Number(params.get('id')); const createEmptyStyle = () => ({ - id: null, name: params.get('domain') || tryCatch(() => new URL(params.get('url-prefix')).hostname) || '', diff --git a/edit/reroute-hotkeys.js b/edit/reroute-hotkeys.js index 9d4d5b50..75945b99 100644 --- a/edit/reroute-hotkeys.js +++ b/edit/reroute-hotkeys.js @@ -28,7 +28,7 @@ const rerouteHotkeys = (() => { } function rerouteHandler(event) { - if (!editor) { + if (typeof editor === 'undefined') { return; } const keyName = CodeMirror.keyName(event); diff --git a/edit/source-editor.js b/edit/source-editor.js index b6abbec2..107a8c5c 100644 --- a/edit/source-editor.js +++ b/edit/source-editor.js @@ -85,7 +85,7 @@ function createSourceEditor(style) { sourceCode: style.sourceCode, vars: style.usercssData.vars }) - .then(newStyle => { + .then(({style: newStyle}) => { delete newStyle.enabled; return Object.assign(style, newStyle); }); @@ -234,17 +234,17 @@ function createSourceEditor(style) { function save() { if (!dirty.isDirty()) return; const code = cm.getValue(); - const exclusionList = exclusions.get(); - exclusions.save({ - id: style.id, - exclusionList - }); + // const exclusionList = exclusions.get(); + // exclusions.save({ + // id: style.id, + // exclusionList + // }); return ensureUniqueStyle(code) .then(() => API.editSaveUsercss({ id: style.id, enabled: style.enabled, sourceCode: code, - exclusions: exclusionList + // exclusions: exclusionList })) .then(replaceStyle) .catch(err => { diff --git a/js/msg.js b/js/msg.js index a4bc52f6..20b17585 100644 --- a/js/msg.js +++ b/js/msg.js @@ -79,9 +79,19 @@ const msg = (() => { } } + function broadcastError(err) { + if (err.message && ( + /Receiving end does not exist/.test(err.message) || + /The message port closed before a response was received/.test(err.message) + )) { + return; + } + console.warn(err); + } + function broadcast(data, filter) { return Promise.all([ - send(data, 'both').catch(console.warn), + send(data, 'both').catch(broadcastError), broadcastTab(data, filter, null, true, 'both') ]); } @@ -116,14 +126,14 @@ const msg = (() => { if (message.id) { request = withCleanup(request, () => bg._msg.storage.delete(message.id)); } - requests.push(request.catch(console.warn)); + requests.push(request.catch(broadcastError)); } return Promise.all(requests); }); } function broadcastExtension(...args) { - return send(...args).catch(console.warn); + return send(...args).catch(broadcastError); } function on(fn) { diff --git a/js/prefs.js b/js/prefs.js index 7d6c8e87..32de5bd4 100644 --- a/js/prefs.js +++ b/js/prefs.js @@ -1,8 +1,8 @@ -/* global prefs: true, contextMenus, FIREFOX_NO_DOM_STORAGE */ +/* global deepCopy debounce API tryJSONparse chromeSync FIREFOX CHROME */ +/* exported prefs */ 'use strict'; -// eslint-disable-next-line no-var -var prefs = new function Prefs() { +const prefs = new function Prefs() { const BG = undefined; const defaults = { 'openEditInWindow': false, // new editor opens in a own browser window diff --git a/js/promisify.js b/js/promisify.js index 4c1ae9e3..8362b00d 100644 --- a/js/promisify.js +++ b/js/promisify.js @@ -1,5 +1,12 @@ +/* exported promisify */ 'use strict'; +/* +Convert chrome APIs into promises. Example: + const storageSyncGet = promisify(chrome.storage.sync.get.bind(chrome.storage.sync)); + storageSyncGet(['key']).then(result => {...}); + +*/ function promisify(fn) { return (...args) => new Promise((resolve, reject) => { diff --git a/js/script-loader.js b/js/script-loader.js index f4c80bf6..0279cae5 100644 --- a/js/script-loader.js +++ b/js/script-loader.js @@ -1,8 +1,8 @@ +/* exported loadScript */ 'use strict'; // loadScript(script: Array|string): Promise -// eslint-disable-next-line no-var -var loadScript = (() => { +const loadScript = (() => { const cache = new Map(); function inject(file) { diff --git a/js/sections-equal.js b/js/sections-equal.js index d01c4bfe..68260560 100644 --- a/js/sections-equal.js +++ b/js/sections-equal.js @@ -1,3 +1,4 @@ +/* exported styleSectionsEqual */ 'use strict'; /** diff --git a/js/storage-util.js b/js/storage-util.js index 11ed7e72..34924f55 100644 --- a/js/storage-util.js +++ b/js/storage-util.js @@ -1,20 +1,14 @@ -/* global loadScript */ +/* global loadScript tryJSONparse API */ +/* exported chromeLocal chromeSync */ 'use strict'; -// eslint-disable-next-line no-var -var [chromeLocal, chromeSync] = (() => { - const native = 'sync' in chrome.storage && - !chrome.runtime.id.includes('@temporary'); - if (!native && BG !== window) { - setupOnChangeRelay(); - } +const [chromeLocal, chromeSync] = (() => { return [ createWrapper('local'), createWrapper('sync'), ]; function createWrapper(name) { - if (!native) createDummyStorage(name); const storage = chrome.storage[name]; const wrapper = { get: data => new Promise(resolve => storage.get(data, resolve)), @@ -58,39 +52,10 @@ var [chromeLocal, chromeSync] = (() => { return wrapper; } - function createDummyStorage(name) { - chrome.storage[name] = { - get: (data, cb) => API.dummyStorageGet({data, name}).then(cb), - set: (data, cb) => API.dummyStorageSet({data, name}).then(cb), - remove: (data, cb) => API.dummyStorageRemove({data, name}).then(cb), - }; - } - function loadLZStringScript() { return window.LZString ? Promise.resolve(window.LZString) : loadScript('/vendor/lz-string-unsafe/lz-string-unsafe.min.js').then(() => (window.LZString = window.LZString || window.LZStringUnsafe)); } - - function setupOnChangeRelay() { - const listeners = new Set(); - const onMessage = msg => { - if (!msg.dummyStorageChanges) return; - for (const fn of listeners.values()) { - fn(msg.dummyStorageChanges, msg.dummyStorageName); - } - }; - Object.assign(chrome.storage.onChanged, { - addListener(fn) { - if (!listeners.size) chrome.runtime.onMessage.addListener(onMessage); - listeners.add(fn); - }, - hasListener: fn => listeners.has(fn), - removeListener(fn) { - listeners.delete(fn); - if (!listeners.size) chrome.runtime.onMessage.removeListener(onMessage); - } - }); - } })(); diff --git a/js/usercss.js b/js/usercss.js index d5a30878..bb4efc5e 100644 --- a/js/usercss.js +++ b/js/usercss.js @@ -1,8 +1,8 @@ /* global loadScript semverCompare colorConverter styleCodeEmpty */ +/* exported usercss */ 'use strict'; -// eslint-disable-next-line no-var -var usercss = (() => { +const usercss = (() => { // true = global // false or 0 = private // = global key name diff --git a/manage/config-dialog.js b/manage/config-dialog.js index 353e98fb..a3188ee3 100644 --- a/manage/config-dialog.js +++ b/manage/config-dialog.js @@ -1,4 +1,6 @@ -/* global messageBox */ +/* global messageBox deepCopy $create $createLink $ t tWordBreak + prefs setupLivePrefs debounce API */ +/* exported configDialog */ 'use strict'; function configDialog(style) { @@ -171,7 +173,7 @@ function configDialog(style) { return; } saving = true; - return API.configUsercssVar(style.id, style.usercssData.vars) + return API.configUsercssVars(style.id, style.usercssData.vars) .then(newVars => { varsInitial = getInitialValues(newVars); vars.forEach(va => onchange({target: va.input, justSaved: true})); diff --git a/manage/filters.js b/manage/filters.js index 24bb8e7b..007ebc4b 100644 --- a/manage/filters.js +++ b/manage/filters.js @@ -1,5 +1,5 @@ -/* global installed messageBox */ -/* global sorter */ +/* global installed messageBox sorter $ $$ $create t debounce prefs API onDOMready */ +/* exported filterAndAppend */ 'use strict'; const filtersSelector = { diff --git a/manage/import-export.js b/manage/import-export.js index b61b98c9..07808c50 100644 --- a/manage/import-export.js +++ b/manage/import-export.js @@ -1,4 +1,5 @@ -/* global messageBox handleUpdate handleDelete applyOnMessage styleSectionsEqual */ +/* global messageBox handleUpdate handleDelete styleSectionsEqual getOwnTab API + tryJSONparse scrollElementIntoView $ $$ API $create t animateElement */ 'use strict'; const STYLISH_DUMP_FILE_EXT = '.txt'; @@ -94,8 +95,8 @@ function importFromString(jsonString, oldStyles) { if (info) { // using saveStyle directly since json was parsed in background page context // FIXME: rewrite importStyle - // return API.saveStyle(Object.assign(item, SAVE_OPTIONS)) - // .then(style => account({style, info, resolve})); + return API.saveStyle(Object.assign(item, SAVE_OPTIONS)) + .then(style => account({style, info, resolve})); } } renderQueue.forEach(style => handleUpdate(style, {reason: 'import'})); diff --git a/manage/incremental-search.js b/manage/incremental-search.js index 7f0451fa..5c0201a2 100644 --- a/manage/incremental-search.js +++ b/manage/incremental-search.js @@ -1,4 +1,5 @@ -/* global installed */ +/* global installed onDOMready $create debounce $ scrollElementIntoView + animateElement */ 'use strict'; onDOMready().then(() => { diff --git a/manage/manage.js b/manage/manage.js index 40809daa..e3997c25 100644 --- a/manage/manage.js +++ b/manage/manage.js @@ -1,10 +1,13 @@ /* -global messageBox getStyleWithNoCode retranslateCSS -global filtersSelector filterAndAppend urlFilterParam showFiltersStats -global checkUpdate handleUpdateInstalled -global objectDiff -global configDialog -global sorter msg +global messageBox getStyleWithNoCode + filterAndAppend urlFilterParam showFiltersStats + checkUpdate handleUpdateInstalled + objectDiff + configDialog + sorter msg prefs API onDOMready $ $$ $create template setupLivePrefs + URLS enforceInputRange t tWordBreak formatDate + getOwnTab getActiveTab openURL animateElement sessionStorageHash debounce + scrollElementIntoView CHROME VIVALDI FIREFOX */ 'use strict'; diff --git a/manage/object-diff.js b/manage/object-diff.js index 1c87f289..cf994a8e 100644 --- a/manage/object-diff.js +++ b/manage/object-diff.js @@ -1,3 +1,4 @@ +/* exported objectDiff */ 'use strict'; function objectDiff(first, second, path = '') { diff --git a/manage/sort.js b/manage/sort.js index 13e5575a..0120f359 100644 --- a/manage/sort.js +++ b/manage/sort.js @@ -1,5 +1,5 @@ -/* global installed */ -/* global messageBox */ +/* global installed messageBox t $ $create prefs */ +/* exported sorter */ 'use strict'; const sorter = (() => { diff --git a/manage/updater-ui.js b/manage/updater-ui.js index 46a197c9..038eb774 100644 --- a/manage/updater-ui.js +++ b/manage/updater-ui.js @@ -1,6 +1,6 @@ -/* global messageBox */ -/* global ENTRY_ID_PREFIX, newUI */ -/* global filtersSelector, filterAndAppend, sorter */ +/* global messageBox ENTRY_ID_PREFIX newUI filtersSelector filterAndAppend + sorter $ $$ $create API onDOMready scrollElementIntoView t chromeLocal */ +/* exported handleUpdateInstalled */ 'use strict'; onDOMready().then(() => { diff --git a/msgbox/msgbox.js b/msgbox/msgbox.js index 9d04c143..3cf7a5bf 100644 --- a/msgbox/msgbox.js +++ b/msgbox/msgbox.js @@ -1,5 +1,4 @@ -/* global focusAccessibility */ -/* global moveFocus */ +/* global focusAccessibility moveFocus $ $create t tHTML animateElement */ 'use strict'; /** diff --git a/options/options.js b/options/options.js index 36ac543e..2f9d929f 100644 --- a/options/options.js +++ b/options/options.js @@ -1,4 +1,6 @@ -/* global messageBox msg */ +/* global messageBox msg setupLivePrefs enforceInputRange + $ $$ $create $createLink + FIREFOX OPERA CHROME URLS openURL prefs t API ignoreChromeError */ 'use strict'; setupLivePrefs(); diff --git a/popup/hotkeys.js b/popup/hotkeys.js index eccb0a35..fe058ea1 100644 --- a/popup/hotkeys.js +++ b/popup/hotkeys.js @@ -1,8 +1,8 @@ -/* global applyOnMessage installed */ +/* global $ $$ API debounce $create t */ 'use strict'; -// eslint-disable-next-line no-var -var hotkeys = (() => { +/* exported hotkeys */ +const hotkeys = (() => { const entries = document.getElementsByClassName('entry'); let togglablesShown; let togglables; diff --git a/popup/popup-exclusions.js b/popup/popup-exclusions.js index d44aebd8..90be8f40 100644 --- a/popup/popup-exclusions.js +++ b/popup/popup-exclusions.js @@ -1,9 +1,9 @@ /* -global messageBox -global exclusions +global messageBox t $create getActiveTab tryRegExp animateElement $ API */ 'use strict'; +/* exported popupExclusions */ const popupExclusions = (() => { // return matches on url ending to prevent duplicates in the exclusion list @@ -163,45 +163,29 @@ const popupExclusions = (() => { entry.styleMeta = style; entry.classList.toggle('excluded', excluded); } - notifyAllTabs({method: 'exclusionsUpdated', style, id: entry.styleId, affects: true, excluded}); } return Promise.resolve(); } function handlePopupSave(style) { - if (typeof style.exclusions === 'undefined') { - style.exclusions = {}; + if (!Array.isArray(style.exclusions)) { + style.exclusions = []; } - const current = Object.keys(style.exclusions); + const current = new Set(style.exclusions); const select = $('#popup-exclusions', messageBox.element); const all = getMultiOptions({select}); - const selected = getMultiOptions({select, selectedOnly: true}); - // Add exclusions - selected.forEach(value => { - let exists = exclusionExists(current, value); - if (!exists.length) { - style.exclusions[value] = exclusions.createRegExp(value); - exists = ['']; + const selected = new Set(getMultiOptions({select, selectedOnly: true})); + for (const value of all) { + if (current.has(value) && !selected.has(value)) { + const index = style.exclusions.indexOf(value); + style.exclusions.splice(index, 1); } - exists.forEach(ending => { - const index = all.indexOf(value + ending); - if (index > -1) { - all.splice(index, 1); - } - }); - }); - // Remove exclusions (unselected in popup modal) - all.forEach(value => { - exclusionExists(current, value).forEach(ending => { - delete style.exclusions[value + ending]; - }); - }); - exclusions.save({ - id: style.id, - exclusionList: style.exclusions - }); + if (!current.has(value) && selected.has(value)) { + style.exclusions.push(value); + } + } + API.setStyleExclusions(style.id, style.exclusions); } return {openPopupDialog, selectExclusions, isExcluded}; - })(); diff --git a/popup/popup.js b/popup/popup.js index b22b73b2..54702ea0 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -1,6 +1,9 @@ /* global configDialog hotkeys -global popupExclusions promisify onTabReady msg +popupExclusions onTabReady msg +getActiveTab FIREFOX getTabRealURL URLS API onDOMready $ $$ prefs CHROME +setupLivePrefs template ignoreChromeError t $create tWordBreak animateElement +tryJSONparse debounce */ 'use strict'; @@ -308,8 +311,8 @@ function createStyleElement({ $('.checker', entry).checked = false; } - const excluded = popupExclusions.isExcluded(tabURL, style.exclusions); - entry.classList.toggle('excluded', excluded); + // const excluded = popupExclusions.isExcluded(tabURL, style.exclusions); + // entry.classList.toggle('excluded', excluded); const styleName = $('.style-name', entry); styleName.lastChild.textContent = style.name; diff --git a/popup/search-results.js b/popup/search-results.js index d69cce08..438652d3 100755 --- a/popup/search-results.js +++ b/popup/search-results.js @@ -1,4 +1,6 @@ -/* global tabURL handleEvent */ +/* global tabURL handleEvent $ $$ prefs template FIREFOX chromeLocal debounce + $create t API tWordBreak formatDate tryCatch tryJSONparse LZString + ignoreChromeError */ 'use strict'; window.addEventListener('showStyles:done', function _() { @@ -135,7 +137,7 @@ window.addEventListener('showStyles:done', function _() { if (result) { result.installed = false; result.installedStyleId = -1; - (BG || window).clearTimeout(result.pingbackTimer); + window.clearTimeout(result.pingbackTimer); renderActionButtons($('#' + RESULT_ID_PREFIX + result.id)); } }); @@ -581,7 +583,8 @@ window.addEventListener('showStyles:done', function _() { } function pingback(result) { - const wnd = BG || window; + const wnd = window; + // FIXME: move this to background page and create an API like installUSOStyle result.pingbackTimer = wnd.setTimeout(wnd.download, PINGBACK_DELAY, BASE_URL + '/styles/install/' + result.id + '?source=stylish-ch'); } diff --git a/vendor-overwrites/colorpicker/colorpicker.js b/vendor-overwrites/colorpicker/colorpicker.js index 38f4af75..2fb84913 100644 --- a/vendor-overwrites/colorpicker/colorpicker.js +++ b/vendor-overwrites/colorpicker/colorpicker.js @@ -1,4 +1,5 @@ -/* global CodeMirror colorConverter */ +/* global colorConverter $create debounce */ +/* exported colorMimicry */ 'use strict'; (window.CodeMirror ? window.CodeMirror.prototype : window).colorpicker = function () {