@@ -171,8 +171,8 @@ function Hallway (sites) {
171 const parts = line.replace(' ', '\t').split('\t')
171 const parts = line.replace(' ', '\t').split('\t')
172 const date = parts[0].trim()
172 const date = parts[0].trim()
173 const body = escapeHtml(parts[1].trim()).trim()
173 const body = escapeHtml(parts[1].trim()).trim()
174− const channel = body.substr(0, 1) === '/' ? body.split(' ')[0].substr(1).toLowerCase() : body.substr(0, 1) === '@' ? 'veranda' : 'lobby'
174+ const channel = body.substr(0, 1) === '/' ? cleanTags(body.split(' ')[0].substr(1).toLowerCase()) : body.substr(0, 1) === '@' ? 'veranda' : 'lobby'
175− const tags = (body.match(reTag) || []).map(a => a.substr(a.indexOf('#') + 1).toLowerCase())
175+ const tags = (body.match(reTag) || []).map(a => cleanTags(a.substr(a.indexOf('#') + 1).toLowerCase()))
176 const offset = new Date() - new Date(date)
176 const offset = new Date() - new Date(date)
177 entries.push({ date, body, author, offset, channel, tags })
177 entries.push({ date, body, author, offset, channel, tags })
@@ -215,6 +215,10 @@ function escapeHtml (unsafe) {
215 return unsafe.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''')
215 return unsafe.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''')
218+function cleanTags (unsafe){
219+ return unsafe.replace(/([^a-z0-9]+)/gi, '-')
218function stripHash (hash) {
222function stripHash (hash) {
219 const decoded = decodeURIComponent(hash)
223 const decoded = decodeURIComponent(hash)
220 return decoded.charAt(0) === '#' ? decoded.substring(1) : decoded
224 return decoded.charAt(0) === '#' ? decoded.substring(1) : decoded