Skip to content

Commit c13a2ce

Browse files
authored
Merge branch 'master' into label-singular-config
2 parents 5e2616d + 952a6d5 commit c13a2ce

11 files changed

+176
-36
lines changed

.all-contributorsrc

+20
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,17 @@
710710
"code"
711711
]
712712
},
713+
{
714+
"login": "Swieckowski",
715+
"name": "Swieckowski",
716+
"avatar_url": "https://avatars0.githubusercontent.com/u/31023010?v=4",
717+
"profile": "https://www.linkedin.com/in/arthur-swieckowski/",
718+
"contributions": [
719+
"code",
720+
"doc",
721+
"test"
722+
]
723+
},
713724
{
714725
"login": "pixelastic",
715726
"name": "Tim Carry",
@@ -749,6 +760,15 @@
749760
"code",
750761
"doc"
751762
]
763+
},
764+
{
765+
"login": "Strangehill",
766+
"name": "Antonio Argote",
767+
"avatar_url": "https://avatars1.githubusercontent.com/u/6064830?v=4",
768+
"profile": "http://antonioargote.com",
769+
"contributions": [
770+
"design"
771+
]
752772
}
753773
]
754774
}

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Netlify CMS
2-
[![All Contributors](https://img.shields.io/badge/all_contributors-87-orange.svg)](#contributors)
2+
[![All Contributors](https://img.shields.io/badge/all_contributors-89-orange.svg)](#contributors)
33
[![Open Source Helpers](https://www.codetriage.com/netlify/netlify-cms/badges/users.svg)](https://www.codetriage.com/netlify/netlify-cms)
44
[![](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/netlify/netlifycms)
55

@@ -62,7 +62,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
6262
| [<img src="https://avatars2.githubusercontent.com/u/799360?v=4" width="100px;"/><br /><sub><b>Bryan Robinson</b></sub>](http://bryanlrobinson.com)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=brob "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/561983?v=4" width="100px;"/><br /><sub><b>Darren</b></sub>](https://github.com/dardub)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=dardub "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/576512?v=4" width="100px;"/><br /><sub><b>Richard Pullinger</b></sub>](http://www.richardpullinger.com)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=rpullinger "Code") | [<img src="https://avatars1.githubusercontent.com/u/3718939?v=4" width="100px;"/><br /><sub><b>Taylor Bryant</b></sub>](https://taylorbryant.blog)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=taylorbryant "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/5881826?v=4" width="100px;"/><br /><sub><b>kvanerkelens</b></sub>](https://github.com/kvanerkelens)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=kvanerkelens "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/8291663?v=4" width="100px;"/><br /><sub><b>Patrick Sier</b></sub>](https://patsier.com/)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=pjsier "Code") | [<img src="https://avatars2.githubusercontent.com/u/6132191?v=4" width="100px;"/><br /><sub><b>Christian Nolte</b></sub>](http://noltech.net)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=drlogout "Code") |
6363
| [<img src="https://avatars1.githubusercontent.com/u/3818?v=4" width="100px;"/><br /><sub><b>Edward Betts</b></sub>](http://edwardbetts.com/)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=EdwardBetts "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/8771435?v=4" width="100px;"/><br /><sub><b>Josh Hardman</b></sub>](https://github.com/jhardman0830)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=jhardman0830 "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/11616378?v=4" width="100px;"/><br /><sub><b>Mantas</b></sub>](https://behance.net/mistermantas)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=mistermantas "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/5244986?v=4" width="100px;"/><br /><sub><b>Marco Biedermann</b></sub>](https://www.marcobiedermann.com)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=marcobiedermann "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/7525670?v=4" width="100px;"/><br /><sub><b>Max Stoiber</b></sub>](https://mxstbr.blog/newsletter)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=mxstbr "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/89368?v=4" width="100px;"/><br /><sub><b>Vyacheslav Matyukhin</b></sub>](http://berekuk.ru)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=berekuk "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/9059048?v=4" width="100px;"/><br /><sub><b>jimmaaay</b></sub>](https://jimmythompson.me)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=jimmaaay "Code") |
6464
| [<img src="https://avatars3.githubusercontent.com/u/802086?v=4" width="100px;"/><br /><sub><b>Luís Miguel</b></sub>](https://github.com/Quicksaver)<br />[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3AQuicksaver "Bug reports") [💻](https://github.com/netlify/netlify-cms/commits?author=Quicksaver "Code") | [<img src="https://avatars2.githubusercontent.com/u/357379?v=4" width="100px;"/><br /><sub><b>Chris Swithinbank</b></sub>](http://chrisswithinbank.net/)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=delucis "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/1262221?v=4" width="100px;"/><br /><sub><b>remmah</b></sub>](https://github.com/remmah)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=remmah "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/29388?v=4" width="100px;"/><br /><sub><b>Sumeet Jain</b></sub>](http://sumeetjain.com)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=sumeetjain "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/26816046?v=4" width="100px;"/><br /><sub><b>Sagar Khatri</b></sub>](https://github.com/ragasirtahk)<br />[📖](https://github.com/netlify/netlify-cms/commits?author=ragasirtahk "Documentation") [💡](#example-ragasirtahk "Examples") | [<img src="https://avatars0.githubusercontent.com/u/8182932?v=4" width="100px;"/><br /><sub><b>Kevin Doocey</b></sub>](https://www.dooceykev.in)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=Doocey "Code") | [<img src="https://avatars2.githubusercontent.com/u/283419?v=4" width="100px;"/><br /><sub><b>Tim Carry</b></sub>](http://www.pixelastic.com/)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=pixelastic "Code") [🎨](#design-pixelastic "Design") [📖](https://github.com/netlify/netlify-cms/commits?author=pixelastic "Documentation") |
65-
| [<img src="https://avatars0.githubusercontent.com/u/30510616?v=4" width="100px;"/><br /><sub><b>Sol Park</b></sub>](https://github.com/solpark)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=solpark "Code") | [<img src="https://avatars0.githubusercontent.com/u/29218846?v=4" width="100px;"/><br /><sub><b>Michael Romani</b></sub>](https://github.com/michaelromani)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=michaelromani "Code") | [<img src="https://avatars1.githubusercontent.com/u/372831?v=4" width="100px;"/><br /><sub><b>Pedro Duarte</b></sub>](http://pedroduarte.me)<br />[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Apeduarte "Bug reports") [💻](https://github.com/netlify/netlify-cms/commits?author=peduarte "Code") [📖](https://github.com/netlify/netlify-cms/commits?author=peduarte "Documentation") |
65+
| [<img src="https://avatars0.githubusercontent.com/u/31023010?v=4" width="100px;"/><br /><sub><b>Swieckowski</b></sub>](https://www.linkedin.com/in/arthur-swieckowski/)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=Swieckowski "Code") [📖](https://github.com/netlify/netlify-cms/commits?author=Swieckowski "Documentation") [⚠️](https://github.com/netlify/netlify-cms/commits?author=Swieckowski "Tests") | [<img src="https://avatars0.githubusercontent.com/u/30510616?v=4" width="100px;"/><br /><sub><b>Sol Park</b></sub>](https://github.com/solpark)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=solpark "Code") | [<img src="https://avatars0.githubusercontent.com/u/29218846?v=4" width="100px;"/><br /><sub><b>Michael Romani</b></sub>](https://github.com/michaelromani)<br />[💻](https://github.com/netlify/netlify-cms/commits?author=michaelromani "Code") | [<img src="https://avatars1.githubusercontent.com/u/372831?v=4" width="100px;"/><br /><sub><b>Pedro Duarte</b></sub>](http://pedroduarte.me)<br />[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Apeduarte "Bug reports") [💻](https://github.com/netlify/netlify-cms/commits?author=peduarte "Code") [📖](https://github.com/netlify/netlify-cms/commits?author=peduarte "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/6064830?v=4" width="100px;"/><br /><sub><b>Antonio Argote</b></sub>](http://antonioargote.com)<br />[🎨](#design-Strangehill "Design") |
6666
<!-- ALL-CONTRIBUTORS-LIST:END -->
6767

6868
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "netlify-cms",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"description": "Netlify CMS lets content editors work on structured content stored in git",
55
"main": "dist/cms.js",
66
"scripts": {

src/formats/__tests__/frontmatter.spec.js

+93-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FrontmatterInfer, FrontmatterJSON, FrontmatterTOML, FrontmatterYAML } from '../frontmatter';
1+
import { FrontmatterInfer, frontmatterJSON, frontmatterTOML, frontmatterYAML } from '../frontmatter';
22

33
jest.mock("../../valueObjects/AssetProxy.js");
44

@@ -15,9 +15,21 @@ describe('Frontmatter', () => {
1515
);
1616
});
1717

18-
it('should parse YAML with --- delimiters when it is explicitly set as the format', () => {
18+
it('should parse YAML with --- delimiters when it is explicitly set as the format without a custom delimiter', () => {
1919
expect(
20-
FrontmatterYAML.fromFile('---\ntitle: YAML\ndescription: Something longer\n---\nContent')
20+
frontmatterYAML().fromFile('---\ntitle: YAML\ndescription: Something longer\n---\nContent')
21+
).toEqual(
22+
{
23+
title: 'YAML',
24+
description: 'Something longer',
25+
body: 'Content',
26+
}
27+
);
28+
});
29+
30+
it('should parse YAML with custom delimiters when it is explicitly set as the format with a custom delimiter', () => {
31+
expect(
32+
frontmatterYAML("~~~").fromFile('~~~\ntitle: YAML\ndescription: Something longer\n~~~\nContent')
2133
).toEqual(
2234
{
2335
title: 'YAML',
@@ -62,9 +74,9 @@ describe('Frontmatter', () => {
6274
);
6375
});
6476

65-
it('should parse TOML with +++ delimiters when it is explicitly set as the format', () => {
77+
it('should parse TOML with +++ delimiters when it is explicitly set as the format without a custom delimiter', () => {
6678
expect(
67-
FrontmatterTOML.fromFile('+++\ntitle = "TOML"\ndescription = "Front matter"\n+++\nContent')
79+
frontmatterTOML("~~~").fromFile('~~~\ntitle = "TOML"\ndescription = "Front matter"\n~~~\nContent')
6880
).toEqual(
6981
{
7082
title: 'TOML',
@@ -98,9 +110,21 @@ describe('Frontmatter', () => {
98110
);
99111
});
100112

101-
it('should parse JSON with { } delimiters when it is explicitly set as the format', () => {
113+
it('should parse JSON with { } delimiters when it is explicitly set as the format without a custom delimiter', () => {
102114
expect(
103-
FrontmatterJSON.fromFile('{\n"title": "The Title",\n"description": "Something longer"\n}\nContent')
115+
frontmatterJSON().fromFile('{\n"title": "The Title",\n"description": "Something longer"\n}\nContent')
116+
).toEqual(
117+
{
118+
title: 'The Title',
119+
description: 'Something longer',
120+
body: 'Content',
121+
}
122+
);
123+
});
124+
125+
it('should parse JSON with { } delimiters when it is explicitly set as the format with a custom delimiter', () => {
126+
expect(
127+
frontmatterJSON("~~~").fromFile('~~~\n"title": "The Title",\n"description": "Something longer"\n~~~\nContent')
104128
).toEqual(
105129
{
106130
title: 'The Title',
@@ -156,9 +180,10 @@ describe('Frontmatter', () => {
156180
);
157181
});
158182

159-
it('should stringify YAML with --- delimiters when it is explicitly set as the format', () => {
183+
it('should stringify YAML with --- delimiters when it is explicitly set as the format without a custom delimiter',
184+
() => {
160185
expect(
161-
FrontmatterYAML.toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'yaml'], title: 'YAML' })
186+
frontmatterYAML().toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'yaml'], title: 'YAML' })
162187
).toEqual(
163188
[
164189
'---',
@@ -173,9 +198,28 @@ describe('Frontmatter', () => {
173198
);
174199
});
175200

176-
it('should stringify TOML with +++ delimiters when it is explicitly set as the format', () => {
201+
it('should stringify YAML with --- delimiters when it is explicitly set as the format with a custom delimiter',
202+
() => {
203+
expect(
204+
frontmatterYAML("~~~").toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'yaml'], title: 'YAML' })
205+
).toEqual(
206+
[
207+
'~~~',
208+
'tags:',
209+
' - front matter',
210+
' - yaml',
211+
'title: YAML',
212+
'~~~',
213+
'Some content',
214+
'On another line\n',
215+
].join('\n')
216+
);
217+
});
218+
219+
it('should stringify TOML with +++ delimiters when it is explicitly set as the format without a custom delimiter',
220+
() => {
177221
expect(
178-
FrontmatterTOML.toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'toml'], title: 'TOML' })
222+
frontmatterTOML().toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'toml'], title: 'TOML' })
179223
).toEqual(
180224
[
181225
'+++',
@@ -188,9 +232,26 @@ describe('Frontmatter', () => {
188232
);
189233
});
190234

191-
it('should stringify JSON with { } delimiters when it is explicitly set as the format', () => {
235+
it('should stringify TOML with +++ delimiters when it is explicitly set as the format with a custom delimiter',
236+
() => {
237+
expect(
238+
frontmatterTOML("~~~").toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'toml'], title: 'TOML' })
239+
).toEqual(
240+
[
241+
'~~~',
242+
'tags = ["front matter", "toml"]',
243+
'title = "TOML"',
244+
'~~~',
245+
'Some content',
246+
'On another line\n',
247+
].join('\n')
248+
);
249+
});
250+
251+
it('should stringify JSON with { } delimiters when it is explicitly set as the format without a custom delimiter',
252+
() => {
192253
expect(
193-
FrontmatterJSON.toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'json'], title: 'JSON' })
254+
frontmatterJSON().toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'json'], title: 'JSON' })
194255
).toEqual(
195256
[
196257
'{',
@@ -205,4 +266,23 @@ describe('Frontmatter', () => {
205266
].join('\n')
206267
);
207268
});
269+
270+
it('should stringify JSON with { } delimiters when it is explicitly set as the format with a custom delimiter',
271+
() => {
272+
expect(
273+
frontmatterJSON("~~~").toFile({ body: 'Some content\nOn another line', tags: ['front matter', 'json'], title: 'JSON' })
274+
).toEqual(
275+
[
276+
'~~~',
277+
'"tags": [',
278+
' "front matter",',
279+
' "json"',
280+
' ],',
281+
' "title": "JSON"',
282+
'~~~',
283+
'Some content',
284+
'On another line\n',
285+
].join('\n')
286+
);
287+
});
208288
});

src/formats/formats.js

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import yamlFormatter from './yaml';
22
import tomlFormatter from './toml';
33
import jsonFormatter from './json';
4-
import { FrontmatterInfer, FrontmatterJSON, FrontmatterTOML, FrontmatterYAML } from './frontmatter';
4+
import { FrontmatterInfer, frontmatterJSON, frontmatterTOML, frontmatterYAML } from './frontmatter';
5+
6+
export const frontmatterFormats = ['yaml-frontmatter','toml-frontmatter','json-frontmatter']
57

68
export const supportedFormats = [
79
'yml',
@@ -37,24 +39,26 @@ export function formatByExtension(extension) {
3739
}[extension];
3840
}
3941

40-
function formatByName(name) {
42+
function formatByName(name, customDelimiter) {
4143
return {
4244
yml: yamlFormatter,
4345
yaml: yamlFormatter,
4446
toml: tomlFormatter,
4547
json: jsonFormatter,
4648
frontmatter: FrontmatterInfer,
47-
'json-frontmatter': FrontmatterJSON,
48-
'toml-frontmatter': FrontmatterTOML,
49-
'yaml-frontmatter': FrontmatterYAML,
49+
'json-frontmatter': frontmatterJSON(customDelimiter),
50+
'toml-frontmatter': frontmatterTOML(customDelimiter),
51+
'yaml-frontmatter': frontmatterYAML(customDelimiter),
5052
}[name];
5153
}
5254

5355
export function resolveFormat(collectionOrEntity, entry) {
56+
// Check for custom delimiter
57+
const customDelimiter = collectionOrEntity.get('frontmatter_delimiter');
5458
// If the format is specified in the collection, use that format.
55-
const format = collectionOrEntity.get('format');
56-
if (format) {
57-
return formatByName(format);
59+
const formatSpecification = collectionOrEntity.get('format');
60+
if (formatSpecification) {
61+
return formatByName(formatSpecification, customDelimiter);
5862
}
5963

6064
// If a file already exists, infer the format from its file extension.
@@ -72,5 +76,5 @@ export function resolveFormat(collectionOrEntity, entry) {
7276
}
7377

7478
// If no format is specified and it cannot be inferred, return the default.
75-
return formatByName('frontmatter');
79+
return formatByName('frontmatter', customDelimiter);
7680
}

src/formats/frontmatter.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@ export const getFormatOpts = format => ({
6060
}[format]);
6161

6262
class FrontmatterFormatter {
63-
constructor(format) {
63+
constructor(format, customDelimiter) {
6464
this.format = getFormatOpts(format);
65+
this.customDelimiter = customDelimiter;
6566
}
6667

6768
fromFile(content) {
6869
const format = this.format || inferFrontmatterFormat(content);
70+
if (this.customDelimiter) this.format.delimiters = this.customDelimiter;
6971
const result = matter(content, { engines: parsers, ...format });
7072
return {
7173
...result.data,
@@ -78,13 +80,14 @@ class FrontmatterFormatter {
7880

7981
// Stringify to YAML if the format was not set
8082
const format = this.format || getFormatOpts('yaml');
83+
if (this.customDelimiter) this.format.delimiters = this.customDelimiter;
8184

8285
// `sortedKeys` is not recognized by gray-matter, so it gets passed through to the parser
8386
return matter.stringify(body, meta, { engines: parsers, sortedKeys, ...format });
8487
}
8588
}
8689

8790
export const FrontmatterInfer = new FrontmatterFormatter();
88-
export const FrontmatterYAML = new FrontmatterFormatter('yaml');
89-
export const FrontmatterTOML = new FrontmatterFormatter('toml');
90-
export const FrontmatterJSON = new FrontmatterFormatter('json');
91+
export const frontmatterYAML = customDelimiter => new FrontmatterFormatter('yaml', customDelimiter);
92+
export const frontmatterTOML = customDelimiter => new FrontmatterFormatter('toml', customDelimiter);
93+
export const frontmatterJSON = customDelimiter => new FrontmatterFormatter('json', customDelimiter);

src/reducers/collections.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import consoleError from 'Lib/consoleError';
44
import { CONFIG_SUCCESS } from 'Actions/config';
55
import { FILES, FOLDER } from 'Constants/collectionTypes';
66
import { INFERABLE_FIELDS } from 'Constants/fieldInference';
7-
import { formatByExtension, formatToExtension, supportedFormats } from 'Formats/formats';
7+
import { formatByExtension, formatToExtension, supportedFormats, frontmatterFormats } from 'Formats/formats';
88

99
const collections = (state = null, action) => {
1010
const configCollections = action.payload && action.payload.collections;
@@ -38,6 +38,11 @@ function validateCollection(configCollection) {
3838
// Cannot infer format from extension.
3939
throw new Error(`Please set a format for collection "${ collectionName }". Supported formats are ${ supportedFormats.join(',') }`);
4040
}
41+
if (has(configCollection, 'frontmatter_delimiter') && !frontmatterFormats.includes(get(configCollection, 'format'))) {
42+
// Cannot set custom delimiter without explicit and proper frontmatter format declaration
43+
throw new Error(`Please set a proper frontmatter format for collection "${ collectionName }" to use a custom delimiter. Supported frontmatter formats are yaml-frontmatter, toml-frontmatter, and json-frontmatter.`);
44+
}
45+
4146
}
4247

4348
const selectors = {

0 commit comments

Comments
 (0)