Implement comments activated by the presence of a 'comments:' field in the article's metadata
This commit is contained in:
parent
9d2411ef61
commit
6c3f31ea6c
6 changed files with 84 additions and 4 deletions
69
js/comments.js
Normal file
69
js/comments.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
function Comments(modules) {
|
||||||
|
var comments = modules.cache.make(function(threadId) {
|
||||||
|
return modules.async.bind(
|
||||||
|
modules.async.http({method: 'GET', url: url(threadId)}),
|
||||||
|
function(queryResult) {
|
||||||
|
if(queryResult.status == 200) {
|
||||||
|
try {
|
||||||
|
return modules.async.wrap(render(JSON.parse(queryResult.responseText)));
|
||||||
|
} catch(e) {
|
||||||
|
return modules.async.fail('Server returned invalid JSON for ' + url);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return modules.async.fail('Could not load comments at ' + url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
get: get
|
||||||
|
};
|
||||||
|
|
||||||
|
function url(threadId) {
|
||||||
|
return blog.path.commentsAt + '/api/v1/statuses/' + threadId + '/context';
|
||||||
|
}
|
||||||
|
|
||||||
|
function get(articleKey) {
|
||||||
|
var threadId = blog.articles[articleKey].metadata.comments;
|
||||||
|
if(blog.path.commentsAt != undefined && threadId != undefined) {
|
||||||
|
var ul = modules.dom.make('ul');
|
||||||
|
modules.async.run(
|
||||||
|
modules.async.bind(
|
||||||
|
comments.get(threadId),
|
||||||
|
modules.async.map(function(comments) {
|
||||||
|
comments.forEach(function(comment) {ul.appendChild(comment);});
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return emptySection(ul, threadId);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function emptySection(ul, threadId) {
|
||||||
|
return [modules.dom.make('div', {class: 'comments'}, [
|
||||||
|
modules.dom.make('h2', {innerText: 'Comments'}),
|
||||||
|
ul,
|
||||||
|
modules.dom.make('a', {
|
||||||
|
href: blog.path.commentsAt + '/notice/' + threadId,
|
||||||
|
innerText: 'Comment on the fediverse'
|
||||||
|
})
|
||||||
|
])];
|
||||||
|
}
|
||||||
|
|
||||||
|
function render(comments) {
|
||||||
|
return comments.descendants.map(function(descendant) {
|
||||||
|
return modules.dom.make('li', {}, [
|
||||||
|
modules.dom.make('cite', {}, [
|
||||||
|
modules.dom.make('a', {
|
||||||
|
href: descendant.account.url,
|
||||||
|
innerText: descendant.account.username
|
||||||
|
}),
|
||||||
|
modules.dom.make('p', {innerText: descendant.created_at}),
|
||||||
|
modules.dom.make('div', {innerHTML: descendant.content})
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,8 @@ function DomRenderer(modules) {
|
||||||
function replaceMarkdown() {
|
function replaceMarkdown() {
|
||||||
var div = document.getElementById('contents');
|
var div = document.getElementById('contents');
|
||||||
if(div.children[0] && div.children[0].tagName.toLowerCase() == 'article') {
|
if(div.children[0] && div.children[0].tagName.toLowerCase() == 'article') {
|
||||||
convertArticle(div.children[0]);
|
var re = new RegExp('/' + blog.path.articlesPath + '/([^.]+)\.html');
|
||||||
|
convertArticle(div.children[0], document.location.pathname.replace(re, '$1'));
|
||||||
} else {
|
} else {
|
||||||
var articles = div.getElementsByClassName('articles')[0];
|
var articles = div.getElementsByClassName('articles')[0];
|
||||||
if(articles != undefined) {
|
if(articles != undefined) {
|
||||||
|
@ -21,11 +22,14 @@ function DomRenderer(modules) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertArticle(article) {
|
function convertArticle(article, key) {
|
||||||
var header = article.getElementsByTagName('header')[0];
|
var header = article.getElementsByTagName('header')[0];
|
||||||
var text = article.getElementsByTagName('pre')[0];
|
var text = article.getElementsByTagName('pre')[0];
|
||||||
if(text != undefined) {
|
if(text != undefined) {
|
||||||
article.replaceChild(getDiv(text.innerText), text);
|
article.replaceChild(getDiv(text.innerText), text);
|
||||||
|
if(key != undefined) {
|
||||||
|
article.appendChild(modules.comments.get(key)[0]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('No content found for this article');
|
console.log('No content found for this article');
|
||||||
}
|
}
|
||||||
|
@ -56,7 +60,7 @@ function DomRenderer(modules) {
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
div
|
div
|
||||||
]);
|
].concat(limit != undefined ? [] : modules.comments.get(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function pageTitle(tag, all) {
|
function pageTitle(tag, all) {
|
||||||
|
|
|
@ -5,7 +5,8 @@ window.addEventListener('load', function() {
|
||||||
var fun = unitJS.Fun();
|
var fun = unitJS.Fun();
|
||||||
var md = new Remarkable({html: true});
|
var md = new Remarkable({html: true});
|
||||||
md.block.ruler.enable(['footnote']);
|
md.block.ruler.enable(['footnote']);
|
||||||
var domRenderer = DomRenderer({fun: fun, md: md, dom: dom});
|
var comments = Comments({async: async, cache: cache, dom: dom});
|
||||||
|
var domRenderer = DomRenderer({comments: comments, fun: fun, md: md, dom: dom});
|
||||||
var navigation = Navigation({async: async, cache: cache, fun: fun, md: md, dom: dom, domRenderer: domRenderer});
|
var navigation = Navigation({async: async, cache: cache, fun: fun, md: md, dom: dom, domRenderer: domRenderer});
|
||||||
domRenderer.replaceMarkdown();
|
domRenderer.replaceMarkdown();
|
||||||
navigation.hijackLinks();
|
navigation.hijackLinks();
|
||||||
|
|
|
@ -18,6 +18,7 @@ data Arguments = BlogConfig {
|
||||||
, articlesPath :: FilePath
|
, articlesPath :: FilePath
|
||||||
, bannerPath :: Maybe FilePath
|
, bannerPath :: Maybe FilePath
|
||||||
, cardImage :: Maybe FilePath
|
, cardImage :: Maybe FilePath
|
||||||
|
, commentsAt :: Maybe String
|
||||||
, favicon :: Maybe FilePath
|
, favicon :: Maybe FilePath
|
||||||
, headPath :: Maybe FilePath
|
, headPath :: Maybe FilePath
|
||||||
, name :: Maybe String
|
, name :: Maybe String
|
||||||
|
@ -49,6 +50,7 @@ blogConfig = BlogConfig
|
||||||
)
|
)
|
||||||
<*> option filePath 'b' "banner" "BANNER_PATH" "path to the file to use for the blog's banner"
|
<*> option filePath 'b' "banner" "BANNER_PATH" "path to the file to use for the blog's banner"
|
||||||
<*> option filePath 'c' "card-image" "CARD_IMAGE" "path to the image to use for the blog's card"
|
<*> option filePath 'c' "card-image" "CARD_IMAGE" "path to the image to use for the blog's card"
|
||||||
|
<*> option filePath 'C' "comments-at" "INSTANCE_URL" "url of the instance where comments are stored"
|
||||||
<*> option filePath 'f' "favicon" "FAVICON" "path to the image to use for the blog's favicon"
|
<*> option filePath 'f' "favicon" "FAVICON" "path to the image to use for the blog's favicon"
|
||||||
<*> option filePath 'H' "head" "HEAD_PATH" "path to the file to add in the blog's head"
|
<*> option filePath 'H' "head" "HEAD_PATH" "path to the file to add in the blog's head"
|
||||||
<*> option str 'n' "name" "BLOG_NAME" "name of the blog"
|
<*> option str 'n' "name" "BLOG_NAME" "name of the blog"
|
||||||
|
|
|
@ -8,6 +8,7 @@ import qualified Arguments as Arguments (Arguments(..))
|
||||||
|
|
||||||
data Path = Path {
|
data Path = Path {
|
||||||
articlesPath :: FilePath
|
articlesPath :: FilePath
|
||||||
|
, commentsAt :: Maybe String
|
||||||
, pagesPath :: Maybe FilePath
|
, pagesPath :: Maybe FilePath
|
||||||
, root :: FilePath
|
, root :: FilePath
|
||||||
}
|
}
|
||||||
|
@ -15,6 +16,7 @@ data Path = Path {
|
||||||
build :: Arguments -> Path
|
build :: Arguments -> Path
|
||||||
build arguments = Path {
|
build arguments = Path {
|
||||||
articlesPath = Arguments.articlesPath arguments
|
articlesPath = Arguments.articlesPath arguments
|
||||||
|
, commentsAt = Arguments.commentsAt arguments
|
||||||
, pagesPath = Arguments.pagesPath arguments
|
, pagesPath = Arguments.pagesPath arguments
|
||||||
, root = Arguments.sourceDir arguments
|
, root = Arguments.sourceDir arguments
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ instance ToJSON ArticleExport where
|
||||||
|
|
||||||
data PathExport = PathExport {
|
data PathExport = PathExport {
|
||||||
articlesPath :: FilePath
|
articlesPath :: FilePath
|
||||||
|
, commentsAt :: Maybe String
|
||||||
, pagesPath :: Maybe FilePath
|
, pagesPath :: Maybe FilePath
|
||||||
} deriving (Generic)
|
} deriving (Generic)
|
||||||
|
|
||||||
|
@ -67,6 +68,7 @@ exportBlog = do
|
||||||
articles = mapWithKey (export blog) $ Blog.articles blog
|
articles = mapWithKey (export blog) $ Blog.articles blog
|
||||||
, path = PathExport {
|
, path = PathExport {
|
||||||
articlesPath = Blog.articlesPath $ Blog.path blog
|
articlesPath = Blog.articlesPath $ Blog.path blog
|
||||||
|
, commentsAt = Blog.commentsAt $ Blog.path blog
|
||||||
, pagesPath = Blog.pagesPath $ Blog.path blog
|
, pagesPath = Blog.pagesPath $ Blog.path blog
|
||||||
}
|
}
|
||||||
, skin = SkinExport {
|
, skin = SkinExport {
|
||||||
|
|
Loading…
Reference in a new issue