git ssb

30+

cel / git-ssb-web



Commit 1e73dbc22e7cbacbfcbbc499676d04157d8499de

Highlight code syntax in blob view and readmes

Charles Lehner committed on 3/30/2016, 10:17:40 PM
Parent: 81785ac357039921e1de71f1df9e2891178e375c

Files changed

index.jschanged
package.jsonchanged
static/styles.csschanged
index.jsView
@@ -18,8 +18,9 @@
1818 var Issues = require('ssb-issues')
1919 var paramap = require('pull-paramap')
2020 var gitPack = require('pull-git-pack')
2121 var Mentions = require('ssb-mentions')
22+var Highlight = require('highlight.js')
2223
2324 // render links to git objects and ssb objects
2425 var blockRenderer = new marked.Renderer()
2526 blockRenderer.urltransform = function (url) {
@@ -29,8 +30,14 @@
2930 return encodeLink([this.options.repo.id, 'commit', url])
3031 return url
3132 }
3233
34+function highlight(code, lang) {
35+ return lang
36+ ? Highlight.highlight(lang, code).value
37+ : Highlight.highlightAuto(code).value
38+}
39+
3340 marked.setOptions({
3441 gfm: true,
3542 mentions: true,
3643 tables: true,
@@ -38,8 +45,9 @@
3845 pedantic: false,
3946 sanitize: true,
4047 smartLists: true,
4148 smartypants: false,
49+ highlight: highlight,
4250 renderer: blockRenderer
4351 })
4452
4553 // hack to make git link mentions work
@@ -107,14 +115,8 @@
107115 .replace(/>/g, '>')
108116 .replace(/"/g, '"')
109117 }
110118
111-function escapeHTMLStream() {
112- return pull.map(function (buf) {
113- return escapeHTML(buf.toString('utf8'))
114- })
115-}
116-
117119 function ucfirst(str) {
118120 return str[0].toLocaleUpperCase() + str.slice(1)
119121 }
120122
@@ -294,10 +296,8 @@
294296 var contentTypes = {
295297 css: 'text/css'
296298 }
297299
298-var staticBase = path.join(__dirname, 'static')
299-
300300 function readReqJSON(req, cb) {
301301 pull(
302302 toPull(req),
303303 pull.collect(function (err, bufs) {
@@ -344,10 +344,8 @@
344344 svg: 'image/svg+xml',
345345 bmp: 'image/bmp'
346346 }
347347
348-var markdownFilenameRegex = /\.md$|\/.markdown$/i
349-
350348 module.exports = function (opts, cb) {
351349 var ssb, reconnect, myId, getRepo, getVotes, getMsg, issues
352350 var about = function (id, cb) { cb(null, {name: id}) }
353351 var reqQueue = []
@@ -504,11 +502,11 @@
504502 return serveFile(req, dirs)
505503 }
506504
507505 function serveFile(req, dirs) {
508- var filename = path.join.apply(path, [staticBase].concat(dirs))
506+ var filename = path.join.apply(path, [__dirname].concat(dirs))
509507 // prevent escaping base dir
510- if (filename.indexOf(staticBase) !== 0)
508+ if (filename.indexOf('../') === 0)
511509 return servePlainError(403, '403 Forbidden')
512510
513511 return readNext(function (cb) {
514512 fs.stat(filename, function (err, stats) {
@@ -597,9 +595,10 @@
597595 'Content-Type': 'text/html'
598596 }],
599597 '<!doctype html><html><head><meta charset=utf-8>',
600598 '<title>' + escapeHTML(title || 'git ssb') + '</title>',
601- '<link rel=stylesheet href="/styles.css"/>',
599+ '<link rel=stylesheet href="/static/styles.css"/>',
600+ '<link rel=stylesheet href="/node_modules/highlight.js/styles/github.css"/>',
602601 '</head>\n',
603602 '<body>',
604603 '<header>',
605604 '<h1><a href="/">git ssb' +
@@ -622,8 +621,21 @@
622621 serveTemplate(err.name, status || 500)
623622 )
624623 }
625624
625+ function renderObjectData(obj, filename, repo) {
626+ var ext = (/\.([^.]+)$/.exec(filename) || [,filename])[1]
627+ return readOnce(function (cb) {
628+ pull(obj.read, pull.collect(function (err, bufs) {
629+ if (err) return cb(err)
630+ var buf = Buffer.concat(bufs, obj.length).toString('utf8')
631+ cb(null, (ext == 'md' || ext == 'markdown')
632+ ? markdown(buf, repo)
633+ : '<pre>' + highlight(buf, ext) + '</pre>')
634+ }))
635+ })
636+ }
637+
626638 /* Feed */
627639
628640 function renderFeed(feedId) {
629641 var opts = {
@@ -1019,9 +1031,9 @@
10191031 var commitPath = [repo.id, 'commit', commit.id]
10201032 var treePath = [repo.id, 'tree', commit.id]
10211033 return '<section class="collapse">' +
10221034 '<strong>' + link(commitPath, commit.title) + '</strong><br>' +
1023- '<code>' + commit.id + '</code> ' +
1035+ '<tt>' + commit.id + '</tt> ' +
10241036 link(treePath, 'Tree') + '<br>' +
10251037 escapeHTML(commit.author.name) + ' &middot; ' + commit.author.date.toLocaleString() +
10261038 (commit.separateAuthor ? '<br>' + escapeHTML(commit.committer.name) + ' committed on ' + commit.committer.date.toLocaleString() : "") +
10271039 '</section>'
@@ -1055,9 +1067,9 @@
10551067 var commitPath = [repo.id, 'commit', commit.id]
10561068 cb(null,
10571069 'Latest: <strong>' + link(commitPath, commit.title) +
10581070 '</strong><br>' +
1059- '<code>' + commit.id + '</code><br> ' +
1071+ '<tt>' + commit.id + '</tt><br> ' +
10601072 escapeHTML(commit.committer.name) + ' committed on ' +
10611073 commit.committer.date.toLocaleString() +
10621074 (commit.separateAuthor ? '<br>' +
10631075 escapeHTML(commit.author.name) + ' authored on ' +
@@ -1113,22 +1125,11 @@
11131125 return cb(null, pull.once(path.length ? '' : '<p>No readme</p>'))
11141126 repo.getObjectFromAny(file.id, function (err, obj) {
11151127 if (err) return cb(err)
11161128 cb(null, cat([
1117- pull.once('<section><h4>' + escapeHTML(file.name) + '</h4><hr/>'),
1118- markdownFilenameRegex.test(file.name) ?
1119- readOnce(function (cb) {
1120- pull(obj.read, pull.collect(function (err, bufs) {
1121- if (err) return cb(err)
1122- var buf = Buffer.concat(bufs, obj.length)
1123- cb(null, markdown(buf.toString(), repo))
1124- }))
1125- })
1126- : cat([
1127- pull.once('<pre>'),
1128- pull(obj.read, escapeHTMLStream()),
1129- pull.once('</pre>')
1130- ]),
1129+ pull.once('<section><h4><a name="readme">' +
1130+ escapeHTML(file.name) + '</a></h4><hr/>'),
1131+ renderObjectData(obj, file.name, repo),
11311132 pull.once('</section>')
11321133 ]))
11331134 })
11341135 })
@@ -1147,9 +1148,9 @@
11471148 var commitPath = [repo.id, 'commit', commit.id]
11481149 var treePath = [repo.id, 'tree', commit.tree]
11491150 cb(null, '<section class="collapse">' +
11501151 '<strong>' + link(commitPath, commit.title) + '</strong>' +
1151- pre(commit.body) +
1152+ (commit.body ? pre(commit.body) : '') +
11521153 '<p>' +
11531154 (commit.separateAuthor ? escapeHTML(commit.author.name) +
11541155 ' authored on ' + commit.author.date.toLocaleString() + '<br>'
11551156 : '') +
@@ -1282,17 +1283,9 @@
12821283 '<section>'),
12831284 extension in imgMimes
12841285 ? pull.once('<img src="' + encodeLink(rawFilePath) +
12851286 '" alt="' + escapeHTML(filename) + '" />')
1286- : markdownFilenameRegex.test(filename)
1287- ? readOnce(function (cb) {
1288- pull(object.read, pull.collect(function (err, bufs) {
1289- if (err) return cb(err)
1290- var buf = Buffer.concat(bufs, object.length)
1291- cb(null, markdown(buf.toString('utf8'), repo))
1292- }))
1293- })
1294- : pull(object.read, escapeHTMLStream(), wrap('pre')),
1287+ : renderObjectData(object, filename, repo),
12951288 pull.once('</section>')
12961289 ])))
12971290 })
12981291 })
package.jsonView
@@ -4,8 +4,9 @@
44 "description": "web server for browsing git repos on ssb",
55 "bin": "server.js",
66 "dependencies": {
77 "asyncmemo": "^0.1.0",
8+ "highlight.js": "^9.2.0",
89 "multicb": "^1.2.1",
910 "pull-cat": "^1.1.8",
1011 "pull-git-pack": "^0.1.2",
1112 "pull-git-repo": "^0.3.1",
static/styles.cssView
@@ -11,8 +11,26 @@
1111 min-width: 16em;
1212 margin: 0 auto;
1313 }
1414
15+pre {
16+ font: 12px/1.45 Consolas, "Liberation Mono", Menlo, Courier, monospace;
17+ padding: .5em 1.25ex;
18+ border: 1px solid #ddd;
19+ background: #f8f8f8;
20+ border-radius: .5ex;
21+}
22+
23+section code {
24+ padding: .5ex;
25+ border-radius: .5ex;
26+ background-color: #f5f5f5;
27+}
28+
29+pre > code {
30+ background-color: #f8f8f8;
31+}
32+
1533 /* header */
1634
1735 header h1 {
1836 font-weight: inherit;
@@ -51,9 +69,9 @@
5169 h3 ~ h4 {
5270 margin-top: 1em;
5371 }
5472
55-a {
73+a:link, a:visited {
5674 color: #006eff;
5775 text-decoration: none;
5876 }
5977 a:hover {

Built with git-ssb-web