Skip to content

Commit

Permalink
feat: support per collection public_folder (#3069)
Browse files Browse the repository at this point in the history
* feat: support per collection public_folder

* test: improve tests readability
  • Loading branch information
erezrokah authored and erquhart committed Jan 14, 2020
1 parent 476f450 commit 0a50efd
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 91 deletions.
234 changes: 150 additions & 84 deletions packages/netlify-cms-core/src/actions/__tests__/config.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,103 +3,169 @@ import { applyDefaults } from '../config';

describe('config', () => {
describe('applyDefaults', () => {
it('should set publish_mode if not set', () => {
const config = fromJS({
foo: 'bar',
media_folder: 'path/to/media',
public_folder: '/path/to/media',
collections: [],
describe('publish_mode', () => {
it('should set publish_mode if not set', () => {
const config = fromJS({
foo: 'bar',
media_folder: 'path/to/media',
public_folder: '/path/to/media',
collections: [],
});
expect(applyDefaults(config).get('publish_mode')).toEqual('simple');
});
expect(applyDefaults(config).get('publish_mode')).toEqual('simple');
});

it('should set publish_mode from config', () => {
const config = fromJS({
foo: 'bar',
publish_mode: 'complex',
media_folder: 'path/to/media',
public_folder: '/path/to/media',
collections: [],
it('should set publish_mode from config', () => {
const config = fromJS({
foo: 'bar',
publish_mode: 'complex',
media_folder: 'path/to/media',
public_folder: '/path/to/media',
collections: [],
});
expect(applyDefaults(config).get('publish_mode')).toEqual('complex');
});
expect(applyDefaults(config).get('publish_mode')).toEqual('complex');
});

it('should set public_folder based on media_folder if not set', () => {
expect(
applyDefaults(
fromJS({
foo: 'bar',
media_folder: 'path/to/media',
collections: [],
}),
).get('public_folder'),
).toEqual('/path/to/media');
});
describe('public_folder', () => {
it('should set public_folder based on media_folder if not set', () => {
expect(
applyDefaults(
fromJS({
foo: 'bar',
media_folder: 'path/to/media',
collections: [],
}),
).get('public_folder'),
).toEqual('/path/to/media');
});

it('should not overwrite public_folder if set', () => {
expect(
applyDefaults(
fromJS({
foo: 'bar',
media_folder: 'path/to/media',
public_folder: '/publib/path',
collections: [],
}),
).get('public_folder'),
).toEqual('/publib/path');
it('should not overwrite public_folder if set', () => {
expect(
applyDefaults(
fromJS({
foo: 'bar',
media_folder: 'path/to/media',
public_folder: '/publib/path',
collections: [],
}),
).get('public_folder'),
).toEqual('/publib/path');
});
});

it('should strip leading slashes from collection folder', () => {
expect(
applyDefaults(
fromJS({
collections: [{ folder: '/foo' }],
}),
).get('collections'),
).toEqual(fromJS([{ folder: 'foo' }]));
});
describe('collections', () => {
it('should strip leading slashes from collection folder', () => {
expect(
applyDefaults(
fromJS({
collections: [{ folder: '/foo' }],
}),
).get('collections'),
).toEqual(fromJS([{ folder: 'foo' }]));
});

it('should strip leading slashes from collection files', () => {
expect(
applyDefaults(
fromJS({
collections: [{ files: [{ file: '/foo' }] }],
}),
).get('collections'),
).toEqual(fromJS([{ files: [{ file: 'foo' }] }]));
});
it('should strip leading slashes from collection files', () => {
expect(
applyDefaults(
fromJS({
collections: [{ files: [{ file: '/foo' }] }],
}),
).get('collections'),
).toEqual(fromJS([{ files: [{ file: 'foo' }] }]));
});

it('should set default slug config', () => {
expect(applyDefaults(fromJS({ collections: [] })).get('slug')).toEqual(
fromJS({ encoding: 'unicode', clean_accents: false, sanitize_replacement: '-' }),
);
});
describe('slug', () => {
it('should set default slug config if not set', () => {
expect(applyDefaults(fromJS({ collections: [] })).get('slug')).toEqual(
fromJS({ encoding: 'unicode', clean_accents: false, sanitize_replacement: '-' }),
);
});

it('should not override slug encoding', () => {
expect(
applyDefaults(fromJS({ collections: [], slug: { encoding: 'ascii' } })).getIn([
'slug',
'encoding',
]),
).toEqual('ascii');
});
it('should not overwrite slug encoding if set', () => {
expect(
applyDefaults(fromJS({ collections: [], slug: { encoding: 'ascii' } })).getIn([
'slug',
'encoding',
]),
).toEqual('ascii');
});

it('should not override slug clean_accents', () => {
expect(
applyDefaults(fromJS({ collections: [], slug: { clean_accents: true } })).getIn([
'slug',
'clean_accents',
]),
).toEqual(true);
});
it('should not overwrite slug clean_accents if set', () => {
expect(
applyDefaults(fromJS({ collections: [], slug: { clean_accents: true } })).getIn([
'slug',
'clean_accents',
]),
).toEqual(true);
});

it('should not overwrite slug sanitize_replacement if set', () => {
expect(
applyDefaults(fromJS({ collections: [], slug: { sanitize_replacement: '_' } })).getIn([
'slug',
'sanitize_replacement',
]),
).toEqual('_');
});
});

describe('public_folder and media_folder', () => {
it('should set collection public_folder collection based on media_folder if not set', () => {
expect(
applyDefaults(
fromJS({
collections: [{ folder: 'foo', media_folder: 'static/images/docs' }],
}),
).get('collections'),
).toEqual(
fromJS([
{
folder: 'foo',
media_folder: 'static/images/docs',
public_folder: 'static/images/docs',
},
]),
);
});

it('should not override slug sanitize_replacement', () => {
expect(
applyDefaults(fromJS({ collections: [], slug: { sanitize_replacement: '_' } })).getIn([
'slug',
'sanitize_replacement',
]),
).toEqual('_');
it('should not overwrite collection public_folder if set', () => {
expect(
applyDefaults(
fromJS({
collections: [
{
folder: 'foo',
media_folder: 'static/images/docs',
public_folder: 'images/docs',
},
],
}),
).get('collections'),
).toEqual(
fromJS([
{
folder: 'foo',
media_folder: 'static/images/docs',
public_folder: 'images/docs',
},
]),
);
});

it("should set collection media_folder and public_folder to an empty string when collection path exists, but collection media_folder doesn't", () => {
expect(
applyDefaults(
fromJS({
collections: [{ folder: 'foo', path: '{{slug}}/index' }],
}),
).get('collections'),
).toEqual(
fromJS([
{ folder: 'foo', path: '{{slug}}/index', media_folder: '', public_folder: '' },
]),
);
});
});
});
});
});
3 changes: 3 additions & 0 deletions packages/netlify-cms-core/src/actions/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ export function applyDefaults(config) {
// default value for media folder when using the path config
collection = collection.set('media_folder', '');
}
if (collection.has('media_folder') && !collection.has('public_folder')) {
collection = collection.set('public_folder', collection.get('media_folder'));
}
return collection.set('folder', trimStart(folder, '/'));
}

Expand Down
10 changes: 5 additions & 5 deletions packages/netlify-cms-core/src/reducers/__tests__/entries.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ describe('entries', () => {
).toBe('/media/image.png');
});

it('should resolve path from public folder when in editorial workflow for collection with no media folder', () => {
it('should resolve path from public folder when in editorial workflow for collection with no public folder', () => {
expect(
selectMediaFilePublicPath(
Map({ public_folder: '/media', publish_mode: EDITORIAL_WORKFLOW }),
Expand All @@ -192,21 +192,21 @@ describe('entries', () => {
).toBe('/media/image.png');
});

it('should resolve path from collection media folder when in editorial workflow for collection with media folder', () => {
it('should resolve path from collection media folder when in editorial workflow for collection with public folder', () => {
expect(
selectMediaFilePublicPath(
Map({ public_folder: '/media', publish_mode: EDITORIAL_WORKFLOW }),
Map({ name: 'posts', folder: 'posts', media_folder: '' }),
Map({ name: 'posts', folder: 'posts', public_folder: '' }),
'image.png',
),
).toBe('image.png');
});

it('should handle relative media_folder', () => {
it('should handle relative public_folder', () => {
expect(
selectMediaFilePublicPath(
Map({ public_folder: '/media', publish_mode: EDITORIAL_WORKFLOW }),
Map({ name: 'posts', folder: 'posts', media_folder: '../../static/media/' }),
Map({ name: 'posts', folder: 'posts', public_folder: '../../static/media/' }),
'image.png',
),
).toBe('../../static/media/image.png');
Expand Down
4 changes: 2 additions & 2 deletions packages/netlify-cms-core/src/reducers/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ export const selectMediaFilePublicPath = (
let publicFolder = config.get('public_folder');

const useWorkflow = config.get('publish_mode') === EDITORIAL_WORKFLOW;
if (useWorkflow && collection && collection.has('media_folder')) {
publicFolder = collection.get('media_folder') as string;
if (useWorkflow && collection && collection.has('public_folder')) {
publicFolder = collection.get('public_folder') as string;
}

return join(publicFolder, basename(mediaPath));
Expand Down
1 change: 1 addition & 0 deletions packages/netlify-cms-core/src/types/redux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ type CollectionObject = {
fields: EntryFields;
isFetching: boolean;
media_folder?: string;
public_folder?: string;
preview_path?: string;
preview_path_date_field?: string;
summary?: string;
Expand Down

0 comments on commit 0a50efd

Please sign in to comment.