diff options
-rw-r--r-- | config/default.toml | 2 | ||||
-rw-r--r-- | src/actions.js | 56 | ||||
-rw-r--r-- | src/app.js | 54 | ||||
-rw-r--r-- | src/domain/posts.js (renamed from src/modules/posts.js) | 30 | ||||
-rw-r--r-- | src/modules/markdown.js | 12 | ||||
-rw-r--r-- | src/responders.js | 3 | ||||
-rw-r--r-- | test/domain/posts.test.js | 23 | ||||
-rw-r--r-- | test/modules/posts.test.js | 49 |
8 files changed, 113 insertions, 116 deletions
diff --git a/config/default.toml b/config/default.toml index 67bb521..acda778 100644 --- a/config/default.toml +++ b/config/default.toml @@ -7,7 +7,7 @@ title = "Test Site" [posts] folder = "./posts" -[taxonomies] +[posts.taxonomies] tag = "tags" category = "categories" diff --git a/src/actions.js b/src/actions.js new file mode 100644 index 0000000..c6e04c0 --- /dev/null +++ b/src/actions.js @@ -0,0 +1,56 @@ +'use strict' + +const send = require('koa-send') +const streamify = require('stream-array') +const responders = require('./responders') + +function toArrayStream (iterator) { + return streamify(Array.from(iterator.entries())) +} + +function home (config, posts) { + const postsStream = toArrayStream(posts) + return async function (ctx, next) { + responders.home(ctx, config, postsStream) + } +} + +function post (config, posts) { + return async function (ctx, next) { + ctx.assert(posts.has(ctx.params.filename), 404, 'Post not found') + const post = posts.get(ctx.params.filename) + + responders.post(ctx, config, post) + } +} + +function taxonGenerator (config, term, items) { + return async function (ctx, next) { + const value = ctx.params.value + ctx.assert( + items.has(ctx.params.value), + 404, + `Could not find ${term} ${value}` + ) + + const taxonItems = toArrayStream(items.get(value)) + + responders.taxon(ctx, config, taxonItems) + } +} + +const prefix = /^\/static\// +async function serveFiles (ctx) { + if (prefix.test(ctx.path)) { + await send(ctx, ctx.path.replace(prefix, ''), { + root: './static' + }) + } +} + +module.exports = { + home, + post, + taxonGenerator, + serveFiles +} diff --git a/src/app.js b/src/app.js index 84722fc..46ebd2e 100644 --- a/src/app.js +++ b/src/app.js @@ -3,10 +3,7 @@ const Koa = require('koa') const app = new Koa() -const streamify = require('stream-array') - -const send = require('koa-send') -const responders = require('./responders.js') +const actions = require('./actions.js') const config = require('./modules/config.js') @@ -15,51 +12,22 @@ const router = new Router() app.context.getURL = router.url.bind(router) -const Posts = require('./modules/posts.js') -const posts = Posts.getFolder(config.posts.folder) - -function toArrayStream (iterator) { - return streamify(Array.from(iterator.entries())) -} - -const postsStream = toArrayStream(posts) -router.get('home', '/', async function (ctx, next) { - responders.home(ctx, config, postsStream) -}) - -router.get('post', '/post/:filename', async function (ctx, next) { - ctx.assert(posts.has(ctx.params.filename), 404, 'Post not found') - const post = posts.get(ctx.params.filename) - post.body = Posts.render(post) - - responders.post(ctx, config, post) -}) +const Posts = require('./domain/posts.js')(config.posts) -const taxonomies = Posts.taxonomise(config.taxonomies, posts) -for (let [term, items] of taxonomies) { - router.get(`taxon-${term}`, `/${term}/:value`, async function (ctx, next) { - const value = ctx.params.value - ctx.assert( - items.has(ctx.params.value), - 404, - `Could not find ${term} ${value}` - ) +router.get('home', '/', actions.home(config, Posts.posts)) - const taxonItems = toArrayStream(items.get(value)) +router.get('post', '/post/:filename', actions.post(config, Posts.posts)) - responders.taxon(ctx, config, taxonItems) - }) +for (let [term, items] of Posts.taxonomies) { + router.get( + `taxon-${term}`, + `/${term}/:value`, + actions.taxonGenerator(config, term, items) + ) } app.use(router.routes()).use(router.allowedMethods()) -const prefix = /^\/static\// -app.use(async function (ctx) { - if (prefix.test(ctx.path)) { - await send(ctx, ctx.path.replace(prefix, ''), { - root: './static' - }) - } -}) +app.use(actions.serveFiles) module.exports = app diff --git a/src/modules/posts.js b/src/domain/posts.js index cf2d80e..14bc7cc 100644 --- a/src/modules/posts.js +++ b/src/domain/posts.js @@ -3,20 +3,12 @@ const fs = require('fs') const path = require('path') const matter = require('gray-matter') -const Markdown = require('markdown-it') const grayMatterOptions = { lang: 'toml', delims: '+++' } -const markdownOptions = { - html: true, - typographer: true -} - -const markdown = new Markdown(markdownOptions) - function* lowercaseKeys (iterator) { for (let [k, v] of iterator) { yield [String(k).toLowerCase(), v] @@ -36,10 +28,6 @@ function getTitle (file) { return path.basename(file.path, path.extname(file.path)) } -function render (post) { - return markdown.render(post.content) -} - function get (filename) { const fileMatter = matter.read(filename, grayMatterOptions) fileMatter.basename = getTitle(fileMatter) @@ -75,14 +63,12 @@ function taxonomise (taxonomies, posts) { return taxons } -function toTags (posts) { - return taxonomise({ tag: 'tags' }, posts).get('tag') -} - -module.exports = { - get, - getFolder, - toTags, - taxonomise, - render +module.exports = function (config) { + const posts = getFolder(config.folder) + const taxonomies = taxonomise(config.taxonomies, posts) + return { + posts, + taxonomies, + get + } } diff --git a/src/modules/markdown.js b/src/modules/markdown.js new file mode 100644 index 0000000..9f0af45 --- /dev/null +++ b/src/modules/markdown.js @@ -0,0 +1,12 @@ +'use strict' + +const Markdown = require('markdown-it') + +const markdownOptions = { + html: true, + typographer: true +} + +const markdown = new Markdown(markdownOptions) + +module.exports = markdown.render.bind(markdown) diff --git a/src/responders.js b/src/responders.js index 1a9e8ce..a11e598 100644 --- a/src/responders.js +++ b/src/responders.js @@ -2,6 +2,7 @@ const fs = require('fs') const rheo = require('rheo') +const markdown = require('./modules/markdown.js') const templateReader = template => () => fs.createReadStream(`${__dirname}/templates/${template}.html`) @@ -55,7 +56,7 @@ module.exports = { .pipe(rheo()) .inner('main', showPage('post')) .inner('article h1', rheo(post.data.get('title'))) - .inner('article main', rheo(post.body)) + .inner('article main', rheo(markdown(post.content))) .pipe(setTitle(config.site.title, post.data.get('title'))) .render() }, diff --git a/test/domain/posts.test.js b/test/domain/posts.test.js new file mode 100644 index 0000000..8866f40 --- /dev/null +++ b/test/domain/posts.test.js @@ -0,0 +1,23 @@ +const test = require('ava') +const path = require('path') + +const Posts = require('../../src/domain/posts.js')({ + folder: path.resolve('../data', __dirname), + taxonomies: { + tag: 'tags', + category: 'categories' + } +}) + +test('get', t => { + const expected = new Map( + Object.entries({ + title: 'This is a test', + description: 'Test file', + tags: ['a', 'b'] + }) + ) + const post = Posts.get(path.resolve(__dirname, '../data/testfile.md')) + t.deepEqual(post.data, expected) + t.is(post.basename, 'testfile', 'must include basename') +}) diff --git a/test/modules/posts.test.js b/test/modules/posts.test.js deleted file mode 100644 index 454488f..0000000 --- a/test/modules/posts.test.js +++ /dev/null @@ -1,49 +0,0 @@ -const test = require('ava') -const path = require('path') - -const Posts = require('../../src/modules/posts.js') - -test('get', t => { - const expected = new Map( - Object.entries({ - title: 'This is a test', - description: 'Test file', - tags: ['a', 'b'] - }) - ) - const post = Posts.get(path.resolve(__dirname, '../data/testfile.md')) - t.deepEqual(post.data, expected) - t.is(post.basename, 'testfile', 'must include basename') -}) - -test('getFolder', t => { - const expected = new Map( - Object.entries({ - title: 'This is a test', - description: 'Test file', - tags: ['a', 'b'] - }) - ) - const actual = Posts.getFolder(path.resolve(__dirname, '../data/')) - t.true(actual.size > 0, 'must return a non-empty map') - t.is( - actual.get('testfile').path, - path.resolve(__dirname, '../data/testfile.md') - ) - t.deepEqual(actual.get('testfile').data, expected) -}) - -test('toTags', t => { - const posts = new Map([ - [ - 'testfile', - { - data: new Map([['title', 'Test Post'], ['tags', ['a', 'b']]]) - } - ] - ]) - const actual = Posts.toTags(posts) - t.is(actual.size, 2) - t.is(actual.get('a')[0].data.get('title'), 'Test Post') - t.deepEqual(actual.get('a'), actual.get('b')) -}) |