shr-buttons
Version:
Simple, customizable sharing buttons
1 lines • 45.3 kB
Source Map (JSON)
{"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"]}