Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
4 changes: 3 additions & 1 deletion choo.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
var Page = require('./lib')
var File = require('./lib/file')
var Page = require('./lib/page')

module.exports = plugin

function plugin (state, emit) {
state.content = state.content || { }
state.file = new File(state)
state.page = new Page(state)
}
1 change: 1 addition & 0 deletions file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/file')
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/page')
65 changes: 65 additions & 0 deletions lib/file/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
var NanoTemplate = require('../template')
var utilsPage = require('../page/utils')
var objectKeys = require('object-keys')
var joinPath = require('join-path')
var methods = require('../methods')
var utils = require('./utils')

var minimatch = require('minimatch')
var isGlob = require('is-glob')

module.exports = wrapper

class File extends NanoTemplate {
constructor (state, value) {
super(state, value)
var self = this

// add utilities
objectKeys(utils).forEach(function (key) {
self[key] = function (...args) {
this._value = utils[key](this._state, this._value, ...args)
return this
}
})
}
}

function wrapper (state) {
return function (value) {
return new File(state, parseInitialValue(state, value))
}
}

function parseInitialValue (state, value) {
// defaults
state = state || { }
state.content = state.content || { }

// grab our content
var href = state.href || '/'
var page = state.content[methods.parseHref(href)] || { }

// set the value
switch (typeof value) {
case 'string':
if (isGlob(value)) return getContentGlob(state, page, value)
else return utilsPage.file(state, page, methods.parseHref(joinPath(href, value)))
case 'object':
// if an object and it contains value grab that value
if (typeof value.value === 'function') return value.value()
else return value
default:
// if no value, pass our page
return value || page
}
}

function getContentGlob (state, page, value) {
return objectKeys(state.content)
.filter(minimatch.filter(value, { matchBase: true }))
.reduce(function (res, cur) {
res[cur] = state.content[cur]
return res
}, { })
}
14 changes: 14 additions & 0 deletions lib/file/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
size,
source: noop
}

function size (state, value, size) {
try {
return value.sizes[size.toString()]
} catch (err) {
return ''
}
}

function noop () { }
32 changes: 31 additions & 1 deletion lib/methods.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
var parsePath = require('parse-filepath')

module.exports = {
parseHref
parseHref,
isDate,
isFile,
isPage,
hasUrl
}

function parseHref (str) {
if (str.length > 1) return str.replace(/\/+$/, '')
else return str
}

function isDate (str) {
return /^\d{4}-\d{1,2}-\d{1,2}$/.test(str)
}

function isFile (value) {
return isPage(value) === false
}

function isPage (value) {
try {
var url = hasUrl(value) ? value.url : value
return parsePath(url).ext === ''
} catch (err) {
return false
}
}

function hasUrl (value) {
return (
typeof value === 'object' &&
typeof value.url === 'string'
)
}
65 changes: 65 additions & 0 deletions lib/page/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
var NanoTemplate = require('../template')
var utilsPage = require('../page/utils')
var objectKeys = require('object-keys')
var joinPath = require('join-path')
var methods = require('../methods')
var utils = require('./utils')

var minimatch = require('minimatch')
var isGlob = require('is-glob')

module.exports = wrapper

class Page extends NanoTemplate {
constructor (state, value) {
super(state, value)
var self = this

// add utilities
objectKeys(utils).forEach(function (key) {
self[key] = function (...args) {
this._value = utils[key](this._state, this._value, ...args)
return this
}
})
}
}

function wrapper (state) {
return function (value) {
return new Page(state, parseInitialValue(state, value))
}
}

function parseInitialValue (state, value) {
// defaults
state = state || { }
state.content = state.content || { }

// grab our content
var href = state.href || '/'
var page = state.content[methods.parseHref(href)] || { }

// set the value
switch (typeof value) {
case 'string':
if (isGlob(value)) return getContentGlob(state, page, value)
else return utilsPage.file(state, page, methods.parseHref(joinPath(href, value)))
case 'object':
// if an object and it contains value grab that value
if (typeof value.value === 'function') return value.value()
else return value
default:
// if no value, pass our page
return value || page
}
}

function getContentGlob (state, page, value) {
return objectKeys(state.content)
.filter(minimatch.filter(value, { matchBase: true }))
.reduce(function (res, cur) {
res[cur] = state.content[cur]
return res
}, { })
}
132 changes: 132 additions & 0 deletions lib/page/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
var objectValues = require('object-values')
var objectKeys = require('object-keys')
var resolve = require('resolve-path')
var methods = require('../methods')

module.exports = {
children,
file,
files,
find,
hasView,
images,
pages,
sortBy
}

function children (state, value) {
// alias for pages
return pages(state, value)
}

function file (state, value, key) {
return find(state, value, key)
}

function files (state, value) {
try {
var base = value.url.replace(/^\//, '') ? value.url : ''
var regex = new RegExp('^' + base + '/[^/]+/?$')
return objectKeys(state.content)
.filter(key => regex.test(key.trim()))
.reduce(readFile, { })
} catch (err) {
return { }
}

function readFile (result, key) {
var file = state.content[key]
if (methods.isFile(file)) result[key] = file
return result
}
}

function find (state, value, url) {
try {
// normalize
url = methods.parseHref(url)

// grab from root
if (url.indexOf('/') === 0) {
return state.content[url]
}

// if on a page grab relative
if (typeof value.url === 'string') {
return state.content[resolve(value.url, url)]
}

// fall back to href
return state.content[resolve(state.href || '/', url)]
} catch (err) {
return { }
}
}

function hasView (state, value) {
try {
return typeof value.view !== 'undefined'
} catch (err) {
return false
}
}

function images (state, value) {
try {
var _files = files(state, value)
return objectKeys(_files).reduce(function (res, key) {
if (_files[key].type === 'image') res[key] = _files[key]
return res
}, { })
} catch (err) {
return { }
}
}

function pages (state, value) {
try {
var base = value.url.replace(/^\//, '') ? value.url : ''
var regex = new RegExp('^' + base + '/[^/]+/?$')
return objectKeys(state.content)
.filter(key => regex.test(key.trim()))
.reduce(readPage, { })
} catch (err) {
return { }
}

function readPage (result, key) {
var page = state.content[key]
if (methods.isPage(page)) result[key] = page
return result
}
}

function sortBy (state, value, key, order) {
try {
return objectValues(value).sort(sort)
} catch (err) {
return [ ]
}

function sort (a, b) {
try {
var alpha = a[key]
var beta = b[key]

// reverse order
if (order === 'desc') {
alpha = b[key]
beta = a[key]
}

// date or string
if (methods.isDate(alpha) && methods.isDate(beta)) {
return new Date(alpha) - new Date(beta)
} else {
return alpha.localeCompare(beta)
}
} catch (err) {
return 0
}
}
}
Loading