From 0c8bfa1cdf6c0af8ff17756711f43703ddbd7216 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Tue, 7 Feb 2017 20:12:05 -0800 Subject: [PATCH 001/308] Initial checkin of new Gatsby docs website --- README.md | 4 + docs/guides/API-File-Image-Uploads.md | 181 +++++++++------ .../how-to-create-a-blog-with-keystone.md | 57 +++-- docs/guides/how-to-send-emails.md | 207 ++++++++++------- docs/guides/v0.3-to-v4.0-Upgrade-Guide.md | 214 ++++++++++++------ docs/index.md | 199 ++++++++++++++++ docs/menu.yaml | 9 + www/.babelrc | 7 + www/.gitignore | 10 + www/components/Container.jsx | 19 ++ www/components/Sidebar.jsx | 92 ++++++++ www/components/navigation.jsx | 85 +++++++ www/css/prism-coy.css | 174 ++++++++++++++ www/gatsby-config.js | 50 ++++ www/gatsby-node.js | 68 ++++++ www/html.js | 45 ++++ www/layouts/default.js | 105 +++++++++ www/package.json | 42 ++++ www/pages/template-doc-page.js | 77 +++++++ www/utils/typography.js | 81 +++++++ 20 files changed, 1489 insertions(+), 237 deletions(-) create mode 100644 docs/index.md create mode 100644 docs/menu.yaml create mode 100644 www/.babelrc create mode 100644 www/.gitignore create mode 100644 www/components/Container.jsx create mode 100644 www/components/Sidebar.jsx create mode 100644 www/components/navigation.jsx create mode 100644 www/css/prism-coy.css create mode 100644 www/gatsby-config.js create mode 100644 www/gatsby-node.js create mode 100644 www/html.js create mode 100644 www/layouts/default.js create mode 100644 www/package.json create mode 100644 www/pages/template-doc-page.js create mode 100644 www/utils/typography.js diff --git a/README.md b/README.md index 7a9c417d3f..0950235262 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +--- +title: KeystoneJS +--- + ![KeystoneJS](http://keystonejs.com/images/logo.svg) =================================== diff --git a/docs/guides/API-File-Image-Uploads.md b/docs/guides/API-File-Image-Uploads.md index 7d579dd48d..8cb3d4cc86 100644 --- a/docs/guides/API-File-Image-Uploads.md +++ b/docs/guides/API-File-Image-Uploads.md @@ -1,20 +1,32 @@ -# API File and Image Uploads +--- +title: API File and Image Uploads +--- -This guide gives code examples on how to set up an API for File and Image transfers to your KeystoneJS installation. It also shows how to set up the server for -local file and image hosting. These examples contain the same code used by [ConnextCMS](http://connextcms.com). +This guide gives code examples on how to set up an API for File and +Image transfers to your KeystoneJS installation. It also shows how to +set up the server for local file and image hosting. These examples +contain the same code used by [ConnextCMS](http://connextcms.com). -## Setup -This guide assumes that you have a working version of [KeystoneJS](https://github.com/keystonejs/keystone). All file path references -assume that you are working from the same directory as the `keystone.js` file. +### Setup -# Creating Models -This guide does not treat images differently than generic files, since they are all files to KeystoneJS. The difference is how you use them -on the front end once you retrieve the file url from the server. With a little modification of the code below, you can create a different file model -called 'images.js' along with a corresponding API and send 'images' to their own directory. +This guide assumes that you have a working version of +[KeystoneJS](https://github.com/keystonejs/keystone). All file path +references assume that you are working from the same directory as the +`keystone.js` file. +## Creating Models -At any rate, below is an example model that leverages the `Types.File` introduced in KeystoneJS v4.0 Beta. This code should be copied into -the file `models/FileUpload.js`. +This guide does not treat images differently than generic files, since +they are all files to KeystoneJS. The difference is how you use them on +the front end once you retrieve the file url from the server. With a +little modification of the code below, you can create a different file +model called 'images.js' along with a corresponding API and send +'images' to their own directory. + + +At any rate, below is an example model that leverages the `Types.File` +introduced in KeystoneJS v4.0 Beta. This code should be copied into the +file `models/FileUpload.js`. ```javascript var keystone = require('keystone'); @@ -38,10 +50,10 @@ var myStorage = new keystone.Storage({ FileUpload.add({ name: { type: Types.Key, index: true}, - file: { + file: { type: Types.File, storage: myStorage - }, + }, createdTimeStamp: { type: String }, alt1: { type: String }, attributes1: { type: String }, @@ -51,7 +63,7 @@ FileUpload.add({ children: { type: String }, url: {type: String}, fileType: {type: String} - + }); @@ -59,12 +71,16 @@ FileUpload.defaultColumns = 'name'; FileUpload.register(); ``` -A lot of the additional fields like `alt1`, or `category` are metadata and may be unnessessary for your purposes. I put them in the model as suggestions. -Feel free to take them out, and it won't hurt anything if you leave them in +A lot of the additional fields like `alt1`, or `category` are metadata +and may be unnessessary for your purposes. I put them in the model as +suggestions. Feel free to take them out, and it won't hurt anything if +you leave them in + +## Opening an API in KeystoneJS -# Opening an API in KeystoneJS -Now we are going to create an API that can be used to upload and download files to KeystoneJS. This is a two step process. The first step is add a few lines -of code to the `routes/index.js` file: +Now we are going to create an API that can be used to upload and +download files to KeystoneJS. This is a two step process. The first step +is add a few lines of code to the `routes/index.js` file: ```javascript var keystone = require('keystone'); @@ -105,11 +121,13 @@ exports = module.exports = function (app) { }; ``` -## Create the API Handler -The second step is to create the new file `routes/api/fileupload.js`. If the `routes/api` directory doesn't exist, -you'll need to create it. Copy the code below into `routes/api/fileupload.js`. +### Create the API Handler -``` +The second step is to create the new file `routes/api/fileupload.js`. If +the `routes/api` directory doesn't exist, you'll need to create it. Copy +the code below into `routes/api/fileupload.js`. + +```javascript var async = require('async'), keystone = require('keystone'); var exec = require('child_process').exec; @@ -198,20 +216,20 @@ exports.remove = function(req, res) { FileData.model.findById(req.params.id).exec(function (err, item) { if (err) return res.apiError('database error', err); - + if (!item) return res.apiError('not found'); item.remove(function (err) { if (err) return res.apiError('database error', err); - + //Delete the file - exec('rm public/uploads/files/'+fileId+'.*', function(err, stdout, stderr) { - if (err) { - console.log('child process exited with error code ' + err.code); - return; - } - console.log(stdout); + exec('rm public/uploads/files/'+fileId+'.*', function(err, stdout, stderr) { + if (err) { + console.log('child process exited with error code ' + err.code); + return; + } + console.log(stdout); }); return res.apiResponse({ @@ -222,13 +240,18 @@ exports.remove = function(req, res) { }); } ``` -## Create the upload directory -Finally, you'll want to create the `public/uploads/files` directory. This is where files will be end up when uploaded via the API. +### Create the upload directory + +Finally, you'll want to create the `public/uploads/files` directory. +This is where files will be end up when uploaded via the API. -# Upload a file -That's it! Your new API is ready to use. Drop the following code into `public/fileAPITest.html`, start KeystoneJS, and open the -test file in your web browser. If KeystoneJS is already running you'll need to kill the process and restart it. If KeystoneJS -won't start after you create the new API files, go back and check your code. +## Upload a file + +That's it! Your new API is ready to use. Drop the following code into +`public/fileAPITest.html`, start KeystoneJS, and open the test file in +your web browser. If KeystoneJS is already running you'll need to kill +the process and restart it. If KeystoneJS won't start after you create +the new API files, go back and check your code. ```html @@ -241,7 +264,7 @@ won't start after you create the new API files, go back and check your code. -

Upload a new file

+

Upload a new file

@@ -260,14 +283,14 @@ won't start after you create the new API files, go back and check your code.
- - - + + ``` -## Gotcha: Two POST Calls Needed -You'll notice that in `fileAPITest.html` there are two POST calls. The first uploads the file itself. The second updates the metadata for the file entry in the database. -It's irritating to make two server calls instead of one, but right now that's the way it has to be. +### Gotcha: Two POST Calls Needed + +You'll notice that in `fileAPITest.html` there are two POST calls. The +first uploads the file itself. The second updates the metadata for the +file entry in the database. It's irritating to make two server calls +instead of one, but right now that's the way it has to be. + + +## Download a file +`fileAPITest.html` creates a list item for each file that is uploaded. +The list item includes a link to the file and uses the `download` +attribute to tell the browser to download the file instead of trying to +open it. You can use the example code above to figure out how to +generate your own download URL for uploaded files. -# Download a file -`fileAPITest.html` creates a list item for each file that is uploaded. The list item includes a link to the file and uses the `download` attribute to tell the browser -to download the file instead of trying to open it. You can use the example code above to figure out how to generate your own download URL for uploaded files. +## README -# README -This guide was written by [Chris Troutner](http://christroutner.com). It was originally inspired by [this gist by Jed Watson](https://gist.github.com/JedWatson/9741171#file-routes-index-js-L24) and -[this tutorial](http://christroutner.com/blog/post/front-end-widgets-part-1-creating-the-db-model) on my own blog. The technique displayed -here is the same used in the [ConnextCMS](http://connextcms.com) software. ConnextCMS is a front end extension for KeystoneJS that mimicks the -WordPress user interface. +This guide was written by [Chris Troutner](http://christroutner.com). It +was originally inspired by [this gist by Jed +Watson](https://gist.github.com/JedWatson/9741171#file-routes-index-js-L24) +and [this +tutorial](http://christroutner.com/blog/post/front-end-widgets-part-1-creating-the-db-model) +on my own blog. The technique displayed here is the same used in the +[ConnextCMS](http://connextcms.com) software. ConnextCMS is a front end +extension for KeystoneJS that mimicks the WordPress user interface. -The latest version of this file can be found in the [christroutner/keystone-guides repository](https://github.com/christroutner/keystone-guides). +The latest version of this file can be found in the +[christroutner/keystone-guides +repository](https://github.com/christroutner/keystone-guides). diff --git a/docs/guides/how-to-create-a-blog-with-keystone.md b/docs/guides/how-to-create-a-blog-with-keystone.md index b90c724d0d..205b2db5b0 100644 --- a/docs/guides/how-to-create-a-blog-with-keystone.md +++ b/docs/guides/how-to-create-a-blog-with-keystone.md @@ -1,12 +1,19 @@ -# How to create a blog with Keystone +--- +title: How to create a blog with Keystone +--- -In this guide we will walk you through building a simple blog with Keystone based on free [Bootstrap-clean-blog](https://blackrockdigital.github.io/startbootstrap-clean-blog/) theme. -Our blog will have 3 page templates: index page with blog feed, single post and About us page. -See the final blog's source code [here](https://github.com/xyzteam2016/xyzcodeblog). +In this guide we will walk you through building a simple blog with +Keystone based on free +[Bootstrap-clean-blog](https://blackrockdigital.github.io/startbootstrap-clean-blog/) +theme. Our blog will have 3 page templates: index page with blog feed, +single post and About us page. See the final blog's source code +[here](https://github.com/xyzteam2016/xyzcodeblog). ## Install prerequisites -Before you begin, make sure you have [Node.js](http://nodejs.org/download) 0.10+ and [MongoDB](http://www.mongodb.org/downloads) v2.4+ installed. +Before you begin, make sure you have +[Node.js](http://nodejs.org/download) 0.10+ and +[MongoDB](http://www.mongodb.org/downloads) v2.4+ installed. ## Use the generator @@ -32,10 +39,13 @@ yo keystone ``` The generator will ask a couple of questions about the configuration. -Go ahead and select the default options. Say `Y` when generator asks you if want you include a `Blog`. -In this guide, we will use `jade` templating engine, and `less` as a CSS pre-processor. +Go ahead and select the default options. Say `Y` when generator asks you +if want you include a `Blog`. In this guide, we will use `jade` +templating engine, and `less` as a CSS pre-processor. -Once you've selected your requirements, the generator will prepare the skeleton of your app, configure the files and install npm dependencies as required. +Once you've selected your requirements, the generator will prepare the +skeleton of your app, configure the files and install npm dependencies +as required. ## Run it for the first time! @@ -46,7 +56,8 @@ cd my-blog node keystone ``` -You can now go to your browser and check out your new project on port 3000 (open http://localhost:3000). +You can now go to your browser and check out your new project on port +3000 (open http://localhost:3000). ## Changing blog styles and templates @@ -70,15 +81,15 @@ By default, there is no Page `Model` shipped with default Keystone project. Sinc 1) Create a new `Page.js` file in `models` folder. Since it is very similar to post data model, you can copy-paste contents of `Post.js` and use it as a template changing all occurrences of `Post` to `Page`. New `Page` model doesn't require so many fields as `Post` model, it would be enough to add the following fields: -``` +```javascript Page.add({ - title: { type: String, required: true }, - state: { type: Types.Select, options: 'draft, published, archived', default: 'draft', index: true }, - image: { type: Types.CloudinaryImage }, - content: { - brief: { type: Types.Html, wysiwyg: true, height: 150 }, - extended: { type: Types.Html, wysiwyg: true, height: 400 }, - }, + title: { type: String, required: true }, + state: { type: Types.Select, options: 'draft, published, archived', default: 'draft', index: true }, + image: { type: Types.CloudinaryImage }, + content: { + brief: { type: Types.Html, wysiwyg: true, height: 150 }, + extended: { type: Types.Html, wysiwyg: true, height: 400 }, + }, }); ``` @@ -92,7 +103,7 @@ As the last step, specify which fields to display in `keystone/pages` in Admin U 5) Add 'About' page link to navigation. Go to `routes/middleware.js` and add a new line to `res.locals.navLinks` -``` +```javascript res.locals.navLinks = [ { label: 'About', key: 'about', href: '/pages/page/about' }, // adding About to blog navigation { label: 'Blog', key: 'blog', href: '/blog' }, @@ -101,11 +112,11 @@ res.locals.navLinks = [ Last but not least, you may want to add `Pages` to Admin UI top navigation for easy access. To do so, open `keystone.js` file located in the root of your project and add a new route to `keystone.set(nav)` -``` +```javascript keystone.set('nav', { - posts: ['posts', 'post-categories'], - users: 'users', - pages: 'pages', // adding pages to Admin UI nav + posts: ['posts', 'post-categories'], + users: 'users', + pages: 'pages', // adding pages to Admin UI nav }); ``` @@ -129,6 +140,7 @@ git commit -m "Initial commit" ``` Login to Heroku and create your app: + ```sh heroku login heroku create my-blog @@ -138,6 +150,7 @@ If you run the `heroku create` command without the name parameter, heroku will a The command will also automatically add a git remote `heroku`. If you want to use an existing git repository, you can add it by running the command: + ```sh heroku git:remote -a my-blog ``` diff --git a/docs/guides/how-to-send-emails.md b/docs/guides/how-to-send-emails.md index 0399e76cf7..a3272a4f9f 100644 --- a/docs/guides/how-to-send-emails.md +++ b/docs/guides/how-to-send-emails.md @@ -1,139 +1,175 @@ -# How to send emails with Keystone +--- +title: How to send emails with Keystone +--- -We often had to send emails in our Keystone projects, so we figured we might as well make that easier. With the standalone [`keystone-email`](http://npm.im/keystone-email) package with Mailgun and Mandrill integrations you'll be sending emails in less than 5 minutes! +We often had to send emails in our Keystone projects, so we figured we +might as well make that easier. With the standalone +[`keystone-email`](http://npm.im/keystone-email) package with Mailgun +and Mandrill integrations you'll be sending emails in less than 5 +minutes! ## Setup -1. Install the `keystone-email package` in your project with `npm install keystone-email --save` +1. Install the `keystone-email package` in your project with `npm + install keystone-email --save` That's everything there is to it from the Keystone side! -You will need a [Mailgun](https://mailgun.com) account to be able to send emails though. (Mailgun gives you 10000 emails/month for free!) Let's create that: +You will need a [Mailgun](https://mailgun.com) account to be able to +send emails though. (Mailgun gives you 10000 emails/month for free!) +Let's create that: 1. Sign up on [mailgun.com](https://mailgun.com) -2. When you've created the account you should see a message saying "You're signed up and we just created your sandbox server xyz.mailgun.org". **Copy the link to your sandbox to a safe place**, we'll use it soon! -3. Click on "authorized recipients" on that page and invite yourself with your own email as an authorized recipient -
- Mailgun Signup Page -
-4. Activate your account and agree to be an authorized recipient in the two emails Mailgun sent you -5. Go to your dashboard, click on your name in the top right corner and show and **copy your private API key** and store it next to the sandbox URL, we'll need that too! -
- Mailgun Signup Page -
- -> Note: You can also use Mandrill with `keystone-email`, but since it has no free tier we'll skip it for this guide, see the [`keystone-email`](http://npm.im/keystone-email) docs for more information! +2. When you've created the account you should see a message saying + "You're signed up and we just created your sandbox server + xyz.mailgun.org". **Copy the link to your sandbox to a safe place**, + we'll use it soon! +3. Click on "authorized recipients" on that page and invite yourself + with your own email as an authorized recipient ![Mailgun Signup + Page](assets/mailgun-go-to-auth-rep.png) +4. Activate your account and agree to be an authorized recipient in the + two emails Mailgun sent you +5. Go to your dashboard, click on your name in the top right corner and + show and **copy your private API key** and store it next to the + sandbox URL, we'll need that too! + +![Mailgun Signup Page](assets/mailgun-dashboard.png) + +> Note: You can also use Mandrill with `keystone-email`, but since it +> has no free tier we'll skip it for this guide, see the +> [`keystone-email`](http://npm.im/keystone-email) docs for more +> information! Now we're all setup to start sending emails! ## Sending your first email -For exemplary purposes, create a `test-email.js` file in the root of your project and require `keystone-email`: +For exemplary purposes, create a `test-email.js` file in the root of +your project and require `keystone-email`: -```JS +```javascript // test-email.js var Email = require('keystone-email'); ``` -`keystone-email` uses templates. You can use whatever templating engine you prefer (set it via the `engine` option) but for this guide we'll be using `pug`! (formally called `jade`) +`keystone-email` uses templates. You can use whatever templating engine +you prefer (set it via the `engine` option) but for this guide we'll be +using `pug`! (formally called `jade`) -Create another file in the root folder called `test-email.pug` and fill it with this content: +Create another file in the root folder called `test-email.pug` and fill +it with this content: -```Jade +```jade doctype html html(lang="en") - head - body - h1 Your first email sent with Keystone! - p Congratulations on sending your first email with Keystone + head + body + h1 Your first email sent with Keystone! + p Congratulations on sending your first email with Keystone ``` Nothing fancy, a simple heading and paragraph for now. -Let's swap back to our `test-email.js` file and tell `keystone-email` which template we want to use. We pass that in as the first argument to `new Email()`: +Let's swap back to our `test-email.js` file and tell `keystone-email` +which template we want to use. We pass that in as the first argument to +`new Email()`: -```JS +```javascript // test-email.js var Email = require('keystone-email'); new Email('test-email.pug', {}); ``` -In the second argument, the email options, we tell it we want to use Mailgun as the email transport mechanism by setting `transport` to `mailgun` (surprisingly!): +In the second argument, the email options, we tell it we want to use +Mailgun as the email transport mechanism by setting `transport` to +`mailgun` (surprisingly!): -```JS +```javascript // test-email.js var Email = require('keystone-email'); new Email('test-email.pug', { - transport: 'mailgun', + transport: 'mailgun', }); ``` -This won't actually `send` the email though! (how should it, we haven't told Keystone where to send the email to yet!) +This won't actually `send` the email though! (how should it, we haven't +told Keystone where to send the email to yet!) -When called, `Email` returns a `send` function that you can use to actually send an email with the specified template. It takes three arguments: the `locals` (the data that goes into the template), the `senderOptions` (where to send the email to/from, the subject, the mailgun options,...) and as the last argument a callback. +When called, `Email` returns a `send` function that you can use to +actually send an email with the specified template. It takes three +arguments: the `locals` (the data that goes into the template), the +`senderOptions` (where to send the email to/from, the subject, the +mailgun options,...) and as the last argument a callback. -Since we don't have any data in our template yet, we'll simply set the `locals` to an empty object: +Since we don't have any data in our template yet, we'll simply set the +`locals` to an empty object: -```JS +```javascript // test-email.js var Email = require('keystone-email'); new Email('test-email.pug', { - transport: 'mailgun', + transport: 'mailgun', }).send({}); ``` -The `senderOptions` are the meat of this function call. We need to tell `keystone-email` where to send the email `to`, where it should pretend to come `from`, what the `subject` is and finally the Mailgun API details and sandbox url: +The `senderOptions` are the meat of this function call. We need to tell +`keystone-email` where to send the email `to`, where it should pretend +to come `from`, what the `subject` is and finally the Mailgun API +details and sandbox url: -```JS +```javascript // test-email.js var Email = require('keystone-email'); new Email('test-email.pug', { - transport: 'mailgun', + transport: 'mailgun', }).send({}, { - apiKey: 'YOURAPIKEYHERE', - domain: 'sandox123asdf234YOURSANDBOX.mailgun.com', - to: 'yourauthorizedrecipient@email.here', - from: { - name: 'Your Site', - email: 'hello@yoursite.com', - }, - subject: 'Your first KeystoneJS email', + apiKey: 'YOURAPIKEYHERE', + domain: 'sandox123asdf234YOURSANDBOX.mailgun.com', + to: 'yourauthorizedrecipient@email.here', + from: { + name: 'Your Site', + email: 'hello@yoursite.com', + }, + subject: 'Your first KeystoneJS email', }); ``` -If you tried to run this, it would already work! 🎉 Let's add a callback though, to make sure we get errors logged if something goes wrong or a message logged if it goes right: +If you tried to run this, it would already work! 🎉 Let's add a callback +though, to make sure we get errors logged if something goes wrong or a +message logged if it goes right: -```JS +```javascript // test-email.js var Email = require('keystone-email'); new Email('test-email.pug', { - transport: 'mailgun', + transport: 'mailgun', }).send({}, { - apiKey: 'YOURAPIKEYHERE', - domain: 'sandox123asdf234YOURSANDBOX.mailgun.com', - to: 'yourauthorizedrecipient@email.here', - from: { - name: 'Your Site', - email: 'hello@yoursite.com', - }, - subject: 'Your first KeystoneJS email', + apiKey: 'YOURAPIKEYHERE', + domain: 'sandox123asdf234YOURSANDBOX.mailgun.com', + to: 'yourauthorizedrecipient@email.here', + from: { + name: 'Your Site', + email: 'hello@yoursite.com', + }, + subject: 'Your first KeystoneJS email', }, function (err, result) { - if (err) { - console.error('🤕 Mailgun test failed with error:\n', err); - } else { - console.log('📬 Successfully sent Mailgun test with result:\n', result); - } + if (err) { + console.error('🤕 Mailgun test failed with error:\n', err); + } else { + console.log('📬 Successfully sent Mailgun test with result:\n', result); + } }); ``` -Now run this file with `node test-email.js`, and you should see this logged in your console: +Now run this file with `node test-email.js`, and you should see this +logged in your console: ``` 📬 Successfully sent Mailgun test with result @@ -141,41 +177,50 @@ Now run this file with `node test-email.js`, and you should see this logged in y message: 'Queued. Thank you.' ``` -Go check your inbox! Congratulations, you just sent your first email with `keystone-email`! +Go check your inbox! Congratulations, you just sent your first email +with `keystone-email`! ## Inserting locals -In a real world scenario you will almost always want to pass data into your templates, for example to say hi to your users by name. Let's do exactly that! +In a real world scenario you will almost always want to pass data into +your templates, for example to say hi to your users by name. Let's do +exactly that! -First, adapt your template to accept data. In Pug (Jade) you use locals with the `#{ variable }` syntax. Change `test-email.pug` to have this content: +First, adapt your template to accept data. In Pug (Jade) you use locals +with the `#{ variable }` syntax. Change `test-email.pug` to have this +content: -```Jade +```jade doctype html html(lang="en") - head - body - h1 Hi #{ firstName }, this is your second email sent with Keystone! - p This is your full name: #{ firstName } #{ name } + head + body + h1 Hi #{ firstName }, this is your second email sent with Keystone! + p This is your full name: #{ firstName } #{ name } ``` -As you can see above, we need to pass `firstName` and `name` to our template via the locals option. Go back to `test-email.js` and take a look at the `Email(...).send()` call we do: +As you can see above, we need to pass `firstName` and `name` to our +template via the locals option. Go back to `test-email.js` and take a +look at the `Email(...).send()` call we do: -```JS +```javascript new Email(/* ... */).send({}, {/* ... */}, function (err, result) {/* ... */}); ``` -See that empty first argument? Specify your first name and your last name in there like so: +See that empty first argument? Specify your first name and your last +name in there like so: -```JS +```javascript new Email(/* ... */).send({ - firstName: 'Max', - name: 'Stoiber', + firstName: 'Max', + name: 'Stoiber', }, {/* ... */}, function (err, result) {/* ... */}); ``` -Now send another email with `node test-email.js`! This is the text you should see once you've received it: +Now send another email with `node test-email.js`! This is the text you +should see once you've received it: ``` Hi Max, this is your second email sent with Keystone! @@ -183,8 +228,10 @@ Hi Max, this is your second email sent with Keystone! Let's hope that this is your first and last name: Max Stoiber ``` -(replacing `Max` and `Stoiber` with your first and last names respectively) +(replacing `Max` and `Stoiber` with your first and last names +respectively) -Amazing, that wasn't too hard, huh? We've successfully sent a personalized email! +Amazing, that wasn't too hard, huh? We've successfully sent a +personalized email! Now go ahead and add emails to your app! diff --git a/docs/guides/v0.3-to-v4.0-Upgrade-Guide.md b/docs/guides/v0.3-to-v4.0-Upgrade-Guide.md index 885e88f495..132e7825b5 100644 --- a/docs/guides/v0.3-to-v4.0-Upgrade-Guide.md +++ b/docs/guides/v0.3-to-v4.0-Upgrade-Guide.md @@ -1,42 +1,75 @@ -# KeystoneJS v0.3.x to v4.0.0 Upgrade Guide +--- +title: KeystoneJS v0.3.x to v4.0.0 Upgrade Guide +--- ## Changes to express application and mounting -**WIP** +### WIP -The mounting process has been rewritten for modularity and clarity. This may introduce some breaking changes if your app has been attaching the Keystone Admin UI to a nonstandard express app (i.e. not using `Keystone.start()`, but should make things simpler going forward. +The mounting process has been rewritten for modularity and clarity. This +may introduce some breaking changes if your app has been attaching the +Keystone Admin UI to a nonstandard express app (i.e. not using +`Keystone.start()`, but should make things simpler going forward. ### Changed -* `keystone.get('express session')` has been replaced by `keystone.expressSession` -* Session initialisation middleware is now executed before the body parser to allow for the Admin UI to include its own bodyParser implementation -* IP Restrictions middleware is now processed first, which means that static assets will now respect restrictions (previously this only restricted routes) -* `keystone.routes(fn)` has been replaced by `keystone.set('routes', fn)` +* `keystone.get('express session')` has been replaced by +`keystone.expressSession` +* Session initialisation middleware is now executed before the body +parser to allow for the Admin UI to include its own bodyParser +implementation +* IP Restrictions middleware is now processed first, which means that +static assets will now respect restrictions (previously this only +restricted routes) +* `keystone.routes(fn)` has been replaced by `keystone.set('routes', +fn)` * the `routes` option supports both: - * the legacy `function (app) {}` way of adding routes to the root express app + * the legacy `function (app) {}` way of adding routes to the root + express app * an `express.Router` instance ### Removed -* `keystone.static` has been removed (replacement TBA, see `admin/server`) -* `keystone.mount` has been removed (replaced by more granular methods, see `admin/server`) -* `keystone.bindEmailTestRoutes` and `keystone.set('email tests')` support (was this actually being used by anyone? let me know - @jedwatson) -* `keystone.set('email rules')` option has been removed; you should just use variables in your templates, rather than globally applied regular expressions. -* The `Types.CloudinaryImage` option `publicID: 'slug'` option has been removed. It has been replaced by the generateFilename function. Documentation for the new option can be found in `fields/types/cloudinaryimage` +* `keystone.static` has been removed (replacement TBA, see +`admin/server`) +* `keystone.mount` has been removed (replaced by more granular methods, +see `admin/server`) +* `keystone.bindEmailTestRoutes` and `keystone.set('email tests')` +support (was this actually being used by anyone? let me know - +@jedwatson) +* `keystone.set('email rules')` option has been removed; you should just +use variables in your templates, rather than globally applied regular +expressions. +* The `Types.CloudinaryImage` option `publicID: 'slug'` option has been +removed. It has been replaced by the generateFilename function. +Documentation for the new option can be found in +`fields/types/cloudinaryimage` ## UpdateHandler Changes -The UpdateHandler functionality has been completely rewritten to use the new, generic `List.updateItem` method. While we have tried to preserve backwards compatibility, there may be minor differences in functionality and the format of messages returned. +The UpdateHandler functionality has been completely rewritten to use the +new, generic `List.updateItem` method. While we have tried to preserve +backwards compatibility, there may be minor differences in functionality +and the format of messages returned. -The structure of error detail passed to the callback has changed, and now matches the new API error format (see [the API Spec](https://github.com/keystonejs/keystone/blob/master/admin/server/api/Readme.md)) +The structure of error detail passed to the callback has changed, and +now matches the new API error format (see [the API +Spec](https://github.com/keystonejs/keystone/blob/master/admin/server/api/Readme.md)) -If you are using the UpdateHandler please test your application comprehensively when upgrading to 0.4 and report any problems you find in the issues. +If you are using the UpdateHandler please test your application +comprehensively when upgrading to 0.4 and report any problems you find +in the issues. Specific changes include: - The `callback` function now receives a single error argument -- `options.validationMethods` is no longer supported, please apply any custom validation before calling `updateHandler.process()` -- `options.errorMessages` is no longer supported, as fields may now return different error conditions and replacing specific error detail with a simple string has the potential to be misleading and frustrating for users. If you want to show custom messages, please handle this on a case-by-case basis in your application. +- `options.validationMethods` is no longer supported, please apply any +custom validation before calling `updateHandler.process()` +- `options.errorMessages` is no longer supported, as fields may now +return different error conditions and replacing specific error detail +with a simple string has the potential to be misleading and frustrating +for users. If you want to show custom messages, please handle this on a +case-by-case basis in your application. The `flashErrors` option now supports the following values: @@ -48,7 +81,8 @@ The `flashErrors` option now supports the following values: ### New `File` field type -The new `File` field type, with the `FS`, `S3` and `Azure` storage adapters, replace the following field types (which are removed in 0.4) - +The new `File` field type, with the `FS`, `S3` and `Azure` storage +adapters, replace the following field types (which are removed in 0.4) - - `azureFile` - `localFile` @@ -61,11 +95,15 @@ For usage instructions, see: - [Azure Storage Adapter](https://github.com/keystonejs/keystone-storage-adapter-azure) - [S3 Storage Adapter](https://github.com/keystonejs/keystone-storage-adapter-s3) -For the full upgrade guide for File fields, see [File-Fields-Upgrade-Guide](https://github.com/keystonejs/keystone/wiki/File-Fields-Upgrade-Guide) in the KeystoneJS Wiki. +For the full upgrade guide for File fields, see +[File-Fields-Upgrade-Guide](https://github.com/keystonejs/keystone/wiki/File-Fields-Upgrade-Guide) +in the KeystoneJS Wiki. ### CloudinaryImage -The `_upload` suffix is no longer required or supported when uploading files from an html form. Now simply provide the cloudinary field path as the name of file upload fields. For example: +The `_upload` suffix is no longer required or supported when uploading +files from an html form. Now simply provide the cloudinary field path as +the name of file upload fields. For example: ```html @@ -76,13 +114,23 @@ The `_upload` suffix is no longer required or supported when uploading files fro ### CloudinaryImages -When the `cloudinary folders` keystone option is set, in 0.3.x `CloudinaryImages` fields would incorrectly use the `cloudinary prefix` option's value as the first part of the folder path for fields that did not specify the `folder` option. This has been fixed; the folder for uploaded images now defaults to `this.list.path + '/' + this.path` +When the `cloudinary folders` keystone option is set, in 0.3.x +`CloudinaryImages` fields would incorrectly use the `cloudinary prefix` +option's value as the first part of the folder path for fields that did +not specify the `folder` option. This has been fixed; the folder for +uploaded images now defaults to `this.list.path + '/' + this.path` -Explicit support for actions with `paths.action` (i.e. submitting a `fieldPath_action` value) has been removed. To remove images from the value, submit the new value for the field without the removed image present. +Explicit support for actions with `paths.action` (i.e. submitting a +`fieldPath_action` value) has been removed. To remove images from the +value, submit the new value for the field without the removed image +present. -The CloudinaryImages field no longer supports deleting removed images from Cloudinary, this may be restored in a subsequent version. +The CloudinaryImages field no longer supports deleting removed images +from Cloudinary, this may be restored in a subsequent version. -Reordering images with `paths.order` (i.e. submitting a `fieldPath_order` value) has also been removed. To sort images, submit the full array of values in the correct order. +Reordering images with `paths.order` (i.e. submitting a +`fieldPath_order` value) has also been removed. To sort images, submit +the full array of values in the correct order. ## Field API Changes @@ -96,45 +144,69 @@ The `geocodeGoogle` option has been renamed to `enableImprove`. ## Mongoose 4 -The bundled version of Mongoose has been updated from 3.x to 4.x. Please review the [Migration Guide](http://mongoosejs.com/docs/migration.html) and [Release Notes](https://github.com/Automattic/mongoose/wiki/4.0-Release-Notes) for more information. +The bundled version of Mongoose has been updated from 3.x to 4.x. Please +review the [Migration Guide](http://mongoosejs.com/docs/migration.html) +and [Release +Notes](https://github.com/Automattic/mongoose/wiki/4.0-Release-Notes) +for more information. ## `Keystone.Email` -`Keystone.Email` was completely rewritten as the standalone, well-tested `keystone-email` module, and requires it to be installed to work. +`Keystone.Email` was completely rewritten as the standalone, well-tested +`keystone-email` module, and requires it to be installed to work. ### Changed * `new Email` now accepts a second argument as the options (e.g. to set the transport) - ```JS - new Email('templatepath.ext', { transport: 'mailgun' }); - ``` -* The template locals are now passed in as the first, the options for send as the second and the callback as the third argument to `.send` - ```JS - new Email('templatepath.ext', { transport: 'mailgun' }) - .send(templateLocals, sendOptions, callback); - ``` +```javascript +new Email('templatepath.ext', { transport: 'mailgun' }); +``` + +* The template locals are now passed in as the first, the options for +send as the second and the callback as the third argument to `.send` + +```javascript +new Email('templatepath.ext', { transport: 'mailgun' }) + .send(templateLocals, sendOptions, callback); +``` ### Removed -These options, APIs or behaviours were removed with the rewrite to an external module. +These options, APIs or behaviours were removed with the rewrite to an +external module. -* We no longer assume `email.jade` as the default filename, you now have to pass an entire filename to or set the `engine` in the `.Email` call +* We no longer assume `email.jade` as the default filename, you now have +to pass an entire filename to or set the `engine` in the `.Email` call ### Deprecated -All of these deprecations will continue to work throughout `v4.x`, though warnings will be added in a future minor release. **We highly encourage moving to the new APIs as soon as possible**, your apps will break in v5 otherwise! - -* `keystone.set('email')` has been deprecated in favor of the `root` option (passed to the `.Email` call) -* The `templateExt` option was deprecated in favor of the `engine` option -* `keystone.set('transport')` has been deprecated in favor of setting `transport` in the `new Email()` options -* `keystone.set('mailgun api key')` and `keystone.set('mailgun domain')` have been deprecated in favor of passing the `apiKey` and `domain` option to the send options in `.send` +All of these deprecations will continue to work throughout `v4.x`, +though warnings will be added in a future minor release. **We highly +encourage moving to the new APIs as soon as possible**, your apps will +break in v5 otherwise! + +* `keystone.set('email')` has been deprecated in favor of the `root` +option (passed to the `.Email` call) +* The `templateExt` option was deprecated in favor of the `engine` +option +* `keystone.set('transport')` has been deprecated in favor of setting +`transport` in the `new Email()` options +* `keystone.set('mailgun api key')` and `keystone.set('mailgun domain')` +have been deprecated in favor of passing the `apiKey` and `domain` +option to the send options in `.send` ## CSV Download -Keystone 0.3 had a feature where you could specify a custom `toCSV` method on a list schema to control which values were included in the CSV. +Keystone 0.3 had a feature where you could specify a custom `toCSV` +method on a list schema to control which values were included in the +CSV. -As the CSV Export has been completely rewritten and now supports the same filter and fields options that the List view in the Admin UI does (including being able to specify which fields are included in the CSV from the Admin UI), the `toCSV` method has been replaced by a new `getCSVData` method: +As the CSV Export has been completely rewritten and now supports the +same filter and fields options that the List view in the Admin UI does +(including being able to specify which fields are included in the CSV +from the Admin UI), the `toCSV` method has been replaced by a new +`getCSVData` method: ```js User.schema.methods.getCSVData = function (data, options) { @@ -145,15 +217,20 @@ User.schema.methods.getCSVData = function (data, options) { }; ``` -Values returned by this method will be added to the CSV regardless of the fields specified to be included. You have access to the fields in `options.fields`. Additionally, you can set values to `undefined` to remove them from the csv if they were included. +Values returned by this method will be added to the CSV regardless of +the fields specified to be included. You have access to the fields in +`options.fields`. Additionally, you can set values to `undefined` to +remove them from the csv if they were included. The current User, if there is one, is provided in `options.user`. -### New Features +## New Features -#### toCSV method on Fields +### toCSV method on Fields -You can now also specify a per-field `toCSV` transform. Provide a function to return a custom value for the field if it is specified in `options.fields`: +You can now also specify a per-field `toCSV` transform. Provide a +function to return a custom value for the field if it is specified in +`options.fields`: ```js User.add({ @@ -163,9 +240,12 @@ User.add({ }) ``` -The `this` scope will be the document being serialised to CSV format. The `field` argument is the field definition, and the `options` argument contains the options passed to `getCSVData` (see above). +The `this` scope will be the document being serialised to CSV format. +The `field` argument is the field definition, and the `options` argument +contains the options passed to `getCSVData` (see above). -For field types that store an object, you can instead provide a list or array of keys to include in the CSV data: +For field types that store an object, you can instead provide a list or +array of keys to include in the CSV data: ```js User.add({ @@ -173,11 +253,13 @@ User.add({ }) ``` -#### Automatic flattening of complex values +### Automatic flattening of complex values -Objects will be flattened to multiple columns, with each key being appended to the field path using camelCase. +Objects will be flattened to multiple columns, with each key being +appended to the field path using camelCase. -So, for example, the following data from a `File` field with the path `attachment`: +So, for example, the following data from a `File` field with the path +`attachment`: ```js { @@ -196,21 +278,27 @@ id,attachmentFilename,attachmentFilesize 56dd3f1a51cb31100cf08457,photo.jpg,83452 ``` -### Removed Options - -The `csv expanded` keystone option has been deprecated. Relationship fields will always be expanded into `fieldName`, `fieldId` columns by default. +## Removed Options -## Other gotchas +The `csv expanded` keystone option has been deprecated. Relationship +fields will always be expanded into `fieldName`, `fieldId` columns by +default. -### Changed Dependencies +## Changed Dependencies -#### Jade +### Jade -Keystone 3 included `jade` as a dependency; this meant your project may have been able to use jade as the view engine without depending on it explicitly. Jade has now been removed from Keystone, so if you're using it you will need to explicitly add it to your `package.json`. +Keystone 3 included `jade` as a dependency; this meant your project may +have been able to use jade as the view engine without depending on it +explicitly. Jade has now been removed from Keystone, so if you're using +it you will need to explicitly add it to your `package.json`. -#### Underscore +### Underscore -Keystone 3 included `underscore` as a dependency; this was utilised by the generator, which should have added an explicit dependency when generating `package.json` files. Unfortunately it didn't, which means your project may expect underscore to be available and it won't be. +Keystone 3 included `underscore` as a dependency; this was utilised by +the generator, which should have added an explicit dependency when +generating `package.json` files. Unfortunately it didn't, which means +your project may expect underscore to be available and it won't be. If you get the following error when starting a project with keystone 4: diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000..0950235262 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,199 @@ +--- +title: KeystoneJS +--- + +![KeystoneJS](http://keystonejs.com/images/logo.svg) +=================================== + +[![Build Status](https://travis-ci.org/keystonejs/keystone.svg?branch=master)](https://travis-ci.org/keystonejs/keystone) + +[KeystoneJS](http://keystonejs.com) is a powerful Node.js content management system and web app framework built on [express](http://expressjs.com) and [mongoose](http://mongoosejs.com). Keystone makes it easy to create sophisticated web sites and apps, and comes with a beautiful auto-generated Admin UI. + +Check out [keystonejs.com](http://keystonejs.com) for documentation and guides. + +You can also deploy a starter project to [Heroku](https://www.heroku.com/) for free to try it out: + +[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy?template=https://github.com/JedWatson/keystone-starter) + + +## Keystone 4.0 Beta Released!!! + +We've been working on a major update to KeystoneJS for the last year, and it's a complete rebuild of Keystone's Admin UI and internal architecture. Improvements include: + +* The Admin UI has been re-written as a single page app using React.js, Redux and Elemental UI +* An updated API for Lists and Fields +* Better support for using Keystone without Express, or with your own express instance +* Core functionality has been refactored and we're breaking Keystone up into separate npm packages +* Startup time has been significantly reduced +* LocalFile, S3File and AzureFile have been replaced by a new generic `keystone.Storage` engine and File field +* We have much higher unit and end-to-end test coverage + +Please try out the beta and let us know what you think: + +``` +npm install --save keystone@next +``` + +We'll be publishing a summary of the new features, changes and improvements as we get closer to the final release. In the meantime, see the [v0.3 -> v4.0 Upgrade Guide](https://github.com/keystonejs/keystone/blob/master/docs/guides/v0.3-to-v4.0-Upgrade-Guide.md) for information on what's changed. + +Also check out our [demo site](http://demo.keystonejs.com/), which has been updated to the new version! + + +## About + +Keystone gives you: +* A simple way to create a dynamic web site or app with well-structured routes, templates and models +* A beautiful Admin UI based on the database models you define +* Enhanced `models` with additional field types and functionality, building on those natively supported by Mongoose +* Out of the box session management and authentication +* An updates framework for managing data updates or initialisation +* Integration with Cloudinary for image uploading, storage and resizing +* Integration with Mandrill for sending emails easily +* Integration with Google Places for clever location fields +* Integration with Embedly for powerful video and rich media embedding tools + +... plus a lot of other tools and utilities to make creating complex web apps easier. + +Use our [Yeoman Generator](https://github.com/keystonejs/generator-keystone) to get up and running with KeystoneJS quickly, then check out our getting started guide & docs at [keystonejs.com/docs/getting-started](http://keystonejs.com/docs/getting-started). + +We have a demo website at [demo.keystonejs.com](http://demo.keystonejs.com/) where you can play with the Keystone Admin UI, and you can [read the source](https://github.com/keystonejs/keystone-demo) to see how it was built. + +### Community + +We have a friendly, growing community and welcome everyone to get involved. + +Here are some ways: + +* Follow [@KeystoneJS](https://twitter.com/KeystoneJS) on twitter for news and announcements +* Vote on the next features on [ProductPains](https://productpains.com/product/keystonejs) +* Chat with us [![Join the chat at https://gitter.im/keystonejs/keystone](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/keystonejs/keystone?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +* If you've got ideas, questions or need some advice, check out the [KeystoneJS Google Group](https://groups.google.com/d/forum/keystonejs) +* Ask technical questions on [Stack Overflow](http://stackoverflow.com/questions/tagged/keystone.js) and tag them `keystonejs` +* Report bugs and issues on our [issue tracker](https://github.com/keystonejs/keystone/issues) +* ... or preferably, submit pull request with patches and / or new features + +We love to hear feedback about Keystone and the projects you're using it for. Ping us at [@KeystoneJS](https://twitter.com/KeystoneJS) on twitter. + +#### Related Projects +If you are using KeystoneJS in any projects we encourage you to add it to our [Related Projects Page](https://github.com/keystonejs/keystone/wiki/Related-Projects). This is also the place to find generators and such that bundle KeystoneJS. + +### Contributing + +If you can, please contribute by reporting issues, discussing ideas, or submitting pull requests with patches and new features. We do our best to respond to all issues and pull requests within a day or two, and make patch releases to npm regularly. + +If you're going to contribute code, please follow our [coding standards](https://github.com/keystonejs/keystone/wiki/Coding-Standards) and read our [CONTRIBUTING.md](https://github.com/keystonejs/keystone/blob/master/CONTRIBUTING.md). + +## Usage + +**Check out the [KeystoneJS Getting Started Guide](http://keystonejs.com/getting-started) to start using KeystoneJS.** + +### Installation + +The easiest way to get started with Keystone is to use the Yeoman generator: + +```bash +$ npm install -g generator-keystone +$ yo keystone +``` + +Answer the questions, and the generator will create a new project based on the options you select, and install the required packages from **npm**. + +Alternatively, to include Keystone in an existing project or start from scratch (without Yeoman), specify `keystone: "^0.3.9"` in the `dependencies` array of your `package.json` file, and run `npm install` from your terminal. + +Then read through the [Documentation](http://keystonejs.com/docs) and the [Example Projects](http://keystonejs.com/examples) to understand how to use it. + +### Configuration + +Config variables can be passed in an object to the `keystone.init` method, or can be set any time before `keystone.start` is called using `keystone.set(key, value)`. This allows for a more flexible order of execution (e.g. if you refer to Lists in your routes, you can set the routes after configuring your Lists, as in the example above). + +See the [KeystoneJS configuration documentation](http://keystonejs.com/docs/configuration) for details and examples of the available configuration options. + +### Database field types + +Keystone builds on the basic data types provided by mongo and allows you to easily add rich, functional fields to your application's models. + +You get helper methods on your models for dealing with each field type easily (such as formatting a date or number, resizing an image, getting an array of the available options for a select field, or using Google's Places API to improve addresses) as well as a beautiful, responsive admin UI to edit your data with. + +See the [KeystoneJS database documentation](http://keystonejs.com/docs/database) for details and examples of the various field types, as well as how to set up and use database models in your application. + +Keystone's field types include: + +* [Boolean](http://keystonejs.com/docs/database/#fieldtypes-boolean) +* [Color](http://keystonejs.com/docs/database/#fieldtypes-color) +* [Date](http://keystonejs.com/docs/database/#fieldtypes-date) +* [Datetime](http://keystonejs.com/docs/database/#fieldtypes-datetime) +* [Email](http://keystonejs.com/docs/database/#fieldtypes-email) +* [Html](http://keystonejs.com/docs/database/#fieldtypes-html) +* [Key](http://keystonejs.com/docs/database/#fieldtypes-key) +* [Location](http://keystonejs.com/docs/database/#fieldtypes-location) +* [Markdown](http://keystonejs.com/docs/database/#fieldtypes-markdown) +* [Money](http://keystonejs.com/docs/database/#fieldtypes-money) +* [Name](http://keystonejs.com/docs/database/#fieldtypes-name) +* [Number](http://keystonejs.com/docs/database/#fieldtypes-number) +* [Password](http://keystonejs.com/docs/database/#fieldtypes-password) +* [Select](http://keystonejs.com/docs/database/#fieldtypes-select) +* [Text](http://keystonejs.com/docs/database/#fieldtypes-text) +* [Textarea](http://keystonejs.com/docs/database/#fieldtypes-textarea) +* [Url](http://keystonejs.com/docs/database/#fieldtypes-url) +* [Azure File](http://keystonejs.com/docs/database/#fieldtypes-azurefile) +* [CloudinaryImage](http://keystonejs.com/docs/database/#fieldtypes-cloudinaryimage) +* [CloudinaryImages](http://keystonejs.com/docs/database/#fieldtypes-cloudinaryimages) +* [Embedly](http://keystonejs.com/docs/database/#fieldtypes-embedly) +* [LocalFile](http://keystonejs.com/docs/database/#fieldtypes-localfile) +* [S3 File](http://keystonejs.com/docs/database/#fieldtypes-s3file) + +Keystone also has [Relationship fields](http://keystonejs.com/docs/database#relationships) for managing one-to-many and many-to-many relationships between different models. + +### Running KeystoneJS in Production + +When you deploy your KeystoneJS app to production, be sure to set your `ENV` environment variable to `production`. +You can do this by setting `NODE_ENV=production` in your `.env` file, which gets handled by [dotenv](https://github.com/motdotla/dotenv). + +Setting your environment enables certain features, including template caching, simpler error reporting and html minification, that are important in production but annoying in development. + +### Linking Keystone for Development and Testing + +If you want to test or develop against the `master` branch of KeystoneJS (or against your own branch), rather than a published version on **npm**, you just need to check it out then use `npm link` to link it to your project. On Mac OS, this is done like this: + +* Clone KeystoneJS locally, e.g. to `~/Development/KeystoneJS` +* From the KeystoneJS directory, run `sudo npm link` (you will need to enter your system password) +* From your project directory, e.g. `~/Development/MySite` (the one with your `package.json` file in it) run `npm link keystone`. This will create a link between `~/Development/MySite/node_modules/keystone` and `~/Development/KeystoneJS`. + +Then `require('keystone')` normally in your app - the development copy will be used. Note that running `npm update` will ignore new versions of keystone that have been published. + +To go back to using a published version of KeystoneJS from npm, from your project directory, run `npm unlink keystone` then `npm install`. + +#### Testing +To run the test suite run `npm test`. + +## Thanks + +KeystoneJS is a free and open source community-driven project. Thanks to our many [contributors](https://github.com/keystonejs/keystone/graphs/contributors) and [users](https://github.com/keystonejs/keystone/stargazers) for making it great. + +Keystone's development is led by [Jed Watson](https://github.com/JedWatson), [Joss Mackison](https://github.com/jossmac) and [Max Stoiber](https://github.com/mxstbr) and supported by [Thinkmill](http://thinkmill.com.au) in Sydney, Australia. + + +## License + +(The MIT License) + +Copyright (c) 2016 Jed Watson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/docs/menu.yaml b/docs/menu.yaml new file mode 100644 index 0000000000..04161d838a --- /dev/null +++ b/docs/menu.yaml @@ -0,0 +1,9 @@ +- title: Introduction + links: + KeystoneJS: / +- title: Guides + links: + API File and Image Uploads: /guides/api-file-image-uploads/ + How to create a blog with Keystone: /guides/how-to-create-a-blog-with-keystone/ + How to send emails with Keystone: /guides/how-to-send-emails/ + KeystoneJS v0.3.x to v4.0.0 Upgrade Guide: /guides/v-0-3-to-v-4-0-upgrade-guide/ diff --git a/www/.babelrc b/www/.babelrc new file mode 100644 index 0000000000..c62b618267 --- /dev/null +++ b/www/.babelrc @@ -0,0 +1,7 @@ +{ + "presets": [ + 'es2015', + 'stage-0', + 'react', + ], +} diff --git a/www/.gitignore b/www/.gitignore new file mode 100644 index 0000000000..0b152cafcf --- /dev/null +++ b/www/.gitignore @@ -0,0 +1,10 @@ +node_modules +npm-debug.log +build +.antwar + +.intermediate-representation/ +.netlify +styles/geomanist/geomanist-regular.woff +styles/geomanist/geomanist-regular.woff2 +public diff --git a/www/components/Container.jsx b/www/components/Container.jsx new file mode 100644 index 0000000000..38cf65b61a --- /dev/null +++ b/www/components/Container.jsx @@ -0,0 +1,19 @@ +import React from 'react' +import { rhythm } from 'utils/typography' + +export default ({ className, style, children, ...otherProps }) => { + if (!className) { + className = '' + } + return ( +
+ { children } +
+ ); +}; diff --git a/www/components/Sidebar.jsx b/www/components/Sidebar.jsx new file mode 100644 index 0000000000..67af896fc3 --- /dev/null +++ b/www/components/Sidebar.jsx @@ -0,0 +1,92 @@ +import React from 'react'; +import Link from 'gatsby-link'; +import { rhythm, scale } from '../utils/typography'; +import { merge, media, presets, style } from 'glamor' +//import { sections, basepath } from 'utilities/pages' +//import Sticky from 'react-stickynode' +//import shallowCompare from 'react-addons-shallow-compare' + +import menuItems from '../../docs/menu.yaml' +console.log(menuItems) + +class Sidebar extends React.Component { + render() { + const { pages, location, activeSection } = this.props + return ( + + ) + }; +} + +const Item = ({ url, title }) => ( +
  • + + { title } + +
  • +); + +export default Sidebar; diff --git a/www/components/navigation.jsx b/www/components/navigation.jsx new file mode 100644 index 0000000000..1116682b65 --- /dev/null +++ b/www/components/navigation.jsx @@ -0,0 +1,85 @@ +import React from 'react'; +import Link from 'gatsby-link' +import Container from './Container'; +import { rhythm, scale, options } from 'utils/typography'; +import { presets } from 'glamor' +import MenuIcon from 'react-icons/lib/md/menu' +import gray from 'gray-percentage' +import Headroom from 'react-headroom' + +export default ({ home = '/', location, openSidebar }) => { + return ( + + +
    + +
    + + +

    + Keystone +

    + +
    +
    + ) +}; diff --git a/www/css/prism-coy.css b/www/css/prism-coy.css new file mode 100644 index 0000000000..0deab4a8c8 --- /dev/null +++ b/www/css/prism-coy.css @@ -0,0 +1,174 @@ +/** + * prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML + * Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics); + * @author Tim Shedor + */ + +/* Margin bottom to accomodate shadow */ +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + margin-bottom: 1em; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + position: relative; + padding: .2em; + border-radius: 0.3em; + color: #c92c2c; + border: 1px solid rgba(0, 0, 0, 0.1); + display: inline; + white-space: normal; +} + +pre[class*="language-"]:before, +pre[class*="language-"]:after { + content: ''; + z-index: -2; + display: block; + position: absolute; + bottom: 0.75em; + left: 0.18em; + width: 40%; + height: 20%; + max-height: 13em; + box-shadow: 0px 13px 8px #979797; + -webkit-transform: rotate(-2deg); + -moz-transform: rotate(-2deg); + -ms-transform: rotate(-2deg); + -o-transform: rotate(-2deg); + transform: rotate(-2deg); +} + +:not(pre) > code[class*="language-"]:after, +pre[class*="language-"]:after { + right: 0.75em; + left: auto; + -webkit-transform: rotate(2deg); + -moz-transform: rotate(2deg); + -ms-transform: rotate(2deg); + -o-transform: rotate(2deg); + transform: rotate(2deg); +} + +.token.comment, +.token.block-comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #7D8B99; +} + +.token.punctuation { + color: #5F6364; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.function-name, +.token.constant, +.token.symbol, +.token.deleted { + color: #c92c2c; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.function, +.token.builtin, +.token.inserted { + color: #2f9c0a; +} + +.token.operator, +.token.entity, +.token.url, +.token.variable { + color: #a67f59; +} + +.token.atrule, +.token.attr-value, +.token.keyword, +.token.class-name { + color: #1990b8; +} + +.token.regex, +.token.important { + color: #e90; +} + +.language-css .token.string, +.style .token.string { + color: #a67f59; +} + +.token.important { + font-weight: normal; +} + +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +.namespace { + opacity: .7; +} + +@media screen and (max-width: 767px) { + pre[class*="language-"]:before, + pre[class*="language-"]:after { + bottom: 14px; + box-shadow: none; + } + +} + +/* Plugin styles */ +.token.tab:not(:empty):before, +.token.cr:before, +.token.lf:before { + color: #e0d7d1; +} + +/* Plugin styles: Line Numbers */ +pre[class*="language-"].line-numbers { + padding-left: 0; +} + +pre[class*="language-"].line-numbers code { + padding-left: 3.8em; +} + +pre[class*="language-"].line-numbers .line-numbers-rows { + left: 0; +} + +/* Plugin styles: Line Highlight */ +pre[class*="language-"][data-line] { + padding-top: 0; + padding-bottom: 0; + padding-left: 0; +} +pre[data-line] code { + position: relative; + padding-left: 4em; +} +pre .line-highlight { + margin-top: 0; +} diff --git a/www/gatsby-config.js b/www/gatsby-config.js new file mode 100644 index 0000000000..b6862607bf --- /dev/null +++ b/www/gatsby-config.js @@ -0,0 +1,50 @@ +module.exports = { + siteMetadata: { + title: 'KeystoneJS', + }, + plugins: [ + `gatsby-plugin-glamor`, + `gatsby-plugin-sharp`, + { + resolve: `gatsby-plugin-google-analytics`, + options: { + trackingId: `UA-53647600-7`, + }, + }, + { + resolve: `gatsby-source-filesystem`, + options: { + name: `docs`, + path: `${__dirname}/../docs`, + }, + }, + `gatsby-parser-remark`, + `gatsby-parser-sharp`, + { + resolve: `gatsby-typegen-remark`, + options: { + plugins: [ + { + resolve: `gatsby-typegen-remark-responsive-image`, + options: { + maxWidth: 800, + wrapperStyle: `margin-bottom: 1.125rem;`, + }, + }, + { + resolve: `gatsby-typegen-remark-responsive-iframe`, + options: { + wrapperStyle: `margin-bottom: 1.125rem;`, + }, + }, + `gatsby-typegen-remark-copy-linked-files`, + `gatsby-typegen-remark-smartypants`, + `gatsby-typegen-remark-prismjs`, + `gatsby-typegen-remark-autolink-headers`, + ], + }, + }, + `gatsby-typegen-filesystem`, + `gatsby-typegen-sharp`, + ], +} diff --git a/www/gatsby-node.js b/www/gatsby-node.js new file mode 100644 index 0000000000..19d45aec6c --- /dev/null +++ b/www/gatsby-node.js @@ -0,0 +1,68 @@ +const _ = require('lodash') +const path = require('path') +const select = require('unist-util-select') +const Promise = require('bluebird') + +exports.createPages = ({ args }) => { + const { graphql } = args + + return new Promise((resolve) => { + const paths = [] + graphql(` + { + allMarkdownRemark(limit: 1000) { + edges { + node { + slug + } + } + } + } + `) + .then((result) => { + if (result.errors) { + console.log(result.errors) + reject(result.errors) + } + + const articleComponent = path.resolve('./pages/template-doc-page.js') + // Create article routes. + _.each(result.data.allMarkdownRemark.edges, (edge) => { + paths.push({ + path: edge.node.slug, // required + component: articleComponent, + context: { + slug: edge.node.slug, + }, + }) + }) + + resolve(paths) + }) + }) +} + +// Add custom slug. +exports.modifyAST = ({ args }) => { + console.time(`local modifyAST`) + const { ast } = args + const files = select(ast, `File[extension="md"]`) + files.forEach((file) => { + const parsedFilePath = path.parse(file.relativePath) + let slug + if (parsedFilePath.name !== `index`) { + slug = `/${_.kebabCase(parsedFilePath.dir)}/${_.kebabCase(parsedFilePath.name)}/` + } else { + slug = `/${_.kebabCase(parsedFilePath.dir)}/` + } + + // If file isn't in subdirectory "dir" will be empty. + slug = slug.replace('//', '/') + + file.children[0].slug = slug + + file.slug = slug + }) + console.timeEnd(`local modifyAST`) + return files +} diff --git a/www/html.js b/www/html.js new file mode 100644 index 0000000000..fae14b4ed7 --- /dev/null +++ b/www/html.js @@ -0,0 +1,45 @@ +import React from 'react' +import { GoogleFont, TypographyStyle } from 'react-typography' +import typography from './utils/typography' +import get from 'lodash/get' + +let stylesStr +if (process.env.NODE_ENV === `production`) { + try { + stylesStr = require(`!raw-loader!./public/styles.css`) + } catch (e) { + console.log(e) + } +} + +module.exports = React.createClass({ + render () { + // TODO add react helmet rewind + let css + if (process.env.NODE_ENV === `production`) { + css =