aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcel <cel@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519>2017-06-27 16:25:55 -1000
committercel <cel@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519>2017-06-27 16:27:16 -1000
commit3e303fe722d3852f27a5f8ce86cbe0cc15584649 (patch)
tree2bcc680ea53740b55c2996a06db12b863328efdd
parent99d000d4bb9514c2639211a31bb6109db84ad231 (diff)
downloadpatchfoo-3e303fe722d3852f27a5f8ce86cbe0cc15584649.tar.gz
patchfoo-3e303fe722d3852f27a5f8ce86cbe0cc15584649.zip
Highlight code in markdown and git files
-rw-r--r--lib/render.js20
-rw-r--r--lib/serve.js22
-rw-r--r--package.json1
3 files changed, 37 insertions, 6 deletions
diff --git a/lib/render.js b/lib/render.js
index ee8ce01..e9d4889 100644
--- a/lib/render.js
+++ b/lib/render.js
@@ -10,6 +10,7 @@ var qs = require('querystring')
var u = require('./util')
var multicb = require('multicb')
var RenderMsg = require('./render-msg')
+var Highlight = require('highlight.js')
module.exports = Render
@@ -83,6 +84,7 @@ function Render(app, opts) {
smartypants: false,
emoji: lexerRenderEmoji,
renderer: new MdRenderer(this),
+ highlight: this.highlight.bind(this),
}
}
@@ -368,3 +370,21 @@ Render.prototype.npmAuthorLink = function (author) {
secondaryLink ? [' (', secondaryLink, ')'] : ''
]
}
+
+// auto-highlight is slow
+var useAutoHighlight = false
+
+Render.prototype.highlight = function (code, lang) {
+ if (code.length > 100000) return u.escapeHTML(code)
+ if (!lang && /^#!\/bin\/[^\/]*sh$/m.test(code)) lang = 'sh'
+ try {
+ return lang
+ ? Highlight.highlight(lang, code).value
+ : useAutoHighlight
+ ? Highlight.highlightAuto(code).value
+ : u.escapeHTML(code)
+ } catch(e) {
+ if (!/^Unknown language/.test(e.message)) console.trace(e)
+ return u.escapeHTML(code)
+ }
+}
diff --git a/lib/serve.js b/lib/serve.js
index 19b0ac8..5f4abff 100644
--- a/lib/serve.js
+++ b/lib/serve.js
@@ -25,6 +25,7 @@ var jpeg = require('jpeg-autorotate')
module.exports = Serve
var emojiDir = path.join(require.resolve('emoji-named-characters'), '../pngs')
+var hlCssDir = path.join(require.resolve('highlight.js'), '../../styles')
var urlIdRegex = /^(?:\/+(([%&@]|%25)(?:[A-Za-z0-9\/+]|%2[Ff]|%2[Bb]){43}(?:=|%3D)\.(?:sha256|ed25519))(?:\.([^?]*))?|(\/.*?))(?:\?(.*))?$/
@@ -296,6 +297,7 @@ Serve.prototype.path = function (url) {
case '/links': return this.links(m[2])
case '/static': return this.static(m[2])
case '/emoji': return this.emoji(m[2])
+ case '/highlight': return this.highlight(m[2])
case '/contacts': return this.contacts(m[2])
case '/about': return this.about(m[2])
case '/git': return this.git(m[2])
@@ -1061,6 +1063,10 @@ Serve.prototype.emoji = function (emoji) {
serveEmoji(this.req, this.res, emoji)
}
+Serve.prototype.highlight = function (dirs) {
+ this.file(path.join(hlCssDir, dirs))
+}
+
Serve.prototype.blob = function (id) {
var self = this
var blobs = self.app.sbot.blobs
@@ -1311,7 +1317,8 @@ Serve.prototype.wrapPage = function (title, searchQ) {
h('title', title),
h('meta', {name: 'viewport', content: 'width=device-width,initial-scale=1'}),
h('link', {rel: 'icon', href: render.toUrl('/static/hermie.ico'), type: 'image/x-icon'}),
- h('style', styles())
+ h('style', styles()),
+ h('link', {rel: 'stylesheet', href: render.toUrl('/highlight/foundation.css')})
),
h('body',
h('nav.nav-bar', h('form', {action: render.toUrl('/search'), method: 'get'},
@@ -1754,8 +1761,10 @@ Serve.prototype.gitTree = function (rev) {
ph('td', u.escapeHTML(item.hash)),
ph('td', 'missing')
])
+ var ext = item.name.replace(/.*\./, '')
var path = '/git/' + item.type + '/' + item.hash
+ '?msg=' + encodeURIComponent(item.msg.key)
+ + (ext ? '&ext=' + ext : '')
var fileDate = new Date(item.msg.value.timestamp)
return ph('tr', [
ph('td',
@@ -1828,7 +1837,8 @@ Serve.prototype.gitBlob = function (rev) {
self.app.git.readObject(obj),
self.wrapBinary({
rawUrl: self.app.render.toUrl('/git/raw/' + rev
- + '?msg=' + encodeURIComponent(msg.key))
+ + '?msg=' + encodeURIComponent(msg.key)),
+ ext: self.query.ext
})
),
]),
@@ -1865,9 +1875,11 @@ Serve.prototype.gitObjectLinks = function (headMsgId, type) {
// wrap a binary source and render it or turn into an embed
Serve.prototype.wrapBinary = function (opts) {
var self = this
+ var ext = opts.ext
return function (read) {
var readRendered, type
- read = ident(function (ext) {
+ read = ident(function (_ext) {
+ if (_ext) ext = _ext
type = ext && mime.lookup(ext) || 'text/plain'
})(read)
return function (abort, cb) {
@@ -1891,9 +1903,7 @@ Serve.prototype.wrapBinary = function (opts) {
})
}
return ph('pre', pull.map(function (buf) {
- return h('div',
- self.app.render.linkify(buf.toString('utf8'))
- ).innerHTML
+ return self.app.render.highlight(buf.toString('utf8'), ext)
})(read))
}
}
diff --git a/package.json b/package.json
index b4260f4..ad452f6 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
"emoji-named-characters": "^1.0.2",
"emoji-server": "^1.0.0",
"hashlru": "^2.1.0",
+ "highlight.js": "^9.12.0",
"human-time": "^0.0.1",
"hyperscript": "^2.0.2",
"jpeg-autorotate": "^3.0.0",