@@ -1,9 +1,9 @@
1'use strict'
1'use strict'
3−const re_channel = /(\s|^)\/([a-zA-Z0-9]+)/g
3+const reChannel = /(\s|^)\/([a-zA-Z0-9]+)/g
4−const re_user = /((\s|^)@<[a-zA-Z0-9./:\-_\+~#= ]*>)/g
4+const reUser = /((\s|^)@<[a-zA-Z0-9./:\-_+~#= ]*>)/g
5−const re_tag = /([^&]|^)\#([a-zA-Z0-9]+)/g
5+const reTag = /([^&]|^)#([a-zA-Z0-9]+)/g
6−const re_url = /((https?):\/\/(([-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b)([-a-zA-Z0-9@:%_\+.~#?&//=]*)))/g
6+const reUrl = /((https?):\/\/(([-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b)([-a-zA-Z0-9@:%_+.~#?&//=]*)))/g
8function Hallway (sites) {
8function Hallway (sites) {
9 const feeds = {}
9 const feeds = {}
@@ -37,14 +37,15 @@ function Hallway (sites) {
38 this.refresh = function (feeds = this.cache) {
38 this.refresh = function (feeds = this.cache) {
39 const entries = this.findEntries(feeds)
39 const entries = this.findEntries(feeds)
40+ const localEntries = entries.filter(entry => this.filterExternals(entry))
40− const channels = this.find(entries, 'channel')
41+ const channels = this.find(localEntries, 'channel')
41− const users = this.find(entries, 'author')
42+ const users = this.find(localEntries, 'author')
42− const tags = this.findTags(entries)
43+ const tags = this.findTags(localEntries)
43− const relevantEntries = entries.filter(val => !this.finder.filter || (val.author === this.finder.filter || val.channel === this.finder.filter || val.tags.includes(this.finder.filter)))
44+ const relevantEntries = localEntries.filter(val => !this.finder.filter || (val.author === this.finder.filter || val.channel === this.finder.filter || val.tags.includes(this.finder.filter)))
45 this._entries.innerHTML = `
46 this._entries.innerHTML = `
47− ${entries.filter((val) => !this.finder.filter || (val.author === this.finder.filter || val.channel === this.finder.filter || val.tags.includes(this.finder.filter))).filter((_, id) => id < Number(this.finder.page) * 20 && id >= (Number(this.finder.page) - 1) * 20).reduce((acc, val) => acc + this.templateEntry(val) + '\n', '')}
48+ ${localEntries.filter((val) => !this.finder.filter || (val.author === this.finder.filter || val.channel === this.finder.filter || val.tags.includes(this.finder.filter))).filter((_, id) => id < Number(this.finder.page) * 20 && id >= (Number(this.finder.page) - 1) * 20).reduce((acc, val) => acc + this.templateEntry(val) + '\n', '')}
49 <div id='pagination'>
50 <div id='pagination'>
50 ${[...Array(Math.ceil(relevantEntries.length / 20)).keys()].reduce((acc, num) => `${acc}<span class='${Number(hallway.finder.page) === num + 1 ? 'selected' : ''}' onclick='filter("${this.finder.filter}^${num + 1}")'>${num + 1}</span>`, '')}
51 ${[...Array(Math.ceil(relevantEntries.length / 20)).keys()].reduce((acc, num) => `${acc}<span class='${Number(hallway.finder.page) === num + 1 ? 'selected' : ''}' onclick='filter("${this.finder.filter}^${num + 1}")'>${num + 1}</span>`, '')}
@@ -54,7 +55,7 @@ function Hallway (sites) {
54 this._sidebar.innerHTML = `
55 this._sidebar.innerHTML = `
55 <a id='hidebar' onclick="toggleVisibility('sidebar');"></a>
56 <a id='hidebar' onclick="toggleVisibility('sidebar');"></a>
56 <ul id='channels'>
57 <ul id='channels'>
57− <li onclick='filter("")' class='${hallway.finder.filter === '' ? 'selected' : ''}'><a href='#'>hallway <span class='right'>${entries.length}</span></a></li>
58+ <li onclick='filter("")' class='${hallway.finder.filter === '' ? 'selected' : ''}'><a href='#'>hallway <span class='right'>${localEntries.length}</span></a></li>
58 ${Object.keys(channels).slice(0, 15).reduce((acc, val) => acc + `<li onclick='filter("${val}")' class='${hallway.finder.filter === val ? 'selected' : ''}'><a href='#${val}'>${val} <span class='right'>${channels[val]}</span></a></li>\n`, '')}
59 ${Object.keys(channels).slice(0, 15).reduce((acc, val) => acc + `<li onclick='filter("${val}")' class='${hallway.finder.filter === val ? 'selected' : ''}'><a href='#${val}'>${val} <span class='right'>${channels[val]}</span></a></li>\n`, '')}
60 <ul id='users'>
61 <ul id='users'>
@@ -71,18 +72,25 @@ function Hallway (sites) {
72 // Entries
73 // Entries
75+ this.filterExternals = function (entry) {
76+ const matches = entry.body.match(reUser)
77+ const locals = Object.keys(feeds)
78+ return matches ? matches.some(match => locals.some(local => match.indexOf(feeds[local].path) !== -1)) : true
74− this.find = function (entries, p) {
81+ this.find = function (entries, key) {
75 const h = {}
82 const h = {}
76− for (const id in entries) {
83+ for (const entry of entries) {
77− if (entries[id] && entries[id][p]) { h[entries[id][p]] = h[entries[id][p]] ? h[entries[id][p]] + 1 : 1 }
84+ if (entry && entry[key]) {
85+ h[entry[key]] = h[entry[key]] ? h[entry[key]] + 1 : 1
82 this.findTags = function (entries) {
91 this.findTags = function (entries) {
83 const tags = {}
92 const tags = {}
84− for (const id in entries) {
93+ for (const entry of entries) {
85− const entry = entries[id]
86 entry.tags.map(tag => {
94 entry.tags.map(tag => {
87 tags[tag] = tags[tag] ? tags[tag] + 1 : 1
95 tags[tag] = tags[tag] ? tags[tag] + 1 : 1
@@ -102,15 +110,15 @@ function Hallway (sites) {
103 this.findMention = function (found) {
111 this.findMention = function (found) {
104 const mention = Object.keys(feeds).filter(user => found.indexOf(feeds[user].path) > -1)
112 const mention = Object.keys(feeds).filter(user => found.indexOf(feeds[user].path) > -1)
105− return mention.length === 1 ? ` <span class='user local'>${mention[0]}</span>` : ` <span class='user external'>${found.substr(5).split(' ')[0]}</span>`
113+ return ` <span class='user local'>${mention[0]}</span>`
108 this.templateEntry = function (entry) {
116 this.templateEntry = function (entry) {
109 entry.html = entry.body
117 entry.html = entry.body
110− .replace(re_channel, `$1<span class='channel'>/$2</span>`)
118+ .replace(reChannel, `$1<span class='channel'>/$2</span>`)
111− .replace(re_user, this.findMention)
119+ .replace(reUser, this.findMention)
112− .replace(re_tag, `$1<span class='tag'>#$2</span>`)
120+ .replace(reTag, `$1<span class='tag'>#$2</span>`)
113− .replace(re_url, `<a target="_blank" href='$1'>$1</a>`)
121+ .replace(reUrl, `<a target="_blank" href='$1'>$1</a>`)
115 const filter = window.location.hash.substr(1).replace(/\+/g, ' ').toLowerCase()
123 const filter = window.location.hash.substr(1).replace(/\+/g, ' ').toLowerCase()
116 const highlight = filter === entry.author.toLowerCase()
124 const highlight = filter === entry.author.toLowerCase()
@@ -160,7 +168,7 @@ function Hallway (sites) {
160 const date = parts[0].trim()
168 const date = parts[0].trim()
161 const body = escapeHtml(parts[1].trim()).trim()
169 const body = escapeHtml(parts[1].trim()).trim()
162 const channel = body.substr(0, 1) === '/' ? body.split(' ')[0].substr(1).toLowerCase() : body.substr(0, 1) === '@' ? 'veranda' : 'lobby'
170 const channel = body.substr(0, 1) === '/' ? body.split(' ')[0].substr(1).toLowerCase() : body.substr(0, 1) === '@' ? 'veranda' : 'lobby'
163− const tags = (body.match(re_tag) || []).map(a => a.substr(a.indexOf('#') + 1).toLowerCase())
171+ const tags = (body.match(reTag) || []).map(a => a.substr(a.indexOf('#') + 1).toLowerCase())
164 const offset = new Date() - new Date(date)
172 const offset = new Date() - new Date(date)
165 entries.push({ date, body, author, offset, channel, tags })
173 entries.push({ date, body, author, offset, channel, tags })
@@ -195,8 +203,8 @@ function Hallway (sites) {
197function toggleVisibility (id) {
205function toggleVisibility (id) {
198− var e = document.getElementById(id)
206+ const e = document.getElementById(id)
199− if (e.style.display == 'block') { e.style.display = 'none' } else { e.style.display = 'block' }
207+ if (e.style.display === 'block') { e.style.display = 'none' } else { e.style.display = 'block' }
202function escapeHtml (unsafe) {
210function escapeHtml (unsafe) {