diff --git a/babel.config.js b/babel.config.js
index 9974bb8e..90242cab 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,3 +1,4 @@
+const path = require('path');
const isProduction = process.env.NODE_ENV === 'production';
const isTest = process.env.NODE_ENV === 'test';
@@ -29,6 +30,24 @@ const plugins = () => {
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-proposal-export-default-from',
+ [
+ 'module-resolver',
+ {
+ root: path.join(__dirname, 'packages/netlify-cms-core/src/components'),
+ alias: {
+ coreSrc: path.join(__dirname, 'packages/netlify-cms-core/src'),
+ Actions: path.join(__dirname, 'packages/netlify-cms-core/src/actions/'),
+ Constants: path.join(__dirname, 'packages/netlify-cms-core/src/constants/'),
+ Formats: path.join(__dirname, 'packages/netlify-cms-core/src/formats/'),
+ Integrations: path.join(__dirname, 'packages/netlify-cms-core/src/integrations/'),
+ Lib: path.join(__dirname, 'packages/netlify-cms-core/src/lib/'),
+ Reducers: path.join(__dirname, 'packages/netlify-cms-core/src/reducers/'),
+ Redux: path.join(__dirname, 'packages/netlify-cms-core/src/redux/'),
+ Routing: path.join(__dirname, 'packages/netlify-cms-core/src/routing/'),
+ ValueObjects: path.join(__dirname, 'packages/netlify-cms-core/src/valueObjects/'),
+ },
+ },
+ ],
];
if (isProduction) {
@@ -65,6 +84,7 @@ const plugins = () => {
];
}
+ defaultPlugins.push('react-hot-loader/babel');
return [
...defaultPlugins,
[
diff --git a/custom-preprocessor.js b/custom-preprocessor.js
index 43a27e2a..55708a3c 100644
--- a/custom-preprocessor.js
+++ b/custom-preprocessor.js
@@ -1,4 +1,4 @@
const babelJest = require('babel-jest');
-const babelConfig = require('./packages/netlify-cms-core/babel.config.js');
+const babelConfig = require('./babel.config.js');
module.exports = babelJest.createTransformer(babelConfig);
diff --git a/package.json b/package.json
index fab8491e..b7fe6f17 100644
--- a/package.json
+++ b/package.json
@@ -82,7 +82,9 @@
"babel-plugin-transform-export-extensions": "^6.22.0",
"babel-plugin-transform-inline-environment-variables": "^0.4.3",
"cache-me-outside": "^0.0.4",
- "cross-env": "^5.1.4",
+ "copy-webpack-plugin": "^5.0.1",
+ "cross-env": "^5.2.0",
+ "css-loader": "^2.1.1",
"cypress": "^3.1.5",
"dom-testing-library": "^3.17.1",
"eslint": "^5.15.1",
@@ -92,18 +94,24 @@
"http-server": "^0.11.1",
"jest": "^24.5.0",
"jest-cli": "^24.5.0",
+ "jest-dom": "^3.1.3",
"jest-emotion": "^10.0.9",
"lerna": "^3.13.1",
"npm-run-all": "^4.1.5",
"prettier": "1.16.4",
"react-test-renderer": "^16.8.4",
+ "react-testing-library": "^6.0.0",
"rimraf": "^2.6.3",
"start-server-and-test": "^1.7.11",
"stylelint": "^9.10.1",
"stylelint-config-recommended": "^2.1.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-processor-styled-components": "^1.5.2",
- "svg-inline-loader": "^0.8.0"
+ "svg-inline-loader": "^0.8.0",
+ "to-string-loader": "^1.1.5",
+ "webpack": "^4.29.6",
+ "webpack-cli": "^3.2.3",
+ "webpack-dev-server": "^3.2.1"
},
"workspaces": [
"packages/*"
diff --git a/packages/netlify-cms-backend-bitbucket/package.json b/packages/netlify-cms-backend-bitbucket/package.json
index 3b626f5d..e65af9cb 100644
--- a/packages/netlify-cms-backend-bitbucket/package.json
+++ b/packages/netlify-cms-backend-bitbucket/package.json
@@ -22,20 +22,15 @@
"js-base64": "^2.5.1",
"semaphore": "^1.1.0"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "lodash": "^4.17.10",
- "netlify-cms-lib-auth": "^2.0.4",
- "netlify-cms-lib-util": "^2.1.0",
- "netlify-cms-ui-default": "^2.0.6",
- "prop-types": "^15.6.2",
- "react": "^16.4.1"
+ "lodash": "^4.17.11",
+ "netlify-cms-lib-auth": "^2.0.6-beta.0",
+ "netlify-cms-lib-util": "^2.1.3-beta.0",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-backend-bitbucket/src/implementation.js b/packages/netlify-cms-backend-bitbucket/src/implementation.js
index 798cd404..6c28cacd 100644
--- a/packages/netlify-cms-backend-bitbucket/src/implementation.js
+++ b/packages/netlify-cms-backend-bitbucket/src/implementation.js
@@ -15,7 +15,7 @@ import API from './API';
const MAX_CONCURRENT_DOWNLOADS = 10;
// Implementation wrapper class
-export default class Bitbucket {
+export default class BitbucketBackend {
constructor(config, options = {}) {
this.config = config;
this.options = {
diff --git a/packages/netlify-cms-backend-bitbucket/src/index.js b/packages/netlify-cms-backend-bitbucket/src/index.js
index d5bebfa2..45139e5c 100644
--- a/packages/netlify-cms-backend-bitbucket/src/index.js
+++ b/packages/netlify-cms-backend-bitbucket/src/index.js
@@ -1,3 +1,10 @@
-export BitbucketBackend from './implementation';
-export API from './API';
-export AuthenticationPage from './AuthenticationPage';
+import Control from './implementation';
+import API from './API';
+import AuthenticationPage from './AuthenticationPage';
+
+export const NetlifyCmsBackendBitbucket = {
+ Control,
+ API,
+ AuthenticationPage,
+};
+export { Control, API, AuthenticationPage };
diff --git a/packages/netlify-cms-backend-git-gateway/package.json b/packages/netlify-cms-backend-git-gateway/package.json
index 777ef14c..08c401be 100644
--- a/packages/netlify-cms-backend-git-gateway/package.json
+++ b/packages/netlify-cms-backend-git-gateway/package.json
@@ -25,23 +25,18 @@
"jwt-decode": "^2.2.0",
"minimatch": "^3.0.4"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "lodash": "^4.17.10",
- "netlify-cms-backend-bitbucket": "^2.0.0",
- "netlify-cms-backend-github": "^2.0.0",
- "netlify-cms-backend-gitlab": "^2.0.0",
- "netlify-cms-lib-auth": "^2.0.0",
- "netlify-cms-lib-util": "^2.0.0",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.6.2",
- "react": "^16.4.1"
+ "lodash": "^4.17.11",
+ "netlify-cms-backend-bitbucket": "^2.1.3-beta.0",
+ "netlify-cms-backend-github": "^2.2.3-beta.0",
+ "netlify-cms-backend-gitlab": "^2.1.4-beta.0",
+ "netlify-cms-lib-auth": "^2.0.6-beta.0",
+ "netlify-cms-lib-util": "^2.1.3-beta.0",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-backend-git-gateway/src/implementation.js b/packages/netlify-cms-backend-git-gateway/src/implementation.js
index 97e7e7dd..5324fa91 100644
--- a/packages/netlify-cms-backend-git-gateway/src/implementation.js
+++ b/packages/netlify-cms-backend-git-gateway/src/implementation.js
@@ -5,7 +5,7 @@ import ini from 'ini';
import { APIError, getBlobSHA, unsentRequest } from 'netlify-cms-lib-util';
import { GitHubBackend } from 'netlify-cms-backend-github';
import { GitLabBackend } from 'netlify-cms-backend-gitlab';
-import { BitBucketBackend, API as BitBucketAPI } from 'netlify-cms-backend-bitbucket';
+import { BitbucketBackend, API as BitBucketAPI } from 'netlify-cms-backend-bitbucket';
import GitHubAPI from './GitHubAPI';
import GitLabAPI from './GitLabAPI';
import AuthenticationPage from './AuthenticationPage';
@@ -168,7 +168,7 @@ export default class GitGateway {
requestFunction: this.requestFunction,
hasWriteAccess: async () => true,
});
- this.backend = new BitBucketBackend(this.config, { ...this.options, API: this.api });
+ this.backend = new BitbucketBackend(this.config, { ...this.options, API: this.api });
}
if (!(await this.api.hasWriteAccess())) {
diff --git a/packages/netlify-cms-backend-git-gateway/src/index.js b/packages/netlify-cms-backend-git-gateway/src/index.js
index 59b7f092..20d203e7 100644
--- a/packages/netlify-cms-backend-git-gateway/src/index.js
+++ b/packages/netlify-cms-backend-git-gateway/src/index.js
@@ -1,2 +1,8 @@
-export GitGatewayBackend from './implementation';
-export AuthenticationPage from './AuthenticationPage';
+import Control from './implementation';
+import AuthenticationPage from './AuthenticationPage';
+
+export const NetlifyCmsBackendGitGateway = {
+ Control,
+ AuthenticationPage,
+};
+export { Control, AuthenticationPage };
diff --git a/packages/netlify-cms-backend-github/package.json b/packages/netlify-cms-backend-github/package.json
index c3bc8084..cdd723e0 100644
--- a/packages/netlify-cms-backend-github/package.json
+++ b/packages/netlify-cms-backend-github/package.json
@@ -23,19 +23,14 @@
"js-base64": "^2.5.1",
"semaphore": "^1.1.0"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
- "lodash": "^4.17.10",
- "netlify-cms-lib-auth": "^2.0.0",
- "netlify-cms-lib-util": "^2.0.0",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.6.2",
- "react": "^16.4.1"
+ "lodash": "^4.17.11",
+ "netlify-cms-lib-auth": "^2.0.6-beta.0",
+ "netlify-cms-lib-util": "^2.1.3-beta.0",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-backend-github/src/index.js b/packages/netlify-cms-backend-github/src/index.js
index 6ccfbd0f..16d2b858 100644
--- a/packages/netlify-cms-backend-github/src/index.js
+++ b/packages/netlify-cms-backend-github/src/index.js
@@ -1,3 +1,10 @@
-export GitHubBackend from './implementation';
-export API from './API';
-export AuthenticationPage from './AuthenticationPage';
+import Control from './implementation';
+import API from './API';
+import AuthenticationPage from './AuthenticationPage';
+
+export const NetlifyCmsBackendGithub = {
+ Control,
+ API,
+ AuthenticationPage,
+};
+export { Control, API, AuthenticationPage };
diff --git a/packages/netlify-cms-backend-gitlab/package.json b/packages/netlify-cms-backend-gitlab/package.json
index 01756ad6..ceb0de17 100644
--- a/packages/netlify-cms-backend-gitlab/package.json
+++ b/packages/netlify-cms-backend-gitlab/package.json
@@ -22,20 +22,15 @@
"js-base64": "^2.5.1",
"semaphore": "^1.1.0"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "lodash": "^4.17.10",
- "netlify-cms-lib-auth": "^2.0.0",
- "netlify-cms-lib-util": "^2.0.0",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.6.2",
- "react": "^16.4.1"
+ "lodash": "^4.17.11",
+ "netlify-cms-lib-auth": "^2.0.6-beta.0",
+ "netlify-cms-lib-util": "^2.1.3-beta.0",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-backend-gitlab/src/index.js b/packages/netlify-cms-backend-gitlab/src/index.js
index a87fc489..30b047e7 100644
--- a/packages/netlify-cms-backend-gitlab/src/index.js
+++ b/packages/netlify-cms-backend-gitlab/src/index.js
@@ -1,3 +1,10 @@
-export GitLabBackend from './implementation';
-export API from './API';
-export AuthenticationPage from './AuthenticationPage';
+import Control from './implementation';
+import API from './API';
+import AuthenticationPage from './AuthenticationPage';
+
+export const NetlifyCmsBackendGitlab = {
+ Control,
+ API,
+ AuthenticationPage,
+};
+export { Control, API, AuthenticationPage };
diff --git a/packages/netlify-cms-backend-test/package.json b/packages/netlify-cms-backend-test/package.json
index bd22da50..ad9bc151 100644
--- a/packages/netlify-cms-backend-test/package.json
+++ b/packages/netlify-cms-backend-test/package.json
@@ -17,23 +17,16 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "dependencies": {
- "uuid": "^3.3.2"
- },
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.8.2",
- "lodash": "^4.17.10",
- "netlify-cms-lib-util": "^2.0.0",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.6.2",
- "react": "^16.4.1",
- "react-immutable-proptypes": "^2.1.0"
+ "lodash": "^4.17.11",
+ "netlify-cms-lib-util": "^2.1.3-beta.0",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
+ "react-immutable-proptypes": "^2.1.0",
+ "uuid": "^3.3.2"
}
}
diff --git a/packages/netlify-cms-backend-test/src/implementation.js b/packages/netlify-cms-backend-test/src/implementation.js
index db1f852d..770c51fa 100644
--- a/packages/netlify-cms-backend-test/src/implementation.js
+++ b/packages/netlify-cms-backend-test/src/implementation.js
@@ -40,7 +40,7 @@ const getFolderEntries = (folder, extension) => {
.reverse();
};
-export default class TestRepo {
+export default class TestBackend {
constructor(config, options = {}) {
this.config = config;
this.assets = [];
diff --git a/packages/netlify-cms-backend-test/src/index.js b/packages/netlify-cms-backend-test/src/index.js
index 7cf84be9..5d35d8cb 100644
--- a/packages/netlify-cms-backend-test/src/index.js
+++ b/packages/netlify-cms-backend-test/src/index.js
@@ -1,2 +1,8 @@
-export TestBackend from './implementation';
-export AuthenticationPage from './AuthenticationPage';
+import Control from './implementation';
+import AuthenticationPage from './AuthenticationPage';
+
+export const NetlifyCmsBackendTest = {
+ Control,
+ AuthenticationPage,
+};
+export { Control, AuthenticationPage };
diff --git a/packages/netlify-cms-core/babel.config.js b/packages/netlify-cms-core/babel.config.js
deleted file mode 100644
index bf48e647..00000000
--- a/packages/netlify-cms-core/babel.config.js
+++ /dev/null
@@ -1,28 +0,0 @@
-const path = require('path');
-const babelConfig = require('../../babel.config.js');
-
-module.exports = {
- ...babelConfig,
- plugins: [
- ...babelConfig.plugins,
- 'react-hot-loader/babel',
- [
- 'module-resolver',
- {
- root: path.join(__dirname, 'src/components'),
- alias: {
- src: path.join(__dirname, 'src'),
- Actions: path.join(__dirname, 'src/actions/'),
- Constants: path.join(__dirname, 'src/constants/'),
- Formats: path.join(__dirname, 'src/formats/'),
- Integrations: path.join(__dirname, 'src/integrations/'),
- Lib: path.join(__dirname, 'src/lib/'),
- Reducers: path.join(__dirname, 'src/reducers/'),
- Redux: path.join(__dirname, 'src/redux/'),
- Routing: path.join(__dirname, 'src/routing/'),
- ValueObjects: path.join(__dirname, 'src/valueObjects/'),
- },
- },
- ],
- ],
-};
diff --git a/packages/netlify-cms-core/package.json b/packages/netlify-cms-core/package.json
index e6d9334f..5fb83198 100644
--- a/packages/netlify-cms-core/package.json
+++ b/packages/netlify-cms-core/package.json
@@ -19,8 +19,6 @@
],
"license": "MIT",
"dependencies": {
- "@emotion/core": "^10.0.9",
- "@emotion/styled": "^10.0.9",
"ajv": "^6.10.0",
"ajv-errors": "^1.0.1",
"copy-text-to-clipboard": "^2.0.0",
@@ -29,16 +27,9 @@
"gotrue-js": "^0.9.24",
"gray-matter": "^4.0.2",
"history": "^4.7.2",
- "immutable": "^3.7.6",
"js-base64": "^2.5.1",
"js-yaml": "^3.12.2",
"jwt-decode": "^2.1.0",
- "lodash": "^4.17.11",
- "moment": "^2.24.0",
- "netlify-cms-editor-component-image": "^2.2.1-beta.0",
- "netlify-cms-lib-auth": "^2.0.6-beta.0",
- "netlify-cms-lib-util": "^2.1.3-beta.0",
- "netlify-cms-ui-default": "^2.4.1-beta.0",
"node-polyglot": "^2.3.0",
"prop-types": "^15.7.2",
"react": "^16.8.4",
@@ -70,11 +61,19 @@
"url": "^0.11.0",
"what-input": "^5.1.4"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "css-loader": "^2.1.1",
- "to-string-loader": "^1.1.5",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
+ "peerDependencies": {
+ "@emotion/core": "^10.0.9",
+ "@emotion/styled": "^10.0.9",
+ "lodash": "^4.17.11",
+ "netlify-cms-editor-component-image": "^2.2.1-beta.0",
+ "netlify-cms-lib-auth": "^2.0.6-beta.0",
+ "netlify-cms-lib-util": "^2.1.3-beta.0",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "moment": "^2.24.0",
+ "immutable": "^3.7.6",
+ "prop-types": "^15.7.2",
+ "react-immutable-proptypes": "^2.1.0",
+ "react": "^16.8.4",
+ "react-dom": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-core/src/actions/auth.js b/packages/netlify-cms-core/src/actions/auth.js
index ce7479b2..ef7a19c6 100644
--- a/packages/netlify-cms-core/src/actions/auth.js
+++ b/packages/netlify-cms-core/src/actions/auth.js
@@ -1,5 +1,5 @@
import { actions as notifActions } from 'redux-notifications';
-import { currentBackend } from 'src/backend';
+import { currentBackend } from 'coreSrc/backend';
const { notifSend } = notifActions;
diff --git a/packages/netlify-cms-core/src/actions/deploys.js b/packages/netlify-cms-core/src/actions/deploys.js
index 31fbc0dd..a956d196 100644
--- a/packages/netlify-cms-core/src/actions/deploys.js
+++ b/packages/netlify-cms-core/src/actions/deploys.js
@@ -1,5 +1,5 @@
import { actions as notifActions } from 'redux-notifications';
-import { currentBackend } from 'src/backend';
+import { currentBackend } from 'coreSrc/backend';
import { selectDeployPreview } from 'Reducers';
const { notifSend } = notifActions;
diff --git a/packages/netlify-cms-core/src/actions/editorialWorkflow.js b/packages/netlify-cms-core/src/actions/editorialWorkflow.js
index 8f264c62..664489a1 100644
--- a/packages/netlify-cms-core/src/actions/editorialWorkflow.js
+++ b/packages/netlify-cms-core/src/actions/editorialWorkflow.js
@@ -2,7 +2,7 @@ import uuid from 'uuid/v4';
import { actions as notifActions } from 'redux-notifications';
import { BEGIN, COMMIT, REVERT } from 'redux-optimist';
import { serializeValues } from 'Lib/serializeEntryValues';
-import { currentBackend } from 'src/backend';
+import { currentBackend } from 'coreSrc/backend';
import { getAsset } from 'Reducers';
import { selectFields } from 'Reducers/collections';
import { EDITORIAL_WORKFLOW } from 'Constants/publishModes';
diff --git a/packages/netlify-cms-core/src/actions/entries.js b/packages/netlify-cms-core/src/actions/entries.js
index 46edf959..9529ce25 100644
--- a/packages/netlify-cms-core/src/actions/entries.js
+++ b/packages/netlify-cms-core/src/actions/entries.js
@@ -1,7 +1,7 @@
import { fromJS, List, Map } from 'immutable';
import { actions as notifActions } from 'redux-notifications';
import { serializeValues } from 'Lib/serializeEntryValues';
-import { currentBackend } from 'src/backend';
+import { currentBackend } from 'coreSrc/backend';
import { getIntegrationProvider } from 'Integrations';
import { getAsset, selectIntegration } from 'Reducers';
import { selectFields } from 'Reducers/collections';
diff --git a/packages/netlify-cms-core/src/actions/mediaLibrary.js b/packages/netlify-cms-core/src/actions/mediaLibrary.js
index 1b469e8d..1f2ed61d 100644
--- a/packages/netlify-cms-core/src/actions/mediaLibrary.js
+++ b/packages/netlify-cms-core/src/actions/mediaLibrary.js
@@ -1,7 +1,7 @@
import { Map } from 'immutable';
import { actions as notifActions } from 'redux-notifications';
import { getBlobSHA } from 'netlify-cms-lib-util';
-import { currentBackend } from 'src/backend';
+import { currentBackend } from 'coreSrc/backend';
import { createAssetProxy } from 'ValueObjects/AssetProxy';
import { selectIntegration } from 'Reducers';
import { getIntegrationProvider } from 'Integrations';
diff --git a/packages/netlify-cms-core/src/actions/search.js b/packages/netlify-cms-core/src/actions/search.js
index eacb0905..16c92dee 100644
--- a/packages/netlify-cms-core/src/actions/search.js
+++ b/packages/netlify-cms-core/src/actions/search.js
@@ -1,4 +1,4 @@
-import { currentBackend } from 'src/backend';
+import { currentBackend } from 'coreSrc/backend';
import { getIntegrationProvider } from 'Integrations';
import { selectIntegration } from 'Reducers';
diff --git a/packages/netlify-cms-core/src/bootstrap.js b/packages/netlify-cms-core/src/bootstrap.js
index a7e5c72d..e35a8afb 100644
--- a/packages/netlify-cms-core/src/bootstrap.js
+++ b/packages/netlify-cms-core/src/bootstrap.js
@@ -12,7 +12,7 @@ import { GlobalStyles } from 'netlify-cms-ui-default';
import { ErrorBoundary } from 'UI';
import App from 'App/App';
import 'EditorWidgets';
-import 'src/mediaLibrary';
+import 'coreSrc/mediaLibrary';
import 'what-input';
const ROOT_ID = 'nc-root';
diff --git a/packages/netlify-cms-core/src/components/App/App.js b/packages/netlify-cms-core/src/components/App/App.js
index e7a42d6f..e0d06b7f 100644
--- a/packages/netlify-cms-core/src/components/App/App.js
+++ b/packages/netlify-cms-core/src/components/App/App.js
@@ -10,7 +10,7 @@ import { Notifs } from 'redux-notifications';
import TopBarProgress from 'react-topbar-progress-indicator';
import { loadConfig } from 'Actions/config';
import { loginUser, logoutUser } from 'Actions/auth';
-import { currentBackend } from 'src/backend';
+import { currentBackend } from 'coreSrc/backend';
import { createNewEntry } from 'Actions/collections';
import { openMediaLibrary } from 'Actions/mediaLibrary';
import MediaLibrary from 'MediaLibrary/MediaLibrary';
diff --git a/packages/netlify-cms-core/src/index.js b/packages/netlify-cms-core/src/index.js
index b74d5d4f..36c4307f 100644
--- a/packages/netlify-cms-core/src/index.js
+++ b/packages/netlify-cms-core/src/index.js
@@ -1,4 +1,55 @@
import bootstrap from './bootstrap';
-import registry from 'Lib/registry';
+import {
+ registerPreviewStyle,
+ getPreviewStyles,
+ registerPreviewTemplate,
+ getPreviewTemplate,
+ registerWidget,
+ getWidget,
+ resolveWidget,
+ registerEditorComponent,
+ getEditorComponents,
+ registerWidgetValueSerializer,
+ getWidgetValueSerializer,
+ registerBackend,
+ getBackend,
+ registerMediaLibrary,
+ getMediaLibrary,
+} from 'Lib/registry';
-export { registry as default, bootstrap as init };
+export const NetlifyCmsCore = {
+ registerPreviewStyle,
+ getPreviewStyles,
+ registerPreviewTemplate,
+ getPreviewTemplate,
+ registerWidget,
+ getWidget,
+ resolveWidget,
+ registerEditorComponent,
+ getEditorComponents,
+ registerWidgetValueSerializer,
+ getWidgetValueSerializer,
+ registerBackend,
+ getBackend,
+ registerMediaLibrary,
+ getMediaLibrary,
+ init: bootstrap,
+};
+export {
+ registerPreviewStyle,
+ getPreviewStyles,
+ registerPreviewTemplate,
+ getPreviewTemplate,
+ registerWidget,
+ getWidget,
+ resolveWidget,
+ registerEditorComponent,
+ getEditorComponents,
+ registerWidgetValueSerializer,
+ getWidgetValueSerializer,
+ registerBackend,
+ getBackend,
+ registerMediaLibrary,
+ getMediaLibrary,
+ bootstrap as init,
+};
diff --git a/packages/netlify-cms-core/src/valueObjects/AssetProxy.js b/packages/netlify-cms-core/src/valueObjects/AssetProxy.js
index 79d69f73..98b86ec1 100644
--- a/packages/netlify-cms-core/src/valueObjects/AssetProxy.js
+++ b/packages/netlify-cms-core/src/valueObjects/AssetProxy.js
@@ -1,5 +1,5 @@
import { resolvePath } from 'netlify-cms-lib-util';
-import { currentBackend } from 'src/backend';
+import { currentBackend } from 'coreSrc/backend';
import store from 'Redux';
import { getIntegrationProvider } from 'Integrations';
import { selectIntegration } from 'Reducers';
diff --git a/packages/netlify-cms-core/webpack.config.js b/packages/netlify-cms-core/webpack.config.js
index 92a5d71b..8dd01cad 100644
--- a/packages/netlify-cms-core/webpack.config.js
+++ b/packages/netlify-cms-core/webpack.config.js
@@ -1,43 +1,21 @@
-const path = require('path');
const webpack = require('webpack');
const pkg = require('./package.json');
-const { getConfig, rules } = require('../../scripts/webpack.js');
+const { getConfig } = require('../../scripts/webpack.js');
const isProduction = process.env.NODE_ENV === 'production';
-const baseConfig = getConfig();
+const versionPlugin = new webpack.DefinePlugin({
+ NETLIFY_CMS_VERSION: null,
+ NETLIFY_CMS_CORE_VERSION: JSON.stringify(`${pkg.version}${isProduction ? '' : '-dev'}`),
+});
-module.exports = {
- ...baseConfig,
- context: path.join(__dirname, 'src'),
- entry: ['./index.js'],
- module: {
- rules: [
- ...Object.entries(rules)
- .filter(([key]) => key !== 'js')
- .map(([, rule]) => rule()),
- {
- test: /\.js$/,
- exclude: /node_modules/,
- use: {
- loader: 'babel-loader',
- options: {
- configFile: path.join(__dirname, 'babel.config.js'),
- },
- },
- },
- {
- test: /\.css$/,
- include: [/(ol|redux-notifications|react-datetime)/],
- use: ['to-string-loader', 'css-loader'],
- },
- ],
- },
- plugins: [
- ...baseConfig.plugins,
- new webpack.DefinePlugin({
- NETLIFY_CMS_VERSION: null,
- NETLIFY_CMS_CORE_VERSION: JSON.stringify(`${pkg.version}${isProduction ? '' : '-dev'}`),
- }),
- ],
+const configs = () => {
+ return getConfig().map(config => {
+ return {
+ ...config,
+ plugins: [...config.plugins, versionPlugin],
+ };
+ });
};
+
+module.exports = configs();
diff --git a/packages/netlify-cms-default-exports/package.json b/packages/netlify-cms-default-exports/package.json
new file mode 100644
index 00000000..5f394a62
--- /dev/null
+++ b/packages/netlify-cms-default-exports/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "netlify-cms-default-exports",
+ "version": "2.0.1",
+ "description": "NetlifyCMS default exports",
+ "repository": "https://github.com/netlify/netlify-cms/tree/master/packages/netlify-cms-default-exports",
+ "bugs": "https://github.com/netlify/netlify-cms/issues",
+ "main": "dist/netlify-cms-editor-component-image.js",
+ "license": "MIT",
+ "keywords": [
+ "netlify",
+ "netlify-cms",
+ "editor",
+ "component"
+ ],
+ "sideEffects": false,
+ "scripts": {
+ "watch": "webpack -w",
+ "develop": "npm run watch",
+ "build": "cross-env NODE_ENV=production webpack",
+ "build:dev": "cross-env NODE_ENV=development webpack"
+ },
+ "dependencies": {
+ "@emotion/core": "^10.0.9",
+ "@emotion/styled": "^10.0.9",
+ "immutable": "^3.7.6",
+ "lodash": "^4.17.11",
+ "moment": "^2.24.0",
+ "prop-types": "^15.7.2",
+ "react-immutable-proptypes": "^2.1.0",
+ "uuid": "^3.3.2"
+ },
+ "peerDependencies": {
+ "react": "^16.8.4",
+ "react-dom": "^16.8.4"
+ }
+}
diff --git a/packages/netlify-cms-default-exports/src/index.js b/packages/netlify-cms-default-exports/src/index.js
new file mode 100644
index 00000000..35864f85
--- /dev/null
+++ b/packages/netlify-cms-default-exports/src/index.js
@@ -0,0 +1,54 @@
+import css from '@emotion/css';
+import {
+ withEmotionCache,
+ CacheProvider,
+ ThemeContext,
+ jsx,
+ Global,
+ keyframes,
+ ClassNames,
+} from '@emotion/core';
+import EmotionStyled from '@emotion/styled';
+import Immutable from 'immutable';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import Lodash from 'lodash/lodash';
+import Moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+import ReactDOM from 'react-dom';
+import * as UUId from 'uuid';
+
+const EmotionCore = {
+ css,
+ withEmotionCache,
+ CacheProvider,
+ ThemeContext,
+ jsx,
+ Global,
+ keyframes,
+ ClassNames,
+};
+export const NetlifyCmsDefaultExports = {
+ EmotionCore,
+ EmotionStyled,
+ Immutable,
+ ImmutablePropTypes,
+ Lodash,
+ Moment,
+ PropTypes,
+ React,
+ ReactDOM,
+ UUId,
+};
+export {
+ EmotionCore,
+ EmotionStyled,
+ Immutable,
+ ImmutablePropTypes,
+ Lodash,
+ Moment,
+ PropTypes,
+ React,
+ ReactDOM,
+ UUId,
+};
diff --git a/packages/netlify-cms-default-exports/webpack.config.js b/packages/netlify-cms-default-exports/webpack.config.js
new file mode 100644
index 00000000..42edd361
--- /dev/null
+++ b/packages/netlify-cms-default-exports/webpack.config.js
@@ -0,0 +1,3 @@
+const { getConfig } = require('../../scripts/webpack.js');
+
+module.exports = getConfig();
diff --git a/packages/netlify-cms-editor-component-image/package.json b/packages/netlify-cms-editor-component-image/package.json
index bf993821..67dfe834 100644
--- a/packages/netlify-cms-editor-component-image/package.json
+++ b/packages/netlify-cms-editor-component-image/package.json
@@ -24,6 +24,6 @@
"webpack-cli": "^3.2.3"
},
"peerDependencies": {
- "react": "^16.4.1"
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-editor-component-image/src/index.js b/packages/netlify-cms-editor-component-image/src/index.js
index 10dd83d8..bf57d56f 100644
--- a/packages/netlify-cms-editor-component-image/src/index.js
+++ b/packages/netlify-cms-editor-component-image/src/index.js
@@ -36,4 +36,5 @@ const image = {
],
};
+export const NetlifyCmsEditorComponentImage = image;
export default image;
diff --git a/packages/netlify-cms-lib-auth/package.json b/packages/netlify-cms-lib-auth/package.json
index 5efbfcd8..a6f5ece1 100644
--- a/packages/netlify-cms-lib-auth/package.json
+++ b/packages/netlify-cms-lib-auth/package.json
@@ -22,13 +22,8 @@
"dependencies": {
"uuid": "^3.1.0"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"immutable": "^3.7.6",
- "lodash": "^4.13.1"
+ "lodash": "^4.17.11"
}
}
diff --git a/packages/netlify-cms-lib-auth/src/index.js b/packages/netlify-cms-lib-auth/src/index.js
index 98c601fc..0cd6f7ee 100644
--- a/packages/netlify-cms-lib-auth/src/index.js
+++ b/packages/netlify-cms-lib-auth/src/index.js
@@ -1,2 +1,4 @@
-export NetlifyAuthenticator from './netlify-auth';
-export ImplicitAuthenticator from './implicit-oauth';
+import NetlifyAuthenticator from './netlify-auth';
+import ImplicitAuthenticator from './implicit-oauth';
+export const NetlifyCmsLibAuth = { NetlifyAuthenticator, ImplicitAuthenticator };
+export { NetlifyAuthenticator, ImplicitAuthenticator };
diff --git a/packages/netlify-cms-lib-util/package.json b/packages/netlify-cms-lib-util/package.json
index 29ded504..223a4731 100644
--- a/packages/netlify-cms-lib-util/package.json
+++ b/packages/netlify-cms-lib-util/package.json
@@ -19,13 +19,8 @@
"js-sha256": "^0.9.0",
"localforage": "^1.7.3"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"immutable": "^3.7.6",
- "lodash": "^4.13.1"
+ "lodash": "^4.17.11"
}
}
diff --git a/packages/netlify-cms-lib-util/src/index.js b/packages/netlify-cms-lib-util/src/index.js
index 81cedfb7..5ff3b8a1 100644
--- a/packages/netlify-cms-lib-util/src/index.js
+++ b/packages/netlify-cms-lib-util/src/index.js
@@ -1,10 +1,53 @@
-export APIError from './APIError';
-export Cursor, { CURSOR_COMPATIBILITY_SYMBOL } from './Cursor';
-export EditorialWorkflowError, { EDITORIAL_WORKFLOW_ERROR } from './EditorialWorkflowError';
-export localForage from './localForage';
-export { resolvePath, basename, fileExtensionWithSeparator, fileExtension } from './path';
-export { filterPromises, resolvePromiseProperties, then } from './promise';
-export unsentRequest from './unsentRequest';
-export { filterByPropExtension, parseResponse, responseParser } from './backendUtil';
-export loadScript from './loadScript';
-export getBlobSHA from './getBlobSHA';
+import APIError from './APIError';
+import Cursor, { CURSOR_COMPATIBILITY_SYMBOL } from './Cursor';
+import EditorialWorkflowError, { EDITORIAL_WORKFLOW_ERROR } from './EditorialWorkflowError';
+import localForage from './localForage';
+import { resolvePath, basename, fileExtensionWithSeparator, fileExtension } from './path';
+import { filterPromises, resolvePromiseProperties, then } from './promise';
+import unsentRequest from './unsentRequest';
+import { filterByPropExtension, parseResponse, responseParser } from './backendUtil';
+import loadScript from './loadScript';
+import getBlobSHA from './getBlobSHA';
+
+export const NetlifyCmsLibUtil = {
+ APIError,
+ Cursor,
+ CURSOR_COMPATIBILITY_SYMBOL,
+ EditorialWorkflowError,
+ EDITORIAL_WORKFLOW_ERROR,
+ localForage,
+ resolvePath,
+ basename,
+ fileExtensionWithSeparator,
+ fileExtension,
+ filterPromises,
+ resolvePromiseProperties,
+ then,
+ unsentRequest,
+ filterByPropExtension,
+ parseResponse,
+ responseParser,
+ loadScript,
+ getBlobSHA,
+};
+export {
+ APIError,
+ Cursor,
+ CURSOR_COMPATIBILITY_SYMBOL,
+ EditorialWorkflowError,
+ EDITORIAL_WORKFLOW_ERROR,
+ localForage,
+ resolvePath,
+ basename,
+ fileExtensionWithSeparator,
+ fileExtension,
+ filterPromises,
+ resolvePromiseProperties,
+ then,
+ unsentRequest,
+ filterByPropExtension,
+ parseResponse,
+ responseParser,
+ loadScript,
+ getBlobSHA,
+};
diff --git a/packages/netlify-cms-media-library-cloudinary/package.json b/packages/netlify-cms-media-library-cloudinary/package.json
index 3e65d9cf..ac241cbe 100644
--- a/packages/netlify-cms-media-library-cloudinary/package.json
+++ b/packages/netlify-cms-media-library-cloudinary/package.json
@@ -23,12 +23,7 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
- "netlify-cms-lib-util": "^2.0.4"
+ "netlify-cms-lib-util": "^2.1.3-beta.0"
}
}
diff --git a/packages/netlify-cms-media-library-cloudinary/src/index.js b/packages/netlify-cms-media-library-cloudinary/src/index.js
index 62fbaff3..e9b9b350 100644
--- a/packages/netlify-cms-media-library-cloudinary/src/index.js
+++ b/packages/netlify-cms-media-library-cloudinary/src/index.js
@@ -83,4 +83,5 @@ async function init({ options = {}, handleInsert } = {}) {
const cloudinaryMediaLibrary = { name: 'cloudinary', init };
+export const NetlifyCmsMediaLibraryCloudinary = cloudinaryMediaLibrary;
export default cloudinaryMediaLibrary;
diff --git a/packages/netlify-cms-media-library-uploadcare/package.json b/packages/netlify-cms-media-library-uploadcare/package.json
index 47ec7ce6..8fb4e0cb 100644
--- a/packages/netlify-cms-media-library-uploadcare/package.json
+++ b/packages/netlify-cms-media-library-uploadcare/package.json
@@ -21,11 +21,6 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"dependencies": {
"uploadcare-widget": "^3.7.0",
"uploadcare-widget-tab-effects": "^1.4.0"
diff --git a/packages/netlify-cms-media-library-uploadcare/src/index.js b/packages/netlify-cms-media-library-uploadcare/src/index.js
index 479f1c22..8904f57f 100644
--- a/packages/netlify-cms-media-library-uploadcare/src/index.js
+++ b/packages/netlify-cms-media-library-uploadcare/src/index.js
@@ -140,4 +140,5 @@ async function init({ options = { config: {} }, handleInsert } = {}) {
*/
const uploadcareMediaLibrary = { name: 'uploadcare', init };
+export const NetlifyCmsMediaLibraryUploadcare = uploadcareMediaLibrary;
export default uploadcareMediaLibrary;
diff --git a/packages/netlify-cms-ui-default/package.json b/packages/netlify-cms-ui-default/package.json
index e1eecc9c..94c55d86 100644
--- a/packages/netlify-cms-ui-default/package.json
+++ b/packages/netlify-cms-ui-default/package.json
@@ -20,16 +20,11 @@
"react-toggled": "^1.1.2",
"react-transition-group": "^2.6.0"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
- "lodash": "^4.13.1",
- "prop-types": "^15.5.10",
- "react": "^16.4.1"
+ "lodash": "^4.17.11",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-ui-default/src/index.js b/packages/netlify-cms-ui-default/src/index.js
index 481a4636..02f9f2b5 100644
--- a/packages/netlify-cms-ui-default/src/index.js
+++ b/packages/netlify-cms-ui-default/src/index.js
@@ -1,12 +1,12 @@
-export Dropdown, { DropdownItem, DropdownButton, StyledDropdownButton } from './Dropdown';
-export Icon from './Icon';
-export ListItemTopBar from './ListItemTopBar';
-export Loader from './Loader';
-export Toggle, { ToggleContainer, ToggleBackground, ToggleHandle } from './Toggle';
-export AuthenticationPage from './AuthenticationPage';
-export WidgetPreviewContainer from './WidgetPreviewContainer';
-export ObjectWidgetTopBar from './ObjectWidgetTopBar';
-export {
+import Dropdown, { DropdownItem, DropdownButton, StyledDropdownButton } from './Dropdown';
+import Icon from './Icon';
+import ListItemTopBar from './ListItemTopBar';
+import Loader from './Loader';
+import Toggle, { ToggleContainer, ToggleBackground, ToggleHandle } from './Toggle';
+import AuthenticationPage from './AuthenticationPage';
+import WidgetPreviewContainer from './WidgetPreviewContainer';
+import ObjectWidgetTopBar from './ObjectWidgetTopBar';
+import {
fonts,
colorsRaw,
colors,
@@ -20,3 +20,60 @@ export {
reactSelectStyles,
GlobalStyles,
} from './styles';
+
+export const NetlifyCmsUiDefault = {
+ Dropdown,
+ DropdownItem,
+ DropdownButton,
+ StyledDropdownButton,
+ ListItemTopBar,
+ Icon,
+ Loader,
+ Toggle,
+ ToggleContainer,
+ ToggleBackground,
+ ToggleHandle,
+ AuthenticationPage,
+ WidgetPreviewContainer,
+ ObjectWidgetTopBar,
+ fonts,
+ colorsRaw,
+ colors,
+ lengths,
+ components,
+ buttons,
+ shadows,
+ borders,
+ transitions,
+ effects,
+ reactSelectStyles,
+ GlobalStyles,
+};
+export {
+ Dropdown,
+ DropdownItem,
+ DropdownButton,
+ StyledDropdownButton,
+ ListItemTopBar,
+ Icon,
+ Loader,
+ Toggle,
+ ToggleContainer,
+ ToggleBackground,
+ ToggleHandle,
+ AuthenticationPage,
+ WidgetPreviewContainer,
+ ObjectWidgetTopBar,
+ fonts,
+ colorsRaw,
+ colors,
+ lengths,
+ components,
+ buttons,
+ shadows,
+ borders,
+ transitions,
+ effects,
+ reactSelectStyles,
+ GlobalStyles,
+};
diff --git a/packages/netlify-cms-widget-boolean/package.json b/packages/netlify-cms-widget-boolean/package.json
index e0f4d53d..06d76574 100644
--- a/packages/netlify-cms-widget-boolean/package.json
+++ b/packages/netlify-cms-widget-boolean/package.json
@@ -19,17 +19,12 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
- "lodash": "^4.17.10",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1",
+ "lodash": "^4.17.11",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
"react-immutable-proptypes": "^2.1.0"
}
}
diff --git a/packages/netlify-cms-widget-boolean/src/index.js b/packages/netlify-cms-widget-boolean/src/index.js
index 3b172e90..a5634e66 100644
--- a/packages/netlify-cms-widget-boolean/src/index.js
+++ b/packages/netlify-cms-widget-boolean/src/index.js
@@ -1 +1,3 @@
-export BooleanControl from './BooleanControl';
+import controlComponent from './BooleanControl';
+export const NetlifyCmsWidgetBoolean = { controlComponent };
+export { controlComponent };
diff --git a/packages/netlify-cms-widget-date/package.json b/packages/netlify-cms-widget-date/package.json
index 24254290..3e774e49 100644
--- a/packages/netlify-cms-widget-date/package.json
+++ b/packages/netlify-cms-widget-date/package.json
@@ -23,19 +23,13 @@
"dependencies": {
"react-datetime": "^2.16.3"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "css-loader": "^2.1.1",
- "to-string-loader": "^1.1.5",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
- "moment": "^2.11.2",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1"
+ "moment": "^2.24.0",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
+ "react-dom": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-widget-date/src/index.js b/packages/netlify-cms-widget-date/src/index.js
index 5e6d2b9a..fb3d1883 100644
--- a/packages/netlify-cms-widget-date/src/index.js
+++ b/packages/netlify-cms-widget-date/src/index.js
@@ -8,4 +8,5 @@ const Widget = (opts = {}) => ({
...opts,
});
+export const NetlifyCmsWidgetDate = { Widget, controlComponent, previewComponent };
export { Widget as default, controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-date/webpack.config.js b/packages/netlify-cms-widget-date/webpack.config.js
index d39ce069..42edd361 100644
--- a/packages/netlify-cms-widget-date/webpack.config.js
+++ b/packages/netlify-cms-widget-date/webpack.config.js
@@ -1,17 +1,3 @@
const { getConfig } = require('../../scripts/webpack.js');
-const baseWebpackConfig = getConfig();
-
-module.exports = {
- ...baseWebpackConfig,
- module: {
- rules: [
- ...baseWebpackConfig.module.rules,
- {
- test: /\.css$/,
- include: [/react-datetime/],
- use: ['to-string-loader', 'css-loader'],
- },
- ],
- },
-};
+module.exports = getConfig();
diff --git a/packages/netlify-cms-widget-datetime/package.json b/packages/netlify-cms-widget-datetime/package.json
index a8681666..352c58cb 100644
--- a/packages/netlify-cms-widget-datetime/package.json
+++ b/packages/netlify-cms-widget-datetime/package.json
@@ -21,19 +21,9 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "dependencies": {
- "netlify-cms-widget-date": "^2.1.1-beta.0"
- },
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
- "react": "^16.4.1"
- },
- "localExternals": [
- "netlify-cms-widget-date"
- ]
+ "netlify-cms-widget-date": "^2.1.1-beta.0",
+ "react": "^16.8.4"
+ }
}
diff --git a/packages/netlify-cms-widget-datetime/src/index.js b/packages/netlify-cms-widget-datetime/src/index.js
index bcdcb67a..01bb74bd 100644
--- a/packages/netlify-cms-widget-datetime/src/index.js
+++ b/packages/netlify-cms-widget-datetime/src/index.js
@@ -8,4 +8,5 @@ const Widget = (opts = {}) => ({
...opts,
});
+export const NetlifyCmsWidgetDatetime = { Widget, controlComponent, previewComponent };
export { Widget as default, controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-file/package.json b/packages/netlify-cms-widget-file/package.json
index 915d9fc8..ba297d93 100644
--- a/packages/netlify-cms-widget-file/package.json
+++ b/packages/netlify-cms-widget-file/package.json
@@ -25,18 +25,13 @@
"common-tags": "^1.8.0",
"uuid": "^3.3.2"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
"react-immutable-proptypes": "^2.1.0"
}
}
diff --git a/packages/netlify-cms-widget-file/src/index.js b/packages/netlify-cms-widget-file/src/index.js
index 68141579..42d382e1 100644
--- a/packages/netlify-cms-widget-file/src/index.js
+++ b/packages/netlify-cms-widget-file/src/index.js
@@ -1,5 +1,6 @@
import withFileControl from './withFileControl';
+import previewComponent from './FilePreview';
-export { withFileControl };
-export const FileControl = withFileControl();
-export FilePreview from './FilePreview';
+const controlComponent = withFileControl();
+export const NetlifyCmsWidgetFile = { controlComponent, previewComponent, withFileControl };
+export { controlComponent, previewComponent, withFileControl };
diff --git a/packages/netlify-cms-widget-image/package.json b/packages/netlify-cms-widget-image/package.json
index 24476553..1820a0d9 100644
--- a/packages/netlify-cms-widget-image/package.json
+++ b/packages/netlify-cms-widget-image/package.json
@@ -21,23 +21,13 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "dependencies": {
- "netlify-cms-widget-file": "^2.2.1-beta.0"
- },
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1"
- },
- "localExternals": [
- "netlify-cms-widget-file"
- ]
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "netlify-cms-widget-file": "^2.2.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
+ }
}
diff --git a/packages/netlify-cms-widget-image/src/index.js b/packages/netlify-cms-widget-image/src/index.js
index b437a158..4f54db31 100644
--- a/packages/netlify-cms-widget-image/src/index.js
+++ b/packages/netlify-cms-widget-image/src/index.js
@@ -1,4 +1,6 @@
import { withFileControl } from 'netlify-cms-widget-file';
-export const ImageControl = withFileControl({ forImage: true });
-export ImagePreview from './ImagePreview';
+const controlComponent = withFileControl({ forImage: true });
+import previewComponent from './ImagePreview';
+export const NetlifyCmsWidgetImage = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-list/package.json b/packages/netlify-cms-widget-list/package.json
index b79144ca..69e2a6b4 100644
--- a/packages/netlify-cms-widget-list/package.json
+++ b/packages/netlify-cms-widget-list/package.json
@@ -21,25 +21,17 @@
"build": "cross-env NODE_ENV=production webpack"
},
"dependencies": {
- "netlify-cms-widget-object": "^2.0.7-beta.0",
"react-sortable-hoc": "^1.0.0"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "lodash": "^4.17.10",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1",
+ "lodash": "^4.17.11",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "netlify-cms-widget-object": "^2.0.7-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
"react-immutable-proptypes": "^2.1.0"
- },
- "localExternals": [
- "netlify-cms-widget-object"
- ]
+ }
}
diff --git a/packages/netlify-cms-widget-list/src/ListControl.js b/packages/netlify-cms-widget-list/src/ListControl.js
index 0bd0f44f..192df0d2 100644
--- a/packages/netlify-cms-widget-list/src/ListControl.js
+++ b/packages/netlify-cms-widget-list/src/ListControl.js
@@ -7,7 +7,7 @@ import { jsx, css, ClassNames } from '@emotion/core';
import { List, Map } from 'immutable';
import { partial } from 'lodash';
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
-import { ObjectControl } from 'netlify-cms-widget-object';
+import { controlComponent as ObjectControl } from 'netlify-cms-widget-object';
import {
TYPES_KEY,
getTypedFieldForValue,
diff --git a/packages/netlify-cms-widget-list/src/index.js b/packages/netlify-cms-widget-list/src/index.js
index 1ed5ac45..0821dfd8 100644
--- a/packages/netlify-cms-widget-list/src/index.js
+++ b/packages/netlify-cms-widget-list/src/index.js
@@ -1,2 +1,4 @@
-export ListControl from './ListControl';
-export { ObjectPreview as ListPreview } from 'netlify-cms-widget-object';
+import controlComponent from './ListControl';
+import { previewComponent } from 'netlify-cms-widget-object';
+export const NetlifyCmsWidgetList = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-map/package.json b/packages/netlify-cms-widget-map/package.json
index b7958559..544292f6 100644
--- a/packages/netlify-cms-widget-map/package.json
+++ b/packages/netlify-cms-widget-map/package.json
@@ -20,19 +20,12 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "css-loader": "^2.1.1",
- "to-string-loader": "^1.1.5",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
- "lodash": "^4.17.10",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1",
+ "lodash": "^4.17.11",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
"react-immutable-proptypes": "^2.1.0"
},
"dependencies": {
diff --git a/packages/netlify-cms-widget-map/src/index.js b/packages/netlify-cms-widget-map/src/index.js
index c5ae4dbe..79fb26b1 100644
--- a/packages/netlify-cms-widget-map/src/index.js
+++ b/packages/netlify-cms-widget-map/src/index.js
@@ -1,5 +1,6 @@
import withMapControl from './withMapControl';
+import previewComponent from './MapPreview';
+const controlComponent = withMapControl();
-export { withMapControl };
-export const MapControl = withMapControl();
-export MapPreview from './MapPreview';
+export const NetlifyCmsWidgetMap = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-map/webpack.config.js b/packages/netlify-cms-widget-map/webpack.config.js
index ca6a676d..42edd361 100644
--- a/packages/netlify-cms-widget-map/webpack.config.js
+++ b/packages/netlify-cms-widget-map/webpack.config.js
@@ -1,17 +1,3 @@
const { getConfig } = require('../../scripts/webpack.js');
-const baseWebpackConfig = getConfig();
-
-module.exports = {
- ...baseWebpackConfig,
- module: {
- rules: [
- ...baseWebpackConfig.module.rules,
- {
- test: /\.css$/,
- include: [/ol/],
- use: ['to-string-loader', 'css-loader'],
- },
- ],
- },
-};
+module.exports = getConfig();
diff --git a/packages/netlify-cms-widget-markdown/package.json b/packages/netlify-cms-widget-markdown/package.json
index 82d73e48..3e98084c 100644
--- a/packages/netlify-cms-widget-markdown/package.json
+++ b/packages/netlify-cms-widget-markdown/package.json
@@ -40,20 +40,15 @@
"unist-builder": "^1.0.2",
"unist-util-visit-parents": "^1.1.1"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "lodash": "^4.17.10",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1",
- "react-dom": "^16.0.0",
+ "lodash": "^4.17.11",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
+ "react-dom": "^16.8.4",
"react-immutable-proptypes": "^2.1.0"
}
}
diff --git a/packages/netlify-cms-widget-markdown/src/index.js b/packages/netlify-cms-widget-markdown/src/index.js
index df1c2ad9..92eb8147 100644
--- a/packages/netlify-cms-widget-markdown/src/index.js
+++ b/packages/netlify-cms-widget-markdown/src/index.js
@@ -1,2 +1,4 @@
-export MarkdownControl from './MarkdownControl';
-export MarkdownPreview from './MarkdownPreview';
+import controlComponent from './MarkdownControl';
+import previewComponent from './MarkdownPreview';
+export const NetlifyCmsWidgetMarkdown = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-number/package.json b/packages/netlify-cms-widget-number/package.json
index cc91ebed..bbcba6e2 100644
--- a/packages/netlify-cms-widget-number/package.json
+++ b/packages/netlify-cms-widget-number/package.json
@@ -19,14 +19,9 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1"
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-widget-number/src/__tests__/number.spec.js b/packages/netlify-cms-widget-number/src/__tests__/number.spec.js
index 00fc8f04..716041f6 100644
--- a/packages/netlify-cms-widget-number/src/__tests__/number.spec.js
+++ b/packages/netlify-cms-widget-number/src/__tests__/number.spec.js
@@ -3,7 +3,7 @@ import { fromJS } from 'immutable';
import { render, fireEvent } from 'react-testing-library';
import 'react-testing-library/cleanup-after-each';
import 'jest-dom/extend-expect';
-import { NumberControl } from '../';
+import { controlComponent as NumberControl } from '../';
const fieldSettings = {
min: -20,
diff --git a/packages/netlify-cms-widget-number/src/index.js b/packages/netlify-cms-widget-number/src/index.js
index c9aab310..3d8aa6ae 100644
--- a/packages/netlify-cms-widget-number/src/index.js
+++ b/packages/netlify-cms-widget-number/src/index.js
@@ -1,2 +1,4 @@
-export NumberControl from './NumberControl';
-export NumberPreview from './NumberPreview';
+import controlComponent from './NumberControl';
+import previewComponent from './NumberPreview';
+export const NetlifyCmsWidgetNumber = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-object/package.json b/packages/netlify-cms-widget-object/package.json
index c29c12c6..e0df3164 100644
--- a/packages/netlify-cms-widget-object/package.json
+++ b/packages/netlify-cms-widget-object/package.json
@@ -21,19 +21,14 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "lodash": "^4.17.10",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1",
+ "lodash": "^4.17.11",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
"react-immutable-proptypes": "^2.1.0"
}
}
diff --git a/packages/netlify-cms-widget-object/src/index.js b/packages/netlify-cms-widget-object/src/index.js
index ea1f17ea..2995beaa 100644
--- a/packages/netlify-cms-widget-object/src/index.js
+++ b/packages/netlify-cms-widget-object/src/index.js
@@ -1,2 +1,4 @@
-export ObjectControl from './ObjectControl';
-export ObjectPreview from './ObjectPreview';
+import controlComponent from './ObjectControl';
+import previewComponent from './ObjectPreview';
+export const NetlifyCmsWidgetObject = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-relation/package.json b/packages/netlify-cms-widget-relation/package.json
index 0813920a..7679ff35 100644
--- a/packages/netlify-cms-widget-relation/package.json
+++ b/packages/netlify-cms-widget-relation/package.json
@@ -23,19 +23,14 @@
"dependencies": {
"react-select": "^2.4.2"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
"immutable": "^3.7.6",
- "lodash": "^4.17.10",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1",
+ "lodash": "^4.17.11",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
"uuid": "^3.1.0"
}
}
diff --git a/packages/netlify-cms-widget-relation/src/__tests__/relation.spec.js b/packages/netlify-cms-widget-relation/src/__tests__/relation.spec.js
index cb51b685..fb42c103 100644
--- a/packages/netlify-cms-widget-relation/src/__tests__/relation.spec.js
+++ b/packages/netlify-cms-widget-relation/src/__tests__/relation.spec.js
@@ -1,206 +1,206 @@
-import React from 'react';
-import { fromJS, Map } from 'immutable';
-import { last } from 'lodash';
-import { render, fireEvent, wait } from 'react-testing-library';
-import 'react-testing-library/cleanup-after-each';
-import 'jest-dom/extend-expect';
-import { RelationControl } from '../';
-
-const fieldConfig = {
- name: 'post',
- collection: 'posts',
- displayFields: ['title', 'slug'],
- searchFields: ['title', 'body'],
- valueField: 'title',
-};
-
-const generateHits = length => {
- const hits = Array.from({ length }, (val, idx) => {
- const title = `Post # ${idx + 1}`;
- const slug = `post-number-${idx + 1}`;
- return { collection: 'posts', data: { title, slug } };
- });
-
- return [
- ...hits,
- {
- collection: 'posts',
- data: { title: 'YAML post', slug: 'post-yaml', body: 'Body yaml' },
- },
- ];
-};
-
-class RelationController extends React.Component {
- state = {
- value: this.props.value,
- queryHits: Map(),
- };
-
- handleOnChange = jest.fn(value => {
- this.setState({ ...this.state, value });
- });
-
- setQueryHits = jest.fn(hits => {
- const queryHits = Map().set('relation-field', hits);
- this.setState({ ...this.state, queryHits });
- });
-
- query = jest.fn((...args) => {
- const queryHits = generateHits(25);
- if (last(args) === 'YAML') {
- return Promise.resolve({ payload: { response: { hits: [last(queryHits)] } } });
- }
- return Promise.resolve({ payload: { response: { hits: queryHits } } });
- });
-
- render() {
- return this.props.children({
- value: this.state.value,
- handleOnChange: this.handleOnChange,
- query: this.query,
- queryHits: this.state.queryHits,
- setQueryHits: this.setQueryHits,
- });
- }
-}
-
-function setup({ field, value }) {
- let renderArgs;
- const setActiveSpy = jest.fn();
- const setInactiveSpy = jest.fn();
-
- const helpers = render(
-
- {({ handleOnChange, value, query, queryHits, setQueryHits }) => {
- renderArgs = { value, onChangeSpy: handleOnChange, setQueryHitsSpy: setQueryHits };
- return (
-
- );
- }}
- ,
- );
-
- const input = helpers.container.querySelector('input');
-
- return {
- ...helpers,
- ...renderArgs,
- setActiveSpy,
- setInactiveSpy,
- input,
- };
-}
-
-describe('Relation widget', () => {
- it('should list the first 20 option hits on initial load', async () => {
- const field = fromJS(fieldConfig);
- const { getAllByText, input } = setup({ field });
- fireEvent.keyDown(input, { key: 'ArrowDown' });
-
- await wait(() => {
- expect(getAllByText(/^Post # (\d{1,2}) post-number-\1$/)).toHaveLength(20);
- });
- });
-
- it('should update option list based on search term', async () => {
- const field = fromJS(fieldConfig);
- const { getAllByText, input } = setup({ field });
- fireEvent.change(input, { target: { value: 'YAML' } });
-
- await wait(() => {
- expect(getAllByText('YAML post post-yaml')).toHaveLength(1);
- });
- });
-
- it('should call onChange with correct selectedItem value and metadata', async () => {
- const field = fromJS(fieldConfig);
- const { getByText, input, onChangeSpy } = setup({ field });
- const value = 'Post # 1';
- const label = 'Post # 1 post-number-1';
- const metadata = {
- post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
- };
-
- await wait(() => {
- fireEvent.keyDown(input, { key: 'ArrowDown' });
- fireEvent.click(getByText(label));
- expect(onChangeSpy).toHaveBeenCalledTimes(1);
- expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
- });
- });
-
- it('should update metadata for initial preview', async () => {
- const field = fromJS(fieldConfig);
- const value = 'Post # 1';
- const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
- const label = 'Post # 1 post-number-1';
- const metadata = {
- post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
- };
-
- setQueryHitsSpy(generateHits(1));
-
- await wait(() => {
- expect(getByText(label)).toBeInTheDocument();
- expect(onChangeSpy).toHaveBeenCalledTimes(1);
- expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
- });
- });
-
- describe('with multiple', () => {
- it('should call onChange with correct selectedItem value and metadata', async () => {
- const field = fromJS({ ...fieldConfig, multiple: true });
- const { getByText, input, onChangeSpy } = setup({ field });
- const metadata1 = {
- post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
- };
- const metadata2 = {
- post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
- };
-
- await wait(() => {
- fireEvent.keyDown(input, { key: 'ArrowDown' });
- fireEvent.click(getByText('Post # 1 post-number-1'));
- fireEvent.keyDown(input, { key: 'ArrowDown' });
- fireEvent.click(getByText('Post # 2 post-number-2'));
-
- expect(onChangeSpy).toHaveBeenCalledTimes(2);
- expect(onChangeSpy).toHaveBeenCalledWith(fromJS(['Post # 1']), metadata1);
- expect(onChangeSpy).toHaveBeenCalledWith(fromJS(['Post # 1', 'Post # 2']), metadata2);
- });
- });
-
- it('should update metadata for initial preview', async () => {
- const field = fromJS({ ...fieldConfig, multiple: true });
- const value = fromJS(['Post # 1', 'Post # 2']);
- const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
- const metadata1 = {
- post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
- };
- const metadata2 = {
- post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
- };
-
- setQueryHitsSpy(generateHits(2));
-
- await wait(() => {
- expect(getByText('Post # 1 post-number-1')).toBeInTheDocument();
- expect(getByText('Post # 2 post-number-2')).toBeInTheDocument();
-
- expect(onChangeSpy).toHaveBeenCalledTimes(2);
- expect(onChangeSpy).toHaveBeenCalledWith(value, metadata1);
- expect(onChangeSpy).toHaveBeenCalledWith(value, metadata2);
- });
- });
- });
-});
+import React from 'react';
+import { fromJS, Map } from 'immutable';
+import { last } from 'lodash';
+import { render, fireEvent, wait } from 'react-testing-library';
+import 'react-testing-library/cleanup-after-each';
+import 'jest-dom/extend-expect';
+import { controlComponent as RelationControl } from '../';
+
+const fieldConfig = {
+ name: 'post',
+ collection: 'posts',
+ displayFields: ['title', 'slug'],
+ searchFields: ['title', 'body'],
+ valueField: 'title',
+};
+
+const generateHits = length => {
+ const hits = Array.from({ length }, (val, idx) => {
+ const title = `Post # ${idx + 1}`;
+ const slug = `post-number-${idx + 1}`;
+ return { collection: 'posts', data: { title, slug } };
+ });
+
+ return [
+ ...hits,
+ {
+ collection: 'posts',
+ data: { title: 'YAML post', slug: 'post-yaml', body: 'Body yaml' },
+ },
+ ];
+};
+
+class RelationController extends React.Component {
+ state = {
+ value: this.props.value,
+ queryHits: Map(),
+ };
+
+ handleOnChange = jest.fn(value => {
+ this.setState({ ...this.state, value });
+ });
+
+ setQueryHits = jest.fn(hits => {
+ const queryHits = Map().set('relation-field', hits);
+ this.setState({ ...this.state, queryHits });
+ });
+
+ query = jest.fn((...args) => {
+ const queryHits = generateHits(25);
+ if (last(args) === 'YAML') {
+ return Promise.resolve({ payload: { response: { hits: [last(queryHits)] } } });
+ }
+ return Promise.resolve({ payload: { response: { hits: queryHits } } });
+ });
+
+ render() {
+ return this.props.children({
+ value: this.state.value,
+ handleOnChange: this.handleOnChange,
+ query: this.query,
+ queryHits: this.state.queryHits,
+ setQueryHits: this.setQueryHits,
+ });
+ }
+}
+
+function setup({ field, value }) {
+ let renderArgs;
+ const setActiveSpy = jest.fn();
+ const setInactiveSpy = jest.fn();
+
+ const helpers = render(
+
+ {({ handleOnChange, value, query, queryHits, setQueryHits }) => {
+ renderArgs = { value, onChangeSpy: handleOnChange, setQueryHitsSpy: setQueryHits };
+ return (
+
+ );
+ }}
+ ,
+ );
+
+ const input = helpers.container.querySelector('input');
+
+ return {
+ ...helpers,
+ ...renderArgs,
+ setActiveSpy,
+ setInactiveSpy,
+ input,
+ };
+}
+
+describe('Relation widget', () => {
+ it('should list the first 20 option hits on initial load', async () => {
+ const field = fromJS(fieldConfig);
+ const { getAllByText, input } = setup({ field });
+ fireEvent.keyDown(input, { key: 'ArrowDown' });
+
+ await wait(() => {
+ expect(getAllByText(/^Post # (\d{1,2}) post-number-\1$/)).toHaveLength(20);
+ });
+ });
+
+ it('should update option list based on search term', async () => {
+ const field = fromJS(fieldConfig);
+ const { getAllByText, input } = setup({ field });
+ fireEvent.change(input, { target: { value: 'YAML' } });
+
+ await wait(() => {
+ expect(getAllByText('YAML post post-yaml')).toHaveLength(1);
+ });
+ });
+
+ it('should call onChange with correct selectedItem value and metadata', async () => {
+ const field = fromJS(fieldConfig);
+ const { getByText, input, onChangeSpy } = setup({ field });
+ const value = 'Post # 1';
+ const label = 'Post # 1 post-number-1';
+ const metadata = {
+ post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
+ };
+
+ await wait(() => {
+ fireEvent.keyDown(input, { key: 'ArrowDown' });
+ fireEvent.click(getByText(label));
+ expect(onChangeSpy).toHaveBeenCalledTimes(1);
+ expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
+ });
+ });
+
+ it('should update metadata for initial preview', async () => {
+ const field = fromJS(fieldConfig);
+ const value = 'Post # 1';
+ const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
+ const label = 'Post # 1 post-number-1';
+ const metadata = {
+ post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
+ };
+
+ setQueryHitsSpy(generateHits(1));
+
+ await wait(() => {
+ expect(getByText(label)).toBeInTheDocument();
+ expect(onChangeSpy).toHaveBeenCalledTimes(1);
+ expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
+ });
+ });
+
+ describe('with multiple', () => {
+ it('should call onChange with correct selectedItem value and metadata', async () => {
+ const field = fromJS({ ...fieldConfig, multiple: true });
+ const { getByText, input, onChangeSpy } = setup({ field });
+ const metadata1 = {
+ post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
+ };
+ const metadata2 = {
+ post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
+ };
+
+ await wait(() => {
+ fireEvent.keyDown(input, { key: 'ArrowDown' });
+ fireEvent.click(getByText('Post # 1 post-number-1'));
+ fireEvent.keyDown(input, { key: 'ArrowDown' });
+ fireEvent.click(getByText('Post # 2 post-number-2'));
+
+ expect(onChangeSpy).toHaveBeenCalledTimes(2);
+ expect(onChangeSpy).toHaveBeenCalledWith(fromJS(['Post # 1']), metadata1);
+ expect(onChangeSpy).toHaveBeenCalledWith(fromJS(['Post # 1', 'Post # 2']), metadata2);
+ });
+ });
+
+ it('should update metadata for initial preview', async () => {
+ const field = fromJS({ ...fieldConfig, multiple: true });
+ const value = fromJS(['Post # 1', 'Post # 2']);
+ const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
+ const metadata1 = {
+ post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
+ };
+ const metadata2 = {
+ post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
+ };
+
+ setQueryHitsSpy(generateHits(2));
+
+ await wait(() => {
+ expect(getByText('Post # 1 post-number-1')).toBeInTheDocument();
+ expect(getByText('Post # 2 post-number-2')).toBeInTheDocument();
+
+ expect(onChangeSpy).toHaveBeenCalledTimes(2);
+ expect(onChangeSpy).toHaveBeenCalledWith(value, metadata1);
+ expect(onChangeSpy).toHaveBeenCalledWith(value, metadata2);
+ });
+ });
+ });
+});
diff --git a/packages/netlify-cms-widget-relation/src/index.js b/packages/netlify-cms-widget-relation/src/index.js
index 2bdf5132..9be2fa60 100644
--- a/packages/netlify-cms-widget-relation/src/index.js
+++ b/packages/netlify-cms-widget-relation/src/index.js
@@ -1,2 +1,4 @@
-export RelationControl from './RelationControl';
-export RelationPreview from './RelationPreview';
+import controlComponent from './RelationControl';
+import previewComponent from './RelationPreview';
+export const NetlifyCmsWidgetRelation = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-select/package.json b/packages/netlify-cms-widget-select/package.json
index e04fcf39..bb2f8dc6 100644
--- a/packages/netlify-cms-widget-select/package.json
+++ b/packages/netlify-cms-widget-select/package.json
@@ -21,18 +21,11 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "jest-dom": "^3.1.3",
- "react-testing-library": "^6.0.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
"immutable": "^3.7.6",
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1",
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4",
"react-immutable-proptypes": "^2.1.0"
},
"dependencies": {
diff --git a/packages/netlify-cms-widget-select/src/__tests__/select.spec.js b/packages/netlify-cms-widget-select/src/__tests__/select.spec.js
index 2dc333bf..f51a6d42 100644
--- a/packages/netlify-cms-widget-select/src/__tests__/select.spec.js
+++ b/packages/netlify-cms-widget-select/src/__tests__/select.spec.js
@@ -3,7 +3,7 @@ import { fromJS } from 'immutable';
import { render, fireEvent } from 'react-testing-library';
import 'react-testing-library/cleanup-after-each';
import 'jest-dom/extend-expect';
-import { SelectControl } from '../';
+import { controlComponent as SelectControl } from '../';
const options = [
{ value: 'foo', label: 'Foo' },
diff --git a/packages/netlify-cms-widget-select/src/index.js b/packages/netlify-cms-widget-select/src/index.js
index d0c60def..5b2228cd 100644
--- a/packages/netlify-cms-widget-select/src/index.js
+++ b/packages/netlify-cms-widget-select/src/index.js
@@ -1,2 +1,4 @@
-export SelectControl from './SelectControl';
-export SelectPreview from './SelectPreview';
+import controlComponent from './SelectControl';
+import previewComponent from './SelectPreview';
+export const NetlifyCmsWidgetSelect = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-string/package.json b/packages/netlify-cms-widget-string/package.json
index a145c944..407fbcc7 100644
--- a/packages/netlify-cms-widget-string/package.json
+++ b/packages/netlify-cms-widget-string/package.json
@@ -19,14 +19,9 @@
"develop": "npm run watch",
"build": "cross-env NODE_ENV=production webpack"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1"
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-widget-string/src/index.js b/packages/netlify-cms-widget-string/src/index.js
index ccd90572..d0c95dd4 100644
--- a/packages/netlify-cms-widget-string/src/index.js
+++ b/packages/netlify-cms-widget-string/src/index.js
@@ -1,2 +1,4 @@
-export StringControl from './StringControl';
-export StringPreview from './StringPreview';
+import controlComponent from './StringControl';
+import previewComponent from './StringPreview';
+export const NetlifyCmsWidgetString = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms-widget-text/package.json b/packages/netlify-cms-widget-text/package.json
index 2278bde0..275a8af5 100644
--- a/packages/netlify-cms-widget-text/package.json
+++ b/packages/netlify-cms-widget-text/package.json
@@ -25,14 +25,9 @@
"dependencies": {
"react-textarea-autosize": "^7.1.0"
},
- "devDependencies": {
- "cross-env": "^5.2.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3"
- },
"peerDependencies": {
- "netlify-cms-ui-default": "^2.0.0",
- "prop-types": "^15.5.10",
- "react": "^16.4.1"
+ "netlify-cms-ui-default": "^2.4.1-beta.0",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.4"
}
}
diff --git a/packages/netlify-cms-widget-text/src/index.js b/packages/netlify-cms-widget-text/src/index.js
index 54082cab..b8941d01 100644
--- a/packages/netlify-cms-widget-text/src/index.js
+++ b/packages/netlify-cms-widget-text/src/index.js
@@ -1,2 +1,5 @@
-export TextControl from './TextControl';
-export TextPreview from './TextPreview';
+import controlComponent from './TextControl';
+import previewComponent from './TextPreview';
+
+export const NetlifyCmsWidgetText = { controlComponent, previewComponent };
+export { controlComponent, previewComponent };
diff --git a/packages/netlify-cms/package.json b/packages/netlify-cms/package.json
index d3acfd1b..8973b59e 100644
--- a/packages/netlify-cms/package.json
+++ b/packages/netlify-cms/package.json
@@ -21,7 +21,12 @@
],
"license": "MIT",
"dependencies": {
+ "@emotion/core": "^10.0.9",
+ "@emotion/styled": "^10.0.9",
"create-react-class": "^15.6.0",
+ "immutable": "^3.7.6",
+ "lodash": "^4.17.11",
+ "moment": "^2.24.0",
"netlify-cms-backend-bitbucket": "^2.1.3-beta.0",
"netlify-cms-backend-git-gateway": "^2.2.5-beta.0",
"netlify-cms-backend-github": "^2.2.3-beta.0",
@@ -29,6 +34,7 @@
"netlify-cms-backend-test": "^2.0.7-beta.0",
"netlify-cms-core": "^2.8.1-beta.0",
"netlify-cms-editor-component-image": "^2.2.1-beta.0",
+ "netlify-cms-media-library-cloudinary": "^1.1.3-beta.0",
"netlify-cms-media-library-uploadcare": "^0.3.5-beta.0",
"netlify-cms-widget-boolean": "^2.0.6-beta.0",
"netlify-cms-widget-date": "^2.1.1-beta.0",
@@ -43,14 +49,10 @@
"netlify-cms-widget-relation": "^2.1.3-beta.0",
"netlify-cms-widget-select": "^2.2.1-beta.0",
"netlify-cms-widget-string": "^2.0.5-beta.0",
- "netlify-cms-widget-text": "^2.0.7-beta.0"
- },
- "devDependencies": {
- "copy-webpack-plugin": "^5.0.1",
- "cross-env": "^5.2.0",
- "friendly-errors-webpack-plugin": "^1.7.0",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.2.3",
- "webpack-dev-server": "^3.2.1"
+ "netlify-cms-widget-text": "^2.0.7-beta.0",
+ "prop-types": "^15.7.2",
+ "react-immutable-proptypes": "^2.1.0",
+ "react": "^16.8.4",
+ "react-dom": "^16.8.4"
}
}
diff --git a/packages/netlify-cms/src/backends.js b/packages/netlify-cms/src/backends.js
index a13085d7..fc4bf96c 100644
--- a/packages/netlify-cms/src/backends.js
+++ b/packages/netlify-cms/src/backends.js
@@ -1,14 +1,12 @@
-import cms from 'netlify-cms-core/src';
-import { GitHubBackend } from 'netlify-cms-backend-github/src';
-import { GitLabBackend } from 'netlify-cms-backend-gitlab/src';
-import { GitGatewayBackend } from 'netlify-cms-backend-git-gateway/src';
-import { BitbucketBackend } from 'netlify-cms-backend-bitbucket/src';
-import { TestBackend } from 'netlify-cms-backend-test/src';
+import { registerBackend } from 'netlify-cms-core/src';
+import { Control as NetlifyCmsBackendGithub } from 'netlify-cms-backend-github/src';
+import { Control as NetlifyCmsBackendGitlab } from 'netlify-cms-backend-gitlab/src';
+import { Control as NetlifyCmsBackendGitGateway } from 'netlify-cms-backend-git-gateway/src';
+import { Control as NetlifyCmsBackendBitbucket } from 'netlify-cms-backend-bitbucket/src';
+import { Control as NetlifyCmsBackendTest } from 'netlify-cms-backend-test/src';
-const { registerBackend } = cms;
-
-registerBackend('git-gateway', GitGatewayBackend);
-registerBackend('github', GitHubBackend);
-registerBackend('gitlab', GitLabBackend);
-registerBackend('bitbucket', BitbucketBackend);
-registerBackend('test-repo', TestBackend);
+registerBackend('git-gateway', NetlifyCmsBackendGitGateway);
+registerBackend('github', NetlifyCmsBackendGithub);
+registerBackend('gitlab', NetlifyCmsBackendGitlab);
+registerBackend('bitbucket', NetlifyCmsBackendBitbucket);
+registerBackend('test-repo', NetlifyCmsBackendTest);
diff --git a/packages/netlify-cms/src/editor-components.js b/packages/netlify-cms/src/editor-components.js
index abb2b9fe..e28bebe8 100644
--- a/packages/netlify-cms/src/editor-components.js
+++ b/packages/netlify-cms/src/editor-components.js
@@ -1,6 +1,4 @@
-import cms from 'netlify-cms-core/src';
+import { registerEditorComponent } from 'netlify-cms-core/src';
import image from 'netlify-cms-editor-component-image/src';
-const { registerEditorComponent } = cms;
-
registerEditorComponent(image);
diff --git a/packages/netlify-cms/src/index.js b/packages/netlify-cms/src/index.js
index 6149c990..c7872237 100644
--- a/packages/netlify-cms/src/index.js
+++ b/packages/netlify-cms/src/index.js
@@ -1,6 +1,6 @@
import createReactClass from 'create-react-class';
import React from 'react';
-import CMS, { init } from 'netlify-cms-core/src';
+import * as CMS from 'netlify-cms-core/src';
import './backends';
import './widgets';
import './editor-components';
@@ -10,7 +10,7 @@ import './media-libraries';
* Load Netlify CMS automatically if `window.CMS_MANUAL_INIT` is set.
*/
if (!window.CMS_MANUAL_INIT) {
- init();
+ CMS.init();
} else {
console.log('`window.CMS_MANUAL_INIT` flag set, skipping automatic initialization.');
}
@@ -20,9 +20,10 @@ if (!window.CMS_MANUAL_INIT) {
*/
if (typeof window !== 'undefined') {
window.CMS = CMS;
- window.initCMS = init;
+ window.initCMS = CMS.init;
window.createClass = window.createClass || createReactClass;
window.h = window.h || React.createElement;
}
-export { CMS as default, init };
+export const NetlifyCms = CMS;
+export { CMS as default };
diff --git a/packages/netlify-cms/src/media-libraries.js b/packages/netlify-cms/src/media-libraries.js
index 076e80af..204d518c 100644
--- a/packages/netlify-cms/src/media-libraries.js
+++ b/packages/netlify-cms/src/media-libraries.js
@@ -1,8 +1,6 @@
-import cms from 'netlify-cms-core/src';
+import { registerMediaLibrary } from 'netlify-cms-core/src';
import uploadcare from 'netlify-cms-media-library-uploadcare/src';
import cloudinary from 'netlify-cms-media-library-cloudinary/src';
-const { registerMediaLibrary } = cms;
-
registerMediaLibrary(uploadcare);
registerMediaLibrary(cloudinary);
diff --git a/packages/netlify-cms/src/widgets.js b/packages/netlify-cms/src/widgets.js
index 45e4ebff..263e18e6 100644
--- a/packages/netlify-cms/src/widgets.js
+++ b/packages/netlify-cms/src/widgets.js
@@ -1,31 +1,69 @@
-import cms from 'netlify-cms-core/src';
-import { StringControl, StringPreview } from 'netlify-cms-widget-string/src';
-import { NumberControl, NumberPreview } from 'netlify-cms-widget-number/src';
-import { TextControl, TextPreview } from 'netlify-cms-widget-text/src';
-import { ImageControl, ImagePreview } from 'netlify-cms-widget-image/src';
-import { FileControl, FilePreview } from 'netlify-cms-widget-file/src';
-import { SelectControl, SelectPreview } from 'netlify-cms-widget-select/src';
-import { MarkdownControl, MarkdownPreview } from 'netlify-cms-widget-markdown/src';
-import { ListControl, ListPreview } from 'netlify-cms-widget-list/src';
-import { ObjectControl, ObjectPreview } from 'netlify-cms-widget-object/src';
-import { RelationControl, RelationPreview } from 'netlify-cms-widget-relation/src';
-import { BooleanControl } from 'netlify-cms-widget-boolean/src';
-import { MapControl, MapPreview } from 'netlify-cms-widget-map/src';
+import { registerWidget } from 'netlify-cms-core/src';
+import * as NetlifyCmsWidgetString from 'netlify-cms-widget-string/src';
+import * as NetlifyCmsWidgetNumber from 'netlify-cms-widget-number/src';
+import * as NetlifyCmsWidgetText from 'netlify-cms-widget-text/src';
+import * as NetlifyCmsWidgetImage from 'netlify-cms-widget-image/src';
+import * as NetlifyCmsWidgetFile from 'netlify-cms-widget-file/src';
+import * as NetlifyCmsWidgetSelect from 'netlify-cms-widget-select/src';
+import * as NetlifyCmsWidgetMarkdown from 'netlify-cms-widget-markdown/src';
+import * as NetlifyCmsWidgetList from 'netlify-cms-widget-list/src';
+import * as NetlifyCmsWidgetObject from 'netlify-cms-widget-object/src';
+import * as NetlifyCmsWidgetRelation from 'netlify-cms-widget-relation/src';
+import * as NetlifyCmsWidgetBoolean from 'netlify-cms-widget-boolean/src';
+import * as NetlifyCmsWidgetMap from 'netlify-cms-widget-map/src';
import DateWidget from 'netlify-cms-widget-date/src';
import DateTimeWidget from 'netlify-cms-widget-datetime/src';
-const { registerWidget } = cms;
-
-registerWidget('string', StringControl, StringPreview);
-registerWidget('text', TextControl, TextPreview);
-registerWidget('number', NumberControl, NumberPreview);
-registerWidget('list', ListControl, ListPreview);
-registerWidget('markdown', MarkdownControl, MarkdownPreview);
-registerWidget('image', ImageControl, ImagePreview);
-registerWidget('file', FileControl, FilePreview);
-registerWidget('select', SelectControl, SelectPreview);
-registerWidget('object', ObjectControl, ObjectPreview);
-registerWidget('relation', RelationControl, RelationPreview);
-registerWidget('boolean', BooleanControl);
-registerWidget('map', MapControl, MapPreview);
+registerWidget(
+ 'string',
+ NetlifyCmsWidgetString.controlComponent,
+ NetlifyCmsWidgetString.previewComponent,
+);
+registerWidget(
+ 'number',
+ NetlifyCmsWidgetNumber.controlComponent,
+ NetlifyCmsWidgetNumber.previewComponent,
+);
+registerWidget(
+ 'text',
+ NetlifyCmsWidgetText.controlComponent,
+ NetlifyCmsWidgetText.previewComponent,
+);
+registerWidget(
+ 'list',
+ NetlifyCmsWidgetList.controlComponent,
+ NetlifyCmsWidgetList.previewComponent,
+);
+registerWidget(
+ 'markdown',
+ NetlifyCmsWidgetMarkdown.controlComponent,
+ NetlifyCmsWidgetMarkdown.previewComponent,
+);
+registerWidget(
+ 'image',
+ NetlifyCmsWidgetImage.controlComponent,
+ NetlifyCmsWidgetImage.previewComponent,
+);
+registerWidget(
+ 'file',
+ NetlifyCmsWidgetFile.controlComponent,
+ NetlifyCmsWidgetFile.previewComponent,
+);
+registerWidget(
+ 'select',
+ NetlifyCmsWidgetSelect.controlComponent,
+ NetlifyCmsWidgetSelect.previewComponent,
+);
+registerWidget(
+ 'object',
+ NetlifyCmsWidgetObject.controlComponent,
+ NetlifyCmsWidgetObject.previewComponent,
+);
+registerWidget(
+ 'relation',
+ NetlifyCmsWidgetRelation.controlComponent,
+ NetlifyCmsWidgetRelation.previewComponent,
+);
+registerWidget('boolean', NetlifyCmsWidgetBoolean.controlComponent);
+registerWidget('map', NetlifyCmsWidgetMap.controlComponent, NetlifyCmsWidgetMap.previewComponent);
registerWidget([DateWidget(), DateTimeWidget()]);
diff --git a/packages/netlify-cms/webpack.config.js b/packages/netlify-cms/webpack.config.js
index 4202c9c2..561b26c6 100644
--- a/packages/netlify-cms/webpack.config.js
+++ b/packages/netlify-cms/webpack.config.js
@@ -3,13 +3,14 @@ const webpack = require('webpack');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const pkg = require('./package.json');
-const { plugins } = require('../../scripts/webpack');
-const coreWebpackConfig = require('../netlify-cms-core/webpack.config.js');
+const { getConfig, plugins } = require('../../scripts/webpack');
+const baseWebpackConfig = getConfig({ baseOnly: true });
const isProduction = process.env.NODE_ENV === 'production';
+console.log(`${pkg.version}${isProduction ? '' : '-dev'}`);
const baseConfig = {
- ...coreWebpackConfig,
+ ...baseWebpackConfig,
context: path.join(__dirname, 'src'),
entry: './index.js',
plugins: [
@@ -25,7 +26,7 @@ const baseConfig = {
messages: ['Netlify CMS is now running at http://localhost:8080'],
},
}),
- new CopyWebpackPlugin([{ from: '../shims/cms.css', to: 'dist/' }]),
+ new CopyWebpackPlugin([{ from: '../shims/cms.css', to: './' }]),
],
devServer: {
contentBase: '../../dev-test',
@@ -49,7 +50,7 @@ if (isProduction) {
entry: [path.join(__dirname, 'shims/deprecate-old-dist.js'), baseConfig.entry],
output: {
...baseConfig.output,
- filename: 'dist/cms.js',
+ filename: 'cms.js',
},
},
];
diff --git a/scripts/externals.js b/scripts/externals.js
new file mode 100644
index 00000000..74a95a27
--- /dev/null
+++ b/scripts/externals.js
@@ -0,0 +1,108 @@
+const fs = require('fs');
+const path = require('path');
+
+/**
+ * Takes a dash [-] separated name and makes it camel-cased
+ * netlify-cms-something to NetlifyCmsSomething
+ * @param {} string
+ */
+const toGlobalName = name =>
+ `${name}`
+ .replace(new RegExp(/[-_/]+/, 'g'), ' ')
+ .replace(new RegExp(/[^\w\s]/, 'g'), '')
+ .replace(
+ new RegExp(/\s+(.)(\w+)/, 'g'),
+ ($1, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`,
+ )
+ .replace(new RegExp(/\s/, 'g'), '')
+ .replace(new RegExp(/\w/), s => s.toUpperCase());
+
+const packages = fs.readdirSync(path.resolve(__dirname, '../packages'));
+
+const packageExports = {};
+packages.map(name => {
+ packageExports[name] = {
+ root: `${toGlobalName(name)}`.split('.'),
+ commonjs2: name,
+ commonjs: name,
+ amd: name,
+ umd: name,
+ };
+});
+
+module.exports = {
+ toGlobalName,
+ externals: {
+ ...packageExports,
+ lodash: {
+ root: ['NetlifyCmsDefaultExports', 'Lodash'],
+ commonjs2: 'lodash',
+ commonjs: 'lodash',
+ amd: 'lodash',
+ umd: 'lodash',
+ },
+ '@emotion/core': {
+ root: ['NetlifyCmsDefaultExports', 'EmotionCore'],
+ commonjs2: '@emotion/core',
+ commonjs: '@emotion/core',
+ amd: '@emotion/core',
+ umd: '@emotion/core',
+ },
+ '@emotion/styled': {
+ root: ['NetlifyCmsDefaultExports', 'EmotionStyled'],
+ commonjs2: '@emotion/styled',
+ commonjs: '@emotion/styled',
+ amd: '@emotion/styled',
+ umd: '@emotion/styled',
+ },
+ immutable: {
+ root: ['NetlifyCmsDefaultExports', 'Immutable'],
+ commonjs2: 'immutable',
+ commonjs: 'immutable',
+ amd: 'immutable',
+ umd: 'immutable',
+ },
+ moment: {
+ root: ['NetlifyCmsDefaultExports', 'Moment'],
+ commonjs2: 'moment',
+ commonjs: 'moment',
+ amd: 'moment',
+ umd: 'moment',
+ },
+ 'prop-types': {
+ root: ['NetlifyCmsDefaultExports', 'PropTypes'],
+ commonjs2: 'prop-types',
+ commonjs: 'prop-types',
+ amd: 'prop-types',
+ umd: 'prop-types',
+ },
+ 'react-immutable-proptypes': {
+ root: ['NetlifyCmsDefaultExports', 'ImmutablePropTypes'],
+ commonjs2: 'react-immutable-proptypes',
+ commonjs: 'react-immutable-proptypes',
+ amd: 'react-immutable-proptypes',
+ umd: 'react-immutable-proptypes',
+ },
+ react: {
+ root: 'React',
+ commonjs2: 'react',
+ commonjs: 'react',
+ amd: 'react',
+ umd: 'react',
+ },
+ 'react-dom': {
+ root: 'ReactDOM',
+ commonjs2: 'react-dom',
+ commonjs: 'react-dom',
+ amd: 'react-dom',
+ umd: 'react-dom',
+ },
+ uuid: {
+ root: ['NetlifyCmsDefaultExports', 'UUId'],
+ commonjs2: 'uuid',
+ commonjs: 'uuid',
+ amd: 'uuid',
+ umd: 'uuid',
+ },
+ },
+};
diff --git a/scripts/webpack.js b/scripts/webpack.js
index b57845a0..eaa00e0b 100644
--- a/scripts/webpack.js
+++ b/scripts/webpack.js
@@ -1,6 +1,7 @@
const path = require('path');
const webpack = require('webpack');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
+const { toGlobalName, externals } = require('./externals');
const pkg = require(path.join(process.cwd(), 'package.json'));
const isProduction = process.env.NODE_ENV === 'production';
@@ -16,6 +17,11 @@ const rules = () => ({
},
},
}),
+ css: () => ({
+ test: /\.css$/,
+ include: [/(ol|redux-notifications|react-datetime)/],
+ use: ['to-string-loader', 'css-loader'],
+ }),
svg: () => ({
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
exclude: [/node_modules/],
@@ -51,16 +57,54 @@ const stats = () => {
};
};
-const getConfig = () => ({
+const umdPath = path.resolve(process.cwd(), 'dist');
+const umdDirPath = path.resolve(process.cwd(), 'dist/umd');
+const cjsPath = path.resolve(process.cwd(), 'dist/cjs');
+const targetOutputs = () => {
+ console.log(`Building [${pkg.name}, library: ${toGlobalName(pkg.name)}]`);
+ return {
+ umd: {
+ path: umdPath,
+ filename: `${pkg.name}.js`,
+ library: toGlobalName(pkg.name),
+ libraryTarget: 'umd',
+ libraryExport: toGlobalName(pkg.name),
+ umdNamedDefine: true,
+ globalObject: 'window',
+ },
+ umddir: {
+ path: umdDirPath,
+ filename: `index.js`,
+ library: toGlobalName(pkg.name),
+ libraryTarget: 'umd',
+ libraryExport: toGlobalName(pkg.name),
+ umdNamedDefine: true,
+ globalObject: 'window',
+ },
+ cjs: {
+ path: cjsPath,
+ filename: 'index.js',
+ library: toGlobalName(pkg.name),
+ libraryTarget: 'window',
+ },
+ };
+};
+
+const umdExternals = Object.keys(pkg.peerDependencies || {}).reduce((previous, key) => {
+ if (!externals[key]) throw `Missing external [${key}]`;
+ previous[key] = externals[key] || null;
+ return previous;
+}, {});
+
+/**
+ * Use [getConfig({ target:'umd' }), getConfig({ target:'cjs' })] for
+ * getting multiple configs and add the new output in targetOutputs if needed.
+ * Default: umd
+ */
+const baseConfig = ({ target = isProduction ? 'umd' : 'umddir' } = {}) => ({
mode: isProduction ? 'production' : 'development',
entry: './src/index.js',
- output: {
- path: process.cwd(),
- filename: pkg.main,
- library: pkg.name,
- libraryTarget: 'umd',
- umdNamedDefine: true,
- },
+ output: targetOutputs()[target],
module: {
rules: Object.values(rules()).map(rule => rule()),
},
@@ -71,16 +115,25 @@ const getConfig = () => ({
/**
* Exclude peer dependencies from package bundles.
*/
- externals: (context, request, cb) => {
- const localExternals = pkg.localExternals || [];
- const peerDeps = Object.keys(pkg.peerDependencies || {});
- const externals = isProduction ? peerDeps : [...localExternals, ...peerDeps];
- const isPeerDep = dep => new RegExp(`^${dep}($|/)`).test(request);
- return externals.some(isPeerDep) ? cb(null, request) : cb();
- },
+ externals:
+ target.substr(0, 3) === 'umd'
+ ? umdExternals
+ : (context, request, cb) => {
+ const externals = Object.keys(pkg.peerDependencies || {});
+ const isPeerDep = dep => new RegExp(`^${dep}($|/)`).test(request);
+ return externals.some(isPeerDep) ? cb(null, request) : cb();
+ },
stats: stats(),
});
+const getConfig = ({ baseOnly = false } = {}) => {
+ if (baseOnly) {
+ // netlify-cms build
+ return baseConfig({ target: 'umd' });
+ }
+ return [baseConfig({ target: 'umd' })];
+};
+
module.exports = {
getConfig,
rules: rules(),
diff --git a/website/package.json b/website/package.json
index b81cb7fc..a031ca92 100755
--- a/website/package.json
+++ b/website/package.json
@@ -28,7 +28,7 @@
"gatsby-transformer-remark": "next",
"gatsby-transformer-yaml": "next",
"github-buttons": "git+https://github.com/ntkme/github-buttons.git",
- "lodash": "^4.17.10",
+ "lodash": "^4.17.11",
"netlify-cms": "^2.0.11",
"postcss-at2x": "^2.0.0",
"postcss-cssnext": "^2.7.0",
diff --git a/yarn.lock b/yarn.lock
index 695bf5a4..e8675ced 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3957,7 +3957,7 @@ create-react-class@^15.5.1, create-react-class@^15.5.2, create-react-class@^15.6
loose-envify "^1.3.1"
object-assign "^4.1.1"
-cross-env@^5.1.4, cross-env@^5.2.0:
+cross-env@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.0.tgz#6ecd4c015d5773e614039ee529076669b9d126f2"
integrity sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==