{"version":3,"sources":["src/js/shr.js","src/js/utils/is.js","src/js/config/constants.js","src/js/config/defaults.js","src/js/utils/ajax.js","src/js/utils/console.js","src/js/utils/css.js","src/js/utils/elements.js","src/js/utils/numbers.js","src/js/utils/objects.js","src/js/utils/storage.js","src/js/utils/urls.js"],"names":["_classCallCheck","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_createClass","protoProps","staticProps","prototype","_defineProperty","obj","value","_slicedToArray","arr","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","Array","isArray","_arr","_n","_d","_e","undefined","_s","_i","Symbol","iterator","next","done","push","err","getConstructor","input","constructor","instanceOf","isNullOrUndefined","isObject","isNumber","Number","isNaN","isString","String","isBoolean","Boolean","isFunction","Function","isNodeList","NodeList","isElement","Element","isEvent","Event","isEmpty","keys","is","nullOrUndefined","object","number","string","boolean","function","array","nodeList","element","event","empty","constants","facebook","domain","url","concat","shareCount","data","og_object","engagement","count","popup","width","height","twitter","pinterest","github","path","token","stargazers_count","youtube","id","error","first","items","statistics","subscriberCount","defaults","debug","wrapper","className","displayZero","format","position","increment","tokens","storage","enabled","ttl","getJSONP","Promise","resolve","reject","name","Math","round","random","script","document","createElement","addEventListener","window","body","removeChild","src","URL","searchParams","set","setAttribute","toString","appendChild","noop","Console","a","arguments","this","console","log","get","bind","call","warn","matches","selector","from","querySelectorAll","includes","wrap","elements","targets","reverse","forEach","index","child","cloneNode","parent","parentNode","sibling","nextSibling","insertBefore","setAttributes","attributes","entries","filter","b","c","type","text","innerText","formatNumber","decimalSeparator","test","toLocaleString","regex","RegExp","replace","extend","sources","d","source","shift","assign","apply","Storage","supported","store","localStorage","getItem","Date","now","json","JSON","parse","setItem","stringify","removeItem","e","getDomain","href","hostname","parts","split","Shr","options","trigger","querySelector","shr","config","networks","getCount","then","updateDisplay","catch","listeners","method","share","openPopup","network","networkConfig","preventDefault","size","closed","focus","left","screenLeft","screen","top","screenTop","x","y","open","useCache","apiUrl","Error","cached","custom","getAttribute","parseInt","toLowerCase","unit","label","textContent","class","insertAdjacentElement","find","n","pathname","substring","pop","encodeURIComponent","watch","MutationObserver","mutations","mutation","addedNodes","node","observe","childList","subtree","map","t"],"mappings":"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","file":"shr.mjs","sourcesContent":["/**\n * @name    Shr.js\n * @version 2.0.2\n * @author \tSam Potts\n * @license MIT\n */\n\nimport constants from './config/constants';\nimport defaults from './config/defaults';\nimport { getJSONP } from './utils/ajax';\nimport Console from './utils/console';\nimport { matches } from './utils/css';\nimport { createElement, wrap } from './utils/elements';\nimport is from './utils/is';\nimport { formatNumber } from './utils/numbers';\nimport { extend } from './utils/objects';\nimport Storage from './utils/storage';\nimport { getDomain } from './utils/urls';\n\nclass Shr {\n    /**\n     * Setup a new instance\n     * @param {String|Element} target\n     * @param {Object} options\n     */\n    constructor(target, options) {\n        this.elements = {\n            count: null,\n            trigger: null,\n            popup: null,\n        };\n\n        if (is.element(target)) {\n            // An Element is passed, use it directly\n            this.elements.trigger = target;\n        } else if (is.string(target)) {\n            // A CSS Selector is passed, fetch it from the DOM\n            this.elements.trigger = document.querySelector(target);\n        }\n\n        if (!is.element(this.elements.trigger) || !is.empty(this.elements.trigger.shr)) {\n            return;\n        }\n\n        this.config = extend({}, defaults, options, { networks: constants });\n\n        this.console = new Console(this.config.debug);\n\n        this.storage = new Storage(this.config.storage.key, this.config.storage.ttl, this.config.storage.enabled);\n\n        this.getCount()\n            .then(data => this.updateDisplay(data))\n            .catch(() => {});\n\n        this.listeners(true);\n\n        this.elements.trigger.shr = this;\n    }\n\n    /**\n     * Destroy the current instance\n     * @returns {Void}\n     */\n    destroy() {\n        this.listeners(false);\n\n        // TODO: Remove the count and unwrap\n    }\n\n    /**\n     * Setup event listeners\n     * @returns {Void}\n     */\n    listeners(toggle = false) {\n        const method = toggle ? 'addEventListener' : 'removeEventListener';\n\n        this.elements.trigger[method]('click', event => this.share(event), false);\n    }\n\n    /**\n     * Gets the href from the trigger link\n     * @returns {String}    The href attribute from the link\n     */\n    get href() {\n        if (!is.element(this.elements.trigger)) {\n            return null;\n        }\n\n        return this.elements.trigger.href;\n    }\n\n    /**\n     * Gets the network for this instance\n     * @returns {String}    The network name in lowercase\n     */\n    get network() {\n        if (!is.element(this.elements.trigger)) {\n            return null;\n        }\n\n        const { networks } = this.config;\n\n        return Object.keys(networks).find(n => getDomain(this.href) === networks[n].domain);\n    }\n\n    /**\n     * Gets the config for the specified network\n     * @returns {Object}    The config options\n     */\n    get networkConfig() {\n        if (is.empty(this.network)) {\n            return null;\n        }\n\n        return this.config.networks[this.network];\n    }\n\n    /**\n     * Gets the URL or ID we are geting the share count for\n     * @returns {String}    The target ID or URL we're sharing\n     */\n    get target() {\n        if (is.empty(this.network)) {\n            return null;\n        }\n\n        const url = new URL(this.href);\n\n        switch (this.network) {\n            case 'facebook':\n                return url.searchParams.get('u');\n\n            case 'github':\n                return url.pathname.substring(1);\n\n            case 'youtube':\n                return url.pathname.split('/').pop();\n\n            default:\n                return url.searchParams.get('url');\n        }\n    }\n\n    /**\n     * Gets for the URL for the JSONP endpoint\n     * @returns {String}    The URL for the JSONP endpoint\n     */\n    get apiUrl() {\n        if (is.empty(this.network)) {\n            return null;\n        }\n\n        const { tokens } = this.config;\n\n        switch (this.network) {\n            case 'github':\n                return this.networkConfig.url(this.target, tokens.github);\n\n            case 'youtube':\n                return this.networkConfig.url(this.target, tokens.youtube);\n\n            default:\n                return this.networkConfig.url(encodeURIComponent(this.target));\n        }\n    }\n\n    /**\n     * Initiate the share process\n     * This must be user triggered or the popup will be blocked\n     * @param {Event} event     The user input event\n     * @returns {Void}\n     */\n    share(event) {\n        this.openPopup(event);\n\n        const { increment } = this.config.count;\n\n        this.getCount()\n            .then(data => this.updateDisplay(data, increment))\n            .catch(() => {});\n    }\n\n    /**\n     * Displays a pop up window to share on the requested social network.\n     * @param {Event} event   - Event that triggered the popup window.\n     * @returns {Void}\n     */\n    openPopup(event) {\n        // Only popup if we need to...\n        if (is.empty(this.network) || !this.networkConfig.popup) {\n            return;\n        }\n\n        // Prevent the link opening\n        if (is.event(event)) {\n            event.preventDefault();\n        }\n\n        // Set variables for the popup\n        const size = this.networkConfig.popup;\n        const { width, height } = size;\n        const name = `shr-popup--${this.network}`;\n\n        // If window already exists, just focus it\n        if (this.popup && !this.popup.closed) {\n            this.popup.focus();\n\n            this.console.log('Popup re-focused.');\n        } else {\n            // Get position\n            const left = window.screenLeft !== undefined ? window.screenLeft : window.screen.left;\n            const top = window.screenTop !== undefined ? window.screenTop : window.screen.top;\n            // Open in the centre of the screen\n            const x = window.screen.width / 2 - width / 2 + left;\n            const y = window.screen.height / 2 - height / 2 + top;\n\n            // Open that window\n            this.popup = window.open(this.href, name, `top=${y},left=${x},width=${width},height=${height}`);\n\n            // Determine if the popup was blocked\n            const blocked = !this.popup || this.popup.closed || !is.boolean(this.popup.closed);\n\n            // Focus new window\n            if (!blocked) {\n                this.popup.focus();\n\n                // Nullify opener to prevent \"tab nabbing\"\n                // https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/\n                // this.popup.opener = null;\n\n                this.console.log('Popup opened.');\n            } else {\n                this.console.error('Popup blocked.');\n            }\n        }\n    }\n\n    /**\n     * Get the count for the url from API\n     * @param {Boolean} useCache        Whether to use the local storage cache or not\n     * @returns {Promise}\n     */\n    getCount(useCache = true) {\n        return new Promise((resolve, reject) => {\n            // Format the JSONP endpoint\n            const url = this.apiUrl;\n\n            // If there's an endpoint. For some social networks, you can't\n            // get the share count (like Twitter) so we won't have any data. The link\n            // will be to share it, but you won't get a count of how many people have.\n\n            if (is.empty(url)) {\n                reject(new Error(`No URL available for ${this.network}.`));\n                return;\n            }\n\n            // Check cache first\n            if (useCache) {\n                const cached = this.storage.get(this.target);\n\n                if (!is.empty(cached) && Object.keys(cached).includes(this.network)) {\n                    const count = cached[this.network];\n                    resolve(is.number(count) ? count : 0);\n                    this.console.log(`getCount for '${this.target}' for '${this.network}' resolved from cache.`);\n                    return;\n                }\n            }\n\n            // When we get here, this means the cached counts are not valid,\n            // or don't exist. We will call the API if the URL is available\n            // at this point.\n\n            // Runs a GET request on the URL\n            getJSONP(url)\n                .then(data => {\n                    let count = 0;\n                    const custom = this.elements.trigger.getAttribute('data-shr-display');\n\n                    // Get value based on config\n                    if (!is.empty(custom)) {\n                        count = data[custom];\n                    } else {\n                        count = this.networkConfig.shareCount(data);\n                    }\n\n                    // Default to zero for undefined\n                    if (is.empty(count)) {\n                        count = 0;\n                    } else {\n                        // Parse\n                        count = parseInt(count, 10);\n\n                        // Handle NaN\n                        if (!is.number(count)) {\n                            count = 0;\n                        }\n                    }\n\n                    // Cache in local storage\n                    this.storage.set({\n                        [this.target]: {\n                            [this.network]: count,\n                        },\n                    });\n\n                    resolve(count);\n                })\n                .catch(reject);\n        });\n    }\n\n    /**\n     * Display the count\n     * @param {Number} input         - The count returned from the share count API\n     * @param {Boolean} increment   -  Determines if we should increment the count or not\n     * @returns {Void}\n     */\n    updateDisplay(input, increment = false) {\n        const { count, wrapper } = this.config;\n        // If we're incrementing (e.g. on click)\n        const number = increment ? input + 1 : input;\n        // Standardize position\n        const position = count.position.toLowerCase();\n\n        // Only display if there's a count\n        if (number > 0 || count.displayZero) {\n            const isAfter = position === 'after';\n            const round = unit => Math.round((number / unit) * 10) / 10;\n            let label = formatNumber(number);\n\n            // Format to 1K, 1M, etc\n            if (count.format) {\n                if (number > 1000000) {\n                    label = `${round(1000000)}M`;\n                } else if (number > 1000) {\n                    label = `${round(1000)}K`;\n                }\n            }\n\n            // Update or insert\n            if (is.element(this.elements.count)) {\n                this.elements.count.textContent = label;\n            } else {\n                // Add wrapper\n                wrap(\n                    this.elements.trigger,\n                    createElement('span', {\n                        class: wrapper.className,\n                    }),\n                );\n\n                // Create count display\n                this.elements.count = createElement(\n                    'span',\n                    {\n                        class: `${count.className} ${count.className}--${position}`,\n                    },\n                    label,\n                );\n\n                // Insert count display\n                this.elements.trigger.insertAdjacentElement(isAfter ? 'afterend' : 'beforebegin', this.elements.count);\n            }\n        }\n    }\n\n    /**\n     * Setup multiple instances\n     * @param {String|Element|NodeList|Array} target\n     * @param {Object} options\n     * @returns {Array} - An array of instances\n     */\n    static setup(target, options = {}) {\n        let targets = null;\n\n        if (is.string(target)) {\n            targets = Array.from(document.querySelectorAll(target));\n        } else if (is.element(target)) {\n            targets = [target];\n        } else if (is.nodeList(target)) {\n            targets = Array.from(target);\n        } else if (is.array(target)) {\n            targets = target.filter(is.element);\n        }\n\n        if (is.empty(targets)) {\n            return null;\n        }\n\n        const config = Object.assign({}, defaults, options);\n\n        if (is.string(target) && config.watch) {\n            // Create an observer instance\n            const observer = new MutationObserver(mutations => {\n                Array.from(mutations).forEach(mutation => {\n                    Array.from(mutation.addedNodes).forEach(node => {\n                        if (!is.element(node) || !matches(node, target)) {\n                            return;\n                        }\n\n                        // eslint-disable-next-line no-unused-vars\n                        const share = new Shr(node, config);\n                    });\n                });\n            });\n\n            // Pass in the target node, as well as the observer options\n            observer.observe(document.body, {\n                childList: true,\n                subtree: true,\n            });\n        }\n\n        return targets.map(t => new Shr(t, options));\n    }\n}\n\nexport default Shr;\n","// ==========================================================================\n// Type checking utils\n// ==========================================================================\n\nconst getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null);\nconst instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\nconst isNullOrUndefined = input => input === null || typeof input === 'undefined';\nconst isObject = input => getConstructor(input) === Object;\nconst isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);\nconst isString = input => getConstructor(input) === String;\nconst isBoolean = input => getConstructor(input) === Boolean;\nconst isFunction = input => getConstructor(input) === Function;\nconst isArray = input => Array.isArray(input);\nconst isNodeList = input => instanceOf(input, NodeList);\nconst isElement = input => instanceOf(input, Element);\nconst isEvent = input => instanceOf(input, Event);\nconst isEmpty = input =>\n    isNullOrUndefined(input) ||\n    ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||\n    (isObject(input) && !Object.keys(input).length);\n\nexport default {\n    nullOrUndefined: isNullOrUndefined,\n    object: isObject,\n    number: isNumber,\n    string: isString,\n    boolean: isBoolean,\n    function: isFunction,\n    array: isArray,\n    nodeList: isNodeList,\n    element: isElement,\n    event: isEvent,\n    empty: isEmpty,\n};\n","import is from '../utils/is';\n\n/**\n * Constants. These are uneditable by the user. These will get merged into\n * the global config after the user defaults so the user can't overwrite these\n * values.\n *\n * @typedef {Object} constants\n * @type {Object}\n *\n * @property {Object} facebook                 - The settings for Facebook within Shr.\n * @property {function} facebook.url          - The method that returns the API Url to get the share count for Facebook.\n * @property {function} facebook.shareCount   - The method that extracts the number we need from the data returned from the API for Facebook.\n *\n * @property {Object} twitter                 - The settings for Twitter within Shr.\n * @property {function} twitter.url           - The method that returns the API Url to get the share count for Twitter.\n * @property {function} twitter.shareCount    - The method that extracts the number we need from the data returned from the API for Twitter.\n *\n * @property {Object} pinterest               - The settings for Pinterest within Shr.\n * @property {function} pinterest.url         - The method that returns the API Url to get the share count for Pinterest.\n * @property {function} pinterest.shareCount  - The method that extracts the number we need from the data returned from the API for Pinterest.\n *\n * @property {Object} github                  - The settings for GitHub within Shr.\n * @property {function} github.url            - The method that returns the API Url to get the share count for GitHub.\n * @property {function} github.shareCount     - The method that extracts the number we need from the data returned from the API for GitHub.\n */\n\nconst constants = {\n    facebook: {\n        domain: 'facebook.com',\n        url: url => `https://graph.facebook.com/?id=${url}&fields=og_object{engagement}`,\n        shareCount: data => data.og_object.engagement.count,\n        popup: {\n            width: 640,\n            height: 360,\n        },\n    },\n\n    twitter: {\n        domain: 'twitter.com',\n        url: () => null,\n        shareCount: () => null,\n        popup: {\n            width: 640,\n            height: 240,\n        },\n    },\n\n    pinterest: {\n        domain: 'pinterest.com',\n        url: url => `https://widgets.pinterest.com/v1/urls/count.json?url=${url}`,\n        shareCount: data => data.count,\n        popup: {\n            width: 830,\n            height: 700,\n        },\n    },\n\n    github: {\n        domain: 'github.com',\n        url: (path, token) => `https://api.github.com/repos/${path}${is.string(token) ? `?access_token=${token}` : ''}`,\n        shareCount: data => data.data.stargazers_count,\n    },\n\n    youtube: {\n        domain: 'youtube.com',\n        url: (id, key) => `https://www.googleapis.com/youtube/v3/channels?part=statistics&id=${id}&key=${key}`,\n        shareCount: data => {\n            if (!is.empty(data.error)) {\n                return null;\n            }\n\n            const [first] = data.items;\n\n            if (is.empty(first)) {\n                return null;\n            }\n\n            return first.statistics.subscriberCount;\n        },\n    },\n};\n\nexport default constants;\n","/**\n * Default Shr Config. All variables, settings and states are stored here\n * and global. These are the defaults. The user can edit these at will when\n * initializing Shr.\n *\n * @typedef {Object} defaults\n * @type {Object}\n *\n * @property {Boolean}  debug                 - The flag for if we debug Shr or not. By defaul this is false.\n\n * @property {Object}   wrapper                 The object containing the settings for the wrapper that's added.\n * @property {String}   wrapper.className       Classname for the wrapper.\n\n * @property {Object}   count                 - The object containing the settings for the count.\n * @property {String}   count.className       - Classname for the share count.\n * @property {Boolean}  count.displayZero     - Determines if we display zero values.\n * @property {Boolean}  count.format          - Display 1000 as 1K, 1000000 as 1M, etc\n * @property {String}   count.position        - Inject the count before or after the link in the DOM\n * @property {Boolean}  count.increment       - Determines if we increment the count on click. This assumes the share is valid.\n *\n * @property {Object}   tokens                 - The object containing authentication tokens.\n * @property {Object}   tokens.github            The optional authentication tokens for GitHub (to prevent rate limiting).\n * @property {String}   tokens.youtube           The public key you need to get the subscriber count for YouTube.\n *\n * @property {Object}   storage                - The object containing the settings for local storage.\n * @property {Boolean}  storage.enabled       -  Determines if local storage is enabled for the browser or not.\n * @property {String}   storage.key            - The key that the storage will use to access Shr data.\n * @property {Number}   storage.ttl            - The time to live for the local storage values if available.\n*/\n\n/**\n *\n */\n\nconst defaults = {\n    debug: false,\n    wrapper: {\n        className: 'shr',\n    },\n    count: {\n        className: 'shr__count',\n        displayZero: false,\n        format: true,\n        position: 'after',\n        increment: true,\n    },\n    tokens: {\n        github: '',\n        youtube: '',\n    },\n    storage: {\n        enabled: true,\n        key: 'shr',\n        ttl: 300000,\n    },\n};\n\nexport default defaults;\n","/**\n * Makes the JSONP request to get the social network to get the share count.\n *\n * @param {string} url          - The URL of the of the sharing API.\n * @param {function} callback   - The callback funciton once the API completes the request.\n */\nexport function getJSONP(url) {\n    return new Promise((resolve, reject) => {\n        // Generate a random callback\n        const name = `jsonp_callback_${Math.round(100000 * Math.random())}`;\n        // Create a faux script\n        const script = document.createElement('script');\n\n        // Handle errors\n        script.addEventListener('error', error => reject(error));\n\n        // Cleanup to prevent memory leaks and hit original callback\n        window[name] = data => {\n            delete window[name];\n            document.body.removeChild(script);\n            resolve(data);\n        };\n\n        // Add callback to URL\n        const src = new URL(url);\n        src.searchParams.set('callback', name);\n\n        // Set src and load\n        script.setAttribute('src', src.toString());\n\n        // Inject to the body\n        document.body.appendChild(script);\n    });\n}\n\nexport default { getJSONP };\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n    constructor(enabled = false) {\n        this.enabled = window.console && enabled;\n\n        if (this.enabled) {\n            this.log('Debugging enabled');\n        }\n    }\n\n    get log() {\n        return this.enabled\n            ? Function.prototype.bind.call(console.log, console) // eslint-disable-line no-console\n            : noop;\n    }\n\n    get warn() {\n        return this.enabled\n            ? Function.prototype.bind.call(console.warn, console) // eslint-disable-line no-console\n            : noop;\n    }\n\n    get error() {\n        return this.enabled\n            ? Function.prototype.bind.call(console.error, console) // eslint-disable-line no-console\n            : noop;\n    }\n}\n","// Element matches a selector\nexport function matches(element, selector) {\n    const prototype = { Element };\n\n    function match() {\n        return Array.from(document.querySelectorAll(selector)).includes(this);\n    }\n\n    const method =\n        prototype.matches ||\n        prototype.webkitMatchesSelector ||\n        prototype.mozMatchesSelector ||\n        prototype.msMatchesSelector ||\n        match;\n\n    return method.call(element, selector);\n}\n\nexport default { matches };\n","import is from './is';\n\n/**\n * Wrap one or more HTMLElement in wrapper container\n * @param {HTMLElement[]} elements\n * @param {HTMLElement} wrapper\n * @returns {Void}\n */\nexport function wrap(elements, wrapper) {\n    // Convert `elements` to an array, if necessary.\n    const targets = elements.length ? elements : [elements];\n\n    // Loops backwards to prevent having to clone the wrapper on the\n    // first element (see `child` below).\n    Array.from(targets)\n        .reverse()\n        .forEach((element, index) => {\n            const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n            // Cache the current parent and sibling.\n            const parent = element.parentNode;\n            const sibling = element.nextSibling;\n\n            // Wrap the element (is automatically removed from its current\n            // parent).\n            child.appendChild(element);\n\n            // If the element had a sibling, insert the wrapper before\n            // the sibling to maintain the HTML structure; otherwise, just\n            // append it to the parent.\n            if (sibling) {\n                parent.insertBefore(child, sibling);\n            } else {\n                parent.appendChild(child);\n            }\n        });\n}\n\n/**\n * Set HTMLElement attributes\n * @param {HTMLElement} element\n * @param {Object} attributes\n * @returns {Void}\n */\nexport function setAttributes(element, attributes) {\n    if (!is.element(element) || is.empty(attributes)) {\n        return;\n    }\n\n    // Assume null and undefined attributes should be left out,\n    // Setting them would otherwise convert them to \"null\" and \"undefined\"\n    Object.entries(attributes)\n        .filter(([, value]) => !is.nullOrUndefined(value))\n        .forEach(([key, value]) => element.setAttribute(key, value));\n}\n\n/**\n * Create a HTMLElement\n * @param {String} type - Type of element to create\n * @param {Object} attributes - Object of HTML attributes\n * @param {String} text - Sets the text content\n * @returns {HTMLElement}\n */\nexport function createElement(type, attributes, text) {\n    // Create a new <element>\n    const element = document.createElement(type);\n\n    // Set all passed attributes\n    if (is.object(attributes)) {\n        setAttributes(element, attributes);\n    }\n\n    // Add text node\n    if (is.string(text)) {\n        element.innerText = text;\n    }\n\n    // Return built element\n    return element;\n}\n\nexport default { wrap };\n","export function formatNumber(number) {\n    // Work out whether decimal separator is . or , for localised numbers\n    const decimalSeparator = /\\./.test((1.1).toLocaleString()) ? '.' : ',';\n    // Round n to an integer and present\n    const regex = new RegExp(`\\\\${decimalSeparator}\\\\d+$`);\n\n    return Math.round(number)\n        .toLocaleString()\n        .replace(regex, '');\n}\n\nexport default { formatNumber };\n","// ==========================================================================\n// Object utils\n// ==========================================================================\n\nimport is from './is';\n\n// Deep extend destination object with N more objects\nexport function extend(target = {}, ...sources) {\n    if (!sources.length) {\n        return target;\n    }\n\n    const source = sources.shift();\n\n    if (!is.object(source)) {\n        return target;\n    }\n\n    Object.keys(source).forEach(key => {\n        if (is.object(source[key])) {\n            if (!Object.keys(target).includes(key)) {\n                Object.assign(target, { [key]: {} });\n            }\n\n            extend(target[key], source[key]);\n        } else {\n            Object.assign(target, { [key]: source[key] });\n        }\n    });\n\n    return extend(target, ...sources);\n}\n\nexport default { extend };\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport is from './is';\nimport { extend } from './objects';\n\nclass Storage {\n    constructor(key, ttl, enabled = true) {\n        this.enabled = enabled && Storage.supported;\n        this.key = key;\n        this.ttl = ttl;\n    }\n\n    // Check for actual support (see if we can use it)\n    static get supported() {\n        try {\n            if (!('localStorage' in window)) {\n                return false;\n            }\n\n            const test = '___test';\n\n            // Try to use it (it might be disabled, e.g. user is in private mode)\n            // see: https://github.com/sampotts/plyr/issues/131\n            window.localStorage.setItem(test, test);\n            window.localStorage.removeItem(test);\n\n            return true;\n        } catch (e) {\n            return false;\n        }\n    }\n\n    get(key) {\n        if (!Storage.supported || !this.enabled) {\n            return null;\n        }\n\n        const store = window.localStorage.getItem(this.key);\n\n        if (is.empty(store)) {\n            return null;\n        }\n\n        // Check TTL\n        const ttl = window.localStorage.getItem(`${this.key}_ttl`);\n\n        if (is.empty(ttl) || ttl < Date.now()) {\n            return null;\n        }\n\n        const json = JSON.parse(store);\n\n        return is.string(key) && key.length ? json[key] : json;\n    }\n\n    set(object) {\n        // Bail if we don't have localStorage support or it's disabled\n        if (!Storage.supported || !this.enabled) {\n            return;\n        }\n\n        // Can only store objectst\n        if (!is.object(object)) {\n            return;\n        }\n\n        // Get current storage\n        let storage = this.get();\n\n        // Default to empty object\n        if (is.empty(storage)) {\n            storage = {};\n        }\n\n        // Update the working copy of the values\n        extend(storage, object);\n\n        // Update storage and TTL record\n        window.localStorage.setItem(this.key, JSON.stringify(storage));\n        window.localStorage.setItem(`${this.key}_ttl`, Date.now() + this.ttl);\n    }\n}\n\nexport default Storage;\n","export function getDomain(href) {\n    const url = new URL(href);\n    let domain = url.hostname;\n    const parts = domain.split('.');\n    const { length } = parts;\n\n    // Extract the root domain\n    if (length > 2) {\n        domain = `${parts[length - 2]}.${parts[length - 1]}`;\n\n        // Check to see if it's using a Country Code Top Level Domain (ccTLD) (i.e. \".me.uk\")\n        if (parts[length - 2].length === 2 && parts[length - 1].length === 2) {\n            domain = `${parts[length - 3]}.${domain}`;\n        }\n    }\n\n    return domain;\n}\n\nexport default { getDomain };\n"]}