Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Extract internal plugin for automatically creating pages so we can reuse for other directories #4490

Merged
merged 19 commits into from
Jun 14, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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
32 changes: 32 additions & 0 deletions packages/gatsby-plugin-page-creator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Logs
logs
*.log

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules

decls
dist

/*.js
34 changes: 34 additions & 0 deletions packages/gatsby-plugin-page-creator/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Logs
logs
*.log

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
*.un~
yarn.lock
src
flow-typed
coverage
decls
examples
40 changes: 40 additions & 0 deletions packages/gatsby-plugin-page-creator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# gatsby-plugin-page-creator

Plugin for creating `File` nodes from the file system. The various "transformer"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Description needs updated

plugins transform `File` nodes into various other types of data e.g.
`gatsby-transformer-json` transforms JSON files into JSON data nodes and
`gatsby-transformer-remark` transforms markdown files into `MarkdownRemark`
nodes from which you can query an HTML representation of the markdown.

## Install

`npm install --save gatsby-plugin-page-creator`

## How to use

```javascript
// gatsby-config.js

module.exports = {
plugins: [
// You can have multiple instances of this plugin
// to read source nodes from different locations on your
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"source nodes" should be "React components"

// filesystem.
//
// The following sets up the Jekyll pattern of having multiple
// "pages" directories in your project
{
resolve: `gatsby-plugin-page-creator`,
options: {
path: `${__dirname}/src/pages/`,
},
},
{
resolve: `gatsby-plugin-page-creator`,
options: {
path: `${__dirname}/src/data/`,
},
},
],
};
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`JavaScript page creator create-path should create unix paths 1`] = `
Array [
"/b/c/de/",
"/bee/",
"/b/d/c/",
]
`;

exports[`JavaScript page creator create-path should deal with windows paths 1`] = `
Array [
"/404/",
"/",
"/blog/",
]
`;
97 changes: 97 additions & 0 deletions packages/gatsby-plugin-page-creator/__tests__/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
const validatePath = require(`../validate-path`)
const createPath = require(`../create-path`)

describe(`JavaScript page creator`, () => {
it(`filters out files that start with underscores`, () => {
const files = [
{
path: `something/blah.js`,
},
{
path: `something/_blah.js`,
},
{
path: `_blah.js`,
},
]

expect(files.filter(file => validatePath(file.path)).length).toEqual(1)
})

it(`filters out files that start with template-*`, () => {
const files = [
{
path: `something/blah.js`,
},
{
path: `something/template-cool-page-type.js`,
},
{
path: `template-cool-page-type.js`,
},
]

expect(files.filter(file => validatePath(file.path)).length).toEqual(1)
})

it(`filters out files that have TypeScript declaration extensions`, () => {
const files = [
{
path: `something/foo.ts`,
},
{
path: `something/bar.tsx`,
},
{
path: `something/declaration-file.d.ts`,
},
{
path: `something-else/other-declaration-file.d.tsx`,
},
]

expect(files.filter(file => validatePath(file.path)).length).toEqual(2)
})

it(`filters out test files`, () => {
const files = [
{
path: `__tests__/something.test.js`,
},
{
path: `foo.spec.js`,
},
{
path: `bar.test.js`,
},
{
path: `page.js`,
},
{
path: `page.jsx`,
},
]

expect(files.filter(file => validatePath(file.path)).length).toEqual(2)
})

describe(`create-path`, () => {
it(`should create unix paths`, () => {
const basePath = `/a/`
const paths = [`/a/b/c/de`, `/a/bee`, `/a/b/d/c/`]

expect(paths.map(p => createPath(basePath, p))).toMatchSnapshot()
})

it(`should deal with windows paths`, () => {
const basePath = `D:/Projets/gatsby-starter/src/pages`
const paths = [
`D:\\Projets\\gatsby-starter\\src\\pages\\404.tsx`,
`D:\\Projets\\gatsby-starter\\src\\pages\\index.tsx`,
`D:\\Projets\\gatsby-starter\\src\\pages\\blog.tsx`,
]

expect(paths.map(p => createPath(basePath, p))).toMatchSnapshot()
})
})
})
1 change: 1 addition & 0 deletions packages/gatsby-plugin-page-creator/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// noop
26 changes: 26 additions & 0 deletions packages/gatsby-plugin-page-creator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "gatsby-plugin-page-creator",
"version": "1.0.0",
"description": "An internal Gatsby plugin that creates pages from component files in src/pages",
"main": "index.js",
"scripts": {
"build": "babel src --out-dir . --ignore __tests__",
"watch": "babel -w src --out-dir . --ignore __tests__",
"prepublish": "cross-env NODE_ENV=production npm run build"
},
"keywords": [
"gatsby"
],
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"contributors": [
"Steven Natera <tektekpush@gmail.com> (https://twitter.com/stevennatera)"
],
"license": "MIT",
"dependencies": {
"babel-runtime": "^6.26.0"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"cross-env": "^5.0.5"
}
}
12 changes: 12 additions & 0 deletions packages/gatsby-plugin-page-creator/src/create-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// @flow
import parsePath from "parse-filepath"
import path from "path"
import slash from "slash"

module.exports = (basePath: string, filePath: string): string => {
const relativePath = path.posix.relative(slash(basePath), slash(filePath))
const { dirname, name } = parsePath(relativePath)
const parsedName = name === `index` ? `` : name

return path.posix.join(`/`, dirname, parsedName, `/`)
}
96 changes: 96 additions & 0 deletions packages/gatsby-plugin-page-creator/src/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const globCB = require(`glob`)
const Promise = require(`bluebird`)
const _ = require(`lodash`)
const chokidar = require(`chokidar`)
const systemPath = require(`path`)
const fs = require(`fs`)

const glob = Promise.promisify(globCB)

const createPath = require(`./create-path`)
const validatePath = require(`./validate-path`)

// Path creator.
// Auto-create pages.
// algorithm is glob /pages directory for js/jsx/cjsx files *not*
// underscored. Then create url w/ our path algorithm *unless* user
// takes control of that page component in gatsby-node.
exports.createPagesStatefully = async (
{ store, boundActionCreators, reporter },
pluginOptions,
doneCb
) => {
const { createPage, deletePage } = boundActionCreators
const program = store.getState().program
const exts = program.extensions.map(e => `${e.slice(1)}`).join(`,`)

if (!(pluginOptions && pluginOptions.path)) {
reporter.panic(
`
"path" is a required option for gatsby-plugin-page-creator

See docs here - https://www.gatsbyjs.org/packages/gatsby-plugin-page-creator/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link should go to /plugins/ instead of /packages/

`
)
}

// Validate that the path exists.
if (!fs.existsSync(pluginOptions.path)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One downside to this is that if someone doesn't want to have a src directory or src/pages directory then this will error. Perhaps the core instance of this plugin could say it is optional so if src/pages doesn't exist, then it just does nothing.

Copy link
Contributor Author

@nodox nodox May 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should this be implemented? I can't see I understand fully? @KyleAMathews @m-allanson

reporter.panic(
`
The path passed to gatsby-plugin-page-creator does not exist on your file system:

${pluginOptions.path}

Please pick a path to an existing directory.
`
)
}

const pagesDirectory = systemPath.posix.join(pluginOptions.path)
const pagesGlob = `${pagesDirectory}/**/*.{${exts}}`

// Get initial list of files.
let files = await glob(pagesGlob)
files.forEach(file => _createPage(file, pagesDirectory, createPage))

// Listen for new component pages to be added or removed.
chokidar
.watch(pagesGlob)
.on(`add`, path => {
if (!_.includes(files, path)) {
_createPage(path, pagesDirectory, createPage)
files.push(path)
}
})
.on(`unlink`, path => {
// Delete the page for the now deleted component.
store
.getState()
.pages.filter(p => p.component === path)
.forEach(page => {
deletePage({
path: createPath(pagesDirectory, path),
component: path,
})
files = files.filter(f => f !== path)
})
})
.on(`ready`, () => doneCb())
}
const _createPage = (filePath, pagesDirectory, createPage) => {
// Filter out special components that shouldn't be made into
// pages.
if (!validatePath(systemPath.posix.relative(pagesDirectory, filePath))) {
return
}

// Create page object
const page = {
path: createPath(pagesDirectory, filePath),
component: filePath,
}

// Add page
createPage(page)
}
21 changes: 21 additions & 0 deletions packages/gatsby-plugin-page-creator/src/validate-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const systemPath = require(`path`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice to keep sharing these internal utility functions with gatsby core

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this isn't necessary now since we're removing layouts in v2 — so this is the only package using this.


const tsDeclarationExtTest = /\.d\.tsx?$/

function isTestFile(path) {
const testFileTest = new RegExp(`(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$`)
return path.match(testFileTest)
}

module.exports = path => {
// Disallow paths starting with an underscore
// and template-.
// and .d.ts
const parsedPath = systemPath.parse(path)
return (
parsedPath.name.slice(0, 1) !== `_` &&
parsedPath.name.slice(0, 9) !== `template-` &&
!tsDeclarationExtTest.test(parsedPath.base) &&
!isTestFile(parsedPath.base)
)
}
1 change: 1 addition & 0 deletions packages/gatsby/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"gatsby-1-config-css-modules": "^1.0.11",
"gatsby-1-config-extract-plugin": "^1.0.3",
"gatsby-cli": "^1.1.49",
"gatsby-plugin-page-creator": "^1.0.0",
"gatsby-link": "^1.6.40",
"gatsby-module-loader": "^1.0.11",
"gatsby-react-router-scroll": "^1.0.14",
Expand Down
Loading