Feat: media folders templates (#3116)
* refactor: typescript backendHelper * test: add string templating tests * test: add createPreviewUrl invalid date test * refactor: move all formatters to one file * feat: support media folders templating * feat: add filename and extension template variables * feat: support paths in string templates * docs: add media folder templating docs * style(docs): remove line break
This commit is contained in:
committed by
Shawn Erquhart
parent
4bc4490c6f
commit
cf57da223d
@ -93,7 +93,7 @@ describe('entries', () => {
|
||||
selectMediaFolder(
|
||||
Map({ media_folder: 'static/media' }),
|
||||
Map({ name: 'posts', folder: 'posts', media_folder: '' }),
|
||||
'posts/title/index.md',
|
||||
Map({ path: 'posts/title/index.md' }),
|
||||
),
|
||||
).toEqual('posts/title');
|
||||
});
|
||||
@ -103,10 +103,37 @@ describe('entries', () => {
|
||||
selectMediaFolder(
|
||||
Map({ media_folder: 'static/media' }),
|
||||
Map({ name: 'posts', folder: 'posts', media_folder: '../' }),
|
||||
'posts/title/index.md',
|
||||
Map({ path: 'posts/title/index.md' }),
|
||||
),
|
||||
).toEqual('posts/');
|
||||
});
|
||||
|
||||
it('should resolve media folder template', () => {
|
||||
const slugConfig = {
|
||||
encoding: 'unicode',
|
||||
clean_accents: false,
|
||||
sanitize_replacement: '-',
|
||||
};
|
||||
|
||||
const entry = fromJS({
|
||||
path: 'content/en/hosting-and-deployment/deployment-with-nanobox.md',
|
||||
data: { title: 'Deployment With NanoBox', category: 'Hosting And Deployment' },
|
||||
});
|
||||
const collection = fromJS({
|
||||
name: 'posts',
|
||||
folder: 'content',
|
||||
media_folder: '../../../{{media_folder}}/{{category}}/{{slug}}',
|
||||
fields: [{ name: 'title', widget: 'string' }],
|
||||
});
|
||||
|
||||
expect(
|
||||
selectMediaFolder(
|
||||
fromJS({ media_folder: 'static/media', slug: slugConfig }),
|
||||
collection,
|
||||
entry,
|
||||
),
|
||||
).toEqual('static/media/hosting-and-deployment/deployment-with-nanobox');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectMediaFilePath', () => {
|
||||
@ -149,7 +176,7 @@ describe('entries', () => {
|
||||
selectMediaFilePath(
|
||||
Map({ media_folder: 'static/media' }),
|
||||
Map({ name: 'posts', folder: 'posts', media_folder: '../../static/media/' }),
|
||||
'posts/title/index.md',
|
||||
Map({ path: 'posts/title/index.md' }),
|
||||
'image.png',
|
||||
),
|
||||
).toBe('static/media/image.png');
|
||||
@ -188,5 +215,33 @@ describe('entries', () => {
|
||||
),
|
||||
).toBe('../../static/media/image.png');
|
||||
});
|
||||
|
||||
it('should resolve public folder template', () => {
|
||||
const slugConfig = {
|
||||
encoding: 'unicode',
|
||||
clean_accents: false,
|
||||
sanitize_replacement: '-',
|
||||
};
|
||||
|
||||
const entry = fromJS({
|
||||
path: 'content/en/hosting-and-deployment/deployment-with-nanobox.md',
|
||||
data: { title: 'Deployment With NanoBox', category: 'Hosting And Deployment' },
|
||||
});
|
||||
const collection = fromJS({
|
||||
name: 'posts',
|
||||
folder: 'content',
|
||||
public_folder: '/{{public_folder}}/{{category}}/{{slug}}',
|
||||
fields: [{ name: 'title', widget: 'string' }],
|
||||
});
|
||||
|
||||
expect(
|
||||
selectMediaFilePublicPath(
|
||||
fromJS({ public_folder: 'static/media', slug: slugConfig }),
|
||||
collection,
|
||||
'image.png',
|
||||
entry,
|
||||
),
|
||||
).toEqual('/static/media/hosting-and-deployment/deployment-with-nanobox/image.png');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
ENTRIES_FAILURE,
|
||||
ENTRY_DELETE_SUCCESS,
|
||||
} from '../actions/entries';
|
||||
|
||||
import { SEARCH_ENTRIES_SUCCESS } from '../actions/search';
|
||||
import {
|
||||
EntriesAction,
|
||||
@ -24,8 +23,10 @@ import {
|
||||
EntryDeletePayload,
|
||||
EntriesRequestPayload,
|
||||
EntryDraft,
|
||||
EntryMap,
|
||||
} from '../types/redux';
|
||||
import { isAbsolutePath, basename } from 'netlify-cms-lib-util/src';
|
||||
import { folderFormatter } from '../lib/formatters';
|
||||
import { isAbsolutePath, basename } from 'netlify-cms-lib-util';
|
||||
|
||||
let collection: string;
|
||||
let loadedEntries: EntryObject[];
|
||||
@ -140,14 +141,23 @@ const DRAFT_MEDIA_FILES = 'DRAFT_MEDIA_FILES';
|
||||
export const selectMediaFolder = (
|
||||
config: Config,
|
||||
collection: Collection | null,
|
||||
entryPath: string | null,
|
||||
entryMap: EntryMap | undefined,
|
||||
) => {
|
||||
let mediaFolder = config.get('media_folder');
|
||||
|
||||
if (collection && collection.has('media_folder')) {
|
||||
const entryPath = entryMap?.get('path');
|
||||
if (entryPath) {
|
||||
const entryDir = dirname(entryPath);
|
||||
mediaFolder = join(entryDir, collection.get('media_folder') as string);
|
||||
const folder = folderFormatter(
|
||||
collection.get('media_folder') as string,
|
||||
entryMap as EntryMap,
|
||||
collection,
|
||||
mediaFolder,
|
||||
'media_folder',
|
||||
config.get('slug'),
|
||||
);
|
||||
mediaFolder = join(entryDir, folder as string);
|
||||
} else {
|
||||
mediaFolder = join(collection.get('folder') as string, DRAFT_MEDIA_FILES);
|
||||
}
|
||||
@ -159,7 +169,7 @@ export const selectMediaFolder = (
|
||||
export const selectMediaFilePath = (
|
||||
config: Config,
|
||||
collection: Collection | null,
|
||||
entryPath: string | null,
|
||||
entryMap: EntryMap | undefined,
|
||||
mediaPath: string,
|
||||
) => {
|
||||
if (isAbsolutePath(mediaPath)) {
|
||||
@ -169,9 +179,9 @@ export const selectMediaFilePath = (
|
||||
let mediaFolder;
|
||||
if (mediaPath.startsWith('/')) {
|
||||
// absolute media paths are not bound to a collection
|
||||
mediaFolder = selectMediaFolder(config, null, null);
|
||||
mediaFolder = selectMediaFolder(config, null, entryMap);
|
||||
} else {
|
||||
mediaFolder = selectMediaFolder(config, collection, entryPath);
|
||||
mediaFolder = selectMediaFolder(config, collection, entryMap);
|
||||
}
|
||||
|
||||
return join(mediaFolder, basename(mediaPath));
|
||||
@ -181,6 +191,7 @@ export const selectMediaFilePublicPath = (
|
||||
config: Config,
|
||||
collection: Collection | null,
|
||||
mediaPath: string,
|
||||
entryMap: EntryMap | undefined,
|
||||
) => {
|
||||
if (isAbsolutePath(mediaPath)) {
|
||||
return mediaPath;
|
||||
@ -189,7 +200,14 @@ export const selectMediaFilePublicPath = (
|
||||
let publicFolder = config.get('public_folder');
|
||||
|
||||
if (collection && collection.has('public_folder')) {
|
||||
publicFolder = collection.get('public_folder') as string;
|
||||
publicFolder = folderFormatter(
|
||||
collection.get('public_folder') as string,
|
||||
entryMap,
|
||||
collection,
|
||||
publicFolder,
|
||||
'public_folder',
|
||||
config.get('slug'),
|
||||
);
|
||||
}
|
||||
|
||||
return join(publicFolder, basename(mediaPath));
|
||||
|
Reference in New Issue
Block a user