From da9ff90d3e1b1348c43cd378c0806e159a700810 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Sun, 18 Jun 2017 12:24:24 +0200 Subject: feat: Parse front matter as metadata --- package.json | 3 ++- src/index.js | 7 ++++++- src/modules/metadata.js | 46 +++++++++++++++++++++++++++++++++++++++++++ src/views/index.html | 4 ++++ test/data/testfile.md | 5 +++++ test/index.test.js | 9 ++++++--- test/modules/metadata.test.js | 33 +++++++++++++++++++++++++++++++ yarn.lock | 38 +++++++++++++++++++++++++++++++++-- 8 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 src/modules/metadata.js create mode 100644 test/data/testfile.md create mode 100644 test/modules/metadata.test.js diff --git a/package.json b/package.json index e66c8a5..1cc7565 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "dependencies": { "koa": "^2.2.0", "koa-nunjucks-next": "^1.1.3", - "koa-router": "^7.2.1" + "koa-router": "^7.2.1", + "gray-matter": "^2.1.1" } } diff --git a/src/index.js b/src/index.js index 630ac08..c16d952 100644 --- a/src/index.js +++ b/src/index.js @@ -10,10 +10,15 @@ const router = new Router() const view = require('koa-nunjucks-next') +const metadata = require('./modules/metadata.js') +const postMetadata = metadata.getFolderMetadata(process.env.POST_DIR) + app.use(view(`${__dirname}/views`)) router.get('/', async function (ctx, next) { - await ctx.render('index') + await ctx.render('index', { + posts: postMetadata + }) }) app.use(router.routes()).use(router.allowedMethods()) diff --git a/src/modules/metadata.js b/src/modules/metadata.js new file mode 100644 index 0000000..9f24d8e --- /dev/null +++ b/src/modules/metadata.js @@ -0,0 +1,46 @@ +'use strict' + +const fs = require('fs') +const path = require('path') +const matter = require('gray-matter') + +const options = { + lang: 'toml', + delims: '+++' +} + +function* lowercaseKeys (iterator) { + for (let [k, v] of iterator) { + yield [String(k).toLowerCase(), v] + } +} + +function canonicaliseMetadata (meta) { + if (meta.data) { + meta.data = new Map(lowercaseKeys(Object.entries(meta.data))) + } else { + meta.data = new Map() + } + return meta +} + +function readFileMetadata (filename) { + return canonicaliseMetadata(matter.read(filename, options)) +} + +function getFileMetadata (filename) { + const result = readFileMetadata(filename) + return result && result.data +} + +function getFolderMetadata (folder) { + return fs + .readdirSync(folder) + .map(f => path.resolve(folder, f)) + .map(readFileMetadata) +} + +module.exports = { + getFileMetadata, + getFolderMetadata +} diff --git a/src/views/index.html b/src/views/index.html index 3b18e51..0e900e6 100644 --- a/src/views/index.html +++ b/src/views/index.html @@ -1 +1,5 @@ hello world + +{% for post in posts %} + {{ post.data.get('title') }} +{% endfor %} diff --git a/test/data/testfile.md b/test/data/testfile.md new file mode 100644 index 0000000..6899d52 --- /dev/null +++ b/test/data/testfile.md @@ -0,0 +1,5 @@ ++++ +Title = "This is a test" +Description = "Test file" +Tags = ["a", "b"] ++++ diff --git a/test/index.test.js b/test/index.test.js index 2e55b2c..ebac87d 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,12 +1,15 @@ const test = require('ava') +const path = require('path') const request = require('supertest') +process.env.POST_DIR = path.resolve(__dirname, '../test/data/') const app = require('../src/index.js') -test(t => - request(app.listen()) +test(t => { + return request(app.listen()) .get('/') .expect(200) .expect(/hello world/) + .expect(/This is a test/) .then(() => t.pass()) -) +}) diff --git a/test/modules/metadata.test.js b/test/modules/metadata.test.js new file mode 100644 index 0000000..139de60 --- /dev/null +++ b/test/modules/metadata.test.js @@ -0,0 +1,33 @@ +const test = require('ava') +const path = require('path') + +const metadata = require('../../src/modules/metadata.js') + +test('getFileMetadata', t => { + const expected = new Map( + Object.entries({ + title: 'This is a test', + description: 'Test file', + tags: ['a', 'b'] + }) + ) + t.deepEqual( + metadata.getFileMetadata(path.resolve(__dirname, '../data/testfile.md')), + expected + ) +}) + +test('getFolderMetadata', t => { + const expected = new Map( + Object.entries({ + title: 'This is a test', + description: 'Test file', + tags: ['a', 'b'] + }) + ) + const actual = metadata.getFolderMetadata(path.resolve(__dirname, '../data/')) + t.true(Array.isArray(actual), 'must return an array') + t.true(actual.length > 0, 'must return a non-empty array') + t.is(actual[0].path, path.resolve(__dirname, '../data/testfile.md')) + t.deepEqual(actual[0].data, expected) +}) diff --git a/yarn.lock b/yarn.lock index 5d00b63..f92a4f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,6 +83,12 @@ ansi-escapes@^1.0.0, ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + dependencies: + ansi-wrap "0.1.0" + ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -101,6 +107,10 @@ ansi-styles@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + any-promise@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -887,6 +897,10 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" +coffee-script@^1.12.4: + version "1.12.6" + resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.6.tgz#285a3f7115689065064d6bf9ef4572db66695cbf" + color-convert@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" @@ -1568,6 +1582,12 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + extend@^3.0.0, extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -1907,6 +1927,16 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +gray-matter@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-2.1.1.tgz#3042d9adec2a1ded6a7707a9ed2380f8a17a430e" + dependencies: + ansi-red "^0.1.1" + coffee-script "^1.12.4" + extend-shallow "^2.0.1" + js-yaml "^3.8.1" + toml "^2.3.2" + har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" @@ -2160,7 +2190,7 @@ is-error@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.1.tgz#684a96d84076577c98f4cdb40c6d26a5123bf19c" -is-extendable@^0.1.1: +is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -2400,7 +2430,7 @@ js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.8.2: +js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.8.1, js-yaml@^3.8.2: version "3.8.4" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" dependencies: @@ -4113,6 +4143,10 @@ to-fast-properties@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" +toml@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.2.tgz#5eded5ca42887924949fd06eb0e955656001e834" + tough-cookie@~2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" -- cgit 1.4.1