diff --git a/apps/blog.json b/apps/blog.json index bee39eae..8fbf41e4 100644 --- a/apps/blog.json +++ b/apps/blog.json @@ -1,5 +1,5 @@ { "type": "tildefriends-app", "emoji": "🪵", - "previous": "&7E+OhgnyEUUIIHPhvWCF6esqRRDdqPHhqJiGp1h6xg4=.sha256" + "previous": "&7Ch5DjIMAEbJm05ofH1U/+wlzn9kr65DChcKKgurE8E=.sha256" } \ No newline at end of file diff --git a/apps/blog/blog.js b/apps/blog/blog.js index 7a9effc4..0958f96b 100644 --- a/apps/blog/blog.js +++ b/apps/blog/blog.js @@ -8,7 +8,7 @@ function escapeAttribute(text) { return (text ?? '').replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", '''); } -function markdown(md) { +export function markdown(md) { let reader = new commonmark.Parser({safe: true}); let writer = new commonmark.HtmlRenderer(); let parsed = reader.parse(md || ''); @@ -17,10 +17,10 @@ function markdown(md) { while ((event = walker.next())) { node = event.node; if (event.entering) { - if (node.type == 'image') { - if (node.destination.startsWith('&')) { - node.destination = '/' + node.destination + '/view'; - } + if (node.destination?.startsWith('&')) { + node.destination = '/' + node.destination + '/view?filename=' + node.firstChild?.literal; + } else if (node.destination?.startsWith('@') || node.destination?.startsWith('%')) { + node.destination = '/~core/ssb/#' + node.destination; } } } @@ -31,6 +31,9 @@ export async function render_blog_post_html(blog_post) { let blob = utf8Decode(await ssb.blobGet(blog_post.blog)); return ` + + +
${escape(blog_post.name)} ${escape(new Date(blog_post.timestamp).toString())}
@@ -44,7 +47,7 @@ export async function render_blog_post_html(blog_post) { function render_blog_post(blog_post) { return `
-

${escape(blog_post.title)}

+

${escape(blog_post.title)}

${escape(blog_post.name)} ${escape(new Date(blog_post.timestamp).toString())}
${markdown(blog_post.summary)}
@@ -62,11 +65,11 @@ export function render_html(blogs) { background-color: #ccc; } - +
-

🪵Tilde Blog

+

🪵Tilde Friends Blog

atom feed
${blogs.map(blog_post => render_blog_post(blog_post)).join('\n')} diff --git a/apps/blog/handler.js b/apps/blog/handler.js index cd7060ca..cca61442 100644 --- a/apps/blog/handler.js +++ b/apps/blog/handler.js @@ -1,17 +1,39 @@ import * as blog from './blog.js'; async function main() { - let blogs = await blog.get_posts(); - for (let blog_post of blogs) { - let title = (blog_post.title || '').replaceAll(/\W/g, '_').toLowerCase(); - if (request.path === title) { - respond({data: await blog.render_blog_post_html(blog_post), content_type: 'text/html; charset=utf-8'}); - return; + if (request.path.startsWith('%') && request.path.endsWith('.sha256')) { + let id = request.path.startsWith('%25') ? '%' + request.path.substring(3) : request.path; + let blob = await ssb.messageContentGet(id); + if (blob) { + let content = JSON.parse(utf8Decode(blob)); + let md = content?.text; + if (content?.type == 'blog') { + md = utf8Decode(await ssb.blobGet(content?.blog)); + } + respond({data: ` + + + + + + ${blog.markdown(md)} + + `, content_type: 'text/html; charset=utf-8'}); + } else { + respond({data: `Message ${id} not found.`, content_type: 'text/html; charset=utf-8'}); } - } - if (request.path == 'atom') { + } else if (request.path == 'atom') { + let blogs = await blog.get_posts(); respond({data: blog.render_atom(blogs), content_type: 'application/atom+xml'}); } else { + let blogs = await blog.get_posts(); + for (let blog_post of blogs) { + let title = (blog_post.title || '').replaceAll(/\W/g, '_').toLowerCase(); + if (request.path === title) { + respond({data: await blog.render_blog_post_html(blog_post), content_type: 'text/html; charset=utf-8'}); + return; + } + } respond({data: blog.render_html(blogs), content_type: 'text/html; charset=utf-8'}); } }