diff --git a/index.js b/index.js index 8cf7b92..0961108 100644 --- a/index.js +++ b/index.js @@ -329,6 +329,7 @@ async function getArticleCounts(db, year) { async function getArticlesByYearMonth(db, year, month) { const articles = db.prepare(` SELECT + id, printf('%d-%02d', year, month) AS year_month, author, title, slug, published_date FROM article @@ -348,7 +349,7 @@ async function getArticlesByYearMonth(db, year, month) { async function getArticlesByCategory(db, name, limit, offset) { const articles = db.prepare(` - SELECT a.slug, a.title, a.author, a.published_date + SELECT a.id, a.slug, a.title, a.author, a.published_date FROM article a JOIN article__category ac ON a.id = ac.article_id JOIN category c ON c.id = ac.category_id @@ -380,7 +381,7 @@ async function countArticlesByCategory(db, name) { async function getArticlesByTag(db, name, limit, offset) { const articles = db.prepare(` - SELECT a.slug, a.title, a.author, a.published_date + SELECT a.id, a.slug, a.title, a.author, a.published_date FROM article a JOIN article__tag a_t ON a.id = a_t.article_id JOIN tag c ON c.id = a_t.tag_id @@ -413,6 +414,45 @@ async function countTags(db) { return count.c } +function questionMarks(list){ + let s = '' + for (let i = 0; i < list.length; i++) { + s += '?, ' + } + return s.replace(/, $/, '') +} + +/** + * Return a list of tags for the given list of article ids + * @param {Database} db - SQLite3 database instance + * @param {Array} ids - a list of article ids + * @returns {Array} A list of [article.id, tag.name] pairs + */ +async function getTagsForArticles(db, ids) { + const tags = db.prepare(` + SELECT a.id, t.name + FROM article a + JOIN article__tag a_t ON a.id = a_t.article_id + JOIN tag t ON t.id = a_t.tag_id + WHERE a.id IN (${questionMarks(ids)}) + ORDER BY a.id, t.name + `).all(...ids).reduce((m, a) => { + if (!m[a.id]) { + m[a.id] = [] + } + m[a.id].push(a.name) + return m + }, {}) + return tags +} + +function applyTagsToArticles(articles, tags) { + return articles.map((a) => { + a.tags = tags[a.id] + return a + }) +} + module.exports = { db, fetchFeed, @@ -441,5 +481,7 @@ module.exports = { countArticlesByCategory, getArticlesByTag, countArticlesByTag, - countTags + countTags, + getTagsForArticles, + applyTagsToArticles } diff --git a/routes/ad/:period.js b/routes/ad/:period.js index f392a6e..0cc2ea3 100644 --- a/routes/ad/:period.js +++ b/routes/ad/:period.js @@ -16,7 +16,9 @@ module.exports.GET = async (req, res) => { if (period.match(/-/)) { // year-month const [year, month] = period.split(/-/) - const articles = await ds.getArticlesByYearMonth(db, year, month) + const _articles = await ds.getArticlesByYearMonth(db, year, month) + const tags = await ds.getTagsForArticles(db, _articles.map((a) => a.id)) + const articles = ds.applyTagsToArticles(_articles, tags) const out = await page.render('ad-year-month', { year, month, articles }) send(res, 200, out) } else { diff --git a/routes/category/:name.js b/routes/category/:name.js index 0eb3dff..273d37d 100644 --- a/routes/category/:name.js +++ b/routes/category/:name.js @@ -32,7 +32,9 @@ module.exports.GET = async (req, res) => { const query = qs.parse(req.query) const p = query.p ? parseInt(query.p) : 1 const {limit, offset} = pagination.getValuesToPaginate({ currentPage: p, perPage: PER_PAGE }) - const articles = await ds.getArticlesByCategory(db, name, limit, offset) + const _articles = await ds.getArticlesByCategory(db, name, limit, offset) + const tags = await ds.getTagsForArticles(db, _articles.map((a) => a.id)) + const articles = ds.applyTagsToArticles(_articles, tags) const count = await ds.countArticlesByCategory(db, name) const totalPages = pagination.getTotalPages({ totalItems: count, perPage: PER_PAGE }) //console.log('category', { articles, path, p, count, totalPages }) diff --git a/routes/tag/:name.js b/routes/tag/:name.js index 541afd0..ac65bc8 100644 --- a/routes/tag/:name.js +++ b/routes/tag/:name.js @@ -17,7 +17,9 @@ module.exports.GET = async (req, res) => { const query = qs.parse(req.query) const p = query.p ? parseInt(query.p) : 1 const {limit, offset} = pagination.getValuesToPaginate({ currentPage: p, perPage: PER_PAGE }) - const articles = await ds.getArticlesByTag(db, name, limit, offset) + const _articles = await ds.getArticlesByTag(db, name, limit, offset) + const tags = await ds.getTagsForArticles(db, _articles.map((a) => a.id)) + const articles = ds.applyTagsToArticles(_articles, tags) const count = await ds.countArticlesByTag(db, name) const totalPages = pagination.getTotalPages({ totalItems: count, perPage: PER_PAGE }) const out = await page.render('tag', { tag, articles, path, p, count, totalPages }) diff --git a/templates/_article-link.ejs b/templates/_article-link.ejs index 017ef44..38b9c72 100644 --- a/templates/_article-link.ejs +++ b/templates/_article-link.ejs @@ -1,3 +1,15 @@
-
<%- art.title %> by <%- art.author %>
+
<%- art.title %>
+
+ +
+ <% if (art.tags) { %> + <% art.tags.forEach((tag) => { %> + <%= tag %> + <% }) %> + <% } %> +
+
diff --git a/templates/_header.ejs b/templates/_header.ejs index 433938d..2f8e167 100644 --- a/templates/_header.ejs +++ b/templates/_header.ejs @@ -46,6 +46,9 @@ + <% + const linkColor = '#367bad' + %>