diff --git a/packages/netlify-cms-core/package.json b/packages/netlify-cms-core/package.json index 9bb2094e..5058fc29 100644 --- a/packages/netlify-cms-core/package.json +++ b/packages/netlify-cms-core/package.json @@ -68,6 +68,7 @@ "semaphore": "^1.0.5", "tomlify-j0.4": "^3.0.0-alpha.0", "url": "^0.11.0", + "url-join": "^4.0.1", "what-input": "^5.1.4", "yaml": "^1.8.3" }, @@ -90,6 +91,7 @@ "devDependencies": { "@types/history": "^4.7.8", "@types/redux-mock-store": "^1.0.2", + "@types/url-join": "^4.0.0", "redux-mock-store": "^1.5.3" } } diff --git a/packages/netlify-cms-core/src/lib/urlHelper.ts b/packages/netlify-cms-core/src/lib/urlHelper.ts index bf089527..4f30a814 100644 --- a/packages/netlify-cms-core/src/lib/urlHelper.ts +++ b/packages/netlify-cms-core/src/lib/urlHelper.ts @@ -1,4 +1,5 @@ import url from 'url'; +import urlJoin from 'url-join'; import diacritics from 'diacritics'; import sanitizeFilename from 'sanitize-filename'; import { isString, escapeRegExp, flow, partialRight } from 'lodash'; @@ -115,3 +116,7 @@ export function sanitizeSlug(str: string, options?: CmsSlug) { return normalizedSlug; } + +export function joinUrlPath(base: string, ...path: string[]) { + return urlJoin(base, ...path); +} 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 f5d31448..02ccc312 100644 --- a/packages/netlify-cms-core/src/reducers/__tests__/entries.spec.js +++ b/packages/netlify-cms-core/src/reducers/__tests__/entries.spec.js @@ -435,6 +435,22 @@ describe('entries', () => { ).toBe('../../static/media/image.png'); }); + it('should handle absolute public_folder', () => { + expect( + selectMediaFilePublicPath( + { public_folder: 'https://www.netlify.com/media' }, + fromJS({ + name: 'posts', + folder: 'posts', + public_folder: 'https://www.netlify.com/media', + }), + 'image.png', + undefined, + undefined, + ), + ).toBe('https://www.netlify.com/media/image.png'); + }); + it('should compile collection public folder template', () => { const slugConfig = { encoding: 'unicode', diff --git a/packages/netlify-cms-core/src/reducers/entries.ts b/packages/netlify-cms-core/src/reducers/entries.ts index 12ceeb66..c348df3e 100644 --- a/packages/netlify-cms-core/src/reducers/entries.ts +++ b/packages/netlify-cms-core/src/reducers/entries.ts @@ -59,6 +59,7 @@ import { trim, once, sortBy, set, orderBy, groupBy } from 'lodash'; import { selectSortDataPath } from './collections'; import { stringTemplate } from 'netlify-cms-lib-widgets'; import { VIEW_STYLE_LIST } from '../constants/collectionViews'; +import { joinUrlPath } from '../lib/urlHelper'; const { keyToPathArray } = stringTemplate; @@ -790,6 +791,10 @@ export function selectMediaFilePublicPath( publicFolder = evaluateFolder(name, config, collection!, entryMap, field); } + if (isAbsolutePath(publicFolder)) { + return joinUrlPath(publicFolder, basename(mediaPath)); + } + return join(publicFolder, basename(mediaPath)); } diff --git a/website/content/docs/configuration-options.md b/website/content/docs/configuration-options.md index 6779b0fa..7c6500be 100644 --- a/website/content/docs/configuration-options.md +++ b/website/content/docs/configuration-options.md @@ -73,6 +73,8 @@ 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`. +This setting can be set to an absolute URL e.g. `https://netlify.com/media` should you wish, however in general this is not advisable as content should have relative paths to other content. + ## Media Library Media library integrations are configured via the `media_library` property, and its value should be an object with at least a `name` property. A `config` property can also be used for options that should be passed to the library in use. diff --git a/yarn.lock b/yarn.lock index 95150f19..5589e0be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3688,6 +3688,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== +"@types/url-join@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/url-join/-/url-join-4.0.0.tgz#72eff71648a429c7d4acf94e03780e06671369bd" + integrity sha512-awrJu8yML4E/xTwr2EMatC+HBnHGoDxc2+ImA9QyeUELI1S7dOCIZcyjki1rkwoA8P2D2NVgLAJLjnclkdLtAw== + "@types/uuid@^3.4.6": version "3.4.9" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.9.tgz#fcf01997bbc9f7c09ae5f91383af076d466594e1" @@ -18367,6 +18372,11 @@ url-join@^2.0.5: resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728" integrity sha1-WvIvGMBSoACkjXuCxenC4v7tpyg= +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + url-loader@^2.0.1: version "2.3.0" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.3.0.tgz#e0e2ef658f003efb8ca41b0f3ffbf76bab88658b"