diff --git a/packages/netlify-cms-core/src/actions/__tests__/config.spec.js b/packages/netlify-cms-core/src/actions/__tests__/config.spec.js index 7b6f3081..922ee800 100644 --- a/packages/netlify-cms-core/src/actions/__tests__/config.spec.js +++ b/packages/netlify-cms-core/src/actions/__tests__/config.spec.js @@ -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'); - }); + 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 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' }] }])); - }); + 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 set default slug config', () => { - expect(applyDefaults(fromJS({ collections: [] })).get('slug')).toEqual( - fromJS({ encoding: 'unicode', clean_accents: false, sanitize_replacement: '-' }), - ); - }); + 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 encoding', () => { - expect( - applyDefaults(fromJS({ collections: [], slug: { encoding: 'ascii' } })).getIn([ - 'slug', - 'encoding', - ]), - ).toEqual('ascii'); - }); + 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 override slug clean_accents', () => { - 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('_'); + }); + }); - it('should not override slug sanitize_replacement', () => { - 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 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: '' }, + ]), + ); + }); + }); }); }); }); diff --git a/packages/netlify-cms-core/src/actions/config.js b/packages/netlify-cms-core/src/actions/config.js index d1cd8422..973affb1 100644 --- a/packages/netlify-cms-core/src/actions/config.js +++ b/packages/netlify-cms-core/src/actions/config.js @@ -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, '/')); } diff --git a/packages/netlify-cms-core/src/reducers/__tests__/entries.spec.js b/packages/netlify-cms-core/src/reducers/__tests__/entries.spec.js index ab6b1dc2..4ca52042 100644 --- a/packages/netlify-cms-core/src/reducers/__tests__/entries.spec.js +++ b/packages/netlify-cms-core/src/reducers/__tests__/entries.spec.js @@ -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 }), @@ -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'); diff --git a/packages/netlify-cms-core/src/reducers/entries.ts b/packages/netlify-cms-core/src/reducers/entries.ts index a8a1055b..f63052aa 100644 --- a/packages/netlify-cms-core/src/reducers/entries.ts +++ b/packages/netlify-cms-core/src/reducers/entries.ts @@ -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)); diff --git a/packages/netlify-cms-core/src/types/redux.ts b/packages/netlify-cms-core/src/types/redux.ts index ee726641..93b09095 100644 --- a/packages/netlify-cms-core/src/types/redux.ts +++ b/packages/netlify-cms-core/src/types/redux.ts @@ -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;