Skip to content

Commit

Permalink
Separate building Page Data and Globbing Pages
Browse files Browse the repository at this point in the history
* Split up all the spaghetti in glob-pages up so that it can be unit
tested.
* Renamed `pathresolver` to `urlResolver`
* Added tests to verify the structure of the data returned by the new
pathResolver.
* updated the urlResolver's tests with the new function name
  • Loading branch information
benstepp committed Apr 6, 2016
1 parent 66bf51c commit cb5d140
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 57 deletions.
13 changes: 13 additions & 0 deletions lib/utils/build-page/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import path from 'path'
import objectAssign from 'object-assign'
import pathResolver from './path-resolver'
import loadFrontmatter from './load-frontmatter'

export default function buildPage (directory, page) {
const pageData = loadFrontmatter(page)

const relativePath = path.relative(path.join(directory, 'pages'), page)
const pathData = pathResolver(relativePath)

return objectAssign({}, pageData, pathData)
}
27 changes: 27 additions & 0 deletions lib/utils/build-page/load-frontmatter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import fs from 'fs'
import path from 'path'
import frontMatter from 'front-matter'
import objectAssign from 'object-assign'
import htmlFrontMatter from 'html-frontmatter'

export default function loadFrontmatter (pagePath) {
const ext = path.extname(pagePath).slice(1)

// Load data for each file type.
// TODO use webpack-require to ensure data loaded
// here (in node context) is consistent with what's loaded
// in the browser.

let data
if (ext === 'md') {
const rawData = frontMatter(fs.readFileSync(pagePath, 'utf-8'))
data = objectAssign({}, rawData.attributes)
} else if (ext === 'html') {
const html = fs.readFileSync(pagePath, 'utf-8')
data = objectAssign({}, htmlFrontMatter(html), { body: html })
} else {
data = {}
}

return data
}
28 changes: 28 additions & 0 deletions lib/utils/build-page/path-resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import slash from 'slash'
import parsePath from 'parse-filepath'
import urlResolver from './url-resolver'

export default function pathResolver (relativePath) {
const data = {}

data.file = parsePath(relativePath)

// Remove the . from extname (.md -> md)
data.file.ext = data.file.extname.slice(1)
// Make sure slashes on parsed.dirname are correct for Windows
data.file.dirname = slash(data.file.dirname)

// Determine require path
data.requirePath = slash(relativePath)

// set the URL path (should this be renamed)
// and now looking at it, it only needs a reference to pageData
data.path = urlResolver(data, data.file)

// Set the "template path"
if (data.file.name === '_template') {
data.templatePath = `/${data.file.dirname}/`
}

return data
}
File renamed without changes.
50 changes: 2 additions & 48 deletions lib/utils/glob-pages.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import glob from 'glob'
import path from 'path'
import parsePath from 'parse-filepath'
import slash from 'slash'
import fs from 'fs'
import frontMatter from 'front-matter'
import htmlFrontMatter from 'html-frontmatter'
import objectAssign from 'object-assign'
import pathResolver from './path-resolver'
import buildPage from './build-page'
const debug = require('debug')('gatsby:glob')

module.exports = (directory, callback) => {
Expand All @@ -32,46 +25,7 @@ module.exports = (directory, callback) => {
if (err) { return callback(err) }

pages.forEach((page) => {
const pageData = {}
pageData.file = {}

pageData.file = parsePath(path.relative(`${directory}/pages`, page))
const parsed = pageData.file

pageData.file.ext = parsed.extname.slice(1)
const ext = pageData.file.ext

// Determine require path
pageData.requirePath = slash(path.relative(`${directory}/pages`, page))

// Make sure slashes on parsed.dirname are correct for Windows
parsed.dirname = slash(parsed.dirname)

// Load data for each file type.
// TODO use webpack-require to ensure data loaded
// here (in node context) is consistent with what's loaded
// in the browser.
let data
if (ext === 'md') {
const rawData = frontMatter(fs.readFileSync(page, 'utf-8'))
data = objectAssign({}, rawData.attributes)
pageData.data = data
} else if (ext === 'html') {
const html = fs.readFileSync(page, 'utf-8')
data = objectAssign({}, htmlFrontMatter(html), { body: html })
pageData.data = data
} else {
data = {}
}

pageData.path = pathResolver(data, parsed)

// Set the "template path"
if (parsed.name === '_template') {
pageData.templatePath = `/${parsed.dirname}/`
}

pagesData.push(pageData)
pagesData.push(buildPage(directory, page))
})

debug(`globbed ${pagesData.length} pages`)
Expand Down
56 changes: 56 additions & 0 deletions test/utils/build-page/path-resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import test from 'ava'
import path from 'path'
import { startsWith } from 'lodash'
import pathResolver from '../../../lib/utils/build-page/path-resolver'

test('it returns an object', t => {
const pagePath = '/'
const result = pathResolver(pagePath)
t.ok(result)
t.is(typeof result, 'object')
})

test('it has a require path', t => {
const pagePath = '/a-blog-post/index.md'
const result = pathResolver(pagePath)
t.ok(result.requirePath)
t.is(typeof result.requirePath, 'string')
})

test('it does not has a path if the name start with _', t => {
t.is(pathResolver('/_metadata.js').path, undefined)
t.is(pathResolver('/_template.html.erb').path, undefined)
t.is(pathResolver('/_notapage.json').path, undefined)
})

test('it has a path if the name doesnt start with _', t => {
t.ok(pathResolver('/2015/back-to-the-future.md').path)
t.ok(pathResolver('/my-first-blog.md').path)
t.ok(pathResolver('/index.md').path)
})

test('it has a templatePath if the name is _template', t => {
const pagePath = '/_template.js'
const result = pathResolver(pagePath)
t.ok(result.templatePath)
t.is(typeof result.templatePath, 'string')
})

test('it does not have a templatePath if not a _template', t => {
t.is(pathResolver('/index.md').templatePath, undefined)
t.is(pathResolver('/another-page.toml').templatePath, undefined)
t.is(pathResolver('/something-else/good-stuff.html').templatePath, undefined)
})

test('the directory name has / slashes', t => {
const pagePath = '/2016/testing-middleman-sites-with-capybara/index.md'
const result = pathResolver(pagePath)

t.same(result.file.dirname, path.posix.normalize(result.file.dirname))
t.same(result.file.dirname, '/2016/testing-middleman-sites-with-capybara')
})

test('the ext doesnt have a leading .', t => {
const result = pathResolver('/index.md')
t.false(startsWith(result.file.ext, '.'))
})
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@
import test from 'ava'
import pathResolver from '../../lib/utils/path-resolver'
import urlResolver from '../../../lib/utils/build-page/url-resolver'

test('returns undefined when filename starts with _', t => {
const parsedPath = { name: '_notapage' }
const data = {}
const pagePath = pathResolver(data, parsedPath)
const pagePath = urlResolver(data, parsedPath)
t.true(pagePath === undefined)
})

test('uses the path from page data', t => {
const parsedPath = { name: 'page', dirname: 'a-directory/' }
const data = { path: '/page-at-root' }
const pagePath = pathResolver(data, parsedPath)
const pagePath = urlResolver(data, parsedPath)
t.same(pagePath, '/page-at-root')
})

test('removes index from path', t => {
const parsedPath = { name: 'index', dirname: 'foo/bar' }
const data = {}
const pagePath = pathResolver(data, parsedPath)
const pagePath = urlResolver(data, parsedPath)
t.same(pagePath, '/foo/bar/')
})

test('removes template from path', t => {
const parsedPath = { name: 'template', dirname: 'foo/bar' }
const data = {}
const pagePath = pathResolver(data, parsedPath)
const pagePath = urlResolver(data, parsedPath)
t.same(pagePath, '/foo/bar/')
})

test('template at root has root path', t => {
const parsedPath = { name: 'template', dirname: '' }
const data = {}
const pagePath = pathResolver(data, parsedPath)
const pagePath = urlResolver(data, parsedPath)
t.same(pagePath, '/')
})

test('index at root has root path', t => {
const parsedPath = { name: 'index', dirname: '' }
const data = {}
const pagePath = pathResolver(data, parsedPath)
const pagePath = urlResolver(data, parsedPath)
t.same(pagePath, '/')
})

test('if not an index create a path like /foo/bar/', t => {
const parsedPath = { name: 'creating-static-websites', dirname: 'blog/2016' }
const data = {}
const pagePath = pathResolver(data, parsedPath)
const pagePath = urlResolver(data, parsedPath)
t.same(pagePath, '/blog/2016/creating-static-websites/')
})

test('if not an index create a path like /foo/bar/', t => {
const parsedPath = { name: 'about-us', dirname: '' }
const data = {}
const pagePath = pathResolver(data, parsedPath)
const pagePath = urlResolver(data, parsedPath)
t.same(pagePath, '/about-us/')
})

0 comments on commit cb5d140

Please sign in to comment.