From 708cb7202808597f7d422d5152772250e1b30a9c Mon Sep 17 00:00:00 2001 From: Matvey Tarasov Date: Wed, 15 Apr 2020 00:37:01 +0300 Subject: [PATCH 1/3] Refactoring controls.js and add url observer like main.js file --- controls.js | 186 ++++++++++++++++++++++++++++-------------------- hide_element.js | 74 +++++++++---------- main.js | 9 +++ manifest.json | 4 ++ 4 files changed, 160 insertions(+), 113 deletions(-) create mode 100644 main.js diff --git a/controls.js b/controls.js index 4f454db..adebe8a 100644 --- a/controls.js +++ b/controls.js @@ -1,93 +1,127 @@ +/** + * + * @param id {String} + * @return {HTMLSpanElement} + */ function muteBtnHTML(id) { - return ` + const element = document.createElement('span'); + element.setAttribute('class', 'mute_message'); + element.setAttribute('id', `mute${id}`); + element.innerHTML = ` 🔇 Заглушить - ` + `; + return element; } -function addControls() { - if (event.target.className == 'im-mess--check fl_l') { - var message = event.target.parentElement; - - var actionsArea = message.getElementsByClassName("im-mess--actions")[0]; - if (actionsArea && actionsArea.lastChild.className != "mute_message") { - var sender_id = message.parentElement.parentElement.parentElement["dataset"].peer - - actionsArea.innerHTML += muteBtnHTML(sender_id); - var muteBtn = actionsArea.getElementsByClassName("mute_message")[0]; - muteBtn.style.display = "none"; - - actionsArea.parentElement.addEventListener("mouseenter", function( event ) { - event.target.getElementsByClassName("mute_message")[0].style.display = "inline-block"; - }); - - actionsArea.parentElement.addEventListener("mouseleave", function( event ) { - event.target.getElementsByClassName("mute_message")[0].style.display = "none"; - }); - - muteBtn.addEventListener("click", function(event) { - var clicked_id = event.target.id.substr(4); // get id of sender from element id - - chrome.storage.sync.set({idToHide: clicked_id}, function() { - for (var item of chatBody.children) { - if (item.dataset.peer == clicked_id) { - item.style.display = "none"; - } - } - - console.log('idToHide: ' + clicked_id); - }); - }); +/** + * + * @param chatBody {HTMLElement} + * @return {function(...[*]=)} + */ +function addControls(chatBody) { + return function (event) { + console.log(event); + if (event.target.className === 'im-mess--check fl_l') { + const message = event.target.parentElement; + addControlButton(message) } } } -var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; +/** + * Create mute button and inset it to the actionArea + * @param actionArea {HTMLElement} + * @param senderId {String} + * @return {HTMLElement} + */ +function addMuteButton(actionArea, senderId) { + const muteButton = muteBtnHTML(senderId); + actionArea.appendChild(muteButton); + muteButton.style.display = "none"; + return muteButton; +} -chatBody.addEventListener('DOMNodeInserted', addControls); +/** + * Add event listeners to the actionArea + * @param actionsArea {HTMLElement} + */ +function addActionAreaEvents(actionsArea) { + actionsArea.parentElement.addEventListener("mouseenter", function (event) { + event.target.getElementsByClassName("mute_message")[0].style.display = "inline-block"; + }); + + actionsArea.parentElement.addEventListener("mouseleave", function (event) { + event.target.getElementsByClassName("mute_message")[0].style.display = "none"; + }); +} + +/** + * + * @param chatBody {HTMLElement} + * @return {function(...[]=)} + */ +function setIdToHideHandle(chatBody) { + return function (event) { + const clickedId = event.target.id.substr(4); // get id of sender from element id + + chrome.storage.sync.set({idToHide: clickedId}, function () { + for (let item of chatBody.children) { + if (item.dataset.peer === clickedId) { + item.style.display = "none"; + } + } + + console.log('idToHide: ' + clickedId); + }); + } +} // Try to add controls until successful. Needed for page refresh. -var controlsInterval = setInterval(function () { - var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; +function createTryToInitInterval() { + const controlsInterval = setInterval(function () { + tryToInitControls(controlsInterval) + }, 200) + return controlsInterval; +} - for (var item of chatBody.children) { +/** + * + * @param message {HTMLElement} + * @param intervalForClean {Number?} + */ +function addControlButton(message, intervalForClean) { + const actionsArea = message.getElementsByClassName("im-mess--actions")[0]; + if (actionsArea && actionsArea.lastChild.className !== "mute_message") { + const senderId = message.parentElement.parentElement.parentElement["dataset"].peer; + const muteBtn = addMuteButton(actionsArea, senderId); + addActionAreaEvents(actionsArea); + muteBtn.addEventListener("click", setIdToHideHandle(chatBody)); + } else if (intervalForClean) { + clearInterval(intervalForClean) + } +} + +/** + * Function hide and mark messages + * @param intervalForClear {Number} + */ +function tryToInitControls(intervalForClear) { + const chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; + + for (let item of chatBody.children) { if (item.className.includes('im-mess-stack _im_mess_stack')) { - var messages = item.children[1].children[1].getElementsByClassName('im-mess im_in _im_mess'); - for (var message of messages) { - var actionsArea = message.getElementsByClassName("im-mess--actions")[0]; - - if (actionsArea && actionsArea.lastChild.className != "mute_message") { - var sender_id = message.parentElement.parentElement.parentElement.dataset.peer; - - actionsArea.innerHTML += muteBtnHTML(sender_id); - var muteBtn = actionsArea.getElementsByClassName("mute_message")[0]; - muteBtn.style.display = "none"; - - actionsArea.parentElement.addEventListener("mouseenter", function( event ) { - event.target.getElementsByClassName("mute_message")[0].style.display = "inline-block"; - }); - - actionsArea.parentElement.addEventListener("mouseleave", function( event ) { - event.target.getElementsByClassName("mute_message")[0].style.display = "none"; - }); - - muteBtn.addEventListener("click", function(event) { - var clicked_id = event.target.id.substr(4); // get id of sender from element id - - chrome.storage.sync.set({idToHide: clicked_id}, function() { - for (var item of chatBody.children) { - if (item.dataset.peer == clicked_id) { - item.style.display = "none"; - } - } - - console.log('idToHide: ' + clicked_id); - }); - }); - } else if (actionsArea.lastChild.className == "mute_message") { - clearInterval(controlsInterval); - } + let messages = item.children[1].children[1].getElementsByClassName('im-mess im_in _im_mess'); + for (let message of messages) { + addControlButton(message, intervalForClear) } } } -}, 200); + +} + +(function init() { + const chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; + chatBody.addEventListener('DOMNodeInserted', addControls); + createTryToInitInterval(); +})(); \ No newline at end of file diff --git a/hide_element.js b/hide_element.js index 43f8dd6..45c249d 100644 --- a/hide_element.js +++ b/hide_element.js @@ -1,37 +1,37 @@ -var idToHide; - -var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; - -chatBody.addEventListener('DOMNodeInserted', function(event) { - if (event.target.className == 'im-mess-stack _im_mess_stack ') { - chrome.storage.sync.get('idToHide', function(data) { - idToHide = data.idToHide; - }); - - chrome.storage.sync.get('isExtensionOn', function(data) { - if (data.isExtensionOn) { - if (event.target.dataset.peer == idToHide) { - event.target.style.display = "none"; - } - } - }); - } -}); - -chrome.storage.sync.get('idToHide', function(data) { - idToHide = data.idToHide; -}); - -// Try to hide until successful. Needed for page refresh. -var hideInterval = setInterval(function () { - var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; - for (var item of chatBody.children) { - if (item.dataset.peer == idToHide) { - if (item.style.display != "none") { - item.style.display = "none"; - } else { - clearInterval(hideInterval); - } - } - } -}, 200); +var idToHide; + +var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; + +chatBody.addEventListener('DOMNodeInserted', function(event) { + if (event.target.className === 'im-mess-stack _im_mess_stack ') { + chrome.storage.sync.get('idToHide', function(data) { + idToHide = data.idToHide; + }); + + chrome.storage.sync.get('isExtensionOn', function(data) { + if (data.isExtensionOn) { + if (event.target.dataset.peer === idToHide) { + event.target.style.display = "none"; + } + } + }); + } +}); + +chrome.storage.sync.get('idToHide', function(data) { + idToHide = data.idToHide; +}); + +// Try to hide until successful. Needed for page refresh. +var hideInterval = setInterval(function () { + var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; + for (var item of chatBody.children) { + if (item.dataset.peer === idToHide) { + if (item.style.display !== "none") { + item.style.display = "none"; + } else { + clearInterval(hideInterval); + } + } + } +}, 200); diff --git a/main.js b/main.js new file mode 100644 index 0000000..d160367 --- /dev/null +++ b/main.js @@ -0,0 +1,9 @@ +const changeUrlDetect = setInterval((function () { + let oldUrl = ''; + return function () { + const currentUrl = window.location.href; + if(currentUrl !== oldUrl){ + oldUrl = currentUrl; + } + } +})(),100); \ No newline at end of file diff --git a/manifest.json b/manifest.json index 0f65ee1..5e00e91 100644 --- a/manifest.json +++ b/manifest.json @@ -21,6 +21,10 @@ }, "manifest_version": 2, "content_scripts": [ + { + "matches": ["https://*.vk.com/*"], + "js": ["main.js"] + }, { "matches": ["https://*.vk.com/im*"], "js": ["hide_element.js"] From a1f1a71b7d338c8f924e7da4a8d050d258faf89a Mon Sep 17 00:00:00 2001 From: Anatoly Kopyl Date: Fri, 17 Apr 2020 19:33:10 +0300 Subject: [PATCH 2/3] Fixed domnodeinserted listener and moved buttons --- controls.css | 4 ++++ controls.js | 12 +++++------- hide_element.js | 38 +++++++++++++++++++++++--------------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/controls.css b/controls.css index 699d601..94c2687 100644 --- a/controls.css +++ b/controls.css @@ -46,4 +46,8 @@ /*background: url('chrome-extension://__MSG_@@extension_id__/mute.png') !important;*/ background-repeat: no-repeat; padding: 6px; +} + +.im-mess--actions { + margin-right: -30px !important; } \ No newline at end of file diff --git a/controls.js b/controls.js index adebe8a..6790b4c 100644 --- a/controls.js +++ b/controls.js @@ -19,13 +19,11 @@ function muteBtnHTML(id) { * @param chatBody {HTMLElement} * @return {function(...[*]=)} */ -function addControls(chatBody) { - return function (event) { - console.log(event); - if (event.target.className === 'im-mess--check fl_l') { - const message = event.target.parentElement; - addControlButton(message) - } +function addControls(event) { + console.log(event); + if (event.target.className === 'im-mess--check fl_l') { + const message = event.target.parentElement; + addControlButton(message) } } diff --git a/hide_element.js b/hide_element.js index 45c249d..319defe 100644 --- a/hide_element.js +++ b/hide_element.js @@ -1,9 +1,27 @@ -var idToHide; +// Returns false if there was an element not hidden +function hideElements(chatBody) { + let idToHide; + chrome.storage.sync.get('idToHide', function(data) { + idToHide = data.idToHide; + }); -var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; + let r = true; + for (var item of chatBody.children) { + if (item.dataset.peer === idToHide) { + if (item.style.display !== "none") { + item.style.display = "none"; + r = false; + } + } + } + return r; +} + +let chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; chatBody.addEventListener('DOMNodeInserted', function(event) { if (event.target.className === 'im-mess-stack _im_mess_stack ') { + let idToHide; chrome.storage.sync.get('idToHide', function(data) { idToHide = data.idToHide; }); @@ -18,20 +36,10 @@ chatBody.addEventListener('DOMNodeInserted', function(event) { } }); -chrome.storage.sync.get('idToHide', function(data) { - idToHide = data.idToHide; -}); - // Try to hide until successful. Needed for page refresh. var hideInterval = setInterval(function () { - var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; - for (var item of chatBody.children) { - if (item.dataset.peer === idToHide) { - if (item.style.display !== "none") { - item.style.display = "none"; - } else { - clearInterval(hideInterval); - } - } + const chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0]; + if (hideElements(chatBody)) { + clearInterval(hideInterval); } }, 200); From b0b79e46a643425d1a48630e22495feee2321936 Mon Sep 17 00:00:00 2001 From: Matvey Tarasov Date: Sat, 18 Apr 2020 17:27:15 +0300 Subject: [PATCH 3/3] Refactoring and add build-tools --- .babelrc | 3 + .gitignore | 3 + {icons => extension/assets/icons}/icon128.png | Bin {icons => extension/assets/icons}/icon140.png | Bin {icons => extension/assets/icons}/icon48.png | Bin mute.png => extension/assets/mute.png | Bin extension/dist/background.js | 117 + extension/dist/dom.js | 887 +++ extension/dist/popup.html | 21 + extension/dist/popup.js | 584 ++ manifest.json => extension/manifest.json | 21 +- hide_element.js | 37 - main.js | 9 - package-lock.json | 5994 +++++++++++++++++ package.json | 33 + background.js => src/background/background.js | 26 +- controls.js => src/dom/controls.js | 61 +- controls.css => src/dom/dom.css | 0 src/dom/hide_element.js | 28 + src/dom/main.js | 20 + popup.css => src/popup/popup.css | 0 popup.html => src/popup/popup.html | 42 +- popup.js => src/popup/popup.js | 92 +- src/utils/Url.js | 47 + src/utils/getChatBody.js | 3 + webpack.config.js | 40 + 26 files changed, 7896 insertions(+), 172 deletions(-) create mode 100644 .babelrc create mode 100644 .gitignore rename {icons => extension/assets/icons}/icon128.png (100%) rename {icons => extension/assets/icons}/icon140.png (100%) rename {icons => extension/assets/icons}/icon48.png (100%) rename mute.png => extension/assets/mute.png (100%) create mode 100644 extension/dist/background.js create mode 100644 extension/dist/dom.js create mode 100644 extension/dist/popup.html create mode 100644 extension/dist/popup.js rename manifest.json => extension/manifest.json (51%) delete mode 100644 hide_element.js delete mode 100644 main.js create mode 100644 package-lock.json create mode 100644 package.json rename background.js => src/background/background.js (97%) rename controls.js => src/dom/controls.js (72%) rename controls.css => src/dom/dom.css (100%) create mode 100644 src/dom/hide_element.js create mode 100644 src/dom/main.js rename popup.css => src/popup/popup.css (100%) rename popup.html => src/popup/popup.html (82%) rename popup.js => src/popup/popup.js (91%) create mode 100644 src/utils/Url.js create mode 100644 src/utils/getChatBody.js create mode 100644 webpack.config.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..8aa924d --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env"] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8be676a --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.cache +/.idea diff --git a/icons/icon128.png b/extension/assets/icons/icon128.png similarity index 100% rename from icons/icon128.png rename to extension/assets/icons/icon128.png diff --git a/icons/icon140.png b/extension/assets/icons/icon140.png similarity index 100% rename from icons/icon140.png rename to extension/assets/icons/icon140.png diff --git a/icons/icon48.png b/extension/assets/icons/icon48.png similarity index 100% rename from icons/icon48.png rename to extension/assets/icons/icon48.png diff --git a/mute.png b/extension/assets/mute.png similarity index 100% rename from mute.png rename to extension/assets/mute.png diff --git a/extension/dist/background.js b/extension/dist/background.js new file mode 100644 index 0000000..f92b34d --- /dev/null +++ b/extension/dist/background.js @@ -0,0 +1,117 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/background/background.js"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./src/background/background.js": +/*!**************************************!*\ + !*** ./src/background/background.js ***! + \**************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +chrome.runtime.onInstalled.addListener(function () { + chrome.storage.sync.set({ + isExtensionOn: true + }, function () { + console.log('isExtensionOn: ' + true); + }); + chrome.declarativeContent.onPageChanged.removeRules(undefined, function () { + chrome.declarativeContent.onPageChanged.addRules([{ + conditions: [new chrome.declarativeContent.PageStateMatcher({ + pageUrl: { + hostEquals: 'vk.com' + } + })], + actions: [new chrome.declarativeContent.ShowPageAction()] + }]); + }); +}); + +/***/ }) + +/******/ }); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vc3JjL2JhY2tncm91bmQvYmFja2dyb3VuZC5qcyJdLCJuYW1lcyI6WyJjaHJvbWUiLCJydW50aW1lIiwib25JbnN0YWxsZWQiLCJhZGRMaXN0ZW5lciIsInN0b3JhZ2UiLCJzeW5jIiwic2V0IiwiaXNFeHRlbnNpb25PbiIsImNvbnNvbGUiLCJsb2ciLCJkZWNsYXJhdGl2ZUNvbnRlbnQiLCJvblBhZ2VDaGFuZ2VkIiwicmVtb3ZlUnVsZXMiLCJ1bmRlZmluZWQiLCJhZGRSdWxlcyIsImNvbmRpdGlvbnMiLCJQYWdlU3RhdGVNYXRjaGVyIiwicGFnZVVybCIsImhvc3RFcXVhbHMiLCJhY3Rpb25zIiwiU2hvd1BhZ2VBY3Rpb24iXSwibWFwcGluZ3MiOiI7UUFBQTtRQUNBOztRQUVBO1FBQ0E7O1FBRUE7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7O1FBRUE7UUFDQTs7UUFFQTtRQUNBOztRQUVBO1FBQ0E7UUFDQTs7O1FBR0E7UUFDQTs7UUFFQTtRQUNBOztRQUVBO1FBQ0E7UUFDQTtRQUNBLDBDQUEwQyxnQ0FBZ0M7UUFDMUU7UUFDQTs7UUFFQTtRQUNBO1FBQ0E7UUFDQSx3REFBd0Qsa0JBQWtCO1FBQzFFO1FBQ0EsaURBQWlELGNBQWM7UUFDL0Q7O1FBRUE7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBLHlDQUF5QyxpQ0FBaUM7UUFDMUUsZ0hBQWdILG1CQUFtQixFQUFFO1FBQ3JJO1FBQ0E7O1FBRUE7UUFDQTtRQUNBO1FBQ0EsMkJBQTJCLDBCQUEwQixFQUFFO1FBQ3ZELGlDQUFpQyxlQUFlO1FBQ2hEO1FBQ0E7UUFDQTs7UUFFQTtRQUNBLHNEQUFzRCwrREFBK0Q7O1FBRXJIO1FBQ0E7OztRQUdBO1FBQ0E7Ozs7Ozs7Ozs7OztBQ2xGQUEsTUFBTSxDQUFDQyxPQUFQLENBQWVDLFdBQWYsQ0FBMkJDLFdBQTNCLENBQXVDLFlBQVk7QUFDL0NILFFBQU0sQ0FBQ0ksT0FBUCxDQUFlQyxJQUFmLENBQW9CQyxHQUFwQixDQUF3QjtBQUFFQyxpQkFBYSxFQUFFO0FBQWpCLEdBQXhCLEVBQWlELFlBQVk7QUFDekRDLFdBQU8sQ0FBQ0MsR0FBUixDQUFZLG9CQUFvQixJQUFoQztBQUNILEdBRkQ7QUFJQVQsUUFBTSxDQUFDVSxrQkFBUCxDQUEwQkMsYUFBMUIsQ0FBd0NDLFdBQXhDLENBQW9EQyxTQUFwRCxFQUErRCxZQUFZO0FBQ3ZFYixVQUFNLENBQUNVLGtCQUFQLENBQTBCQyxhQUExQixDQUF3Q0csUUFBeEMsQ0FBaUQsQ0FBQztBQUM5Q0MsZ0JBQVUsRUFBRSxDQUFDLElBQUlmLE1BQU0sQ0FBQ1Usa0JBQVAsQ0FBMEJNLGdCQUE5QixDQUErQztBQUN4REMsZUFBTyxFQUFFO0FBQUVDLG9CQUFVLEVBQUU7QUFBZDtBQUQrQyxPQUEvQyxDQUFELENBRGtDO0FBSTlDQyxhQUFPLEVBQUUsQ0FBQyxJQUFJbkIsTUFBTSxDQUFDVSxrQkFBUCxDQUEwQlUsY0FBOUIsRUFBRDtBQUpxQyxLQUFELENBQWpEO0FBTUgsR0FQRDtBQVFILENBYkQsRSIsImZpbGUiOiJiYWNrZ3JvdW5kLmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZ2V0dGVyIH0pO1xuIFx0XHR9XG4gXHR9O1xuXG4gXHQvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSBmdW5jdGlvbihleHBvcnRzKSB7XG4gXHRcdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuIFx0XHR9XG4gXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG4gXHR9O1xuXG4gXHQvLyBjcmVhdGUgYSBmYWtlIG5hbWVzcGFjZSBvYmplY3RcbiBcdC8vIG1vZGUgJiAxOiB2YWx1ZSBpcyBhIG1vZHVsZSBpZCwgcmVxdWlyZSBpdFxuIFx0Ly8gbW9kZSAmIDI6IG1lcmdlIGFsbCBwcm9wZXJ0aWVzIG9mIHZhbHVlIGludG8gdGhlIG5zXG4gXHQvLyBtb2RlICYgNDogcmV0dXJuIHZhbHVlIHdoZW4gYWxyZWFkeSBucyBvYmplY3RcbiBcdC8vIG1vZGUgJiA4fDE6IGJlaGF2ZSBsaWtlIHJlcXVpcmVcbiBcdF9fd2VicGFja19yZXF1aXJlX18udCA9IGZ1bmN0aW9uKHZhbHVlLCBtb2RlKSB7XG4gXHRcdGlmKG1vZGUgJiAxKSB2YWx1ZSA9IF9fd2VicGFja19yZXF1aXJlX18odmFsdWUpO1xuIFx0XHRpZihtb2RlICYgOCkgcmV0dXJuIHZhbHVlO1xuIFx0XHRpZigobW9kZSAmIDQpICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgJiYgdmFsdWUuX19lc01vZHVsZSkgcmV0dXJuIHZhbHVlO1xuIFx0XHR2YXIgbnMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLnIobnMpO1xuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkobnMsICdkZWZhdWx0JywgeyBlbnVtZXJhYmxlOiB0cnVlLCB2YWx1ZTogdmFsdWUgfSk7XG4gXHRcdGlmKG1vZGUgJiAyICYmIHR5cGVvZiB2YWx1ZSAhPSAnc3RyaW5nJykgZm9yKHZhciBrZXkgaW4gdmFsdWUpIF9fd2VicGFja19yZXF1aXJlX18uZChucywga2V5LCBmdW5jdGlvbihrZXkpIHsgcmV0dXJuIHZhbHVlW2tleV07IH0uYmluZChudWxsLCBrZXkpKTtcbiBcdFx0cmV0dXJuIG5zO1xuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IFwiLi9zcmMvYmFja2dyb3VuZC9iYWNrZ3JvdW5kLmpzXCIpO1xuIiwiY2hyb21lLnJ1bnRpbWUub25JbnN0YWxsZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKCkge1xyXG4gICAgY2hyb21lLnN0b3JhZ2Uuc3luYy5zZXQoeyBpc0V4dGVuc2lvbk9uOiB0cnVlIH0sIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBjb25zb2xlLmxvZygnaXNFeHRlbnNpb25PbjogJyArIHRydWUpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgY2hyb21lLmRlY2xhcmF0aXZlQ29udGVudC5vblBhZ2VDaGFuZ2VkLnJlbW92ZVJ1bGVzKHVuZGVmaW5lZCwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGNocm9tZS5kZWNsYXJhdGl2ZUNvbnRlbnQub25QYWdlQ2hhbmdlZC5hZGRSdWxlcyhbe1xyXG4gICAgICAgICAgICBjb25kaXRpb25zOiBbbmV3IGNocm9tZS5kZWNsYXJhdGl2ZUNvbnRlbnQuUGFnZVN0YXRlTWF0Y2hlcih7XHJcbiAgICAgICAgICAgICAgICBwYWdlVXJsOiB7IGhvc3RFcXVhbHM6ICd2ay5jb20nIH0sXHJcbiAgICAgICAgICAgIH0pXSxcclxuICAgICAgICAgICAgYWN0aW9uczogW25ldyBjaHJvbWUuZGVjbGFyYXRpdmVDb250ZW50LlNob3dQYWdlQWN0aW9uKCldXHJcbiAgICAgICAgfV0pO1xyXG4gICAgfSk7XHJcbn0pOyJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/extension/dist/dom.js b/extension/dist/dom.js new file mode 100644 index 0000000..757e969 --- /dev/null +++ b/extension/dist/dom.js @@ -0,0 +1,887 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/dom/main.js"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./node_modules/css-loader/dist/cjs.js!./src/dom/dom.css": +/*!***************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./src/dom/dom.css ***! + \***************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +// Imports +var ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js"); +exports = ___CSS_LOADER_API_IMPORT___(false); +// Module +exports.push([module.i, ".mute_message .mutetooltip {\n visibility: hidden;\n width: 120px;\n background-color: #555;\n color: #fff;\n text-align: center;\n padding: 5px 0;\n border-radius: 6px;\n \n /* Position the tooltip text */\n position: absolute;\n z-index: 1;\n bottom: 125%;\n left: 50%;\n margin-left: -60px;\n \n /* Fade in tooltip */\n opacity: 0;\n transition: opacity 0.3s;\n}\n\n/* Tooltip arrow */\n.mute_message .mutetooltip::after {\n content: \"\";\n position: absolute;\n top: 100%;\n left: 50%;\n margin-left: -5px;\n border-width: 5px;\n border-style: solid;\n border-color: #555 transparent transparent transparent;\n}\n\n/* Show the tooltip text when you mouse over the tooltip container */\n.mute_message:hover .mutetooltip {\n visibility: visible;\n opacity: 1;\n}\n\n.mute_message {\n width: 16px;\n height: 16px;\n position: relative; \n display: inline-block;\n vertical-align: top;\n /*background: url('chrome-extension://__MSG_@@extension_id__/mute.png') !important;*/\n background-repeat: no-repeat;\n padding: 6px;\n}", ""]); +// Exports +module.exports = exports; + + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/api.js": +/*!*****************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/api.js ***! + \*****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +// css base code, injected by the css-loader +// eslint-disable-next-line func-names +module.exports = function (useSourceMap) { + var list = []; // return the list of modules as css string + + list.toString = function toString() { + return this.map(function (item) { + var content = cssWithMappingToString(item, useSourceMap); + + if (item[2]) { + return "@media ".concat(item[2], " {").concat(content, "}"); + } + + return content; + }).join(''); + }; // import a list of modules into the list + // eslint-disable-next-line func-names + + + list.i = function (modules, mediaQuery, dedupe) { + if (typeof modules === 'string') { + // eslint-disable-next-line no-param-reassign + modules = [[null, modules, '']]; + } + + var alreadyImportedModules = {}; + + if (dedupe) { + for (var i = 0; i < this.length; i++) { + // eslint-disable-next-line prefer-destructuring + var id = this[i][0]; + + if (id != null) { + alreadyImportedModules[id] = true; + } + } + } + + for (var _i = 0; _i < modules.length; _i++) { + var item = [].concat(modules[_i]); + + if (dedupe && alreadyImportedModules[item[0]]) { + // eslint-disable-next-line no-continue + continue; + } + + if (mediaQuery) { + if (!item[2]) { + item[2] = mediaQuery; + } else { + item[2] = "".concat(mediaQuery, " and ").concat(item[2]); + } + } + + list.push(item); + } + }; + + return list; +}; + +function cssWithMappingToString(item, useSourceMap) { + var content = item[1] || ''; // eslint-disable-next-line prefer-destructuring + + var cssMapping = item[3]; + + if (!cssMapping) { + return content; + } + + if (useSourceMap && typeof btoa === 'function') { + var sourceMapping = toComment(cssMapping); + var sourceURLs = cssMapping.sources.map(function (source) { + return "/*# sourceURL=".concat(cssMapping.sourceRoot || '').concat(source, " */"); + }); + return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); + } + + return [content].join('\n'); +} // Adapted from convert-source-map (MIT) + + +function toComment(sourceMap) { + // eslint-disable-next-line no-undef + var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); + var data = "sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(base64); + return "/*# ".concat(data, " */"); +} + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js": +/*!****************************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js ***! + \****************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var isOldIE = function isOldIE() { + var memo; + return function memorize() { + if (typeof memo === 'undefined') { + // Test for IE <= 9 as proposed by Browserhacks + // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805 + // Tests for existence of standard globals is to allow style-loader + // to operate correctly into non-standard environments + // @see https://github.com/webpack-contrib/style-loader/issues/177 + memo = Boolean(window && document && document.all && !window.atob); + } + + return memo; + }; +}(); + +var getTarget = function getTarget() { + var memo = {}; + return function memorize(target) { + if (typeof memo[target] === 'undefined') { + var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself + + if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { + try { + // This will throw an exception if access to iframe is blocked + // due to cross-origin restrictions + styleTarget = styleTarget.contentDocument.head; + } catch (e) { + // istanbul ignore next + styleTarget = null; + } + } + + memo[target] = styleTarget; + } + + return memo[target]; + }; +}(); + +var stylesInDom = []; + +function getIndexByIdentifier(identifier) { + var result = -1; + + for (var i = 0; i < stylesInDom.length; i++) { + if (stylesInDom[i].identifier === identifier) { + result = i; + break; + } + } + + return result; +} + +function modulesToDom(list, options) { + var idCountMap = {}; + var identifiers = []; + + for (var i = 0; i < list.length; i++) { + var item = list[i]; + var id = options.base ? item[0] + options.base : item[0]; + var count = idCountMap[id] || 0; + var identifier = "".concat(id, " ").concat(count); + idCountMap[id] = count + 1; + var index = getIndexByIdentifier(identifier); + var obj = { + css: item[1], + media: item[2], + sourceMap: item[3] + }; + + if (index !== -1) { + stylesInDom[index].references++; + stylesInDom[index].updater(obj); + } else { + stylesInDom.push({ + identifier: identifier, + updater: addStyle(obj, options), + references: 1 + }); + } + + identifiers.push(identifier); + } + + return identifiers; +} + +function insertStyleElement(options) { + var style = document.createElement('style'); + var attributes = options.attributes || {}; + + if (typeof attributes.nonce === 'undefined') { + var nonce = true ? __webpack_require__.nc : undefined; + + if (nonce) { + attributes.nonce = nonce; + } + } + + Object.keys(attributes).forEach(function (key) { + style.setAttribute(key, attributes[key]); + }); + + if (typeof options.insert === 'function') { + options.insert(style); + } else { + var target = getTarget(options.insert || 'head'); + + if (!target) { + throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid."); + } + + target.appendChild(style); + } + + return style; +} + +function removeStyleElement(style) { + // istanbul ignore if + if (style.parentNode === null) { + return false; + } + + style.parentNode.removeChild(style); +} +/* istanbul ignore next */ + + +var replaceText = function replaceText() { + var textStore = []; + return function replace(index, replacement) { + textStore[index] = replacement; + return textStore.filter(Boolean).join('\n'); + }; +}(); + +function applyToSingletonTag(style, index, remove, obj) { + var css = remove ? '' : obj.media ? "@media ".concat(obj.media, " {").concat(obj.css, "}") : obj.css; // For old IE + + /* istanbul ignore if */ + + if (style.styleSheet) { + style.styleSheet.cssText = replaceText(index, css); + } else { + var cssNode = document.createTextNode(css); + var childNodes = style.childNodes; + + if (childNodes[index]) { + style.removeChild(childNodes[index]); + } + + if (childNodes.length) { + style.insertBefore(cssNode, childNodes[index]); + } else { + style.appendChild(cssNode); + } + } +} + +function applyToTag(style, options, obj) { + var css = obj.css; + var media = obj.media; + var sourceMap = obj.sourceMap; + + if (media) { + style.setAttribute('media', media); + } else { + style.removeAttribute('media'); + } + + if (sourceMap && btoa) { + css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */"); + } // For old IE + + /* istanbul ignore if */ + + + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + while (style.firstChild) { + style.removeChild(style.firstChild); + } + + style.appendChild(document.createTextNode(css)); + } +} + +var singleton = null; +var singletonCounter = 0; + +function addStyle(obj, options) { + var style; + var update; + var remove; + + if (options.singleton) { + var styleIndex = singletonCounter++; + style = singleton || (singleton = insertStyleElement(options)); + update = applyToSingletonTag.bind(null, style, styleIndex, false); + remove = applyToSingletonTag.bind(null, style, styleIndex, true); + } else { + style = insertStyleElement(options); + update = applyToTag.bind(null, style, options); + + remove = function remove() { + removeStyleElement(style); + }; + } + + update(obj); + return function updateStyle(newObj) { + if (newObj) { + if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) { + return; + } + + update(obj = newObj); + } else { + remove(); + } + }; +} + +module.exports = function (list, options) { + options = options || {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of