Commit f1d5a7c472bb8e838a7fd395f59be8d473f8a872
implement blogs via blobs, currently read only...
Dominic Tarr committed on 12/5/2017, 8:15:44 AMParent: 930a234f8e8c982d1f957647399cb38c7eae3dba
Files changed
app/html/blogCard.js | changed |
app/page/blogIndex.js | changed |
app/page/blogShow.js | changed |
main.js | changed |
blogs/blog.js | added |
blogs/post.js | added |
app/html/blogCard.js | ||
---|---|---|
@@ -1,9 +1,8 @@ | ||
1 | 1 | var nest = require('depnest') |
2 | 2 | var h = require('mutant/h') |
3 | 3 | var isString= require('lodash/isString') |
4 | 4 | var maxBy= require('lodash/maxBy') |
5 | -var marksum = require('markdown-summary') | |
6 | 5 | var markdown = require('ssb-markdown') |
7 | 6 | var ref = require('ssb-ref') |
8 | 7 | var htmlEscape = require('html-escape') |
9 | 8 | |
@@ -28,13 +27,16 @@ | ||
28 | 27 | 'about.obs.name': 'first', |
29 | 28 | 'about.html.avatar': 'first', |
30 | 29 | 'translations.sync.strings': 'first', |
31 | 30 | 'unread.sync.isUnread': 'first', |
32 | - // 'message.html.markdown': 'first', | |
33 | 31 | 'message.html.channel': 'first', |
34 | 32 | 'message.html.timeago': 'first', |
35 | 33 | 'blob.sync.url': 'first', |
36 | - 'emoji.sync.url': 'first' | |
34 | + 'emoji.sync.url': 'first', | |
35 | + | |
36 | + 'message.html.title': 'first', | |
37 | + 'message.html.summary': 'first', | |
38 | + 'message.html.thumbnail': 'first', | |
37 | 39 | }) |
38 | 40 | |
39 | 41 | exports.create = function (api) { |
40 | 42 | |
@@ -84,9 +86,8 @@ | ||
84 | 86 | return nest('app.html.blogCard', (blog, opts = {}) => { |
85 | 87 | var strings = api.translations.sync.strings() |
86 | 88 | |
87 | 89 | if(!blog.value) return |
88 | - if('string' !== typeof blog.value.content.text) return | |
89 | 90 | |
90 | 91 | const lastReply = blog.replies && maxBy(blog.replies, r => r.timestamp) |
91 | 92 | |
92 | 93 | const goToBlog = () => api.history.sync.push(blog) |
@@ -96,43 +97,46 @@ | ||
96 | 97 | |
97 | 98 | const { content, author } = blog.value |
98 | 99 | |
99 | 100 | var img = h('Thumbnail') |
100 | - var m = /\!\[[^]+\]\(([^\)]+)\)/.exec(marksum.image(content.text)) | |
101 | - if(m) { | |
101 | + | |
102 | + var image = api.message.html.thumbnail(blog) | |
103 | + | |
104 | + if(image) { | |
102 | 105 | //Hey this works! fit an image into a specific size (see blog-card.mcss) |
103 | 106 | //centered, and scaled to fit the square (works with both landscape and portrait!) |
104 | 107 | //This is functional css not opinionated css, so all embedded. |
105 | - img.style = 'background-image: url("'+api.blob.sync.url(m[1])+'"); background-position:center; background-size: cover;' | |
106 | - } else { | |
108 | + img.style = 'background-image: url("'+api.blob.sync.url(image)+'"); background-position:center; background-size: cover;' | |
109 | + | |
110 | + } | |
111 | + else { | |
107 | 112 | var style = { 'background-color': api.about.obs.color(blog.key) } |
108 | 113 | img = h('Thumbnail -empty', { style }, [ |
109 | 114 | h('i.fa.fa-file-text-o') |
110 | 115 | ]) |
116 | + | |
111 | 117 | } |
112 | 118 | |
113 | - const title = render(marksum.title(content.text)) | |
114 | - const summary = render(marksum.summary(content.text)) | |
115 | - | |
116 | 119 | const className = blog.unread ? '-unread': '' |
117 | 120 | |
118 | - return h('BlogCard', { id, className, 'ev-click': onClick }, [ | |
121 | + var b = h('BlogCard', { id, className, 'ev-click': onClick }, [ | |
119 | 122 | h('div.context', [ |
120 | 123 | api.about.html.avatar(author, 'tiny'), |
121 | 124 | h('div.name', api.about.obs.name(author)), |
122 | 125 | api.message.html.timeago(blog) |
123 | 126 | ]), |
124 | 127 | h('div.content', [ |
125 | 128 | img, |
126 | 129 | h('div.text', [ |
127 | - h('h2', {innerHTML: title}), | |
130 | + h('h2', api.message.html.title(blog)), | |
128 | 131 | content.channel |
129 | 132 | ? api.message.html.channel(blog) |
130 | 133 | : '', |
131 | - h('div.summary', {innerHTML: summary}) | |
134 | + h('div.summary', api.message.html.summary(blog)) | |
132 | 135 | ]) |
133 | 136 | ]) |
134 | 137 | ]) |
138 | + | |
139 | + return b | |
135 | 140 | }) |
136 | 141 | } |
137 | 142 | |
138 | - |
app/page/blogIndex.js | ||
---|---|---|
@@ -53,9 +53,11 @@ | ||
53 | 53 | const { recps, channel } = blog.value.content |
54 | 54 | var onClick |
55 | 55 | if (channel && !recps) |
56 | 56 | onClick = (ev) => api.history.sync.push(Object.assign({}, blog, { page: 'blogShow' })) |
57 | - | |
58 | 57 | return api.app.html.blogCard(blog, { onClick }) |
59 | 58 | } |
60 | 59 | } |
61 | 60 | |
61 | + | |
62 | + | |
63 | + |
app/page/blogShow.js | ||
---|---|---|
@@ -15,9 +15,13 @@ | ||
15 | 15 | 'contact.html.follow': 'first', |
16 | 16 | 'message.html.channel': 'first', |
17 | 17 | 'message.html.markdown': 'first', |
18 | 18 | 'message.html.timeago': 'first', |
19 | - 'feed.obs.thread': 'first' | |
19 | + 'feed.obs.thread': 'first', | |
20 | + | |
21 | + 'message.html.title': 'first', | |
22 | + 'message.html.content': 'first', | |
23 | + | |
20 | 24 | }) |
21 | 25 | |
22 | 26 | exports.create = (api) => { |
23 | 27 | return nest('app.page.blogShow', blogShow) |
@@ -26,10 +30,10 @@ | ||
26 | 30 | // blogMsg = a thread (message, may be decorated with replies) |
27 | 31 | |
28 | 32 | const { author, content } = blogMsg.value |
29 | 33 | |
30 | - const blog = content.text | |
31 | - const title = api.message.html.markdown(content.title || getTitle(blog)) | |
34 | + const blog = api.message.html.content(blogMsg) | |
35 | + const title = api.message.html.title(blogMsg) | |
32 | 36 | |
33 | 37 | const comments = api.app.html.comments(blogMsg.key) |
34 | 38 | |
35 | 39 | const { lastId: branch } = api.feed.obs.thread(blogMsg.key) |
@@ -57,12 +61,13 @@ | ||
57 | 61 | ]), |
58 | 62 | ]) |
59 | 63 | ]), |
60 | 64 | h('div.break', h('hr')), |
61 | - h('section.blog', markdown(blog)), | |
65 | + h('section.blog', blog), | |
62 | 66 | comments, |
63 | 67 | ]), |
64 | 68 | ]) |
65 | 69 | ]) |
66 | 70 | } |
67 | 71 | } |
68 | 72 | |
73 | + |
main.js | ||
---|---|---|
@@ -30,8 +30,14 @@ | ||
30 | 30 | state: require('./state/obs'), |
31 | 31 | unread: require('./unread'), |
32 | 32 | }, |
33 | 33 | { |
34 | + blogs: { | |
35 | + post: require('./blogs/post'), | |
36 | + blog: require('./blogs/blog') | |
37 | + } | |
38 | + }, | |
39 | + { | |
34 | 40 | profile: require('patch-profile'), |
35 | 41 | history: require('patch-history'), |
36 | 42 | core: require('patchcore') |
37 | 43 | } |
@@ -53,4 +59,5 @@ | ||
53 | 59 | console.log('autofollowed', err, follows); |
54 | 60 | }) |
55 | 61 | else |
56 | 62 | console.log('no invite') |
63 | + |
blogs/blog.js | ||
---|---|---|
@@ -1,0 +1,57 @@ | ||
1 | +var pull = require('pull-stream') | |
2 | +const h = require('mutant').h | |
3 | + | |
4 | +exports.gives = { | |
5 | + message: { | |
6 | + html: { | |
7 | + title: true, | |
8 | + summary: true, | |
9 | + thumbnail: true, | |
10 | + content: true | |
11 | + } | |
12 | + } | |
13 | +} | |
14 | + | |
15 | +exports.needs = { | |
16 | + message: { html: { markdown: 'first' } }, | |
17 | + sbot: { pull: { getBlob: 'first' } } | |
18 | +} | |
19 | + | |
20 | + | |
21 | +exports.create = function (api) { | |
22 | + | |
23 | + return { | |
24 | + message: { | |
25 | + html: { | |
26 | + title: function (data) { | |
27 | + if('blog' == typeof data.value.content.type) return | |
28 | + return data.value.content.title | |
29 | + }, | |
30 | + summary: function (data) { | |
31 | + if('blog' == typeof data.value.content.type) return | |
32 | + return data.value.content.title | |
33 | + }, | |
34 | + thumbnail: function (data) { | |
35 | + if('blog' == typeof data.value.content.type) return | |
36 | + return data.value.content.title | |
37 | + }, | |
38 | + content: function (data) { | |
39 | + if('blog' == typeof data.value.content.type) return | |
40 | + var div = h('Markdown') | |
41 | + pull( | |
42 | + api.sbot.pull.getBlob(data.value.content.blog), | |
43 | + pull.collect(function (err, ary) { | |
44 | + if(err) return | |
45 | + var md = api.message.html.markdown({text:Buffer.concat(ary).toString()}) | |
46 | + div.innerHTML = md.innerHTML | |
47 | + }) | |
48 | + ) | |
49 | + return div | |
50 | + } | |
51 | + } | |
52 | + } | |
53 | + } | |
54 | +} | |
55 | + | |
56 | + | |
57 | + |
blogs/post.js | ||
---|---|---|
@@ -1,0 +1,69 @@ | ||
1 | +var marksum = require('markdown-summary') | |
2 | + | |
3 | +//var markdown = require('ssb-markdown') | |
4 | + | |
5 | + | |
6 | +exports.gives = { | |
7 | + message: { | |
8 | + html: { | |
9 | + title: true, | |
10 | + summary: true, | |
11 | + thumbnail: true, | |
12 | + content: true | |
13 | + } | |
14 | + } | |
15 | +} | |
16 | + | |
17 | +exports.needs = { | |
18 | + message: { html: { markdown: 'first' } } | |
19 | +} | |
20 | + | |
21 | + | |
22 | +exports.create = function (api) { | |
23 | + | |
24 | + function render (source) { | |
25 | + return markdown.block(source, { | |
26 | + emoji: (emoji) => { | |
27 | + return renderEmoji(emoji, api.emoji.sync.url(emoji)) | |
28 | + }, | |
29 | + toUrl: (id) => { | |
30 | + if (ref.isBlob(id)) return api.blob.sync.url(id) | |
31 | + return id | |
32 | + }, | |
33 | + imageLink: (id) => id | |
34 | + }) | |
35 | + } | |
36 | + function fromPost(fn) { | |
37 | + return function (data) { | |
38 | + if('post' !== data.value.content.type) return | |
39 | + return api.message.html.markdown ({text: fn(data.value.content)}) | |
40 | + } | |
41 | + } | |
42 | + | |
43 | + return { | |
44 | + message: { | |
45 | + html: { | |
46 | + title: fromPost(function (content) { | |
47 | + return content.title || marksum.title(content.text) | |
48 | + }), | |
49 | + summary: fromPost(function (content) { | |
50 | + return content.summary || marksum.summary(content.text) | |
51 | + }), | |
52 | + thumbnail: function (data) { | |
53 | + if('post' !== data.value.content.type) return | |
54 | + var content = data.value.content | |
55 | + if(content.thumbnail) return content.thumbnail | |
56 | + var img = marksum.image(content.text) | |
57 | + var m = /\!\[[^]+\]\(([^\)]+)\)/.exec(img) | |
58 | + if(m) return m[1] | |
59 | + }, | |
60 | + content: fromPost(function (content) { | |
61 | + return content.text | |
62 | + }) | |
63 | + } | |
64 | + } | |
65 | + } | |
66 | +} | |
67 | + | |
68 | + | |
69 | + |
Built with git-ssb-web