about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAlan Pearce2017-06-24 22:05:18 +0200
committerAlan Pearce2017-06-24 22:05:18 +0200
commitdd819c45b58088f9a98384ab237268d865836fe0 (patch)
treeabf2c2847571041454a9119dff7ccfc6b7d0f854
parentbdd6610208e9fe5971e6aed4378598092f2b9b5a (diff)
downloadhomestead-dd819c45b58088f9a98384ab237268d865836fe0.tar.lz
homestead-dd819c45b58088f9a98384ab237268d865836fe0.tar.zst
homestead-dd819c45b58088f9a98384ab237268d865836fe0.zip
refactor: re-architect to be closer to ADR
-rw-r--r--config/default.toml2
-rw-r--r--src/actions.js56
-rw-r--r--src/app.js54
-rw-r--r--src/domain/posts.js (renamed from src/modules/posts.js)30
-rw-r--r--src/modules/markdown.js12
-rw-r--r--src/responders.js3
-rw-r--r--test/domain/posts.test.js23
-rw-r--r--test/modules/posts.test.js49
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'))
-})