);
diff --git a/packages/netlify-cms-widget-relation/src/RelationControl.js b/packages/netlify-cms-widget-relation/src/RelationControl.js
index e96e37ea..f2956a65 100644
--- a/packages/netlify-cms-widget-relation/src/RelationControl.js
+++ b/packages/netlify-cms-widget-relation/src/RelationControl.js
@@ -43,7 +43,7 @@ injectGlobal`
.react-autosuggest__suggestion--focused {
background-color: #ddd;
}
-`
+`;
export default class RelationControl extends React.Component {
static propTypes = {
@@ -55,10 +55,7 @@ export default class RelationControl extends React.Component {
fetchID: PropTypes.string,
query: PropTypes.func.isRequired,
clearSearch: PropTypes.func.isRequired,
- queryHits: PropTypes.oneOfType([
- PropTypes.array,
- PropTypes.object,
- ]),
+ queryHits: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
classNameWrapper: PropTypes.string.isRequired,
setActiveStyle: PropTypes.func.isRequired,
setInactiveStyle: PropTypes.func.isRequired,
@@ -88,12 +85,18 @@ export default class RelationControl extends React.Component {
* Load extra post data into the store after first query.
*/
if (this.didInitialSearch) return;
- if (this.props.queryHits !== prevProps.queryHits && this.props.queryHits.get && this.props.queryHits.get(this.controlID)) {
+ if (
+ this.props.queryHits !== prevProps.queryHits &&
+ this.props.queryHits.get &&
+ this.props.queryHits.get(this.controlID)
+ ) {
this.didInitialSearch = true;
const suggestion = this.props.queryHits.get(this.controlID);
if (suggestion && suggestion.length === 1) {
const val = this.getSuggestionValue(suggestion[0]);
- this.props.onChange(val, { [this.props.field.get('collection')]: { [val]: suggestion[0].data } });
+ this.props.onChange(val, {
+ [this.props.field.get('collection')]: { [val]: suggestion[0].data },
+ });
}
}
}
@@ -104,7 +107,9 @@ export default class RelationControl extends React.Component {
onSuggestionSelected = (event, { suggestion }) => {
const value = this.getSuggestionValue(suggestion);
- this.props.onChange(value, { [this.props.field.get('collection')]: { [value]: suggestion.data } });
+ this.props.onChange(value, {
+ [this.props.field.get('collection')]: { [value]: suggestion.data },
+ });
};
onSuggestionsFetchRequested = debounce(({ value }) => {
@@ -119,19 +124,21 @@ export default class RelationControl extends React.Component {
this.props.clearSearch();
};
- getSuggestionValue = (suggestion) => {
+ getSuggestionValue = suggestion => {
const { field } = this.props;
const valueField = field.get('valueField');
return suggestion.data[valueField];
};
- renderSuggestion = (suggestion) => {
+ renderSuggestion = suggestion => {
const { field } = this.props;
const valueField = field.get('displayFields') || field.get('valueField');
if (List.isList(valueField)) {
return (
);
}
@@ -147,7 +154,7 @@ export default class RelationControl extends React.Component {
queryHits,
classNameWrapper,
setActiveStyle,
- setInactiveStyle
+ setInactiveStyle,
} = this.props;
const inputProps = {
@@ -160,7 +167,7 @@ export default class RelationControl extends React.Component {
onBlur: setInactiveStyle,
};
- const suggestions = (queryHits.get) ? queryHits.get(this.controlID, []) : [];
+ const suggestions = queryHits.get ? queryHits.get(this.controlID, []) : [];
return (
diff --git a/packages/netlify-cms-widget-relation/src/RelationPreview.js b/packages/netlify-cms-widget-relation/src/RelationPreview.js
index 916cec6b..4b763bf8 100644
--- a/packages/netlify-cms-widget-relation/src/RelationPreview.js
+++ b/packages/netlify-cms-widget-relation/src/RelationPreview.js
@@ -2,9 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
-const RelationPreview = ({ value }) => (
-
{ value }
-)
+const RelationPreview = ({ value }) =>
{value} ;
RelationPreview.propTypes = {
value: PropTypes.node,
diff --git a/packages/netlify-cms-widget-select/src/SelectControl.js b/packages/netlify-cms-widget-select/src/SelectControl.js
index fbbe5bfd..45679d4d 100644
--- a/packages/netlify-cms-widget-select/src/SelectControl.js
+++ b/packages/netlify-cms-widget-select/src/SelectControl.js
@@ -12,13 +12,15 @@ export default class SelectControl extends React.Component {
setActiveStyle: PropTypes.func.isRequired,
setInactiveStyle: PropTypes.func.isRequired,
field: ImmutablePropTypes.contains({
- options: ImmutablePropTypes.listOf(PropTypes.oneOfType([
- PropTypes.string,
- ImmutablePropTypes.contains({
- label: PropTypes.string.isRequired,
- value: PropTypes.string.isRequired,
- }),
- ])).isRequired,
+ options: ImmutablePropTypes.listOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ ImmutablePropTypes.contains({
+ label: PropTypes.string.isRequired,
+ value: PropTypes.string.isRequired,
+ }),
+ ]),
+ ).isRequired,
}),
};
@@ -26,7 +28,7 @@ export default class SelectControl extends React.Component {
value: '',
};
- handleChange = (e) => {
+ handleChange = e => {
this.props.onChange(e.target.value);
};
@@ -40,7 +42,7 @@ export default class SelectControl extends React.Component {
const options = [
...(field.get('default', false) ? [] : [{ label: '', value: '' }]),
- ...fieldOptions.map((option) => {
+ ...fieldOptions.map(option => {
if (typeof option === 'string') {
return { label: option, value: option };
}
@@ -57,11 +59,11 @@ export default class SelectControl extends React.Component {
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
>
- {
- options.map(
- (option, idx) =>
{option.label}
- )
- }
+ {options.map((option, idx) => (
+
+ {option.label}
+
+ ))}
);
}
diff --git a/packages/netlify-cms-widget-select/src/SelectPreview.js b/packages/netlify-cms-widget-select/src/SelectPreview.js
index c4b5ab2f..7daf92ca 100644
--- a/packages/netlify-cms-widget-select/src/SelectPreview.js
+++ b/packages/netlify-cms-widget-select/src/SelectPreview.js
@@ -4,7 +4,7 @@ import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
const SelectPreview = ({ value }) => (
{value ? value.toString() : null}
-)
+);
SelectPreview.propTypes = {
value: PropTypes.string,
diff --git a/packages/netlify-cms-widget-string/src/StringControl.js b/packages/netlify-cms-widget-string/src/StringControl.js
index e9c512fe..3f7d3212 100644
--- a/packages/netlify-cms-widget-string/src/StringControl.js
+++ b/packages/netlify-cms-widget-string/src/StringControl.js
@@ -22,7 +22,7 @@ export default class StringControl extends React.Component {
onChange,
classNameWrapper,
setActiveStyle,
- setInactiveStyle
+ setInactiveStyle,
} = this.props;
return (
diff --git a/packages/netlify-cms-widget-string/src/StringPreview.js b/packages/netlify-cms-widget-string/src/StringPreview.js
index dbd5998f..3c82bcad 100644
--- a/packages/netlify-cms-widget-string/src/StringPreview.js
+++ b/packages/netlify-cms-widget-string/src/StringPreview.js
@@ -2,9 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
-const StringPreview = ({ value }) => (
-
{ value }
-);
+const StringPreview = ({ value }) =>
{value} ;
StringPreview.propTypes = {
value: PropTypes.node,
diff --git a/packages/netlify-cms-widget-text/src/TextPreview.js b/packages/netlify-cms-widget-text/src/TextPreview.js
index 5e47b371..f3417216 100644
--- a/packages/netlify-cms-widget-text/src/TextPreview.js
+++ b/packages/netlify-cms-widget-text/src/TextPreview.js
@@ -2,9 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
-const TextPreview = ({ value }) => (
-
{ value }
-)
+const TextPreview = ({ value }) =>
{value} ;
TextPreview.propTypes = {
value: PropTypes.node,
diff --git a/packages/netlify-cms/README.md b/packages/netlify-cms/README.md
index 5cdb470d..92504005 100644
--- a/packages/netlify-cms/README.md
+++ b/packages/netlify-cms/README.md
@@ -1,4 +1,5 @@
# Netlify CMS
+
[![All Contributors](https://img.shields.io/badge/all_contributors-110-orange.svg)](#contributors)
[![Open Source Helpers](https://www.codetriage.com/netlify/netlify-cms/badges/users.svg)](https://www.codetriage.com/netlify/netlify-cms)
[![](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/netlify/netlifycms)
@@ -24,9 +25,9 @@ Read more about Netlify CMS [Core Concepts](https://www.netlifycms.org/docs/intr
The Netlify CMS can be used in two different ways.
-* A Quick and easy install, that just requires you to create a single HTML file and a configuration file. All the CMS Javascript and CSS are loaded from a CDN.
-To learn more about this installation method, refer to the [Quick Start Guide](https://www.netlifycms.org/docs/quick-start/)
-* A complete, more complex install, that gives you more flexibility but requires that you use a static site builder with a build system that supports npm packages.
+- A Quick and easy install, that just requires you to create a single HTML file and a configuration file. All the CMS Javascript and CSS are loaded from a CDN.
+ To learn more about this installation method, refer to the [Quick Start Guide](https://www.netlifycms.org/docs/quick-start/)
+- A complete, more complex install, that gives you more flexibility but requires that you use a static site builder with a build system that supports npm packages.
# Community
@@ -45,7 +46,9 @@ Please make sure you understand its [implications and guarantees](https://writin
# Thanks
## Services
+
These services support Netlify CMS development by providing free infrastructure.
+
@@ -57,6 +60,7 @@ These services support Netlify CMS development by providing free infrastructure.
## Contributors
+
These wonderful folks are responsible for developing and maintaining Netlify CMS. ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key))
@@ -79,6 +83,7 @@ These wonderful folks are responsible for developing and maintaining Netlify CMS
| [
David Ko ](https://github.com/daveyko)
[💻](https://github.com/netlify/netlify-cms/commits?author=daveyko "Code") | [
Iñaki García ](http://www.txorua.com)
[🎨](#design-igarbla "Design") | [
Sam ](https://github.com/gazebosx3)
[💻](https://github.com/netlify/netlify-cms/commits?author=gazebosx3 "Code") | [
Josh Dzielak ](https://dzello.com)
[📖](https://github.com/netlify/netlify-cms/commits?author=dzello "Documentation") | [
Jeremy Bise ](http://thosegeeks.com)
[📖](https://github.com/netlify/netlify-cms/commits?author=jeremybise "Documentation") | [
terrierscript ](https://terrierscript.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=terrierscript "Code") | [
Christopher Geary ](https://twitter.com/crgeary)
[🔌](#plugin-crgeary "Plugin/utility libraries") |
| [
Brian Macdonald ](https://github.com/brianlmacdonald)
[💻](https://github.com/netlify/netlify-cms/commits?author=brianlmacdonald "Code") | [
John Vandenberg ](https://jayvdb.github.io/)
[📖](https://github.com/netlify/netlify-cms/commits?author=jayvdb "Documentation") | [
MarkZither ](https://github.com/MarkZither)
[📖](https://github.com/netlify/netlify-cms/commits?author=MarkZither "Documentation") | [
Rob Phoenix ](https://www.robphoenix.com)
[📖](https://github.com/netlify/netlify-cms/commits?author=robphoenix "Documentation") | [
Steve Lathrop ](https://www.SteLa.io)
[💻](https://github.com/netlify/netlify-cms/commits?author=slathrop "Code") [📖](https://github.com/netlify/netlify-cms/commits?author=slathrop "Documentation") [💡](#example-slathrop "Examples") | [
Maciej Matuszewski ](https://github.com/maciejmatu)
[💻](https://github.com/netlify/netlify-cms/commits?author=maciejmatu "Code") | [
Eko Eryanto ](https://github.com/ekoeryanto)
[🔌](#plugin-ekoeryanto "Plugin/utility libraries") |
| [
Taylor D. Edmiston ](http://blog.tedmiston.com/)
[📖](https://github.com/netlify/netlify-cms/commits?author=tedmiston "Documentation") | [
Daniel Mahon ](https://www.mahonstudios.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=danielmahon "Code") | [
Evan Hennessy ](https://www.hennessyevan.com)
[🔌](#plugin-hennessyevan "Plugin/utility libraries") | [
Hasan Azizul Haque ](https://hasanavi.me)
[💻](https://github.com/netlify/netlify-cms/commits?author=hasanavi "Code") [📖](https://github.com/netlify/netlify-cms/commits?author=hasanavi "Documentation") [🤔](#ideas-hasanavi "Ideas, Planning, & Feedback") | [
Robert Karlsson ](https://github.com/robertkarlsson)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Arobertkarlsson "Bug reports") | [
Gil Greenberg ](http://gilgreenberg.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=gil-- "Code") |
+
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
diff --git a/packages/netlify-cms/scripts/deprecate-old-dist.js b/packages/netlify-cms/scripts/deprecate-old-dist.js
index 0d755c26..ed130bca 100644
--- a/packages/netlify-cms/scripts/deprecate-old-dist.js
+++ b/packages/netlify-cms/scripts/deprecate-old-dist.js
@@ -1 +1,3 @@
-console.warn('You seem to be loading Netlify CMS by fetching `dist/cms.js` from a CDN. That file is deprecated and will be removed in the next major release. Please use `dist/netlify-cms.js` instead.')
+console.warn(
+ 'You seem to be loading Netlify CMS by fetching `dist/cms.js` from a CDN. That file is deprecated and will be removed in the next major release. Please use `dist/netlify-cms.js` instead.',
+);
diff --git a/packages/netlify-cms/webpack.config.js b/packages/netlify-cms/webpack.config.js
index 4cb063f0..aeb15ca7 100644
--- a/packages/netlify-cms/webpack.config.js
+++ b/packages/netlify-cms/webpack.config.js
@@ -13,8 +13,8 @@ const baseConfig = {
entry: './index.js',
plugins: [
...Object.entries(plugins)
- .filter(([ key ]) => key !== 'friendlyErrors')
- .map(([ , plugin ]) => plugin()),
+ .filter(([key]) => key !== 'friendlyErrors')
+ .map(([, plugin]) => plugin()),
new webpack.DefinePlugin({
NETLIFY_CMS_VERSION: JSON.stringify(`${pkg.version}${isProduction ? '' : '-dev'}`),
NETLIFY_CMS_CORE_VERSION: null,
@@ -44,10 +44,7 @@ if (isProduction) {
*/
{
...baseConfig,
- entry: [
- path.join(__dirname, 'scripts/deprecate-old-dist.js'),
- baseConfig.entry,
- ],
+ entry: [path.join(__dirname, 'scripts/deprecate-old-dist.js'), baseConfig.entry],
output: {
...baseConfig.output,
filename: 'dist/cms.js',
diff --git a/scripts/cache.js b/scripts/cache.js
index 0f2ac5fa..21736808 100644
--- a/scripts/cache.js
+++ b/scripts/cache.js
@@ -1,6 +1,6 @@
-const os = require('os')
-const path = require('path')
-const cache = require('cache-me-outside')
+const os = require('os');
+const path = require('path');
+const cache = require('cache-me-outside');
cache({
cacheFolder: path.join('/', 'opt', 'build', 'cache', 'fast-cache'),
@@ -12,4 +12,4 @@ cache({
},
],
ignoreIfFolderExists: false,
-})
+});
diff --git a/setupTestFramework.js b/setupTestFramework.js
index 00614510..7babb39e 100644
--- a/setupTestFramework.js
+++ b/setupTestFramework.js
@@ -1,4 +1,4 @@
-import * as emotion from 'emotion'
-import { createSerializer } from 'jest-emotion'
+import * as emotion from 'emotion';
+import { createSerializer } from 'jest-emotion';
-expect.addSnapshotSerializer(createSerializer(emotion))
+expect.addSnapshotSerializer(createSerializer(emotion));
diff --git a/website/.stylelintrc b/website/.stylelintrc
new file mode 100644
index 00000000..4f7a87c3
--- /dev/null
+++ b/website/.stylelintrc
@@ -0,0 +1,13 @@
+{
+ "extends": [
+ "stylelint-config-recommended"
+ ],
+ "rules": {
+ "at-rule-no-unknown": [true, {
+ "ignoreAtRules": ["/^neat/"]
+ }],
+ "no-descending-specificity": [true, {
+ "severity": "warning"
+ }]
+ }
+}
\ No newline at end of file
diff --git a/website/README.md b/website/README.md
index 3c175453..e3e89443 100755
--- a/website/README.md
+++ b/website/README.md
@@ -4,7 +4,7 @@ This directory builds netlifycms.org. If you'd like to propose changes to the si
## Local development
-The site is built with [GatsbyJS](https://gatsbyjs.org/).
+The site is built with [GatsbyJS](https://gatsbyjs.org/).
To run the site locally, you'll need to have [Node](https://nodejs.org) and [Yarn](https://yarnpkg.com/en/) installed on your computer.
diff --git a/website/content/blog/netlify-cms-2-0-launches-with-bitbucket-support-and-a-new-monorepo-architecture.md b/website/content/blog/netlify-cms-2-0-launches-with-bitbucket-support-and-a-new-monorepo-architecture.md
index 62be4d37..5fa5ce2b 100644
--- a/website/content/blog/netlify-cms-2-0-launches-with-bitbucket-support-and-a-new-monorepo-architecture.md
+++ b/website/content/blog/netlify-cms-2-0-launches-with-bitbucket-support-and-a-new-monorepo-architecture.md
@@ -9,19 +9,20 @@ description: >-
of features.
date: '2018-07-26'
---
-Today we’re releasing Netlify CMS 2.0, which adds support for using Bitbucket as a backend.
-With this release, [Netlify CMS](https://www.netlifycms.org/) now supports all major Git collaboration providers, adding Bitbucket to the list of supported providers which already includes GitLab and GitHub.
+Today we’re releasing Netlify CMS 2.0, which adds support for using Bitbucket as a backend.
-While you could already use Netlify CMS with most static site generators, our long-term vision is to be tool-agnostic so you can use whatever tool helps you work best. The latest release brings us one step closer by giving the option of an open source, Git-centric CMS to tens of thousands of businesses that depend on Bitbucket, including 60 of the Fortune 100.
+With this release, [Netlify CMS](https://www.netlifycms.org/) now supports all major Git collaboration providers, adding Bitbucket to the list of supported providers which already includes GitLab and GitHub.
+
+While you could already use Netlify CMS with most static site generators, our long-term vision is to be tool-agnostic so you can use whatever tool helps you work best. The latest release brings us one step closer by giving the option of an open source, Git-centric CMS to tens of thousands of businesses that depend on Bitbucket, including 60 of the Fortune 100.
## Becoming a Monorepo
The other big change with 2.0 is the migration from a single codebase to a collection of interdependent packages called a “monorepo”. Netlify CMS still lives in a [single repository on GitHub](https://github.com/netlify/netlify-cms), but the many extensions that were kept within Netlify CMS itself are now completely separate from the application core. This brings a few benefits:
-* Extension authors can easily copy an existing extension from the Netlify CMS repo and create a custom version.
-* Your custom extensions can now do anything the “official” extensions can do (because official extensions are no longer taking advantage of privileged internal code).
-* The monorepo approach provides a foundation that will encourage a more modular CMS, with shared parts that make extension authoring easier.
+- Extension authors can easily copy an existing extension from the Netlify CMS repo and create a custom version.
+- Your custom extensions can now do anything the “official” extensions can do (because official extensions are no longer taking advantage of privileged internal code).
+- The monorepo approach provides a foundation that will encourage a more modular CMS, with shared parts that make extension authoring easier.
## What’s next
diff --git a/website/content/blog/netlify-cms-now-supports-gitlab-as-a-backend.md b/website/content/blog/netlify-cms-now-supports-gitlab-as-a-backend.md
index 3a0e49ad..519acb75 100644
--- a/website/content/blog/netlify-cms-now-supports-gitlab-as-a-backend.md
+++ b/website/content/blog/netlify-cms-now-supports-gitlab-as-a-backend.md
@@ -4,24 +4,25 @@ author: Benaiah Mischenko
description: >-
Netlify CMS, the open source, headless CMS that provides a user-friendly UI
around your Git repository, can now be used with GitLab in addition to
- GitHub.
+ GitHub.
date: '2018-06-13'
---
-Netlify CMS is releasing support for GitLab as a backend, creating the world's first completely open source stack for Git-based content editing.
+
+Netlify CMS is releasing support for GitLab as a backend, creating the world's first completely open source stack for Git-based content editing.
VIDEO
-We heard [you](https://github.com/netlify/netlify-cms/pull/517#issuecomment-383283557) (and [you](https://github.com/netlify/netlify-cms/pull/517#issuecomment-355386542), and [you](https://github.com/netlify/netlify-cms/pull/517#issuecomment-343569725), and [you](https://github.com/netlify/netlify-cms/pull/517#issuecomment-333629637))! While you want to use Netlify CMS as the headless content management system for your JAMstack projects, all of your code lives in GitLab. Our long-term vision is to be tool-agnostic so you can use whatever tool helps you work best. But while you can already use Netlify CMS with most static site generators, backend support was limited to GitHub.
+We heard [you](https://github.com/netlify/netlify-cms/pull/517#issuecomment-383283557) (and [you](https://github.com/netlify/netlify-cms/pull/517#issuecomment-355386542), and [you](https://github.com/netlify/netlify-cms/pull/517#issuecomment-343569725), and [you](https://github.com/netlify/netlify-cms/pull/517#issuecomment-333629637))! While you want to use Netlify CMS as the headless content management system for your JAMstack projects, all of your code lives in GitLab. Our long-term vision is to be tool-agnostic so you can use whatever tool helps you work best. But while you can already use Netlify CMS with most static site generators, backend support was limited to GitHub.
-Immediately after the December release of Netlify CMS 1.0, contributors got to work on improving the API for backend integrations. At the urging of the community, we prioritized support for GitLab. With today’s release of Netlify CMS 1.9.0, you can now use GitLab as the backend for Netlify CMS.
+Immediately after the December release of Netlify CMS 1.0, contributors got to work on improving the API for backend integrations. At the urging of the community, we prioritized support for GitLab. With today’s release of Netlify CMS 1.9.0, you can now use GitLab as the backend for Netlify CMS.
-Adding support for GitLab means that millions more developers can now use Netlify CMS with their projects. Seriously — millions. GitLab is used by more than 100,000 organizations like Ticketmaster, Intel, Red Hat, and CERN.
+Adding support for GitLab means that millions more developers can now use Netlify CMS with their projects. Seriously — millions. GitLab is used by more than 100,000 organizations like Ticketmaster, Intel, Red Hat, and CERN.
## How it works
Netlify CMS is an open source content management system for your Git workflow that enables you to provide editors with a friendly UI and intuitive workflow. You can use it with any static site generator to create faster, more flexible web projects. Content is stored in your GitLab repository alongside your code for easier versioning, multi-channel publishing, and the option to handle content updates directly in Git.
-In case you want an even easier way to get started, or just want to poke around in the code, you can use the button below to automatically deploy a starter site that uses the Hugo static site generator along with Netlify CMS.
+In case you want an even easier way to get started, or just want to poke around in the code, you can use the button below to automatically deploy a starter site that uses the Hugo static site generator along with Netlify CMS.
diff --git a/website/content/docs/add-to-your-site.md b/website/content/docs/add-to-your-site.md
index c41df6f7..df8cec91 100755
--- a/website/content/docs/add-to-your-site.md
+++ b/website/content/docs/add-to-your-site.md
@@ -60,19 +60,19 @@ npm install netlify-cms --save
Then import it (assuming your project has tooling for imports):
```js
-import CMS from 'netlify-cms'
+import CMS from 'netlify-cms';
// Now the registry is available via the CMS object.
-CMS.registerPreviewTemplate('my-template', MyTemplate)
+CMS.registerPreviewTemplate('my-template', MyTemplate);
```
## Configuration
-Configuration will be different for every site, so we'll break it down into parts. All code snippets in this section will be added to your `admin/config.yml` file.
+Configuration will be different for every site, so we'll break it down into parts. All code snippets in this section will be added to your `admin/config.yml` file.
### Backend
-We're using [Netlify](https://www.netlify.com) for our hosting and authentication in this tutorial, so backend configuration is fairly straightforward.
+We're using [Netlify](https://www.netlify.com) for our hosting and authentication in this tutorial, so backend configuration is fairly straightforward.
For GitHub and GitLab repositories, you can start your Netlify CMS `config.yml` file with these lines:
@@ -103,7 +103,7 @@ Netlify CMS allows users to upload images directly within the editor. For this t
```yaml
# This line should *not* be indented
-media_folder: "images/uploads" # Media files will be stored in the repo under images/uploads
+media_folder: 'images/uploads' # Media files will be stored in the repo under images/uploads
```
If you're creating a new folder for uploaded media, you'll need to know where your static site generator expects static files. You can refer to the paths outlined above in [App File Structure](#app-file-structure), and put your media folder in the same location where you put the `admin` folder.
@@ -112,14 +112,13 @@ Note that the`media_folder` file path is relative to the project root, so the ex
```yaml
# These lines should *not* be indented
-media_folder: "static/images/uploads" # Media files will be stored in the repo under static/images/uploads
-public_folder: "/images/uploads" # The src attribute for uploaded media will begin with /images/uploads
+media_folder: 'static/images/uploads' # Media files will be stored in the repo under static/images/uploads
+public_folder: '/images/uploads' # The src attribute for uploaded media will begin with /images/uploads
```
The configuration above adds a new setting, `public_folder`. While `media_folder` specifies where uploaded files will be saved in the repo, `public_folder` indicates where they can be found in the published site. This path is used in image `src` attributes and is relative to the file where it's called. For this reason, we usually start the path at the site root, using the opening `/`.
-*If `public_folder` is not set, Netlify CMS will default to the same value as `media_folder`, adding an opening `/` if one is not included.*
-
+_If `public_folder` is not set, Netlify CMS will default to the same value as `media_folder`, adding an opening `/` if one is not included._
### Collections
@@ -128,14 +127,12 @@ Collections define the structure for the different content types on your static
Let's say your site has a blog, with the posts stored in `_posts/blog`, and files saved in a date-title format, like `1999-12-31-lets-party.md`. Each post begins with settings in yaml-formatted front matter, like so:
```yaml
----
layout: blog
title: "Let's Party"
date: 1999-12-31 11:59:59 -0800
-thumbnail: "/images/prince.jpg"
+thumbnail: '/images/prince.jpg'
rating: 5
----
-
+...
This is the post body, where I write about our last chance to party before the Y2K bug destroys us all.
```
@@ -143,18 +140,18 @@ Given this example, our `collections` settings would look like this:
```yaml
collections:
- - name: "blog" # Used in routes, e.g., /admin/collections/blog
- label: "Blog" # Used in the UI
- folder: "_posts/blog" # The path to the folder where the documents are stored
+ - name: 'blog' # Used in routes, e.g., /admin/collections/blog
+ label: 'Blog' # Used in the UI
+ folder: '_posts/blog' # The path to the folder where the documents are stored
create: true # Allow users to create new documents in this collection
- slug: "{{year}}-{{month}}-{{day}}-{{slug}}" # Filename template, e.g., YYYY-MM-DD-title.md
+ slug: '{{year}}-{{month}}-{{day}}-{{slug}}' # Filename template, e.g., YYYY-MM-DD-title.md
fields: # The fields for each document, usually in front matter
- - {label: "Layout", name: "layout", widget: "hidden", default: "blog"}
- - {label: "Title", name: "title", widget: "string"}
- - {label: "Publish Date", name: "date", widget: "datetime"}
- - {label: "Featured Image", name: "thumbnail", widget: "image"}
- - {label: "Rating (scale of 1-5)", name: "rating", widget: "number"}
- - {label: "Body", name: "body", widget: "markdown"}
+ - { label: 'Layout', name: 'layout', widget: 'hidden', default: 'blog' }
+ - { label: 'Title', name: 'title', widget: 'string' }
+ - { label: 'Publish Date', name: 'date', widget: 'datetime' }
+ - { label: 'Featured Image', name: 'thumbnail', widget: 'image' }
+ - { label: 'Rating (scale of 1-5)', name: 'rating', widget: 'number' }
+ - { label: 'Body', name: 'body', widget: 'markdown' }
```
Let's break that down:
@@ -205,14 +202,14 @@ The entries for any collection can be filtered based on the value of a single fi
```yaml
collections:
- - name: "posts"
- label: "Post"
- folder: "_posts"
+ - name: 'posts'
+ label: 'Post'
+ folder: '_posts'
filter:
field: language
value: en
fields:
- - {label: "Language", name: "language"}
+ - { label: 'Language', name: 'language' }
```
## Authentication
diff --git a/website/content/docs/architecture.md b/website/content/docs/architecture.md
index c0cea65a..05715d32 100755
--- a/website/content/docs/architecture.md
+++ b/website/content/docs/architecture.md
@@ -14,9 +14,10 @@ The structure of an entry is defined as a series of fields, each with a `name`,
The `widget` determines the UI widget that the content editor will use when editing this field of an entry, as well as how the content of the field is presented in the editing preview.
-Entries are loaded and persisted through a `backend` that will typically represent a `git` repository.
+Entries are loaded and persisted through a `backend` that will typically represent a `git` repository.
## State shape / reducers
+
**Auth:** Keeps track of the logged state and the current user.
**Config:** Holds the environment configuration (backend type, available collections and fields).
@@ -28,6 +29,7 @@ Entries are loaded and persisted through a `backend` that will typically represe
**EntryDraft:** Reused for each entry that is edited or created. It holds the entry's temporary data until it's persisted on the backend.
## Selectors
+
Selectors are functions defined within reducers used to compute derived data from the Redux store. The available selectors are:
**selectEntry:** Selects a single entry, given the collection and a slug.
@@ -37,6 +39,7 @@ Selectors are functions defined within reducers used to compute derived data fro
**getAsset:** Selects a single AssetProxy object for the given URI.
## Value Objects
+
**AssetProxy:** AssetProxy is a Value Object that holds information regarding an asset file (such as an image, for example), whether it's persisted online or held locally in cache.
For a file persisted online, the AssetProxy only keeps information about its URI. For local files, the AssetProxy will keep a reference to the actual File object while generating the expected final URIs and on-demand blobs for local preview.
@@ -44,26 +47,28 @@ For a file persisted online, the AssetProxy only keeps information about its URI
The AssetProxy object can be used directly inside a media tag (such as `
`), as it will always return something that can be used by the media tag to render correctly (either the URI for the online file or a single-use blob).
## Components structure and Workflows
+
Components are separated into two main categories: Container components and Presentational components.
### Entry Editing
+
For either updating an existing entry or creating a new one, the `EntryEditor` is used and the flow is the same:
-* When mounted, the `EntryPage` container component dispatches the `createDraft` action, setting the `entryDraft` state to a blank state (in case of a new entry) or to a copy of the selected entry (in case of an edit).
-* The `EntryPage` will also render widgets for each field type in the given entry.
-* Widgets are used for editing entry fields. There are different widgets for different field types, and they are always defined in a pair containing a `control` and a `preview` component. The control component is responsible for presenting the user with the appropriate interface for manipulating the current field value, while the preview component is responsible for displaying the value with the appropriate styling.
+- When mounted, the `EntryPage` container component dispatches the `createDraft` action, setting the `entryDraft` state to a blank state (in case of a new entry) or to a copy of the selected entry (in case of an edit).
+- The `EntryPage` will also render widgets for each field type in the given entry.
+- Widgets are used for editing entry fields. There are different widgets for different field types, and they are always defined in a pair containing a `control` and a `preview` component. The control component is responsible for presenting the user with the appropriate interface for manipulating the current field value, while the preview component is responsible for displaying the value with the appropriate styling.
#### Widget components implementation
+
The control component receives one (1) callback as a prop: `onChange`.
-* onChange (required): Should be called when the users changes the current value. It will ultimately end up updating the EntryDraft object in the Redux Store, thus updating the preview component.
-* onAddAsset & onRemoveAsset (optionals): If the field accepts file uploads for media (images, for example), these callbacks should be invoked with a `AssetProxy` value object. `onAddAsset` will get the current media stored in the Redux state tree while `onRemoveAsset` will remove it. AssetProxy objects are stored in the `Medias` object and referenced in the `EntryDraft` object on the state tree.
+- onChange (required): Should be called when the users changes the current value. It will ultimately end up updating the EntryDraft object in the Redux Store, thus updating the preview component.
+- onAddAsset & onRemoveAsset (optionals): If the field accepts file uploads for media (images, for example), these callbacks should be invoked with a `AssetProxy` value object. `onAddAsset` will get the current media stored in the Redux state tree while `onRemoveAsset` will remove it. AssetProxy objects are stored in the `Medias` object and referenced in the `EntryDraft` object on the state tree.
Both control and preview widgets receive a `getAsset` selector via props. Displaying the media (or its URI) for the user should always be done via `getAsset`, as it returns an AssetProxy that can return the correct value for both medias already persisted on the server and cached media not yet uploaded.
The actual persistence of the content and medias inserted into the control component is delegated to the backend implementation. The backend will be called with the updated values and a list of assetProxy objects for each field of the entry, and should return a promise that can resolve into the persisted entry object and the list of the persisted media URIs.
-
## Editorial Workflow implementation
Instead of adding logic to `CollectionPage` and `EntryPage`, the Editorial Workflow is implemented as Higher Order Components, adding UI and dispatching additional actions.
diff --git a/website/content/docs/authentication-backends.md b/website/content/docs/authentication-backends.md
index a4b1eb77..f44fc8f0 100644
--- a/website/content/docs/authentication-backends.md
+++ b/website/content/docs/authentication-backends.md
@@ -18,13 +18,13 @@ To use it in your own project stored on GitHub or GitLab, follow these steps:
steps to get started.
2. Add the following lines to your Netlify CMS `config.yml` file:
- ```yaml
- backend:
- name: git-gateway
- accept_roles: #optional - accepts all users if left out
- - admin
- - editor
- ```
+ ```yaml
+ backend:
+ name: git-gateway
+ accept_roles: #optional - accepts all users if left out
+ - admin
+ - editor
+ ```
3. Optionally, you can assign roles to users in your Netlify dashboard, and then limit which
roles can access the CMS by defining the `accept_roles` field as shown in the example above.
@@ -50,11 +50,11 @@ To enable it:
docs](https://www.netlify.com/docs/authentication-providers/#using-an-authentication-provider).
2. Add the following lines to your Netlify CMS `config.yml` file:
- ```yaml
- backend:
- name: github
- repo: owner-name/repo-name # Path to your GitHub repository
- ```
+ ```yaml
+ backend:
+ name: github
+ repo: owner-name/repo-name # Path to your GitHub repository
+ ```
If you prefer to run your own authentication server, check out the section on [external OAuth clients](#external-oauth-clients).
@@ -72,14 +72,14 @@ To enable it:
1. Follow the [GitLab docs](https://docs.gitlab.com/ee/integration/oauth_provider.html#adding-an-application-through-the-profile) to add your Netlify CMS instance as an OAuth application. For the **Redirect URI**, enter `https://api.netlify.com/auth/done`, and check the box for `api` scope.
2. Follow the [Netlify
- docs](https://www.netlify.com/docs/authentication-providers/#using-an-authentication-provider) to add your new GitLab Application ID and Secret to your Netlify site dashboard.
-2. In your repository, add the following lines to your Netlify CMS `config.yml` file:
+ docs](https://www.netlify.com/docs/authentication-providers/#using-an-authentication-provider) to add your new GitLab Application ID and Secret to your Netlify site dashboard.
+3. In your repository, add the following lines to your Netlify CMS `config.yml` file:
- ```yaml
- backend:
- name: gitlab
- repo: owner-name/repo-name # Path to your GitLab repository
- ```
+ ```yaml
+ backend:
+ name: gitlab
+ repo: owner-name/repo-name # Path to your GitLab repository
+ ```
### Client-Side Implicit Grant
@@ -88,26 +88,26 @@ With GitLab's Implicit Grant, users can authenticate with GitLab directly from t
1. Follow the [GitLab docs](https://docs.gitlab.com/ee/integration/oauth_provider.html#adding-an-application-through-the-profile) to add your Netlify CMS instance as an OAuth application. For the **Redirect URI**, enter the address where you access Netlify CMS, for example, `https://www.mysite.com/admin/`. For scope, select `api`.
2. GitLab will give you an **Application ID**. Copy this and enter it in your Netlify CMS `config.yml` file, along with the following settings:
- ```yaml
- backend:
- name: gitlab
- repo: owner-name/repo-name # Path to your GitLab repository
- auth_type: implicit # Required for implicit grant
- app_id: your-app-id # Application ID from your GitLab settings
- ```
+ ```yaml
+ backend:
+ name: gitlab
+ repo: owner-name/repo-name # Path to your GitLab repository
+ auth_type: implicit # Required for implicit grant
+ app_id: your-app-id # Application ID from your GitLab settings
+ ```
- You can also use Implicit Grant with a self-hosted GitLab instance. This requires adding `api_root`, `base_url`, and `auth_endpoint` fields:
+ You can also use Implicit Grant with a self-hosted GitLab instance. This requires adding `api_root`, `base_url`, and `auth_endpoint` fields:
- ```yaml
- backend:
- name: gitlab
- repo: owner-name/repo-name # Path to your GitLab repository
- auth_type: implicit # Required for implicit grant
- app_id: your-app-id # Application ID from your GitLab settings
- api_root: https://my-hosted-gitlab-instance.com/api/v4
- base_url: https://my-hosted-gitlab-instance.com
- auth_endpoint: oauth/authorize
- ```
+ ```yaml
+ backend:
+ name: gitlab
+ repo: owner-name/repo-name # Path to your GitLab repository
+ auth_type: implicit # Required for implicit grant
+ app_id: your-app-id # Application ID from your GitLab settings
+ api_root: https://my-hosted-gitlab-instance.com/api/v4
+ base_url: https://my-hosted-gitlab-instance.com
+ auth_endpoint: oauth/authorize
+ ```
Note that in both cases, GitLab will also provide you with a client secret. You should _never_ store this in your repo or reveal it in the client.
@@ -121,11 +121,11 @@ To enable it:
docs](https://www.netlify.com/docs/authentication-providers/#using-an-authentication-provider).
2. Add the following lines to your Netlify CMS `config.yml` file:
- ```yaml
- backend:
- name: bitbucket
- repo: owner-name/repo-name # Path to your Bitbucket repository
- ```
+ ```yaml
+ backend:
+ name: bitbucket
+ repo: owner-name/repo-name # Path to your Bitbucket repository
+ ```
## External OAuth Clients
@@ -145,12 +145,12 @@ Check each project's documentation for instructions on how to configure it.
Netlify CMS backends allow some additional fields for certain use cases. A full reference is below. Note that these are properties of the `backend` field, and should be nested under that field.
-| Field | Default | Description |
-| --------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `repo` | none | **Required** for `github`, `gitlab`, and `bitbucket` backends; ignored by `git-gateway`. Follows the pattern `[org-or-username]/[repo-name]`. |
-| `accept_roles` | none | `git-gateway` only. Limits CMS access to your defined array of user roles. Omitting this field gives access to all registered users. |
-| `branch` | `master` | The branch where published content is stored. All CMS commits and PRs are made to this branch. |
-| `api_root` | `https://api.github.com` (GitHub), `https://gitlab.com/api/v4` (GitLab), or `https://api.bitbucket.org/2.0` (Bitbucket) | The API endpoint. Only necessary in certain cases, like with GitHub Enterprise or self-hosted GitLab. |
-| `site_domain` | `location.hostname` (or `cms.netlify.com` when on `localhost`) | Sets the `site_id` query param sent to the API endpoint. Non-Netlify auth setups will often need to set this for local development to work properly. |
-| `base_url` | `https://api.netlify.com` (GitHub, Bitbucket) or `https://gitlab.com` (GitLab) | OAuth client URL. **Required** when using an external OAuth server or self-hosted GitLab. |
-| `auth_endpoint` | `auth` (GitHub, Bitbucket) or `oauth/authorize` (GitLab) | Path to append to `base_url` for authentication requests. Optional. |
+| Field | Default | Description |
+| --------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `repo` | none | **Required** for `github`, `gitlab`, and `bitbucket` backends; ignored by `git-gateway`. Follows the pattern `[org-or-username]/[repo-name]`. |
+| `accept_roles` | none | `git-gateway` only. Limits CMS access to your defined array of user roles. Omitting this field gives access to all registered users. |
+| `branch` | `master` | The branch where published content is stored. All CMS commits and PRs are made to this branch. |
+| `api_root` | `https://api.github.com` (GitHub), `https://gitlab.com/api/v4` (GitLab), or `https://api.bitbucket.org/2.0` (Bitbucket) | The API endpoint. Only necessary in certain cases, like with GitHub Enterprise or self-hosted GitLab. |
+| `site_domain` | `location.hostname` (or `cms.netlify.com` when on `localhost`) | Sets the `site_id` query param sent to the API endpoint. Non-Netlify auth setups will often need to set this for local development to work properly. |
+| `base_url` | `https://api.netlify.com` (GitHub, Bitbucket) or `https://gitlab.com` (GitLab) | OAuth client URL. **Required** when using an external OAuth server or self-hosted GitLab. |
+| `auth_endpoint` | `auth` (GitHub, Bitbucket) or `oauth/authorize` (GitLab) | Path to append to `base_url` for authentication requests. Optional. |
diff --git a/website/content/docs/beta-features.md b/website/content/docs/beta-features.md
index 8b276448..3775dde8 100644
--- a/website/content/docs/beta-features.md
+++ b/website/content/docs/beta-features.md
@@ -9,6 +9,7 @@ We run new functionality in an open beta format from time to time. That means th
**Use these features at your own risk.**
## Custom Mount Element
+
Netlify CMS always creates it's own DOM element for mounting the application, which means it always
takes over the entire page, and is generally inflexible if you're trying to do something creative,
like injecting it into a shared context.
@@ -18,6 +19,7 @@ as `nc-root`. If Netlify CMS finds an element with this ID during initialization
within that element instead of creating it's own.
## Manual Initialization
+
Netlify CMS can now be manually initialized, rather than automatically loading up the moment you import it. The whole point of this at the moment is to inject configuration into Netlify CMS before it loads, bypassing need for an actual Netlify CMS `config.yml`. This is important, for example, when creating tight integrations with static site generators.
Injecting config is technically already possible by setting `window.CMS_CONFIG` before importing/requiring/running Netlify CMS, but most projects are modular and don't want to use globals, plus `window.CMS_CONFIG` is an internal, not technically supported, and provides no validation.
@@ -65,6 +67,7 @@ CMS.registerPreviewTemplate(...);
```
## Raw CSS in `registerPreviewStyle`
+
`registerPreviewStyle` can now accept a CSS string, in addition to accepting a url. The feature is activated by passing in an object as the second argument, with `raw` set to a truthy value.This is critical for integrating with modern build tooling. Here's an example using webpack:
```js
@@ -73,12 +76,13 @@ CMS.registerPreviewTemplate(...);
* Takes advantage of the `toString` method in the return value of `css-loader`.
*/
import CMS from 'netlify-cms';
-import styles from '!css-loader!sass-loader!../main.scss'
+import styles from '!css-loader!sass-loader!../main.scss';
-CMS.registerPreviewStyle(styles.toString(), { raw: true })
+CMS.registerPreviewStyle(styles.toString(), { raw: true });
```
## Squash merge GitHub pull requests
+
When using the [Editorial Workflow](/docs/configuration-options/#publish-mode) with the `github` or GitHub-connected `git-gateway` backends, Netlify CMS creates a pull request for each unpublished entry. Every time the unpublished entry is changed and saved, a new commit is added to the pull request. When the entry is published, the pull request is merged, and all of those commits are added to your project commit history in a merge commit.
The squash merge option causes all commits to be "squashed" into a single commit when the pull request is merged, and the resulting commit is rebased onto the target branch, avoiding the merge commit altogether.
@@ -91,6 +95,7 @@ backend:
```
## Commit Message Templates
+
You can customize the templates used by Netlify CMS to generate commit messages by setting the `commit_messages` option under `backend` in your Netlify CMS `config.yml`.
Template tags wrapped in curly braces will be expanded to include information about the file changed by the commit. For example, `{{path}}` will include the full path to the file changed.
@@ -109,13 +114,13 @@ backend:
Netlify CMS generates the following commit types:
-Commit type | When is it triggered? | Available template tags
---------------|------------------------------|-----------------------------
-`create` | A new entry is created | `slug`, `path`, `collection`
-`update` | An existing entry is changed | `slug`, `path`, `collection`
-`delete` | An exising entry is deleted | `slug`, `path`, `collection`
-`uploadMedia` | A media file is uploaded | `path`
-`deleteMedia` | A media file is deleted | `path`
+| Commit type | When is it triggered? | Available template tags |
+| ------------- | ---------------------------- | ---------------------------- |
+| `create` | A new entry is created | `slug`, `path`, `collection` |
+| `update` | An existing entry is changed | `slug`, `path`, `collection` |
+| `delete` | An exising entry is deleted | `slug`, `path`, `collection` |
+| `uploadMedia` | A media file is uploaded | `path` |
+| `deleteMedia` | A media file is deleted | `path` |
Template tags produce the following output:
diff --git a/website/content/docs/collection-types.md b/website/content/docs/collection-types.md
index d1db9c9b..8df4bdfd 100644
--- a/website/content/docs/collection-types.md
+++ b/website/content/docs/collection-types.md
@@ -19,15 +19,15 @@ Unlike file collections, folder collections have the option to allow editors to
Example:
```yaml
-- label: "Blog"
- name: "blog"
- folder: "_posts/blog"
+- label: 'Blog'
+ name: 'blog'
+ folder: '_posts/blog'
create: true
fields:
- - {label: "Title", name: "title", widget: "string"}
- - {label: "Publish Date", name: "date", widget: "datetime"}
- - {label: "Featured Image", name: "thumbnail", widget: "image"}
- - {label: "Body", name: "body", widget: "markdown"}
+ - { label: 'Title', name: 'title', widget: 'string' }
+ - { label: 'Publish Date', name: 'date', widget: 'datetime' }
+ - { label: 'Featured Image', name: 'thumbnail', widget: 'image' }
+ - { label: 'Body', name: 'body', widget: 'markdown' }
```
### Filtered folder collections
@@ -36,29 +36,29 @@ The entries for any folder collection can be filtered based on the value of a si
The `filter` option requires two fields:
-* `field`: the name of the collection field to filter on
-* `value`: the desired field value
+- `field`: the name of the collection field to filter on
+- `value`: the desired field value
The example below creates two collections in the same folder, filtered by the `language` field. The first collection includes posts with `language: en`, and the second, with `language: es`.
```yaml
collections:
- - label: "Blog in English"
- name: "english_posts"
- folder: "_posts"
- filter: {field: "language", value: "en"}
+ - label: 'Blog in English'
+ name: 'english_posts'
+ folder: '_posts'
+ filter: { field: 'language', value: 'en' }
fields:
- - {label: "Language", name: "language", widget: "select", options: ["en", "es"]}
- - {label: "Title", name: "title", widget: "string"}
- - {label: "Content", name: "body", widget: "markdown"}
- - label: "Blog en Español"
- name: "spanish_posts"
- folder: "_posts"
- filter: {field: "language", value: "es"}
+ - { label: 'Language', name: 'language', widget: 'select', options: ['en', 'es'] }
+ - { label: 'Title', name: 'title', widget: 'string' }
+ - { label: 'Content', name: 'body', widget: 'markdown' }
+ - label: 'Blog en Español'
+ name: 'spanish_posts'
+ folder: '_posts'
+ filter: { field: 'language', value: 'es' }
fields:
- - {label: "Lenguaje", name: "language", widget: "select", options: ["en", "es"]}
- - {label: "Titulo", name: "title", widget: "string"}
- - {label: "Contenido", name: "body", widget: "markdown"}
+ - { label: 'Lenguaje', name: 'language', widget: 'select', options: ['en', 'es'] }
+ - { label: 'Titulo', name: 'title', widget: 'string' }
+ - { label: 'Contenido', name: 'body', widget: 'markdown' }
```
## File collections
@@ -72,32 +72,32 @@ When configuring a `files` collection, each file in the collection is configured
Example:
```yaml
-- label: "Pages"
- name: "pages"
+- label: 'Pages'
+ name: 'pages'
files:
- - label: "About Page"
- name: "about"
- file: "site/content/about.yml"
+ - label: 'About Page'
+ name: 'about'
+ file: 'site/content/about.yml'
fields:
- - {label: Title, name: title, widget: string}
- - {label: Intro, name: intro, widget: markdown}
+ - { label: Title, name: title, widget: string }
+ - { label: Intro, name: intro, widget: markdown }
- label: Team
name: team
widget: list
fields:
- - {label: Name, name: name, widget: string}
- - {label: Position, name: position, widget: string}
- - {label: Photo, name: photo, widget: image}
- - label: "Locations Page"
- name: "locations"
- file: "site/content/locations.yml"
+ - { label: Name, name: name, widget: string }
+ - { label: Position, name: position, widget: string }
+ - { label: Photo, name: photo, widget: image }
+ - label: 'Locations Page'
+ name: 'locations'
+ file: 'site/content/locations.yml'
fields:
- - {label: Title, name: title, widget: string}
- - {label: Intro, name: intro, widget: markdown}
+ - { label: Title, name: title, widget: string }
+ - { label: Intro, name: intro, widget: markdown }
- label: Locations
name: locations
widget: list
fields:
- - {label: Name, name: name, widget: string}
- - {label: Address, name: address, widget: string}
+ - { label: Name, name: name, widget: string }
+ - { label: Address, name: address, widget: string }
```
diff --git a/website/content/docs/configuration-options.md b/website/content/docs/configuration-options.md
index a912871c..d5dcdca0 100644
--- a/website/content/docs/configuration-options.md
+++ b/website/content/docs/configuration-options.md
@@ -18,14 +18,12 @@ To see working configuration examples, you can [start from a template](https://w
You can find details about all configuration options below. Note that [YAML syntax](https://en.wikipedia.org/wiki/YAML#Basic_components) allows lists and objects to be written in block or inline style, and the code samples below include a mix of both.
-
## Backend
-*This setting is required.*
+_This setting is required._
The `backend` option specifies how to access the content for your site, including authentication. Full details and code samples can be found in [Authentication & Backends](https://www.netlifycms.org/docs/authentication-backends).
-
## Publish Mode
By default, all entries created or edited in the Netlify CMS are committed directly into the main repository branch.
@@ -42,16 +40,15 @@ publish_mode: editorial_workflow
From a technical perspective, the workflow translates editor UI actions into common Git commands:
-Actions in Netlify UI ... | Perform these Git actions
---- | ---
-Save draft | Commits to a new branch (named according to the pattern `cms/collectionName-entrySlug`), and opens a pull request
-Edit draft | Pushes another commit to the draft branch/pull request
-Approve and publish draft | Merges pull request and deletes branch
-
+| Actions in Netlify UI ... | Perform these Git actions |
+| ------------------------- | ----------------------------------------------------------------------------------------------------------------- |
+| Save draft | Commits to a new branch (named according to the pattern `cms/collectionName-entrySlug`), and opens a pull request |
+| Edit draft | Pushes another commit to the draft branch/pull request |
+| Approve and publish draft | Merges pull request and deletes branch |
## Media and Public Folders
-*This setting is required.*
+_This setting is required._
Netlify CMS users can upload files to your repository using the Media Gallery. The following settings specify where these files are saved, and where they can be accessed on your built site.
@@ -62,9 +59,9 @@ Netlify CMS users can upload files to your repository using the Media Gallery. T
**Example**
-``` yaml
-media_folder: "static/images/uploads"
-public_folder: "/images/uploads"
+```yaml
+media_folder: 'static/images/uploads'
+public_folder: '/images/uploads'
```
Based on the settings above, if a user used an image widget field called `avatar` to upload and select an image called `philosoraptor.png`, the image would be saved to the repository at `/static/images/uploads/philosoraptor.png`, and the `avatar` field for the file would be set to `/images/uploads/philosoraptor.png`.
@@ -92,15 +89,15 @@ The `slug` option allows you to change how filenames for entries are created and
**Example**
-``` yaml
+```yaml
slug:
- encoding: "ascii"
+ encoding: 'ascii'
clean_accents: true
```
## Collections
-*This setting is required.*
+_This setting is required._
The `collections` setting is the heart of your Netlify CMS configuration, as it determines how content types and editor fields in the UI generate files and content in your repository. Each collection you configure displays in the left sidebar of the Content page of the editor UI, in the order they are entered into your Netlify CMS `config.yml` file.
@@ -136,13 +133,12 @@ You may also specify a custom `extension` not included in the list above, as lon
- `toml`: parses and saves files as TOML-formatted data files; saves with `toml` extension by default
- `json`: parses and saves files as JSON-formatted data files; saves with `json` extension by default
- `frontmatter`: parses files and saves files with data frontmatter followed by an unparsed body text (edited using a `body` field); saves with `md` extension by default; default for collections that can't be inferred. Collections with `frontmatter` format (either inferred or explicitly set) can parse files with frontmatter in YAML, TOML, or JSON format. However, they will be saved with YAML frontmatter.
-- `yaml-frontmatter`: same as the `frontmatter` format above, except frontmatter will be both parsed and saved only as YAML, followed by unparsed body text. The default delimiter for this option is `---`.
-- `toml-frontmatter`: same as the `frontmatter` format above, except frontmatter will be both parsed and saved only as TOML, followed by unparsed body text. The default delimiter for this option is `+++`.
-- `json-frontmatter`: same as the `frontmatter` format above, except frontmatter will be both parsed and saved as JSON, followed by unparsed body text. The default delimiter for this option is `{` `}`.
+- `yaml-frontmatter`: same as the `frontmatter` format above, except frontmatter will be both parsed and saved only as YAML, followed by unparsed body text. The default delimiter for this option is `---`.
+- `toml-frontmatter`: same as the `frontmatter` format above, except frontmatter will be both parsed and saved only as TOML, followed by unparsed body text. The default delimiter for this option is `+++`.
+- `json-frontmatter`: same as the `frontmatter` format above, except frontmatter will be both parsed and saved as JSON, followed by unparsed body text. The default delimiter for this option is `{` `}`.
`frontmatter_delimiter`: if you have an explicit frontmatter format declared, this option allows you to specify a custom delimiter like `~~~`. If you need different beginning and ending delimiters, you can use an array like `["(", ")"]`.
-
### `slug`
For folder collections where users can create new items, the `slug` option specifies a template for generating new filenames based on a file's creation date and `title` field. (This means that all collections with `create: true` must have a `title` field.)
@@ -160,7 +156,7 @@ For folder collections where users can create new items, the `slug` option speci
**Example:**
```yaml
-slug: "{{year}}-{{month}}-{{day}}_{{slug}}"
+slug: '{{year}}-{{month}}-{{day}}_{{slug}}'
```
### `fields`
@@ -182,13 +178,13 @@ In files with frontmatter, one field should be named `body`. This special field
```yaml
fields:
- - label: "Title"
- name: "title"
- widget: "string"
- pattern: ['.{20,}', "Must have at least 20 characters"]
- - {label: "Layout", name: "layout", widget: "hidden", default: "blog"}
- - {label: "Featured Image", name: "thumbnail", widget: "image", required: false}
- - {label: "Body", name: "body", widget: "markdown"}
+ - label: 'Title'
+ name: 'title'
+ widget: 'string'
+ pattern: ['.{20,}', 'Must have at least 20 characters']
+ - { label: 'Layout', name: 'layout', widget: 'hidden', default: 'blog' }
+ - { label: 'Featured Image', name: 'thumbnail', widget: 'image', required: false }
+ - { label: 'Body', name: 'body', widget: 'markdown' }
```
### `editor`
@@ -200,6 +196,6 @@ This setting changes options for the editor view of the collection. It has one o
**Example:**
```yaml
- editor:
- preview: false
+editor:
+ preview: false
```
diff --git a/website/content/docs/contributor-guide.md b/website/content/docs/contributor-guide.md
index 56f54851..6e076c3e 100644
--- a/website/content/docs/contributor-guide.md
+++ b/website/content/docs/contributor-guide.md
@@ -8,8 +8,8 @@ We're hoping that Netlify CMS will do for the [JAMstack](https://www.jamstack.or
While we work on building this page (and you can help!), here are some links with more information about getting involved:
-* [Setup instructions and Contribution Guidelines](https://github.com/netlify/netlify-cms/blob/master/CONTRIBUTING.md)
-* [Join us on Gitter](https://gitter.im/netlify/NetlifyCMS)
-* [Code of Conduct](https://github.com/netlify/netlify-cms/blob/master/CODE_OF_CONDUCT.md)
-* [Project Milestones](https://github.com/netlify/netlify-cms/milestones)
-* [Good First Issues](https://github.com/netlify/netlify-cms/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22+-label%3Aclaimed)
+- [Setup instructions and Contribution Guidelines](https://github.com/netlify/netlify-cms/blob/master/CONTRIBUTING.md)
+- [Join us on Gitter](https://gitter.im/netlify/NetlifyCMS)
+- [Code of Conduct](https://github.com/netlify/netlify-cms/blob/master/CODE_OF_CONDUCT.md)
+- [Project Milestones](https://github.com/netlify/netlify-cms/milestones)
+- [Good First Issues](https://github.com/netlify/netlify-cms/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22+-label%3Aclaimed)
diff --git a/website/content/docs/custom-widgets.md b/website/content/docs/custom-widgets.md
index b13ebeea..8e4507a7 100644
--- a/website/content/docs/custom-widgets.md
+++ b/website/content/docs/custom-widgets.md
@@ -6,8 +6,8 @@ group: guides
The NetlifyCMS exposes a `window.CMS` global object that you can use to register custom widgets, previews, and editor plugins. The same object is also the default export if you import Netify CMS as an npm module. The available widget extension methods are:
-* **registerWidget:** lets you register a custom widget.
-* **registerEditorComponent:** lets you add a block component to the Markdown editor.
+- **registerWidget:** lets you register a custom widget.
+- **registerEditorComponent:** lets you add a block component to the Markdown editor.
### Writing React Components inline
@@ -30,17 +30,17 @@ CMS.registerWidget(name, control, [preview]);
**Params:**
-| Param | Type | Description |
-| ----------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `name` | `string` | Widget name, allows this widget to be used via the field `widget` property in config |
-| `control` | `React.Component` or `string`|
React component that renders the control, receives the following props: **value:** Current field value **onChange:** Callback function to update the field value Name of a registered widget whose control should be used (includes built in widgets). |
-| [`preview`] | `React.Component`, optional | Renders the widget preview, receives the following props:
**value:** Current preview value **field:** Immutable map of current field configuration **metadata:** Immutable map of any available metadata for the current field **getAsset:** Function for retrieving an asset url for image/file fields **entry:** Immutable Map of all entry data **fieldsMetaData:** Immutable map of metadata from all fields. |
+| Param | Type | Description |
+| ----------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `name` | `string` | Widget name, allows this widget to be used via the field `widget` property in config |
+| `control` | `React.Component` or `string` |
React component that renders the control, receives the following props: **value:** Current field value **onChange:** Callback function to update the field value Name of a registered widget whose control should be used (includes built in widgets). |
+| [`preview`] | `React.Component`, optional | Renders the widget preview, receives the following props:
**value:** Current preview value **field:** Immutable map of current field configuration **metadata:** Immutable map of any available metadata for the current field **getAsset:** Function for retrieving an asset url for image/file fields **entry:** Immutable Map of all entry data **fieldsMetaData:** Immutable map of metadata from all fields. |
-* **field:** The field type that this widget will be used for.
-* **control:** A React component that renders the editing interface for this field. Two props will be passed:
- * **value:** The current value for this field.
- * **onChange:** Callback function to update the field value.
-* **preview (optional):** A React component that renders the preview of how the content will look. A `value` prop will be passed to this component.
+- **field:** The field type that this widget will be used for.
+- **control:** A React component that renders the editing interface for this field. Two props will be passed:
+ - **value:** The current value for this field.
+ - **onChange:** Callback function to update the field value.
+- **preview (optional):** A React component that renders the preview of how the content will look. A `value` prop will be passed to this component.
**Example:**
@@ -77,12 +77,12 @@ CMS.registerWidget('categories', CategoriesControl, CategoriesPreview);
Register a block level component for the Markdown editor:
```js
-CMS.registerEditorComponent(definition)
+CMS.registerEditorComponent(definition);
```
**Params**
-* **definition:** The component definition; must specify: id, label, fields, patterns, fromBlock, toBlock, toPreview
+- **definition:** The component definition; must specify: id, label, fields, patterns, fromBlock, toBlock, toPreview
**Example:**
@@ -133,38 +133,38 @@ With custom widgets, the widget control can also optionally implement an `isVali
No errors:
```javascript
- isValid = () => {
- // Do internal validation
- return true;
- };
+isValid = () => {
+ // Do internal validation
+ return true;
+};
```
Existing error:
```javascript
- isValid = () => {
- // Do internal validation
- return false;
- };
+isValid = () => {
+ // Do internal validation
+ return false;
+};
```
**Object with `error` (useful for returning custom error messages)**
Existing error:
```javascript
- isValid = () => {
- // Do internal validation
- return { error: 'Your error message.' };
- };
+isValid = () => {
+ // Do internal validation
+ return { error: 'Your error message.' };
+};
```
**Promise**
You can also return a promise from `isValid`. While the promise is pending, the widget will be marked as "in error". When the promise resolves, the error is automatically cleared.
```javascript
- isValid = () => {
- return this.existingPromise;
- };
+isValid = () => {
+ return this.existingPromise;
+};
```
Note: Do not create a promise inside `isValid` - `isValid` is called right before trying to persist. This means that even if a previous promise was already resolved, when the user hits 'save', `isValid` will be called again. If it returns a new promise, it will be immediately marked as "in error" until the new promise resolves.
diff --git a/website/content/docs/customization.md b/website/content/docs/customization.md
index 0d7a1176..6cb87e1d 100644
--- a/website/content/docs/customization.md
+++ b/website/content/docs/customization.md
@@ -6,8 +6,8 @@ group: guides
The NetlifyCMS exposes a `window.CMS` global object that you can use to register custom widgets, previews and editor plugins. The available customization methods are:
-* **registerPreviewStyle:** Register a custom stylesheet to use on the preview pane.
-* **registerPreviewTemplate:** Registers a template for a collection.
+- **registerPreviewStyle:** Register a custom stylesheet to use on the preview pane.
+- **registerPreviewTemplate:** Registers a template for a collection.
Explore the [NetlifyCMS GitHub example](https://github.com/netlify/netlify-cms/blob/9ced3f16c8bcc3d1a36773b126842d023c589eaf/example/index.html#L90-L91), a working example you can review on GitHub.
@@ -25,7 +25,7 @@ CMS.registerPreviewStyle(file);
**Params:**
-* **file:** css file path
+- **file:** css file path
**Example:**
@@ -60,12 +60,13 @@ Registers a template for a collection.
**Params:**
-* collection: The name of the collection which this preview component will be used for.
-* react_component: A React component that renders the collection data. Four props will be passed to your component during render:
- * entry: Immutable collection containing the entry data.
- * widgetFor: Returns the appropriate widget preview component for a given field.
- * [widgetsFor](#lists-and-objects): Returns an array of objects with widgets and associated field data. For use with list and object type entries.
- * getAsset: Returns the correct filePath or in-memory preview for uploaded images.
+- collection: The name of the collection which this preview component will be used for.
+- react_component: A React component that renders the collection data. Four props will be passed to your component during render:
+
+ - entry: Immutable collection containing the entry data.
+ - widgetFor: Returns the appropriate widget preview component for a given field.
+ - [widgetsFor](#lists-and-objects): Returns an array of objects with widgets and associated field data. For use with list and object type entries.
+ - getAsset: Returns the correct filePath or in-memory preview for uploaded images.
**Example:**
```html
@@ -87,7 +88,9 @@ Registers a template for a collection.
CMS.registerPreviewTemplate("posts", PostPreview);
```
+
### Lists and Objects
+
The API for accessing the individual fields of list- and object-type entries is similar to the API
for accessing fields in standard entries, but there are a few key differences. Access to these
nested fields is facilitated through the `widgetsFor` function, which is passed to the preview
@@ -96,6 +99,7 @@ Registers a template for a collection.
Immutable.js. If some of the methods that we use are unfamiliar, such as `getIn`, check out
[their docs](https://facebook.github.io/immutable-js/docs/#/) to get a better understanding.
**List Example:**
+
```html
```
+
**Object Example:**
+
```html
```
+
### Accessing Metadata
- Preview Components also receive an additional prop: `fieldsMetaData`. It contains aditional information (besides the plain plain textual value of each field) that can be useful for preview purposes.
+
+ Preview Components also receive an additional prop: `fieldsMetaData`. It contains aditional information (besides the plain plain textual value of each field) that can be useful for preview purposes.
For example, the Relation widget passes the whole selected relation data in `fieldsMetaData`.
+
```js
export default class ArticlePreview extends React.Component {
render() {
- const {entry, fieldsMetaData} = this.props;
+ const { entry, fieldsMetaData } = this.props;
const author = fieldsMetaData.getIn(['authors', data.author]);
- return
{ entry.getIn(['data', 'title']) }
- {author &&}
-
+ return (
+
+ {entry.getIn(['data', 'title'])}
+ {author && }
+
+ );
}
}
```
diff --git a/website/content/docs/examples.md b/website/content/docs/examples.md
index bf47c32f..9a05dceb 100644
--- a/website/content/docs/examples.md
+++ b/website/content/docs/examples.md
@@ -6,10 +6,10 @@ group: start
Do you have a great, open source example? Submit a pull request to this page!
-Example | Tools | Type | Source | More info |
---- | --- | --- | --- | ---
-[This Developing Journey](https://briandouglas.me) | middleman | blog | [bdougie/blog](https://github.com/bdougie/blog) | [blog post](https://www.netlify.com/blog/2017/04/20/creating-a-blog-with-middleman-and-netlify-cms/)
-[JAMstack Recipes](https://jamstack-cms.netlify.com) | Hugo, Azure | demo | [hlaueriksson/jamstack-cms](https://github.com/hlaueriksson/jamstack-cms) | [blog post](http://conductofcode.io/post/managing-content-for-a-jamstack-site-with-netlify-cms/)
-[The Ragasirtahk Blog](https://www.ragasirtahk.tk/) | Hugo | blog | [ragasirtahk/the-ragasirtahk-blog](https://github.com/ragasirtahk/the-ragasirtahk-blog) | [blog post](https://www.ragasirtahk.tk/2018/01/setting-up-netlify-cms-on-hugo/)
-[Forest Garden Wales](https://www.forestgarden.wales/) | Hugo | blog | [forestgardenwales/forestgarden.wales](https://github.com/forestgardenwales/forestgarden.wales) | [blog post](https://www.forestgarden.wales/blog/now-using-netlify-cms/)
-[Cup of Data](https://www.cupofdata.com/blog) | Gatsby | blog | [cupofdata/cupofdata.com](https://github.com/cupofdata/cupofdata.com) | -
+| Example | Tools | Type | Source | More info |
+| ------------------------------------------------------ | ----------- | ---- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
+| [This Developing Journey](https://briandouglas.me) | middleman | blog | [bdougie/blog](https://github.com/bdougie/blog) | [blog post](https://www.netlify.com/blog/2017/04/20/creating-a-blog-with-middleman-and-netlify-cms/) |
+| [JAMstack Recipes](https://jamstack-cms.netlify.com) | Hugo, Azure | demo | [hlaueriksson/jamstack-cms](https://github.com/hlaueriksson/jamstack-cms) | [blog post](http://conductofcode.io/post/managing-content-for-a-jamstack-site-with-netlify-cms/) |
+| [The Ragasirtahk Blog](https://www.ragasirtahk.tk/) | Hugo | blog | [ragasirtahk/the-ragasirtahk-blog](https://github.com/ragasirtahk/the-ragasirtahk-blog) | [blog post](https://www.ragasirtahk.tk/2018/01/setting-up-netlify-cms-on-hugo/) |
+| [Forest Garden Wales](https://www.forestgarden.wales/) | Hugo | blog | [forestgardenwales/forestgarden.wales](https://github.com/forestgardenwales/forestgarden.wales) | [blog post](https://www.forestgarden.wales/blog/now-using-netlify-cms/) |
+| [Cup of Data](https://www.cupofdata.com/blog) | Gatsby | blog | [cupofdata/cupofdata.com](https://github.com/cupofdata/cupofdata.com) | - |
diff --git a/website/content/docs/intro.md b/website/content/docs/intro.md
index e6efc807..e9bc8068 100755
--- a/website/content/docs/intro.md
+++ b/website/content/docs/intro.md
@@ -8,13 +8,12 @@ Netlify CMS is an open source content management system for your Git workflow th
At its core, Netlify CMS is an open-source React app that acts as a wrapper for the Git workflow, using the GitHub, GitLab, or Bitbucket API. This provides many advantages, including:
-* **Fast, web-based UI:** with rich-text editing, real-time preview, and drag-and-drop media uploads.
-* **Platform agnostic:** works with most static site generators.
-* **Easy installation:** add two files to your site and hook up the backend by including in your build process or linking to our CDN.
-* **Modern authentication:** using GitHub, GitLab, or Bitbucket and JSON web tokens.
-* **Flexible content types:** specify an unlimited number of content types with custom fields.
-* **Fully extensible:** create custom-styled previews, UI widgets, and editor plugins.
-
+- **Fast, web-based UI:** with rich-text editing, real-time preview, and drag-and-drop media uploads.
+- **Platform agnostic:** works with most static site generators.
+- **Easy installation:** add two files to your site and hook up the backend by including in your build process or linking to our CDN.
+- **Modern authentication:** using GitHub, GitLab, or Bitbucket and JSON web tokens.
+- **Flexible content types:** specify an unlimited number of content types with custom fields.
+- **Fully extensible:** create custom-styled previews, UI widgets, and editor plugins.
## Find out more
diff --git a/website/content/docs/start-with-a-template.md b/website/content/docs/start-with-a-template.md
index 7f971d33..f172b304 100644
--- a/website/content/docs/start-with-a-template.md
+++ b/website/content/docs/start-with-a-template.md
@@ -25,11 +25,11 @@ After clicking one of those buttons, you’ll authenticate with GitHub or GitLab
1. The template deploy process will send you an invitation to your new site, sent from `no-reply@netlify.com`.
- ![Sample email subject line: You've been invited to join radiologist-amanda-53841.netlify.com](https://www.netlifycms.org/img/email-subject.png?raw=true)
+ ![Sample email subject line: You've been invited to join radiologist-amanda-53841.netlify.com](https://www.netlifycms.org/img/email-subject.png?raw=true)
2. Click the link to accept the invite, and you’ll be directed to your site, with a prompt to create a password.
- !["Complete your signup" modal on the Kaldi coffee site](https://www.netlifycms.org/img/create-password.png?raw=true)
+ !["Complete your signup" modal on the Kaldi coffee site](https://www.netlifycms.org/img/create-password.png?raw=true)
3. Enter a password, sign in, and you’ll be directed straight to the CMS. (For future visits, you can go straight to `
/admin/`.)
diff --git a/website/content/docs/update-the-cms-version.md b/website/content/docs/update-the-cms-version.md
index b6650ae9..cd35917c 100644
--- a/website/content/docs/update-the-cms-version.md
+++ b/website/content/docs/update-the-cms-version.md
@@ -15,11 +15,12 @@ If you are using a package manager like Yarn or NPM, you will use their standard
If you are using the CMS through a CDN like Unpkg, then that depends on the version tag you are using. You can find the version tag you are using in the `/admin/index.html` file of your site.
- (Recommended) If you use `^2.0.0`, the CMS will do all updates except major versions automatically.
- - It will upgrade to `2.0.1`, `2.1.0`, `2.1.2`.
- - It will not upgrade to `3.0.0` or higher.
- - It will not upgrade to beta versions.
+
+ - It will upgrade to `2.0.1`, `2.1.0`, `2.1.2`.
+ - It will not upgrade to `3.0.0` or higher.
+ - It will not upgrade to beta versions.
- If you use `~2.0.0`, the CMS will do only patch updates automatically.
- - It will upgrade `2.0.1`, `2.0.2`.
- - It will not upgrade to `2.1.0` or higher.
- - It will not upgrade beta versions.
+ - It will upgrade `2.0.1`, `2.0.2`.
+ - It will not upgrade to `2.1.0` or higher.
+ - It will not upgrade beta versions.
diff --git a/website/content/docs/widgets/boolean.md b/website/content/docs/widgets/boolean.md
index 083cee69..420c7a94 100644
--- a/website/content/docs/widgets/boolean.md
+++ b/website/content/docs/widgets/boolean.md
@@ -1,5 +1,5 @@
---
-label: "Boolean"
+label: 'Boolean'
target: boolean
---
@@ -13,5 +13,5 @@ The boolean widget translates a toggle switch input to a true/false value.
- **Example:**
```yaml
- - {label: "Draft", name: "draft", widget: "boolean", default: true}
+ - { label: 'Draft', name: 'draft', widget: 'boolean', default: true }
```
diff --git a/website/content/docs/widgets/date.md b/website/content/docs/widgets/date.md
index 42e6b273..f2c44257 100644
--- a/website/content/docs/widgets/date.md
+++ b/website/content/docs/widgets/date.md
@@ -1,5 +1,5 @@
---
-label: "Date"
+label: 'Date'
target: date
---
@@ -14,9 +14,9 @@ The date widget translates a date picker input to a date string. For saving date
- **Example:**
```yaml
- - label: "Birthdate"
- name: "birthdate"
- widget: "date"
- default: ""
- format: "MMM Do YY"
+ - label: 'Birthdate'
+ name: 'birthdate'
+ widget: 'date'
+ default: ''
+ format: 'MMM Do YY'
```
diff --git a/website/content/docs/widgets/datetime.md b/website/content/docs/widgets/datetime.md
index 65f2700b..c01ebe4d 100644
--- a/website/content/docs/widgets/datetime.md
+++ b/website/content/docs/widgets/datetime.md
@@ -1,5 +1,5 @@
---
-label: "DateTime"
+label: 'DateTime'
target: datetime
---
@@ -14,9 +14,9 @@ The datetime widget translates a datetime picker to a datetime string. For savin
- **Example:**
```yaml
- - label: "Start time"
- name: "start"
- widget: "datetime"
- default: ""
- format: "LLL"
+ - label: 'Start time'
+ name: 'start'
+ widget: 'datetime'
+ default: ''
+ format: 'LLL'
```
diff --git a/website/content/docs/widgets/file.md b/website/content/docs/widgets/file.md
index dbe3186c..11392cd2 100644
--- a/website/content/docs/widgets/file.md
+++ b/website/content/docs/widgets/file.md
@@ -1,5 +1,5 @@
---
-label: "File"
+label: 'File'
target: file
---
@@ -13,8 +13,8 @@ The file widget allows editors to upload a file or select an existing one from t
- **Example:**
```yaml
- - label: "Manual PDF"
- name: "manual_pdf"
- widget: "file"
- default: "/uploads/general-manual.pdf"
+ - label: 'Manual PDF'
+ name: 'manual_pdf'
+ widget: 'file'
+ default: '/uploads/general-manual.pdf'
```
diff --git a/website/content/docs/widgets/hidden.md b/website/content/docs/widgets/hidden.md
index 4e5fffeb..336049db 100644
--- a/website/content/docs/widgets/hidden.md
+++ b/website/content/docs/widgets/hidden.md
@@ -1,5 +1,5 @@
---
-label: "Hidden"
+label: 'Hidden'
target: hidden
---
@@ -8,10 +8,10 @@ Hidden widgets do not display in the UI. In folder collections that allow users
- **Name:** `hidden`
- **UI:** none
- **Data type:** any valid data type
-- **Options:**
+- **Options:**
- `default`: accepts any valid data type; recommended for collections that allow adding new items
- **Example:**
```yaml
- - {label: "Layout", name: "layout", widget: "hidden", default: "blog"}
+ - { label: 'Layout', name: 'layout', widget: 'hidden', default: 'blog' }
```
diff --git a/website/content/docs/widgets/image.md b/website/content/docs/widgets/image.md
index 4af9f8bf..f0d0b5c8 100644
--- a/website/content/docs/widgets/image.md
+++ b/website/content/docs/widgets/image.md
@@ -1,5 +1,5 @@
---
-label: "Image"
+label: 'Image'
target: image
---
@@ -13,8 +13,8 @@ The image widget allows editors to upload an image or select an existing one fro
- **Example:**
```yaml
- - label: "Featured Image"
- name: "thumbnail"
- widget: "image"
- default: "/uploads/chocolate-dogecoin.jpg"
+ - label: 'Featured Image'
+ name: 'thumbnail'
+ widget: 'image'
+ default: '/uploads/chocolate-dogecoin.jpg'
```
diff --git a/website/content/docs/widgets/index.md b/website/content/docs/widgets/index.md
index ede4a16f..2270f758 100644
--- a/website/content/docs/widgets/index.md
+++ b/website/content/docs/widgets/index.md
@@ -10,20 +10,20 @@ Widgets are specified as collection fields in the Netlify CMS `config.yml` file.
To see working examples of all of the built-in widgets, try making a 'Kitchen Sink' collection item on the [CMS demo site](https://cms-demo.netlify.com). (No login required: click the login button and the CMS will open.) You can refer to the demo [configuration code](https://github.com/netlify/netlify-cms/blob/master/packages/netlify-cms/example/config.yml) to see how each field was configured.
-
## Common widget options
The following options are available on all fields:
- `required`: specify as `false` to make a field optional; defaults to `true`
- `pattern`: add field validation by specifying a list with a [regex pattern](https://regexr.com/) and an error message; more extensive validation can be achieved with [custom widgets](https://www.netlifycms.org/docs/custom-widgets/#advanced-field-validation)
+
- **Example:**
```yaml
- - label: "Title"
- name: "title"
- widget: "string"
- pattern: [".{12,}", "Must have at least 12 characters"]
+ - label: 'Title'
+ name: 'title'
+ widget: 'string'
+ pattern: ['.{12,}', 'Must have at least 12 characters']
```
## Default widgets
diff --git a/website/content/docs/widgets/list.md b/website/content/docs/widgets/list.md
index 41181f29..6d733e17 100644
--- a/website/content/docs/widgets/list.md
+++ b/website/content/docs/widgets/list.md
@@ -1,5 +1,5 @@
---
-label: "List"
+label: 'List'
target: list
---
@@ -16,44 +16,44 @@ The list widget allows you to create a repeatable item in the UI which saves as
- **Example** (`field`/`fields` not specified):
```yaml
- - label: "Tags"
- name: "tags"
- widget: "list"
- default: ["news"]
+ - label: 'Tags'
+ name: 'tags'
+ widget: 'list'
+ default: ['news']
```
- **Example** (`allow_add` marked `false`):
```yaml
- - label: "Tags"
- name: "tags"
- widget: "list"
+ - label: 'Tags'
+ name: 'tags'
+ widget: 'list'
allow_add: false
- default: ["news"]
+ default: ['news']
```
- **Example** (with `field`):
```yaml
- - label: "Gallery"
- name: "galleryImages"
- widget: "list"
+ - label: 'Gallery'
+ name: 'galleryImages'
+ widget: 'list'
field:
- - {label: Image, name: image, widget: image}
+ - { label: Image, name: image, widget: image }
```
- **Example** (with `fields`):
```yaml
- - label: "Testimonials"
- name: "testimonials"
- widget: "list"
+ - label: 'Testimonials'
+ name: 'testimonials'
+ widget: 'list'
fields:
- - {label: Quote, name: quote, widget: string, default: "Everything is awesome!"}
+ - { label: Quote, name: quote, widget: string, default: 'Everything is awesome!' }
- label: Author
name: author
widget: object
fields:
- - {label: Name, name: name, widget: string, default: "Emmet"}
- - {label: Avatar, name: avatar, widget: image, default: "/img/emmet.jpg"}
+ - { label: Name, name: name, widget: string, default: 'Emmet' }
+ - { label: Avatar, name: avatar, widget: image, default: '/img/emmet.jpg' }
```
diff --git a/website/content/docs/widgets/markdown.md b/website/content/docs/widgets/markdown.md
index 2df28322..c5b52ffb 100644
--- a/website/content/docs/widgets/markdown.md
+++ b/website/content/docs/widgets/markdown.md
@@ -1,11 +1,11 @@
---
-label: "Markdown"
+label: 'Markdown'
target: markdown
---
The markdown widget provides a full fledged text editor - which is based on [slate](https://github.com/ianstormtaylor/slate) - that allows users to format text with features such as headings and blockquotes. Users are also allowed to write in markdown by simply flipping a switch.
-*Please note:* in case you want to use your markdown editor to fill a markdown's file content after the frontmatter, you'll have name the field as `body` so then the CMS can recognize it and save the file accordingly.
+_Please note:_ in case you want to use your markdown editor to fill a markdown's file content after the frontmatter, you'll have name the field as `body` so then the CMS can recognize it and save the file accordingly.
- **Name:** `markdown`
- **UI:** full text editor
@@ -16,10 +16,9 @@ The markdown widget provides a full fledged text editor - which is based on [sla
- **Example:**
```yaml
- - {label: "Blog post content", name: "body", widget: "markdown"}
+ - { label: 'Blog post content', name: 'body', widget: 'markdown' }
```
This would render as:
![Markdown widget example](/img/widgets-markdown.png)
-
diff --git a/website/content/docs/widgets/number.md b/website/content/docs/widgets/number.md
index 383f35f4..aaa3f5ba 100644
--- a/website/content/docs/widgets/number.md
+++ b/website/content/docs/widgets/number.md
@@ -1,5 +1,5 @@
---
-label: "Number"
+label: 'Number'
target: number
---
@@ -16,11 +16,11 @@ The number widget uses an HTML number input, saving the value as a string, integ
- **Example:**
```yaml
- - label: "Puppy Count"
- name: "puppies"
- widget: "number"
+ - label: 'Puppy Count'
+ name: 'puppies'
+ widget: 'number'
default: 2
- valueType: "int"
+ valueType: 'int'
min: 1
max: 101
```
diff --git a/website/content/docs/widgets/object.md b/website/content/docs/widgets/object.md
index fb3eb6c8..fbb1b715 100644
--- a/website/content/docs/widgets/object.md
+++ b/website/content/docs/widgets/object.md
@@ -1,5 +1,5 @@
---
-label: "Object"
+label: 'Object'
target: object
---
@@ -14,22 +14,22 @@ The object widget allows you to group multiple widgets together, nested under a
- **Example:**
```yaml
- - label: "Profile"
- name: "profile"
- widget: "object"
+ - label: 'Profile'
+ name: 'profile'
+ widget: 'object'
fields:
- - {label: "Public", name: "public", widget: "boolean", default: true}
- - {label: "Name", name: "name", widget: "string"}
- - label: "Birthdate"
- name: "birthdate"
- widget: "date"
- default: ""
- format: "MM/DD/YYYY"
- - label: "Address"
- name: "address"
- widget: "object"
- fields:
- - {label: "Street Address", name: "street", widget: "string"}
- - {label: "City", name: "city", widget: "string"}
- - {label: "Postal Code", name: "post-code", widget: "string"}
+ - { label: 'Public', name: 'public', widget: 'boolean', default: true }
+ - { label: 'Name', name: 'name', widget: 'string' }
+ - label: 'Birthdate'
+ name: 'birthdate'
+ widget: 'date'
+ default: ''
+ format: 'MM/DD/YYYY'
+ - label: 'Address'
+ name: 'address'
+ widget: 'object'
+ fields:
+ - { label: 'Street Address', name: 'street', widget: 'string' }
+ - { label: 'City', name: 'city', widget: 'string' }
+ - { label: 'Postal Code', name: 'post-code', widget: 'string' }
```
diff --git a/website/content/docs/widgets/relation.md b/website/content/docs/widgets/relation.md
index 6d5af6f4..e411453c 100644
--- a/website/content/docs/widgets/relation.md
+++ b/website/content/docs/widgets/relation.md
@@ -1,5 +1,5 @@
---
-label: "Relation"
+label: 'Relation'
target: relation
---
@@ -17,12 +17,13 @@ The relation widget allows you to reference items from another collection. It pr
- **Example** (assuming a separate "authors" collection with "name" and "twitterHandle" fields):
```yaml
- - label: "Post Author"
- name: "author"
- widget: "relation"
- collection: "authors"
- searchFields: ["name", "twitterHandle"]
- valueField: "name"
- displayFields: ["twitterHandle", "followerCount"]
+ - label: 'Post Author'
+ name: 'author'
+ widget: 'relation'
+ collection: 'authors'
+ searchFields: ['name', 'twitterHandle']
+ valueField: 'name'
+ displayFields: ['twitterHandle', 'followerCount']
```
+
The generated UI input will search the authors collection by name and twitterHandle, and display each author's handle and follower count. On selection, the author name will be saved for the field.
diff --git a/website/content/docs/widgets/select.md b/website/content/docs/widgets/select.md
index 2cf37ed7..46220d02 100644
--- a/website/content/docs/widgets/select.md
+++ b/website/content/docs/widgets/select.md
@@ -1,5 +1,5 @@
---
-label: "Select"
+label: 'Select'
target: select
---
@@ -11,25 +11,25 @@ The select widget allows you to pick a single string value from a dropdown menu.
- **Options:**
- `default`: accepts a string; defaults to an empty string
- `options`: (**required**) a list of options for the dropdown menu; can be listed in two ways:
- - string values: the label displayed in the dropdown is the value saved in the file
- - object with `label` and `value` fields: the label displays in the dropdown; the value is saved in the file
+ - string values: the label displayed in the dropdown is the value saved in the file
+ - object with `label` and `value` fields: the label displays in the dropdown; the value is saved in the file
- **Example** (options as strings):
```yaml
- - label: "Align Content"
- name: "align"
- widget: "select"
- options: ["left", "center", "right"]
+ - label: 'Align Content'
+ name: 'align'
+ widget: 'select'
+ options: ['left', 'center', 'right']
```
+
- **Example** (options as objects):
```yaml
- - label: "City"
- name: "airport-code"
- widget: "select"
+ - label: 'City'
+ name: 'airport-code'
+ widget: 'select'
options:
- - { label: "Chicago", value: "ORD" }
- - { label: "Paris", value: "CDG" }
- - { label: "Tokyo", value: "HND" }
+ - { label: 'Chicago', value: 'ORD' }
+ - { label: 'Paris', value: 'CDG' }
+ - { label: 'Tokyo', value: 'HND' }
```
-
diff --git a/website/content/docs/widgets/string.md b/website/content/docs/widgets/string.md
index bb5e8afb..346c8d00 100644
--- a/website/content/docs/widgets/string.md
+++ b/website/content/docs/widgets/string.md
@@ -1,5 +1,5 @@
---
-label: "String"
+label: 'String'
target: string
---
@@ -13,5 +13,5 @@ The string widget translates a basic text input to a string value. For larger te
- **Example:**
```yaml
- - {label: "Title", name: "title", widget: "string"}
+ - { label: 'Title', name: 'title', widget: 'string' }
```
diff --git a/website/content/docs/widgets/text.md b/website/content/docs/widgets/text.md
index f1e0392d..25332ef5 100644
--- a/website/content/docs/widgets/text.md
+++ b/website/content/docs/widgets/text.md
@@ -1,5 +1,5 @@
---
-label: "Text"
+label: 'Text'
target: text
---
@@ -13,6 +13,5 @@ The text widget takes a multiline text field and saves it as a string. For short
- **Example:**
```yaml
- - {label: "Description", name: "description", widget: "text"}
+ - { label: 'Description', name: 'description', widget: 'text' }
```
-
diff --git a/website/content/pages/community.md b/website/content/pages/community.md
index 3561904b..1d75a9f8 100644
--- a/website/content/pages/community.md
+++ b/website/content/pages/community.md
@@ -2,13 +2,16 @@
title: Community
headline: Be a part of building the CMS of the future.
-subhead: We’re serious about being community driven, so everyone is welcome to join the [community chat](https://gitter.im/netlify/NetlifyCMS), and to be a part of our bi-weekly planning sessions (details below).
-primarycta: "[Register on Eventbrite →](https://www.eventbrite.com/e/netlify-cms-planning-session-bi-weekly-tickets-35794058994)"
+subhead:
+ We’re serious about being community driven, so everyone is welcome to join the [community chat](https://gitter.im/netlify/NetlifyCMS), and to be a part of our bi-weekly planning sessions (details below).
+primarycta:
+ '[Register on Eventbrite →](https://www.eventbrite.com/e/netlify-cms-planning-session-bi-weekly-tickets-35794058994)'
upcomingevent:
hook: The next development planning session is on
-howitworks: Every other week we have public development planning sessions. They're web based, last about an hour, and are geared toward contributors and those interested in contributing. Sessions currently take place every other Wednesday, 9am - 10am PT.
+howitworks:
+ Every other week we have public development planning sessions. They're web based, last about an hour, and are geared toward contributors and those interested in contributing. Sessions currently take place every other Wednesday, 9am - 10am PT.
howtojoin: |
**On the web:**
diff --git a/website/data/global.yaml b/website/data/global.yaml
index e5addedc..9ce2adc4 100644
--- a/website/data/global.yaml
+++ b/website/data/global.yaml
@@ -1,6 +1,6 @@
footer:
buttons:
- - name: "Twitter"
- url: "https://twitter.com/netlifycms"
- - name: "GitHub"
- url: "https://github.com/netlify/netlify-cms"
+ - name: 'Twitter'
+ url: 'https://twitter.com/netlifycms'
+ - name: 'GitHub'
+ url: 'https://github.com/netlify/netlify-cms'
diff --git a/website/data/landing.yaml b/website/data/landing.yaml
index 460899c2..8bcac2ca 100644
--- a/website/data/landing.yaml
+++ b/website/data/landing.yaml
@@ -1,41 +1,52 @@
hero:
- headline: "Open source content management for your Git workflow"
- subhead: "Use Netlify CMS with any static site generator for a faster and more flexible web project"
+ headline: 'Open source content management for your Git workflow'
+ subhead:
+ 'Use Netlify CMS with any static site generator for a faster and more flexible web project'
devfeatures:
- - feature: "Static + content management = ♥"
- description: "Get the speed, security, and scalability of a static site, while still providing a convenient editing interface for content."
- - feature: "An integrated part of your Git workflow"
- description: "Content is stored in your Git repository alongside your code for easier versioning, multi-channel publishing, and the option to handle content updates directly in Git."
- - feature: "An extensible CMS built on React"
- description: "Netlify CMS is built as a single-page React app. Create custom-styled previews, UI widgets, and editor plugins or add backends to support different Git platform APIs."
+ - feature: 'Static + content management = ♥'
+ description:
+ 'Get the speed, security, and scalability of a static site, while still providing a convenient editing interface for content.'
+ - feature: 'An integrated part of your Git workflow'
+ description:
+ 'Content is stored in your Git repository alongside your code for easier versioning, multi-channel publishing, and the option to handle content updates directly in Git.'
+ - feature: 'An extensible CMS built on React'
+ description:
+ 'Netlify CMS is built as a single-page React app. Create custom-styled previews, UI widgets, and editor plugins or add backends to support different Git platform APIs.'
cta:
- primaryhook: "Getting started is simple and free."
- primary: "Choose a template that’s pre-configured with a static site generator and deploys to a global CDN in one click."
- button: "[Get started](/docs/start-with-a-template/)"
+ primaryhook: 'Getting started is simple and free.'
+ primary:
+ 'Choose a template that’s pre-configured with a static site generator and deploys to a global CDN in one click.'
+ button: '[Get started](/docs/start-with-a-template/)'
editors:
- hook: "A CMS that developers and content editors can agree on"
- intro: "You get to implement modern front end tools to deliver a faster, safer, and more scalable site. Editors get a friendly UI and intuitive workflow that meets their content management requirements."
+ hook: 'A CMS that developers and content editors can agree on'
+ intro:
+ 'You get to implement modern front end tools to deliver a faster, safer, and more scalable site. Editors get a friendly UI and intuitive workflow that meets their content management requirements.'
features:
- - feature: "Editor-friendly user interface"
- description: "The web-based app includes rich-text editing, real-time preview, and drag-and-drop media uploads."
- imgpath: "feature-editor.svg"
- - feature: "Intuitive workflow for content teams"
- description: "Writers and editors can easily manage content from draft to review to publish across any number of custom content types."
- imgpath: "feature-workflow.svg"
- - feature: "Instant access without GitHub account"
- description: "With [Git Gateway](/docs/authentication-backends/#git-gateway-with-netlify-identity), you can add CMS access for any team member — even if they don’t have a GitHub account. "
- imgpath: "feature-access.svg"
+ - feature: 'Editor-friendly user interface'
+ description:
+ 'The web-based app includes rich-text editing, real-time preview, and drag-and-drop media uploads.'
+ imgpath: 'feature-editor.svg'
+ - feature: 'Intuitive workflow for content teams'
+ description:
+ 'Writers and editors can easily manage content from draft to review to publish across any number of custom content types.'
+ imgpath: 'feature-workflow.svg'
+ - feature: 'Instant access without GitHub account'
+ description:
+ 'With [Git Gateway](/docs/authentication-backends/#git-gateway-with-netlify-identity), you can add CMS access for any team member — even if they don’t have a GitHub account. '
+ imgpath: 'feature-access.svg'
community:
- hook: "Supported by a growing community"
+ hook: 'Supported by a growing community'
features:
- - feature: "Built on the JAMstack"
- description: "Netlify CMS is based on client-side JavaScript, reusable APIs and prebuilt Markup. Compared to server-side CMS like WordPress, this means better performance, higher security, lower cost of scaling, and a better developer experience. You can learn more about the JAMstack on [jamstack.org](https://jamstack.org)."
- - feature: "Support when you need it"
- description: "Get up and running with comprehensive [documentation](/docs) and templates or work through difficult problems with help from the community on [Gitter](https://gitter.im/netlify/NetlifyCMS)."
- - feature: "A community-driven project you can help evolve"
- description: "Netlify CMS is built by a community of more than 100 contributors — and you can help. Join our [bi-weekly planning sessions](/community) or read the [contributing guide](/docs/contributor-guide) to join in."
- contributors: "Made possible by awesome contributors"
-
+ - feature: 'Built on the JAMstack'
+ description:
+ 'Netlify CMS is based on client-side JavaScript, reusable APIs and prebuilt Markup. Compared to server-side CMS like WordPress, this means better performance, higher security, lower cost of scaling, and a better developer experience. You can learn more about the JAMstack on [jamstack.org](https://jamstack.org).'
+ - feature: 'Support when you need it'
+ description:
+ 'Get up and running with comprehensive [documentation](/docs) and templates or work through difficult problems with help from the community on [Gitter](https://gitter.im/netlify/NetlifyCMS).'
+ - feature: 'A community-driven project you can help evolve'
+ description:
+ 'Netlify CMS is built by a community of more than 100 contributors — and you can help. Join our [bi-weekly planning sessions](/community) or read the [contributing guide](/docs/contributor-guide) to join in.'
+ contributors: 'Made possible by awesome contributors'
diff --git a/website/data/notifications.yml b/website/data/notifications.yml
index 8b54ffb9..3811d56e 100644
--- a/website/data/notifications.yml
+++ b/website/data/notifications.yml
@@ -1,28 +1,29 @@
notifications:
-- loud: true
- message: >-
- Register to join us online for our next community dev meeting, every other
- Wednesday at 9am-10am PT!
- published: false
- title: Netlify CMS Development Planning Sessions Promo
- url: >-
- https://www.eventbrite.com/e/netlify-cms-planning-session-bi-weekly-tickets-35794058994
-- loud: true
- message: >-
- We have a community on Gitter - join now to ask questions and discuss the
- project with other devs!
- published: false
- title: Gitter shoutout
- url: 'https://gitter.im/netlify/netlifycms'
-- loud: true
- message: >-
- Netlify CMS now supports GitLab!
- published: false
- title: GitLab announcement
- url: '/blog/2018/06/netlify-cms-now-supports-gitlab-as-a-backend/'
-- loud: true
- message: >-
- Announcing 2.0 - Bitbucket support and monorepo architecture!
- published: true
- title: 2.0 announcement
- url: '/blog/2018/07/netlify-cms-2-0-launches-with-bitbucket-support-and-a-new-monorepo-architecture'
+ - loud: true
+ message: >-
+ Register to join us online for our next community dev meeting, every other
+ Wednesday at 9am-10am PT!
+ published: false
+ title: Netlify CMS Development Planning Sessions Promo
+ url: >-
+ https://www.eventbrite.com/e/netlify-cms-planning-session-bi-weekly-tickets-35794058994
+ - loud: true
+ message: >-
+ We have a community on Gitter - join now to ask questions and discuss the
+ project with other devs!
+ published: false
+ title: Gitter shoutout
+ url: 'https://gitter.im/netlify/netlifycms'
+ - loud: true
+ message: >-
+ Netlify CMS now supports GitLab!
+ published: false
+ title: GitLab announcement
+ url: '/blog/2018/06/netlify-cms-now-supports-gitlab-as-a-backend/'
+ - loud: true
+ message: >-
+ Announcing 2.0 - Bitbucket support and monorepo architecture!
+ published: true
+ title: 2.0 announcement
+ url:
+ '/blog/2018/07/netlify-cms-2-0-launches-with-bitbucket-support-and-a-new-monorepo-architecture'
diff --git a/website/gatsby-browser.js b/website/gatsby-browser.js
index 16395bdf..48e480dd 100644
--- a/website/gatsby-browser.js
+++ b/website/gatsby-browser.js
@@ -5,6 +5,6 @@ exports.onClientEntry = () => {
new SmoothScroll('a[href*="#"]', {
offset() {
return document.querySelector('#header').offsetHeight;
- }
+ },
});
};
diff --git a/website/gatsby-config.js b/website/gatsby-config.js
index 4af8061b..4f57c791 100644
--- a/website/gatsby-config.js
+++ b/website/gatsby-config.js
@@ -15,7 +15,7 @@ const postCssPlugins = [
colorfunctions(),
hdBackgrounds(),
cssextend(),
- cssvars({ variables: styleVariables })
+ cssvars({ variables: styleVariables }),
];
module.exports = {
@@ -27,30 +27,30 @@ module.exports = {
docs: [
{
name: 'start',
- title: 'Quick Start'
+ title: 'Quick Start',
},
{
name: 'guides',
- title: 'Guides'
+ title: 'Guides',
},
{
name: 'reference',
- title: 'Reference'
+ title: 'Reference',
},
{
name: 'contributing',
- title: 'Contributing'
- }
- ]
- }
+ title: 'Contributing',
+ },
+ ],
+ },
},
plugins: [
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/content`,
- name: 'content'
- }
+ name: 'content',
+ },
},
'gatsby-transformer-yaml',
'gatsby-transformer-json',
@@ -58,8 +58,8 @@ module.exports = {
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/data`,
- name: 'data'
- }
+ name: 'data',
+ },
},
{
resolve: 'gatsby-transformer-remark',
@@ -69,13 +69,13 @@ module.exports = {
'gatsby-remark-autolink-headers',
'gatsby-remark-prismjs'
]
- }
+ },
},
{
resolve: 'gatsby-plugin-postcss-sass',
options: {
- postCssPlugins
- }
+ postCssPlugins,
+ },
},
'gatsby-plugin-react-helmet',
'gatsby-plugin-react-next',
@@ -89,8 +89,8 @@ module.exports = {
background_color: '#ffffff',
theme_color: '#ffffff',
display: 'standalone',
- icon: 'static/img/favicon/icon-512x512.png'
- }
- }
- ]
+ icon: 'static/img/favicon/icon-512x512.png',
+ },
+ },
+ ],
};
diff --git a/website/gatsby-node.js b/website/gatsby-node.js
index 7b6b8442..c7b4e484 100644
--- a/website/gatsby-node.js
+++ b/website/gatsby-node.js
@@ -43,8 +43,8 @@ exports.createPages = async ({ graphql, boundActionCreators }) => {
path: slug,
component: template,
context: {
- slug
- }
+ slug,
+ },
});
});
};
@@ -70,7 +70,7 @@ exports.onCreateNode = ({ node, boundActionCreators, getNode }) => {
createNodeField({
node,
name: 'date',
- value: date.toJSON()
+ value: date.toJSON(),
});
}
@@ -78,14 +78,14 @@ exports.onCreateNode = ({ node, boundActionCreators, getNode }) => {
createNodeField({
node,
name: 'slug',
- value: slug
+ value: slug,
});
// used to create GitHub edit link
createNodeField({
node,
name: 'path',
- value: relativePath
+ value: relativePath,
});
}
};
diff --git a/website/src/components/docs-nav.js b/website/src/components/docs-nav.js
index 4b0b1b5e..ba3ce3f6 100644
--- a/website/src/components/docs-nav.js
+++ b/website/src/components/docs-nav.js
@@ -9,7 +9,7 @@ import Link from 'gatsby-link';
*/
class TableOfContents extends Component {
state = {
- headings: []
+ headings: [],
};
componentDidMount() {
@@ -19,12 +19,12 @@ class TableOfContents extends Component {
contentHeadings.forEach(h => {
headings.push({
id: h.id,
- text: h.innerText
+ text: h.innerText,
});
});
this.setState({
- headings
+ headings,
});
}
@@ -52,10 +52,7 @@ const DocsNav = ({ items, location }) => (
{item.group.edges.map(({ node }) => (
-
+
{node.frontmatter.title}
{location.pathname === node.fields.slug && }
diff --git a/website/src/components/docsearch.js b/website/src/components/docsearch.js
index bd595bcd..116ed163 100644
--- a/website/src/components/docsearch.js
+++ b/website/src/components/docsearch.js
@@ -4,7 +4,7 @@ import searchIcon from '../img/search.svg';
class DocSearch extends Component {
state = {
- enabled: true
+ enabled: true,
};
componentDidMount() {
if (window.docsearch) {
@@ -12,7 +12,7 @@ class DocSearch extends Component {
apiKey: '08d03dc80862e84c70c5a1e769b13019',
indexName: 'netlifycms',
inputSelector: '.algolia-search',
- debug: false // Set debug to true if you want to inspect the dropdown
+ debug: false, // Set debug to true if you want to inspect the dropdown
});
} else {
this.setState({ enabled: false });
@@ -26,11 +26,7 @@ class DocSearch extends Component {
return (
-
+
);
}
diff --git a/website/src/components/edit-link.js b/website/src/components/edit-link.js
index ae338377..f8ea8bf3 100644
--- a/website/src/components/edit-link.js
+++ b/website/src/components/edit-link.js
@@ -3,7 +3,8 @@ import React from 'react';
const EditLink = ({ path }) => (
+ href={`https://github.com/netlify/netlify-cms/blob/master/website/content/${path}`}
+ >
(
height="14px"
viewBox="0 0 512 512"
enableBackground="new 0 0 512 512"
- xmlSpace="preserve">
+ xmlSpace="preserve"
+ >
@@ -60,10 +59,7 @@ class Header extends Component {
Docs
-
+
Contributing
diff --git a/website/src/components/markdownify.js b/website/src/components/markdownify.js
index e13baa4b..252c80fa 100644
--- a/website/src/components/markdownify.js
+++ b/website/src/components/markdownify.js
@@ -2,10 +2,7 @@ import React, { Fragment } from 'react';
import Markdown from 'react-markdown';
const Markdownify = ({ source }) => (
-
+
);
export default Markdownify;
diff --git a/website/src/components/mobile-nav.js b/website/src/components/mobile-nav.js
index 7463a9c5..5da281d4 100644
--- a/website/src/components/mobile-nav.js
+++ b/website/src/components/mobile-nav.js
@@ -14,10 +14,7 @@ class MobileNav extends Component {
{items.map(item => (
{item.group.edges.map(({ node }) => (
-
+
{node.frontmatter.title}
))}
diff --git a/website/src/components/video-embed.js b/website/src/components/video-embed.js
index 83f6e319..aa366c33 100644
--- a/website/src/components/video-embed.js
+++ b/website/src/components/video-embed.js
@@ -4,11 +4,11 @@ import screenshotEditor from '../img/screenshot-editor.jpg';
class VideoEmbed extends Component {
state = {
- toggled: false
+ toggled: false,
};
toggleVideo = () => {
this.setState({
- toggled: true
+ toggled: true,
});
};
render() {
@@ -25,9 +25,7 @@ class VideoEmbed extends Component {
/>
);
- const imgPlaceholder = (
-
- );
+ const imgPlaceholder = ;
return (
diff --git a/website/src/components/widgets.js b/website/src/components/widgets.js
index eb734c1c..970ebd56 100644
--- a/website/src/components/widgets.js
+++ b/website/src/components/widgets.js
@@ -5,28 +5,24 @@ import '../css/imports/widgets.css';
class Widgets extends Component {
state = {
- currentWidget: null
+ currentWidget: null,
};
componentDidMount() {
const { widgets } = this.props;
- const hash = window.location.hash
- ? window.location.hash.replace('#', '')
- : '';
+ const hash = window.location.hash ? window.location.hash.replace('#', '') : '';
- const widgetsContainHash = widgets.edges.some(
- w => w.node.frontmatter.target === hash
- );
+ const widgetsContainHash = widgets.edges.some(w => w.node.frontmatter.target === hash);
if (widgetsContainHash) {
return this.setState({
- currentWidget: hash
+ currentWidget: hash,
});
}
this.setState({
- currentWidget: widgets.edges[0].node.frontmatter.target
+ currentWidget: widgets.edges[0].node.frontmatter.target,
});
}
@@ -34,11 +30,11 @@ class Widgets extends Component {
event.preventDefault();
this.setState(
{
- currentWidget: target
+ currentWidget: target,
},
() => {
history.pushState(null, null, `#${target}`);
- }
+ },
);
};
@@ -56,7 +52,7 @@ class Widgets extends Component {
this.handleWidgetChange(event, target)}
>
@@ -72,7 +68,7 @@ class Widgets extends Component {
{label}
diff --git a/website/src/css/imports/base.css b/website/src/css/imports/base.css
index d25107dc..61fb3e24 100755
--- a/website/src/css/imports/base.css
+++ b/website/src/css/imports/base.css
@@ -1,4 +1,15 @@
-@import url(https://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,700,900|Roboto+Mono:400,700);
+@import url(
+ https://fonts.googleapis.com/css?family=Roboto:400,
+ 100,
+ 100italic,
+ 300,
+ 300italic,
+ 400italic,
+ 500,
+ 700,
+ 900|Roboto+Mono:400,
+ 700
+);
body {
background-color: $shadeBlue;
@@ -52,7 +63,8 @@ h3 {
margin: 0;
}
-p, ul {
+p,
+ul {
font-size: 18px;
line-height: 26px;
margin-top: 0;
@@ -79,7 +91,7 @@ ul {
}
}
-*[class^="btn-"] {
+*[class^='btn-'] {
border-radius: $borderRadius;
box-sizing: border-box;
display: inline-block;
@@ -92,7 +104,7 @@ ul {
overflow: hidden;
&:after {
- content: "";
+ content: '';
position: absolute;
top: -40%;
left: -210%;
@@ -100,13 +112,13 @@ ul {
height: 200%;
opacity: 0;
transform: rotate(30deg);
- background: rgba(255,255,255,0.2);
+ background: rgba(255, 255, 255, 0.2);
background: linear-gradient(
to right,
rgba(255, 255, 255, 0.2) 0%,
rgba(255, 255, 255, 0.2) 77%,
rgba(255, 255, 255, 0.6) 92%,
- rgba(255, 255, 255, 0.0) 100%
+ rgba(255, 255, 255, 0) 100%
);
}
diff --git a/website/src/css/imports/community.css b/website/src/css/imports/community.css
index 984d013f..1101a83d 100644
--- a/website/src/css/imports/community.css
+++ b/website/src/css/imports/community.css
@@ -49,9 +49,8 @@
}
img:hover {
transform: scale(1.3);
- box-shadow: 0 2px 6px 0 rgba(0,0,0,0.25), 0 4px 12px 0 rgba(0,0,0,0.25);
+ box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.25), 0 4px 12px 0 rgba(0, 0, 0, 0.25);
}
}
-
}
}
diff --git a/website/src/css/imports/cta.css b/website/src/css/imports/cta.css
index b1e717f3..b88592d4 100644
--- a/website/src/css/imports/cta.css
+++ b/website/src/css/imports/cta.css
@@ -1,5 +1,4 @@
.cta {
-
@media screen and (min-width: $desktop) {
position: relative;
top: -65px;
@@ -20,7 +19,7 @@
display: flex;
align-items: center;
justify-content: space-between;
- box-shadow: 0 10px 30px 0 rgba(28,30,30,0.10), 0 3px 9px 0 rgba(28,30,30,0.15);
+ box-shadow: 0 10px 30px 0 rgba(28, 30, 30, 0.1), 0 3px 9px 0 rgba(28, 30, 30, 0.15);
border-radius: $largeBorderRadius;
}
@@ -42,15 +41,14 @@
font-size: $tiny;
letter-spacing: 0.5px;
background-color: $blue;
- background-image: linear-gradient(-180deg, #4A7FDD 0%, #3A69C7 100%);
- box-shadow: 0 4px 12px 0 rgba(68,74,87,0.10), 0 1px 3px 0 rgba(68,74,87,0.20);
+ background-image: linear-gradient(-180deg, #4a7fdd 0%, #3a69c7 100%);
+ box-shadow: 0 4px 12px 0 rgba(68, 74, 87, 0.1), 0 1px 3px 0 rgba(68, 74, 87, 0.2);
border-radius: $borderRadius;
padding: 12px 18px 12px 18px;
- transition: .2s;
+ transition: 0.2s;
display: inline-block;
margin-top: $tiny;
-
@media screen and (min-width: $desktop) {
flex-shrink: 0;
margin: 0 0 0 $small;
@@ -58,14 +56,12 @@
&:hover {
transform: scale(1.05);
- box-shadow: 0 4px 12px 0 rgba(68,74,87,0.20), 0 1px 3px 0 rgba(68,74,87,0.40);
+ box-shadow: 0 4px 12px 0 rgba(68, 74, 87, 0.2), 0 1px 3px 0 rgba(68, 74, 87, 0.4);
}
&:active {
transform: scale(0.95);
box-shadow: none;
}
}
-
}
-
}
diff --git a/website/src/css/imports/docs.css b/website/src/css/imports/docs.css
index e1302472..64e4ff67 100644
--- a/website/src/css/imports/docs.css
+++ b/website/src/css/imports/docs.css
@@ -12,8 +12,8 @@
}
}
- .docs-nav {
- display: none;
+ .docs-nav {
+ display: none;
@media screen and (min-width: $tablet) {
display: block;
@@ -30,7 +30,7 @@
}
&:after {
- content: " ";
+ content: ' ';
position: absolute;
top: 7px;
right: 20px;
@@ -68,7 +68,7 @@
margin: 10px 0;
text-decoration: none;
text-transform: capitalize;
- transition: color .2s ease;
+ transition: color 0.2s ease;
&.active {
color: $darkGreen;
@@ -111,64 +111,63 @@
}
}
- h1,
- h2 {
- font-size: 36px;
- line-height: 48px;
+ h1,
+ h2 {
+ font-size: 36px;
+ line-height: 48px;
- &.intro-headline {
- padding: 0 $small;
- margin-bottom: 86px;
- }
- }
+ &.intro-headline {
+ padding: 0 $small;
+ margin-bottom: 86px;
+ }
+ }
h2 {
font-size: $small;
}
- h3 {
- color: $grey;
- font-size: 20px;
- margin-top: $medium;
+ h3 {
+ color: $grey;
+ font-size: 20px;
+ margin-top: $medium;
margin-bottom: $small;
- &.inverse {
- color: white;
- }
+ &.inverse {
+ color: white;
+ }
}
.meta-info {
font-size: $tiny;
}
-
- table {
- width: 100%;
- text-align: left;
- margin: 34px 0 $medium 0;
- th,
- td {
- padding: $micro;
- }
+ table {
+ width: 100%;
+ text-align: left;
+ margin: 34px 0 $medium 0;
- th {
- font-size: 18px;
- font-weight: $bold;
- }
+ th,
+ td {
+ padding: $micro;
+ }
- tbody tr {
- &:nth-child(odd) {
- background: #fdfdfd;
- }
- }
+ th {
+ font-size: 18px;
+ font-weight: $bold;
+ }
- td {
- font-size: 14px;
- }
+ tbody tr {
+ &:nth-child(odd) {
+ background: #fdfdfd;
+ }
+ }
+
+ td {
+ font-size: 14px;
+ }
}
}
-
.docs-content,
.blog-content {
font-size: 18px;
@@ -179,7 +178,7 @@
}
#pencil {
- fill: #7CA511;
+ fill: #7ca511;
}
@media screen and (min-width: $tablet) {
@@ -204,9 +203,9 @@
}
img {
- max-width: 100%;
- height: auto;
- }
+ max-width: 100%;
+ height: auto;
+ }
table {
background: #f7f7f7;
@@ -236,4 +235,4 @@
.blog-list-item h2 {
margin: 48px 0 0;
line-height: 36px;
-}
\ No newline at end of file
+}
diff --git a/website/src/css/imports/editors.css b/website/src/css/imports/editors.css
index 18a471bf..73f7bd85 100644
--- a/website/src/css/imports/editors.css
+++ b/website/src/css/imports/editors.css
@@ -6,7 +6,8 @@
text-align: center;
}
- h2, p {
+ h2,
+ p {
max-width: $desktop;
@media screen and (min-width: $desktop) {
@@ -45,7 +46,6 @@
@media screen and (max-width: $desktop) {
margin-top: $large;
}
-
}
}
}
diff --git a/website/src/css/imports/footer.css b/website/src/css/imports/footer.css
index c740de5a..07a21f36 100644
--- a/website/src/css/imports/footer.css
+++ b/website/src/css/imports/footer.css
@@ -12,7 +12,7 @@ footer {
color: $grey;
font-family: $roboto;
font-size: 12px;
- opacity: .5;
+ opacity: 0.5;
}
a {
color: $grey;
@@ -39,5 +39,4 @@ footer {
background-color: $darkerGreen;
}
}
-
}
diff --git a/website/src/css/imports/gitter.css b/website/src/css/imports/gitter.css
index ea5b1841..c222f4d9 100644
--- a/website/src/css/imports/gitter.css
+++ b/website/src/css/imports/gitter.css
@@ -7,16 +7,16 @@
letter-spacing: 0.5px;
color: $grey;
background-color: $green;
- box-shadow: 0 2px 16px 0 rgba(68,74,87,0.15), 0 1px 4px 0 rgba(68,74,87,0.30);
+ box-shadow: 0 2px 16px 0 rgba(68, 74, 87, 0.15), 0 1px 4px 0 rgba(68, 74, 87, 0.3);
}
&:hover {
background-color: $lightGreen;
- box-shadow: 0 2px 16px 0 rgba(68,74,87,0.25), 0 1px 4px 0 rgba(68,74,87,0.50);
+ box-shadow: 0 2px 16px 0 rgba(68, 74, 87, 0.25), 0 1px 4px 0 rgba(68, 74, 87, 0.5);
}
&:focus {
- box-shadow: 0 0 6px 3px rgba(62,160,127,.6);
+ box-shadow: 0 0 6px 3px rgba(62, 160, 127, 0.6);
transition: none;
}
diff --git a/website/src/css/imports/hero.css b/website/src/css/imports/hero.css
index 1ac692e2..6683afe0 100644
--- a/website/src/css/imports/hero.css
+++ b/website/src/css/imports/hero.css
@@ -1,7 +1,7 @@
.hero {
@neat-row;
background: $darkerGrey;
- background-image: linear-gradient(-180deg, #2A2C24 0%, $darkerGrey 20%);
+ background-image: linear-gradient(-180deg, #2a2c24 0%, $darkerGrey 20%);
color: $blueGrey;
overflow: hidden;
padding: calc($xl * 2.25) 0 0 0;
@@ -65,15 +65,15 @@
font-size: $tiny;
letter-spacing: 0.5px;
background-color: $blue;
- background-image: linear-gradient(-180deg, #4A7FDD 0%, #3A69C7 100%);
- box-shadow: 0 4px 12px 0 rgba(0,0,0,0.3), 0 1px 3px 0 rgba(0,0,0,0.6);
+ background-image: linear-gradient(-180deg, #4a7fdd 0%, #3a69c7 100%);
+ box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.3), 0 1px 3px 0 rgba(0, 0, 0, 0.6);
border-radius: $borderRadius;
padding: 10px 14px 8px 14px;
- transition: .2s;
+ transition: 0.2s;
&:hover {
transform: scale(1.05);
- box-shadow: 0 4px 12px 0 rgba(0,0,0,0.5), 0 1px 3px 0 rgba(0,0,0,1);
+ box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.5), 0 1px 3px 0 rgba(0, 0, 0, 1);
}
&:active {
transform: scale(0.95);
@@ -82,7 +82,6 @@
}
.hero-features {
-
@media screen and (min-width: $tablet) {
@neat-span-columns 5;
}
@@ -90,7 +89,6 @@
.feature {
margin: 0 0 $medium 0;
}
-
}
.hero-graphic {
@@ -104,10 +102,11 @@
margin: 0;
}
- img, iframe {
+ img,
+ iframe {
width: 100%;
border-radius: $largeBorderRadius;
- box-shadow: 0 10px 30px 0 rgba(0,0,0,0.15), 0 3px 9px 0 rgba(0,0,0,0.30);
+ box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.15), 0 3px 9px 0 rgba(0, 0, 0, 0.3);
}
.hero-videolink {
@@ -124,8 +123,8 @@
font-weight: $semibold;
text-align: center;
color: $blue;
- background-color: rgba(255,255,255,0.85);
- box-shadow: 0 3px 9px 0 rgba(0,0,0,0.05), 0 1px 3px 0 rgba(0,0,0,0.15);
+ background-color: rgba(255, 255, 255, 0.85);
+ box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.05), 0 1px 3px 0 rgba(0, 0, 0, 0.15);
border-radius: 100px;
transition: 0.1s;
}
@@ -134,7 +133,7 @@
.hero-videolink {
color: white;
background-color: $blue;
- box-shadow: 0 6px 18px 0 rgba(0,0,0,0.15), 0 2px 6px 0 rgba(0,0,0,0.30);
+ box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.15), 0 2px 6px 0 rgba(0, 0, 0, 0.3);
transform: scale(1.1);
}
}
@@ -146,108 +145,106 @@
}
}
- /*COMMUNITY PAGE*/
+ /*COMMUNITY PAGE*/
- &.community {
- .hero-copy {
- text-align: left;
- @media screen and (min-width: $tablet) {
- @neat-span-columns 5;
- }
- }
- }
-
- .ctas {
- margin-bottom: $small;
-
- @media screen and (min-width: $mobile) {
- text-align: left;
- }
-
- ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
- }
-
- a {
- color: $green;
- font-weight: $semibold;
- }
-}
-
-.calendar-cta {
- text-align: center;
- background: $darkerGrey;
- background-image: linear-gradient(-17deg, $darkerGrey 17%, $darkGrey 94%);
- border-radius: $largeBorderRadius;
- box-shadow: 0 $micro $small rgba(0,0,0,0.1);
- padding: $medium;
- box-sizing: border-box;
-
- @media screen and (min-width: $tablet) {
- max-width: 446px;
- }
-
- @media screen and (min-width: $tablet) {
- @neat-span-columns 5;
- @neat-shift 1;
- display: inline-block;
- position: fixed;
- right: $medium;
- max-height: calc(100vh - ($xl * 1.5) - $medium);
- overflow-y: auto;
- }
-
- @media screen and (min-width: 1280px) {
- right: initial;
- left: calc(50% - $large);
- }
-
- .calendar {
- border-radius: $largeBorderRadius;
- overflow: hidden;
- box-shadow: 0 $micro $small rgba(0,0,0,0.5);
- margin: $small auto;
- max-width: 250px;
-
- .month {
- background: $green;
- color: $grey;
- font-weight: $black;
- text-transform: uppercase;
- letter-spacing: 4px;
- font-size: $tiny;
- padding: $tiny;
- }
-
- .day {
- font-size: $xl;
- font-weight: $black;
- color: white;
- border: 1px solid $grey;
- border-top: none;
- border-bottom-left-radius: $largeBorderRadius;
- border-bottom-right-radius: $largeBorderRadius;
+ &.community {
+ .hero-copy {
+ text-align: left;
+ @media screen and (min-width: $tablet) {
+ @neat-span-columns 5;
+ }
}
}
- strong {
- display: inline-block;
- }
+ .ctas {
+ margin-bottom: $small;
- h2:not(:first-child) {
- font-weight: $light;
- }
+ @media screen and (min-width: $mobile) {
+ text-align: left;
+ }
- .cal-cta {
- margin-top: $micro;
+ ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ }
a {
color: $green;
+ font-weight: $semibold;
+ }
+ }
+
+ .calendar-cta {
+ text-align: center;
+ background: $darkerGrey;
+ background-image: linear-gradient(-17deg, $darkerGrey 17%, $darkGrey 94%);
+ border-radius: $largeBorderRadius;
+ box-shadow: 0 $micro $small rgba(0, 0, 0, 0.1);
+ padding: $medium;
+ box-sizing: border-box;
+
+ @media screen and (min-width: $tablet) {
+ max-width: 446px;
+ }
+
+ @media screen and (min-width: $tablet) {
+ @neat-span-columns 5;
+ @neat-shift 1;
+ display: inline-block;
+ position: fixed;
+ right: $medium;
+ max-height: calc(100vh - ($xl * 1.5) - $medium);
+ overflow-y: auto;
+ }
+
+ @media screen and (min-width: 1280px) {
+ right: initial;
+ left: calc(50% - $large);
+ }
+
+ .calendar {
+ border-radius: $largeBorderRadius;
+ overflow: hidden;
+ box-shadow: 0 $micro $small rgba(0, 0, 0, 0.5);
+ margin: $small auto;
+ max-width: 250px;
+
+ .month {
+ background: $green;
+ color: $grey;
+ font-weight: $black;
+ text-transform: uppercase;
+ letter-spacing: 4px;
+ font-size: $tiny;
+ padding: $tiny;
+ }
+
+ .day {
+ font-size: $xl;
+ font-weight: $black;
+ color: white;
+ border: 1px solid $grey;
+ border-top: none;
+ border-bottom-left-radius: $largeBorderRadius;
+ border-bottom-right-radius: $largeBorderRadius;
+ }
+ }
+
+ strong {
+ display: inline-block;
+ }
+
+ h2:not(:first-child) {
+ font-weight: $light;
+ }
+
+ .cal-cta {
+ margin-top: $micro;
+
+ a {
+ color: $green;
+ }
}
}
}
-
-
-}
diff --git a/website/src/css/imports/utilities.css b/website/src/css/imports/utilities.css
index c1dce614..0e44e09a 100644
--- a/website/src/css/imports/utilities.css
+++ b/website/src/css/imports/utilities.css
@@ -1,83 +1,83 @@
@keyframes fadeInUp {
- 0% {
- opacity: 0;
- transform: translateY(10px);
- }
- 100% {
- opacity: 1;
- transform: translateY(0);
- }
+ 0% {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+ 100% {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
.centered-text {
- text-align: center;
+ text-align: center;
}
.container {
- @neat-outer-container;
+ @neat-outer-container;
}
.half,
.third,
.quarter {
- padding-bottom: $small;
- @neat-span-columns 12;
+ padding-bottom: $small;
+ @neat-span-columns 12;
@media screen and (min-width: $tablet) {
- @neat-span-columns 6;
- padding-bottom: 0;
- }
+ @neat-span-columns 6;
+ padding-bottom: 0;
+ }
- &:nth-child(even) {
- @media screen and (min-width: $mobile) and (max-width: 767px) {
- margin-right: 0;
- }
- }
+ &:nth-child(even) {
+ @media screen and (min-width: $mobile) and (max-width: 767px) {
+ margin-right: 0;
+ }
+ }
}
.third {
- @media screen and (min-width: $tablet) {
- @neat-span-columns 4;
- }
+ @media screen and (min-width: $tablet) {
+ @neat-span-columns 4;
+ }
}
.quarter {
- @media screen and (min-width: $tablet) {
- @neat-span-columns 3;
- }
+ @media screen and (min-width: $tablet) {
+ @neat-span-columns 3;
+ }
}
.clearfix {
- &:after {
- content: ' ';
- width: 100%;
- display: table;
- }
+ &:after {
+ content: ' ';
+ width: 100%;
+ display: table;
+ }
}
.section-label {
- color: $grey;
- font-size: 12px;
- font-weight: $semibold;
+ color: $grey;
+ font-size: 12px;
+ font-weight: $semibold;
letter-spacing: 1.5px;
text-transform: uppercase;
- &:after {
+ &:after {
background: $darkGreen;
content: ' ';
display: block;
height: 2px;
margin-top: 5px;
- width: $small;
- }
+ width: $small;
+ }
- &.inverse {
- color: white;
+ &.inverse {
+ color: white;
&.mono:after {
background: $grey;
}
- }
+ }
&.extended {
display: inline-block;
@@ -94,75 +94,75 @@
}
img.responsive {
- width: 100%;
- height: auto;
+ width: 100%;
+ height: auto;
}
.img-bg-hero {
- color: white;
- background-size: 100% auto;
- background-size: cover !important;
+ color: white;
+ background-size: 100% auto;
+ background-size: cover !important;
- h1,
- h2 {
- color: white;
- font-weight: $light;
+ h1,
+ h2 {
+ color: white;
+ font-weight: $light;
- @media screen and (min-width: $tablet) {
- font-weight: $thin;
- }
- }
+ @media screen and (min-width: $tablet) {
+ font-weight: $thin;
+ }
+ }
}
.pagination {
- text-align: center;
- margin: 0;
- padding: 0;
- list-style-type: none;
+ text-align: center;
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
- @media screen and (min-width: $tablet) {
- @neat-span-columns 8;
- @neat-shift 2;
- }
+ @media screen and (min-width: $tablet) {
+ @neat-span-columns 8;
+ @neat-shift 2;
+ }
- li {
- margin: 0;
- padding: 0;
- display: inline;
+ li {
+ margin: 0;
+ padding: 0;
+ display: inline;
- @media screen and (min-width: $tablet) {
- display: inline-block;
- }
+ @media screen and (min-width: $tablet) {
+ display: inline-block;
+ }
- &.active a,
- a[aria-label] {
- display: inline-block;
- }
- }
+ &.active a,
+ a[aria-label] {
+ display: inline-block;
+ }
+ }
- a {
- text-decoration: none;
- font-weight: $light;
- color: $grey;
- width: 18px;
- font-size: $tiny;
- padding: $micro;
- border-radius: 99px;
- display: none;
+ a {
+ text-decoration: none;
+ font-weight: $light;
+ color: $grey;
+ width: 18px;
+ font-size: $tiny;
+ padding: $micro;
+ border-radius: 99px;
+ display: none;
- @media screen and (min-width: $tablet) {
- display: inline-block;
- }
- }
+ @media screen and (min-width: $tablet) {
+ display: inline-block;
+ }
+ }
- .active a {
- color: white;
- background: $green;
- }
+ .active a {
+ color: white;
+ background: $green;
+ }
- .disabled a {
- color: $lighterGrey;
- }
+ .disabled a {
+ color: $lighterGrey;
+ }
}
.unordered-list ul {
@@ -203,7 +203,6 @@ img.responsive {
color: $grey;
position: relative;
-
&:before,
&:after {
position: absolute;
diff --git a/website/src/css/imports/whatsnew.css b/website/src/css/imports/whatsnew.css
index cdb844f3..65eea6f4 100644
--- a/website/src/css/imports/whatsnew.css
+++ b/website/src/css/imports/whatsnew.css
@@ -42,7 +42,7 @@
li {
.update-metadata {
font-size: 13px;
- color: rgba(255,255,255,0.6);
+ color: rgba(255, 255, 255, 0.6);
display: block;
margin-bottom: $micro;
.update-version {
@@ -60,5 +60,4 @@
}
}
}
-
}
diff --git a/website/src/css/lib/prism.css b/website/src/css/lib/prism.css
index 6add2d26..5a67be55 100644
--- a/website/src/css/lib/prism.css
+++ b/website/src/css/lib/prism.css
@@ -4,46 +4,45 @@
* @author Rose Pritchard
*/
-code[class*="language-"],
-pre[class*="language-"] {
- color: #ccc;
- background: none;
- font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
- text-align: left;
- white-space: pre;
- word-spacing: normal;
- word-break: normal;
- word-wrap: normal;
- line-height: 1.5;
+code[class*='language-'],
+pre[class*='language-'] {
+ color: #ccc;
+ background: none;
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+ word-break: normal;
+ word-wrap: normal;
+ line-height: 1.5;
- -moz-tab-size: 4;
- -o-tab-size: 4;
- tab-size: 4;
-
- -webkit-hyphens: none;
- -moz-hyphens: none;
- -ms-hyphens: none;
- hyphens: none;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
}
/* Code blocks */
-pre[class*="language-"] {
- padding: 1em;
- margin: .5em 0;
- overflow: auto;
+pre[class*='language-'] {
+ padding: 1em;
+ margin: 0.5em 0;
+ overflow: auto;
}
-:not(pre) > code[class*="language-"],
-pre[class*="language-"] {
- background: #2d2d2d;
+:not(pre) > code[class*='language-'],
+pre[class*='language-'] {
+ background: #2d2d2d;
}
/* Inline code */
-:not(pre) > code[class*="language-"] {
- padding: .1em;
- border-radius: .3em;
- white-space: normal;
+:not(pre) > code[class*='language-'] {
+ padding: 0.1em;
+ border-radius: 0.3em;
+ white-space: normal;
}
.token.comment,
@@ -51,35 +50,35 @@ pre[class*="language-"] {
.token.prolog,
.token.doctype,
.token.cdata {
- color: #999;
+ color: #999;
}
.token.punctuation {
- color: #ccc;
+ color: #ccc;
}
.token.tag,
.token.attr-name,
.token.namespace,
.token.deleted {
- color: #e2777a;
+ color: #e2777a;
}
.token.function-name {
- color: #6196cc;
+ color: #6196cc;
}
.token.boolean,
.token.number,
.token.function {
- color: #f08d49;
+ color: #f08d49;
}
.token.property,
.token.class-name,
.token.constant,
.token.symbol {
- color: #f8c555;
+ color: #f8c555;
}
.token.selector,
@@ -87,7 +86,7 @@ pre[class*="language-"] {
.token.atrule,
.token.keyword,
.token.builtin {
- color: #cc99cd;
+ color: #cc99cd;
}
.token.string,
@@ -95,27 +94,27 @@ pre[class*="language-"] {
.token.attr-value,
.token.regex,
.token.variable {
- color: #7ec699;
+ color: #7ec699;
}
.token.operator,
.token.entity,
.token.url {
- color: #67cdcc;
+ color: #67cdcc;
}
.token.important,
.token.bold {
- font-weight: bold;
+ font-weight: bold;
}
.token.italic {
- font-style: italic;
+ font-style: italic;
}
.token.entity {
- cursor: help;
+ cursor: help;
}
.token.inserted {
- color: green;
+ color: green;
}
diff --git a/website/src/html.js b/website/src/html.js
index 4f8ecd7a..8ab4cfe2 100644
--- a/website/src/html.js
+++ b/website/src/html.js
@@ -14,12 +14,7 @@ module.exports = class HTML extends React.Component {
render() {
let css;
if (process.env.NODE_ENV === 'production') {
- css = (
-
- );
+ css = ;
}
return (
@@ -27,32 +22,11 @@ module.exports = class HTML extends React.Component {
-
-
-
-
-
+
+
+
+
+
{this.props.headComponents}
@@ -64,15 +38,11 @@ module.exports = class HTML extends React.Component {
{this.props.preBodyComponents}
-
+
{this.props.postBodyComponents}
-
-
+
+