Add links to static pages and handle dynamic navigation on the JS side
This commit is contained in:
parent
937a6858e0
commit
47f5c70e21
6 changed files with 74 additions and 38 deletions
|
@ -6,6 +6,7 @@ dateFormat = en-US
|
|||
latestLink = See only latest
|
||||
latestPage = Latest articles{? tagged ${tag}?}
|
||||
metadata = {?by ${author} ?}on ${date}{? tagged ${tags}?}
|
||||
pagesList = Pages
|
||||
rssLink = Subscribe
|
||||
rssTitle = Follow all articles{? tagged ${tag}?}
|
||||
tagsList = Tags
|
||||
|
|
|
@ -6,20 +6,21 @@ import * as Dom from UnitJS.Dom;
|
|||
import {defined} from UnitJS.Fun;
|
||||
|
||||
return {
|
||||
article: article,
|
||||
articlesList: articlesList,
|
||||
render: render,
|
||||
replaceMarkdown: replaceMarkdown
|
||||
};
|
||||
|
||||
function replaceMarkdown() {
|
||||
var div = document.getElementById('contents');
|
||||
if(div.children[0] && div.children[0].tagName.toLowerCase() == 'article') {
|
||||
convertArticle(div.children[0], true);
|
||||
var contentType = window.location.pathname.slice(1).replace(/\/.*/, '');
|
||||
convertContent(contentType, div.children[0], true);
|
||||
} else {
|
||||
var articles = div.getElementsByClassName('articles')[0];
|
||||
if(articles != undefined) {
|
||||
for(var i = 0; i < articles.children.length; i++) {
|
||||
convertArticle(articles.children[i]);
|
||||
convertContent('article', articles.children[i]);
|
||||
}
|
||||
} else {
|
||||
console.log('No articles found for this page');
|
||||
|
@ -27,13 +28,15 @@ function replaceMarkdown() {
|
|||
}
|
||||
}
|
||||
|
||||
function convertArticle(article, comments) {
|
||||
function convertContent(contentType, article, comments) {
|
||||
var header = article.getElementsByTagName('header')[0];
|
||||
header.appendChild(Metadata.get(article.id));
|
||||
if(contentType == 'article') {
|
||||
header.appendChild(Metadata.get(article.id));
|
||||
}
|
||||
var text = article.getElementsByTagName('pre')[0];
|
||||
if(text != undefined) {
|
||||
article.replaceChild(getDiv(text.innerText), text);
|
||||
if(comments) {
|
||||
if(contentType == 'article' && comments) {
|
||||
Metadata.getComments(article.id)
|
||||
.forEach(article.appendChild.bind(article));
|
||||
}
|
||||
|
@ -56,19 +59,33 @@ function getDiv(markdown) {
|
|||
return d;
|
||||
}
|
||||
|
||||
function article(key, markdown, limit) {
|
||||
var url = ["", blog.path.articlesPath, key + (limit != undefined ? '.html' : '.md')].join('/');
|
||||
var lines = markdown.split(/\n/).slice(blog.articles[key].bodyOffset);
|
||||
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) {
|
||||
return [];
|
||||
} else {
|
||||
return Metadata.getComments(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);
|
||||
var div = getDiv(lines.slice(0, limit).join('\n'));
|
||||
return Dom.make('article', {}, [
|
||||
Dom.make('header', {}, [
|
||||
Dom.make('a', {href: url}, [
|
||||
Dom.make('h1', {innerText: blog.articles[key].title})
|
||||
]),
|
||||
Metadata.get(key)
|
||||
]),
|
||||
Dom.make('h1', {}, [
|
||||
Dom.make('a', {href: url, innerText: resource.title})
|
||||
])].concat(contentType == 'article' ? Metadata.get(key) : [])
|
||||
),
|
||||
div
|
||||
].concat(limit != undefined ? [] : Metadata.getComments(key)));
|
||||
].concat(commentsSection(contentType, key, limit)));
|
||||
}
|
||||
|
||||
function pageTitle(tag, all) {
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
import {article, articlesList} from DomRenderer;
|
||||
import {articlesList, render} from DomRenderer;
|
||||
import blog from Hablo.Config;
|
||||
import * as Async from UnitJS.Async;
|
||||
import * as Cache from UnitJS.Cache;
|
||||
import * as Dom from UnitJS.Dom;
|
||||
import * as Fun from UnitJS.Fun;
|
||||
|
||||
var articles = Cache.make(function(key) {
|
||||
var url = ["", blog.path.articlesPath, key + '.md'].join('/');
|
||||
return Async.bind(
|
||||
Async.http({method: 'GET', url: url}),
|
||||
function(queryResult) {
|
||||
if(queryResult.status == 200) {
|
||||
return Async.wrap(queryResult.responseText);
|
||||
} else {
|
||||
return Async.fail(
|
||||
"Could not load article " + url + " (" + queryResult.status + " " + queryResult.statusText + ")"
|
||||
);
|
||||
var cache = {};
|
||||
['article', 'page'].forEach(function(contentType) {
|
||||
cache[contentType] = Cache.make(function(key) {
|
||||
var url = ["", blog.path[contentType + 'sPath'], key + '.md'].join('/');
|
||||
return Async.bind(
|
||||
Async.http({method: 'GET', url: url}),
|
||||
function(queryResult) {
|
||||
if(queryResult.status == 200) {
|
||||
return Async.wrap(queryResult.responseText);
|
||||
} else {
|
||||
return Async.fail(
|
||||
"Could not load " + contentType + " " + url + " (" + queryResult.status + " " + queryResult.statusText + ")"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('popstate', function(e) {
|
||||
if(e.state != undefined) {
|
||||
navigate(e.state.url);
|
||||
|
@ -60,27 +64,29 @@ function navigate(url) {
|
|||
if(blog.tags[path[0]] != undefined) {
|
||||
show(getArticlesList(path[0], path[1] == "all.html"));
|
||||
} else if(path[0] == blog.path.articlesPath) {
|
||||
show(getArticle(path[1].replace(/\.html$/, '')));
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
function getArticle(key) {
|
||||
function getResource(contentType, key) {
|
||||
return Async.bind(
|
||||
articles.get(key),
|
||||
cache[contentType].get(key),
|
||||
Async.map(
|
||||
function(contents) {return [article(key, contents)];}
|
||||
function(contents) {return [render(contentType, key, contents)];}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function preview(key) {
|
||||
return Async.bind(
|
||||
articles.get(key),
|
||||
cache.article.get(key),
|
||||
function(contents) {
|
||||
return Async.wrap(
|
||||
article(key, contents, blog.skin.previewLinesCount)
|
||||
render('article', key, contents, blog.skin.previewLinesCount)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -32,6 +32,7 @@ variables = Map.fromList [
|
|||
, ("latestLink", [])
|
||||
, ("latestPage", ["tag"])
|
||||
, ("metadata", ["author", "date", "tags"])
|
||||
, ("pagesList", [])
|
||||
, ("rssLink", [])
|
||||
, ("rssTitle", ["tag"])
|
||||
, ("tagsList", [])
|
||||
|
|
16
src/DOM.hs
16
src/DOM.hs
|
@ -12,7 +12,7 @@ import ArticlesList (
|
|||
)
|
||||
import Blog (Blog(..), Skin(..), URL(..), template)
|
||||
import Control.Monad.Reader (ReaderT, asks)
|
||||
import qualified Data.Map as Map (keys)
|
||||
import qualified Data.Map as Map (elems, keys)
|
||||
import Data.Text (pack, empty)
|
||||
import DOM.Card (HasCard)
|
||||
import qualified DOM.Card as Card (make)
|
||||
|
@ -63,12 +63,18 @@ markdown raw (Markdown {key, Markdown.path, body, title}) =
|
|||
let url = absoluteLink $ path <.> extension in
|
||||
article_ [id_ $ pack key] (do
|
||||
header_ (do
|
||||
a_ [href_ $ pack url] . h1_ $ toHtml title
|
||||
h1_ . a_ [href_ $ pack url] $ toHtml title
|
||||
)
|
||||
pre_ . toHtml $ unlines body
|
||||
)
|
||||
where extension = if raw then "md" else "html"
|
||||
|
||||
mDLink :: MarkdownContent a => Bool -> a -> HtmlGenerator ()
|
||||
mDLink raw a = a_ [href_ $ pack url] $ toHtml title
|
||||
where
|
||||
Markdown {Markdown.path, title} = getMarkdown a
|
||||
url = absoluteLink $ path <.> (if raw then "md" else "html")
|
||||
|
||||
tag :: String -> HtmlGenerator ()
|
||||
tag name = li_ (
|
||||
a_ [href_ . pack $ absoluteLink name ++ "/", class_ "tag"] $ toHtml name
|
||||
|
@ -104,10 +110,14 @@ htmlDocument someContent =
|
|||
)
|
||||
body_ (do
|
||||
maybe defaultBanner toHtmlRaw =<< (asks $skin.$banner)
|
||||
div_ [id_ "navigator"] (do
|
||||
div_ [id_ "tags"] (do
|
||||
h2_ . toHtml =<< template "tagsList" []
|
||||
ul_ . mapM_ tag . Map.keys =<< asks tags
|
||||
)
|
||||
div_ [id_ "pages"] (do
|
||||
h2_ . toHtml =<< template "pagesList" []
|
||||
ul_ . mapM_ (mDLink False) . Map.elems =<< asks pages
|
||||
)
|
||||
div_ [id_ "contents"] $ content someContent
|
||||
)
|
||||
)
|
||||
|
|
|
@ -16,6 +16,7 @@ defaultWording = Wording $ Map.fromList [
|
|||
, ("latestLink", "See only latest")
|
||||
, ("latestPage", "Latest articles{? tagged ${tag}?}")
|
||||
, ("metadata", "{?by ${author} ?}on ${date}{? tagged ${tags}?}")
|
||||
, ("pagesList", "Pages")
|
||||
, ("rssLink", "Subscribe")
|
||||
, ("rssTitle", "Follow all articles{? tagged ${tag}?}")
|
||||
, ("tagsList", "Tags")
|
||||
|
|
Loading…
Reference in a new issue