filesafe/dist/js/misc/newsfeed.js.map
Bobby Wibowo 6daa1e529e
Added src/js/misc/newsfeed.js
A small script to pull feed from blog.fiery.me as news thingy.
2020-07-28 03:46:15 +07:00

1 line
9.9 KiB
Plaintext

{"version":3,"sources":["newsfeed.js"],"names":["const","newsfeed","lsKey","feedUrl","maxItems","dismissed","done","simpleParseDate","string","months","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","match","undefined","date","Date","setUTCDate","setUTCMonth","setUTCFullYear","setUTCHours","setUTCMinutes","setUTCSeconds","formatRelativeDate","delta","fuzzy","unit","minute","Math","floor","hour","day","formatNotification","item","parsedDate","pubDate","dateDelta","round","isRecentWeek","element","document","createElement","dataset","identifier","className","innerHTML","title","description","slice","toLocaleString","dismissNotification","parentNode","removeChild","keys","Object","length","let","i","localStorage","JSON","stringify","do","axios","get","responseType","then","response","data","documentElement","Element","Error","items","querySelectorAll","parse","id","column","querySelector","min","titleElement","descriptionElement","pubDateElement","linkElement","textContent","link","notificationElement","addEventListener","event","target","appendChild","body","catch","console","error","onloaded","page","apiChecked","readyState","window"],"mappings":"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","file":"newsfeed.js","sourcesContent":["/* global page, axios */\n\nconst newsfeed = {\n lsKey: 'newsfeed',\n feedUrl: 'https://blog.fiery.me/rss-newsfeed.xml',\n maxItems: 3,\n dismissed: {},\n done: false\n}\n\nnewsfeed.simpleParseDate = string => {\n // For now limited to support the following examples (used in blog.fiery.me):\n // Mon, 27 Jul 2020 18:30:00 GMT\n // Sat, 16 May 2020 14:55:00 GMT\n // Probably better to use a library if it needs to support other formats.\n const months = { Jan: 0, Feb: 1, Mar: 2, Apr: 3, May: 4, Jun: 5, Jul: 6, Aug: 7, Sep: 8, Oct: 9, Nov: 10, Dec: 11 }\n const match = string.match(/[a-zA-Z]*,\\s(\\d{2})\\s([a-zA-Z]{3})\\s(\\d{4})\\s(\\d{2}):(\\d{2}):(\\d{2})\\sGMT/)\n if (match && (months[match[2]] !== undefined)) {\n const date = new Date()\n date.setUTCDate(match[1])\n date.setUTCMonth(months[match[2]])\n date.setUTCFullYear(match[3])\n date.setUTCHours(match[4])\n date.setUTCMinutes(match[5])\n date.setUTCSeconds(match[6])\n return date\n }\n}\n\nnewsfeed.formatRelativeDate = delta => {\n // https://stackoverflow.com/a/7641812\n const minute = 60\n const hour = minute * 60\n const day = hour * 24\n const week = day * 7\n\n let fuzzy\n let unit\n if (delta < minute) {\n fuzzy = delta\n unit = 'second'\n } else if (delta < hour) {\n fuzzy = Math.floor(delta / minute)\n unit = 'minute'\n } else if (delta < day) {\n fuzzy = Math.floor(delta / hour)\n unit = 'hour'\n } else if (delta < week) {\n fuzzy = Math.floor(delta / day)\n unit = 'day'\n } else {\n fuzzy = Math.floor(delta / week)\n unit = 'week'\n }\n\n return `${fuzzy} ${unit}${fuzzy !== 1 ? 's' : ''} ago`\n}\n\nnewsfeed.formatNotification = item => {\n const parsedDate = newsfeed.simpleParseDate(item.pubDate)\n const dateDelta = Math.round((+new Date() - parsedDate) / 1000)\n const isRecentWeek = dateDelta <= 604800\n\n const element = document.createElement('div')\n element.dataset.identifier = item.identifier\n element.className = 'notification is-info'\n element.innerHTML = `\n <button class=\"delete\" title=\"Dismiss\"></button>\n <div class=\"content\">\n <div class=\"news-title\">\n <a href=\"${item.link}\" target=\"_blank\">${item.title || 'Untitled'}</a>\n </div>\n <div class=\"news-excerpt\">\n ${item.description\n ? `${item.description.slice(-1) === '…'\n ? `${item.description.slice(0, -1)} <a href=\"${item.link}\" target=\"_blank\">[…]</a>`\n : item.description}`\n : 'N/A'}\n </div>\n <div class=\"news-date${isRecentWeek ? ' is-recent-week' : ''}\" title=\"${parsedDate.toLocaleString()}\">\n ${newsfeed.formatRelativeDate(dateDelta)}\n </div>\n <div>\n `\n return element\n}\n\nnewsfeed.dismissNotification = element => {\n if (!element || !element.dataset.identifier) return\n\n newsfeed.dismissed[element.dataset.identifier] = 1\n element.parentNode.removeChild(element)\n\n const keys = Object.keys(newsfeed.dismissed)\n if (keys.length > newsfeed.maxItems)\n for (let i = 0; i < keys.length - newsfeed.maxItems; i++)\n delete newsfeed.dismissed[keys[i]]\n\n localStorage[newsfeed.lsKey] = JSON.stringify(newsfeed.dismissed)\n}\n\nnewsfeed.do = () => {\n return axios.get(newsfeed.feedUrl, {\n responseType: 'document'\n }).then(response => {\n if (response && response.data && response.data.documentElement instanceof Element) {\n const items = response.data.documentElement.querySelectorAll('item')\n\n if (items.length) {\n const dismissed = localStorage[newsfeed.lsKey]\n if (dismissed)\n newsfeed.dismissed = JSON.parse(dismissed)\n\n const element = document.createElement('section')\n element.id = 'newsfeed'\n element.className = 'section'\n element.innerHTML = `\n <div class=\"columns is-gapless\">\n <div class=\"column is-hidden-mobile\"></div>\n <div class=\"column is-hidden-mobile\"></div>\n <div class=\"column\"></div>\n </div>\n `\n const column = element.querySelector('.columns > .column:last-child')\n\n for (let i = 0; i < Math.min(newsfeed.maxItems, items.length); i++) {\n const titleElement = items[i].querySelector('title')\n const descriptionElement = items[i].querySelector('description')\n const pubDateElement = items[i].querySelector('pubDate')\n const linkElement = items[i].querySelector('link')\n\n const title = titleElement ? titleElement.textContent : ''\n const description = descriptionElement ? descriptionElement.textContent : ''\n const pubDate = pubDateElement ? pubDateElement.textContent : ''\n const link = linkElement ? linkElement.textContent : ''\n\n const identifier = title + '|' + description + '|' + pubDate + '|' + link\n\n if (!newsfeed.dismissed[identifier]) {\n const notificationElement = newsfeed.formatNotification({\n title, description, pubDate, link, identifier\n })\n\n notificationElement.querySelector('.delete').addEventListener('click', function () {\n newsfeed.dismissNotification(event.target.parentNode)\n })\n\n column.appendChild(notificationElement)\n }\n }\n\n document.body.appendChild(element)\n }\n } else {\n throw Error('response.data.documentElement is NOT an instance of Element')\n }\n }).catch(console.error)\n}\n\nnewsfeed.onloaded = () => {\n // If the main script had already done its API check, yet newsfeed haven't been triggered, do it\n // This would only happen if this newsfeed script only gets loaded after the main script's API check\n if (typeof page !== 'undefined' && page.apiChecked && !newsfeed.done)\n newsfeed.do()\n}\n\nif (document.readyState === 'interactive' || document.readyState === 'complete')\n newsfeed.onloaded()\nelse\n window.addEventListener('DOMContentLoaded', () => newsfeed.onloaded())\n"]}