diff --git a/README.md b/README.md index be44cc739e7c9..79a55e0c5464a 100644 --- a/README.md +++ b/README.md @@ -336,6 +336,14 @@ exports.data = { export default MyComponent ... ``` +You can also use a named export for the data object: + +```javascript +export const data = { + title: 'This is a title', +} +``` + ### Structure of a Gatsby site * `config.toml` - Core application configuration is stored here. Available via a `require` or `import` of 'config'. Values: diff --git a/lib/isomorphic/create-routes.js b/lib/isomorphic/create-routes.js index 92747beffac6d..d9fc1cdedfd55 100644 --- a/lib/isomorphic/create-routes.js +++ b/lib/isomorphic/create-routes.js @@ -145,7 +145,7 @@ module.exports = (files, pagesReq) => { handler = wrappers[page.file.ext] page.data = pagesReq(`./${page.requirePath}`) } else if (reactComponentFileTypes.indexOf(page.file.ext) !== -1) { - handler = pagesReq(`./${page.requirePath}`) + handler = requireComponent(pagesReq(`./${page.requirePath}`)) page.data = page.data === undefined ? {} : page.data } diff --git a/lib/utils/build-page/load-frontmatter.js b/lib/utils/build-page/load-frontmatter.js index 8f0dc47baaff9..226964a98bc0a 100644 --- a/lib/utils/build-page/load-frontmatter.js +++ b/lib/utils/build-page/load-frontmatter.js @@ -3,6 +3,7 @@ import fs from 'fs' import path from 'path' import frontMatter from 'front-matter' import objectAssign from 'object-assign' +import _ from 'lodash' import htmlFrontMatter from 'html-frontmatter' import * as babylon from 'babylon' import traverse from 'babel-traverse' @@ -81,6 +82,21 @@ export default function loadFrontmatter(pagePath: string): {} { }) } }, + ExportNamedDeclaration: function ExportNamedDeclaration(astPath) { + const { declaration } = astPath.node + if (declaration && declaration.type === 'VariableDeclaration') { + const dataVariableDeclarator = _.find( + declaration.declarations, + d => d.id.name === 'data' + ) + + if (dataVariableDeclarator && dataVariableDeclarator.init) { + dataVariableDeclarator.init.properties.forEach(node => { + data[node.key.name] = parseData(node.value) + }) + } + } + }, }) } catch (e) { // Ignore errors — we print out parse errors for user elsewhere. diff --git a/test/fixtures/javascript-pages-frontmatter/pages/array-literal-named-export.js b/test/fixtures/javascript-pages-frontmatter/pages/array-literal-named-export.js new file mode 100644 index 0000000000000..2901f258167e4 --- /dev/null +++ b/test/fixtures/javascript-pages-frontmatter/pages/array-literal-named-export.js @@ -0,0 +1,13 @@ +/* eslint-disable react/display-name */ +import React from 'react' + +export const data = { + titles: ['My title', 'My other title'], +} + +export default () => ( +
+

My title

+

My other title

+
+) diff --git a/test/fixtures/javascript-pages-frontmatter/pages/object-literal-named-export.js b/test/fixtures/javascript-pages-frontmatter/pages/object-literal-named-export.js new file mode 100644 index 0000000000000..1a0e27f0b707a --- /dev/null +++ b/test/fixtures/javascript-pages-frontmatter/pages/object-literal-named-export.js @@ -0,0 +1,16 @@ +/* eslint-disable react/display-name */ +import React from 'react' + +export const data = { + titles: { + main: 'My title', + sub: 'My other title', + }, +} + +export default () => ( +
+

My title

+

My other title

+
+) diff --git a/test/fixtures/javascript-pages-frontmatter/pages/string-literal-named-export.js b/test/fixtures/javascript-pages-frontmatter/pages/string-literal-named-export.js new file mode 100644 index 0000000000000..d90f8990df3e2 --- /dev/null +++ b/test/fixtures/javascript-pages-frontmatter/pages/string-literal-named-export.js @@ -0,0 +1,8 @@ +/* eslint-disable react/display-name */ +import React from 'react' + +export const data = { + title: 'Foo', +} + +export default () =>

Foo

diff --git a/test/fixtures/javascript-pages-frontmatter/pages/template-literal-named-export.js b/test/fixtures/javascript-pages-frontmatter/pages/template-literal-named-export.js new file mode 100644 index 0000000000000..64a25e5532c47 --- /dev/null +++ b/test/fixtures/javascript-pages-frontmatter/pages/template-literal-named-export.js @@ -0,0 +1,9 @@ +/* eslint-disable react/display-name */ +import React from 'react' + +export const data = { + // eslint-disable-next-line + title: `Bar`, +} + +export default () =>

Bar

diff --git a/test/utils/build-page/load-frontmatter.js b/test/utils/build-page/load-frontmatter.js index 42f72444a6a9e..13cf2dcf7e2de 100644 --- a/test/utils/build-page/load-frontmatter.js +++ b/test/utils/build-page/load-frontmatter.js @@ -8,6 +8,13 @@ test('it works for string literal titles', t => { t.is(data.title, 'Foo') }) +test('it works for string literal titles declared as a named export', t => { + const pagePath = + '../../fixtures/javascript-pages-frontmatter/pages/string-literal-named-export.js' + const data = loadFrontmatter(pagePath) + t.is(data.title, 'Foo') +}) + test('it works for template literal titles', t => { const pagePath = '../../fixtures/javascript-pages-frontmatter/pages/template-literal.js' @@ -15,6 +22,13 @@ test('it works for template literal titles', t => { t.is(data.title, 'Bar') }) +test('it works for template literal titles declared as a named export', t => { + const pagePath = + '../../fixtures/javascript-pages-frontmatter/pages/template-literal-named-export.js' + const data = loadFrontmatter(pagePath) + t.is(data.title, 'Bar') +}) + test('it works with array literal values', t => { const pagePath = '../../fixtures/javascript-pages-frontmatter/pages/array-literal.js' @@ -23,6 +37,14 @@ test('it works with array literal values', t => { t.is(data.titles[1], 'My other title') }) +test('it works with array literal values declared as a named export', t => { + const pagePath = + '../../fixtures/javascript-pages-frontmatter/pages/array-literal-named-export.js' + const data = loadFrontmatter(pagePath) + t.is(data.titles[0], 'My title') + t.is(data.titles[1], 'My other title') +}) + test('it works with object literal values', t => { const pagePath = '../../fixtures/javascript-pages-frontmatter/pages/object-literal.js' @@ -30,3 +52,11 @@ test('it works with object literal values', t => { t.is(data.titles.main, 'My title') t.is(data.titles.sub, 'My other title') }) + +test('it works with object literal values declared as a named export', t => { + const pagePath = + '../../fixtures/javascript-pages-frontmatter/pages/object-literal-named-export.js' + const data = loadFrontmatter(pagePath) + t.is(data.titles.main, 'My title') + t.is(data.titles.sub, 'My other title') +})