Release 1.1.0.1
This commit is contained in:
parent
3e223e7169
commit
7e7d7e0804
4 changed files with 74 additions and 56 deletions
|
@ -1,5 +1,10 @@
|
|||
# Revision history for hablo
|
||||
|
||||
## 1.1.0.1 -- 2021-01-20
|
||||
|
||||
* Ensure compilation on Nix as far as 18.09
|
||||
* Fix missing metadata when landing on articles
|
||||
|
||||
## 1.1.0.0 -- 2020-12-13
|
||||
|
||||
* Implement static pages
|
||||
|
|
|
@ -3,7 +3,7 @@ cabal-version: >= 1.10
|
|||
-- For further documentation, see http://haskell.org/cabal/users-guide/
|
||||
|
||||
name: hablo
|
||||
version: 1.1.0.0
|
||||
version: 1.1.0.1
|
||||
synopsis: A minimalist static blog generator
|
||||
description:
|
||||
Hablo is a fediverse-oriented static blog generator for articles written
|
||||
|
@ -50,15 +50,15 @@ library
|
|||
, Pretty
|
||||
, RSS
|
||||
-- other-extensions:
|
||||
build-depends: aeson >= 1.4.0 && < 1.6
|
||||
build-depends: aeson >= 1.2.0 && < 1.6
|
||||
, base >= 4.9.1 && < 4.15
|
||||
, bytestring >= 0.10.8 && < 0.12
|
||||
, containers >= 0.5.11 && < 0.7
|
||||
, directory >= 1.3.1 && < 1.4
|
||||
, filepath >= 1.4.2 && < 1.5
|
||||
, lucid >= 2.9.11 && < 2.10
|
||||
, lucid >= 2.8.0 && < 2.10
|
||||
, mtl >= 2.2.2 && < 2.3
|
||||
, optparse-applicative >= 0.14.3 && < 0.17
|
||||
, optparse-applicative >= 0.14.0 && < 0.17
|
||||
, parsec >= 3.1.13 && < 3.2
|
||||
, template >= 0.2.0 && < 0.3
|
||||
, text >= 1.2.3 && < 1.3
|
||||
|
|
|
@ -7,15 +7,37 @@ import {defined} from UnitJS.Fun;
|
|||
|
||||
return {
|
||||
articlesList: articlesList,
|
||||
getResource: getResource,
|
||||
render: render,
|
||||
replaceMarkdown: replaceMarkdown
|
||||
};
|
||||
|
||||
function getResource(url) {
|
||||
var i = url.lastIndexOf('/');
|
||||
var path = url.slice(1, i);
|
||||
if(path == blog.path.articlesPath) {
|
||||
return {type: 'article', key: url.slice(i+1).replace(/\.html/, '')};
|
||||
} else if(path == blog.path.pagesPath) {
|
||||
return {type: 'page', key: url.slice(i+1).replace(/\.html/, '')};
|
||||
} else if(path == '' || blog.tags[path] != undefined) {
|
||||
var tag = path.length > 0 ? path : undefined;
|
||||
return {type: 'list', tag: tag, all: url.slice(i+1) == 'all.html'};
|
||||
} else {
|
||||
return {type: 'unknown'};
|
||||
}
|
||||
}
|
||||
|
||||
function resourceUrl(resource, limit) {
|
||||
var directory = blog.path[resource.type + 'sPath'];
|
||||
var extension = limit != undefined ? '.html' : '.md';
|
||||
return ["", directory, resource.key + extension].join('/');
|
||||
}
|
||||
|
||||
function replaceMarkdown() {
|
||||
var div = document.getElementById('contents');
|
||||
if(div.children[0] && div.children[0].tagName.toLowerCase() == 'article') {
|
||||
var contentType = window.location.pathname.slice(1).replace(/\/.*/, '');
|
||||
convertContent(contentType, div.children[0], true);
|
||||
var resourceType = getResource(window.location.pathname).type;
|
||||
convertContent(resourceType, div.children[0], true);
|
||||
} else {
|
||||
var articles = div.getElementsByClassName('articles')[0];
|
||||
if(articles != undefined) {
|
||||
|
@ -28,15 +50,15 @@ function replaceMarkdown() {
|
|||
}
|
||||
}
|
||||
|
||||
function convertContent(contentType, article, comments) {
|
||||
function convertContent(resourceType, article, comments) {
|
||||
var header = article.getElementsByTagName('header')[0];
|
||||
if(contentType == 'article') {
|
||||
if(resourceType == 'article') {
|
||||
header.appendChild(Metadata.get(article.id));
|
||||
}
|
||||
var text = article.getElementsByTagName('pre')[0];
|
||||
if(text != undefined) {
|
||||
article.replaceChild(getDiv(text.innerText), text);
|
||||
if(contentType == 'article' && comments) {
|
||||
if(resourceType == 'article' && comments) {
|
||||
Metadata.getComments(article.id)
|
||||
.forEach(article.appendChild.bind(article));
|
||||
}
|
||||
|
@ -59,59 +81,53 @@ function getDiv(markdown) {
|
|||
return d;
|
||||
}
|
||||
|
||||
function contentUrl(contentType, key, limit) {
|
||||
var directory = blog.path[contentType + 'sPath'];
|
||||
var extension = limit != undefined ? '.html' : '.md';
|
||||
return ["", directory, key + extension].join('/');
|
||||
}
|
||||
|
||||
function commentsSection(contentType, key, limit) {
|
||||
if(contentType != 'article' || limit != undefined) {
|
||||
function commentsSection(resource, limit) {
|
||||
if(resource.type != 'article' || limit != undefined) {
|
||||
return [];
|
||||
} else {
|
||||
return Metadata.getComments(key);
|
||||
return Metadata.getComments(resource.key);
|
||||
}
|
||||
}
|
||||
|
||||
function render(contentType, key, markdown, limit) {
|
||||
var url = contentUrl(contentType, key, limit);
|
||||
var resource = blog[contentType + 's'][key];
|
||||
var lines = markdown.split(/\n/).slice(resource.bodyOffset);
|
||||
function render(resource, markdown, limit) {
|
||||
var url = resourceUrl(resource, limit);
|
||||
var content = blog[resource.type + 's'][resource.key];
|
||||
var lines = markdown.split(/\n/).slice(content.bodyOffset);
|
||||
var div = getDiv(lines.slice(0, limit).join('\n'));
|
||||
return Dom.make('article', {}, [
|
||||
Dom.make('header', {}, [
|
||||
Dom.make('h1', {}, [
|
||||
Dom.make('a', {href: url, innerText: resource.title})
|
||||
])].concat(contentType == 'article' ? Metadata.get(key) : [])
|
||||
Dom.make('a', {href: url, innerText: content.title})
|
||||
])].concat(resource.type == 'article' ? Metadata.get(resource.key) : [])
|
||||
),
|
||||
div
|
||||
].concat(commentsSection(contentType, key, limit)));
|
||||
].concat(commentsSection(resource, limit)));
|
||||
}
|
||||
|
||||
function pageTitle(tag, all) {
|
||||
return Template.render(all ? 'allPage' : 'latestPage', {tag: tag});
|
||||
function pageTitle(resource) {
|
||||
return Template.render(resource.all ? 'allPage' : 'latestPage', {tag: resource.tag});
|
||||
}
|
||||
|
||||
function otherUrl(tag, all) {
|
||||
var path = [tag, all ? '' : 'all.html'];
|
||||
function otherUrl(resource) {
|
||||
var path = [resource.tag, resource.all ? '' : 'all.html'];
|
||||
return '/' + path.filter(defined).join('/');
|
||||
}
|
||||
|
||||
function articlesList(tag, all) {
|
||||
function articlesList(resource) {
|
||||
return function(articlePreviews) {
|
||||
return [
|
||||
Dom.make('h2', {innerText: pageTitle(tag, all)}),
|
||||
Dom.make('ul', {}, articlesListLinks(tag, all)),
|
||||
Dom.make('h2', {innerText: pageTitle(resource)}),
|
||||
Dom.make('ul', {}, articlesListLinks(resource)),
|
||||
Dom.make('div', {class: 'articles'}, articlePreviews.filter(defined))
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
function articlesListLinks(tag, all) {
|
||||
function articlesListLinks(resource) {
|
||||
var links = [
|
||||
Dom.make('a', {
|
||||
innerText: all ? blog.wording.latestLink : blog.wording.allLink,
|
||||
href: otherUrl(tag, all),
|
||||
innerText: resource.all ? blog.wording.latestLink : blog.wording.allLink,
|
||||
href: otherUrl(resource),
|
||||
class: 'other'
|
||||
})
|
||||
];
|
||||
|
@ -120,7 +136,7 @@ function articlesListLinks(tag, all) {
|
|||
innerText: blog.wording.rssLink,
|
||||
href: 'rss.xml',
|
||||
class: 'RSS',
|
||||
title: Template.render('rssTitle', {tag: tag})
|
||||
title: Template.render('rssTitle', {tag: resource.tag})
|
||||
}));
|
||||
}
|
||||
return links.map(function(e) {return Dom.make('li', {}, [e]);});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {articlesList, render} from DomRenderer;
|
||||
import {articlesList, getResource, render} from DomRenderer;
|
||||
import blog from Hablo.Config;
|
||||
import * as Async from UnitJS.Async;
|
||||
import * as Cache from UnitJS.Cache;
|
||||
|
@ -60,23 +60,20 @@ function visit(url) {
|
|||
}
|
||||
|
||||
function navigate(url) {
|
||||
var path = decodeURI(url).split("/").slice(1);
|
||||
if(blog.tags[path[0]] != undefined) {
|
||||
show(getArticlesList(path[0], path[1] == "all.html"));
|
||||
} else if(path[0] == blog.path.articlesPath) {
|
||||
show(getResource('article', path[1].replace(/\.html$/, '')));
|
||||
} else if(path[0] == blog.path.pagesPath) {
|
||||
show(getResource('page', path[1].replace(/\.html$/, '')));
|
||||
} else {
|
||||
show(getArticlesList(null, path[0] == "all.html"));
|
||||
var resource = getResource(url);
|
||||
switch(resource.type) {
|
||||
case 'list': show(getArticlesList(resource)); break;
|
||||
case 'article':
|
||||
case 'page': show(getCached(resource)); break;
|
||||
default: console.log("No idea how to navigate to " + url);
|
||||
}
|
||||
}
|
||||
|
||||
function getResource(contentType, key) {
|
||||
function getCached(resource) {
|
||||
return Async.bind(
|
||||
cache[contentType].get(key),
|
||||
cache[resource.type].get(resource.key),
|
||||
Async.map(
|
||||
function(contents) {return [render(contentType, key, contents)];}
|
||||
function(contents) {return [render(resource, contents)];}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -86,23 +83,23 @@ function preview(key) {
|
|||
cache.article.get(key),
|
||||
function(contents) {
|
||||
return Async.wrap(
|
||||
render('article', key, contents, blog.skin.previewLinesCount)
|
||||
render({type: 'article', key: key}, contents, blog.skin.previewLinesCount)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function articleIds(tag, all) {
|
||||
var ids = tag != undefined ? blog.tags[tag] : Object.keys(blog.articles);
|
||||
function articleIds(resource) {
|
||||
var ids = resource.tag != undefined ? blog.tags[resource.tag] : Object.keys(blog.articles);
|
||||
var reverseDate = function (id) {return -blog.articles[id].metadata.date;};
|
||||
ids.sort(Fun.compare(reverseDate));
|
||||
return ids.slice(0, all ? undefined : blog.skin.previewArticlesCount);
|
||||
return ids.slice(0, resource.all ? undefined : blog.skin.previewArticlesCount);
|
||||
}
|
||||
|
||||
function getArticlesList(tag, all) {
|
||||
function getArticlesList(resource) {
|
||||
return Async.bind(
|
||||
Async.parallel.apply(null, articleIds(tag, all).map(preview)),
|
||||
Async.map(articlesList(tag, all))
|
||||
Async.parallel.apply(null, articleIds(resource).map(preview)),
|
||||
Async.map(articlesList(resource))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue