diff --git a/README.md b/README.md index 37b3df058755b..9432d056ee5ca 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,35 @@ module.exports = React.createClass({ }) ``` +#### frontmatter and metadata +Gatsby uses frontmatter and html-frontmatter to pull metadata out of files. This data is typically used in links leading to each page. The most relevant example is a list of blog posts in which you display the title, description, tags, etc. in the form of `{post.title}` in the React.js component. + +As seen in our previous markdown file, the title is part of the frontmatter +``` +--- +title: This is a title +--- + +# Hi friends. +This is a markdown file. +``` + +An html example as follows. +``` + + +

Hello World

+``` + +Gatsby will additionally pull data out of js|jsx files. The files are statically analyzed and an `exports.data` object is pulled. An example as follows. +``` +exports.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 f07d283a27a47..c90aa6487e92b 100644 --- a/lib/isomorphic/create-routes.js +++ b/lib/isomorphic/create-routes.js @@ -132,14 +132,8 @@ module.exports = (files, pagesReq) => { handler = wrappers[page.file.ext] page.data = pagesReq(`./${page.requirePath}`) } else if (reactComponentFileTypes.indexOf(page.file.ext) !== -1) { - handler = requireComponent(pagesReq(`./${page.requirePath}`)) - page.data = (() => { - if (pagesReq(`./${page.requirePath}`).metadata) { - return pagesReq(`./${page.requirePath}`).metadata() - } else { - return {} - } - })() + handler = pagesReq(`./${page.requirePath}`) + page.data = page.data = (page.data === undefined) ? {} : page.data } // Determine parent template for page. diff --git a/lib/utils/build-page/load-frontmatter.js b/lib/utils/build-page/load-frontmatter.js index 398d597acd549..5810bb0db8eca 100644 --- a/lib/utils/build-page/load-frontmatter.js +++ b/lib/utils/build-page/load-frontmatter.js @@ -4,6 +4,8 @@ import path from 'path' import frontMatter from 'front-matter' import objectAssign from 'object-assign' import htmlFrontMatter from 'html-frontmatter' +import * as babylon from 'babylon' +import traverse from 'babel-traverse' export default function loadFrontmatter (pagePath: string): {} { const ext: string = path.extname(pagePath).slice(1) @@ -21,6 +23,32 @@ export default function loadFrontmatter (pagePath: string): {} { const html = fs.readFileSync(pagePath, { encoding: 'utf-8' }) // $FlowIssue - https://github.com/facebook/flow/issues/1870 data = objectAssign({}, htmlFrontMatter(html), { body: html }) + } else if (ext === 'js' || ext === 'jsx') { + try { + const code = fs.readFileSync(pagePath, { encoding: 'utf-8' }) + const options = { + sourceType: 'module', + allowImportExportEverywhere: true, + plugins: ['*'] // may only need ['jsx', 'objectRestSpread']? + } + const ast = babylon.parse(code, options); + + data = {} + traverse(ast, { + AssignmentExpression(path) { + if (path.node.left.type === 'MemberExpression' && + path.node.left.property.name === 'data') { + path.node.right.properties.forEach((prop) => { + data[prop.key.name] = prop.value.value + }) + } + } + }) + } catch (e) { + console.log('Failed to parse file') + console.log(e) + data = {} + } } else { data = {} } diff --git a/package.json b/package.json index 15822c2e2466a..17117a3fd2ab0 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "babel-preset-react": "^6.11.1", "babel-preset-react-hmre": "^1.1.1", "babel-preset-stage-0": "^6.5.0", + "babel-traverse": "^6.18.0", "boom": "^2.7.2", "cjsx-loader": "^3.0.0", "coffee-loader": "^0.7.2",