feat: provide usable UMD builds for all packages (#2141)

This commit is contained in:
Tony Alves 2019-03-16 15:44:29 -07:00 committed by Shawn Erquhart
parent 1d935c704d
commit 82cc7941cc
89 changed files with 1025 additions and 712 deletions

View File

@ -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,
[

View File

@ -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);

View File

@ -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/*"

View File

@ -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"
}
}

View File

@ -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 = {

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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())) {

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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 = [];

View File

@ -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 };

View File

@ -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/'),
},
},
],
],
};

View File

@ -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"
}
}

View File

@ -1,5 +1,5 @@
import { actions as notifActions } from 'redux-notifications';
import { currentBackend } from 'src/backend';
import { currentBackend } from 'coreSrc/backend';
const { notifSend } = notifActions;

View File

@ -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;

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -1,4 +1,4 @@
import { currentBackend } from 'src/backend';
import { currentBackend } from 'coreSrc/backend';
import { getIntegrationProvider } from 'Integrations';
import { selectIntegration } from 'Reducers';

View File

@ -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';

View File

@ -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';

View File

@ -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,
};

View File

@ -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';

View File

@ -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();

View File

@ -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"
}
}

View File

@ -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,
};

View File

@ -0,0 +1,3 @@
const { getConfig } = require('../../scripts/webpack.js');
module.exports = getConfig();

View File

@ -24,6 +24,6 @@
"webpack-cli": "^3.2.3"
},
"peerDependencies": {
"react": "^16.4.1"
"react": "^16.8.4"
}
}

View File

@ -36,4 +36,5 @@ const image = {
],
};
export const NetlifyCmsEditorComponentImage = image;
export default image;

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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,
};

View File

@ -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"
}
}

View File

@ -83,4 +83,5 @@ async function init({ options = {}, handleInsert } = {}) {
const cloudinaryMediaLibrary = { name: 'cloudinary', init };
export const NetlifyCmsMediaLibraryCloudinary = cloudinaryMediaLibrary;
export default cloudinaryMediaLibrary;

View File

@ -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"

View File

@ -140,4 +140,5 @@ async function init({ options = { config: {} }, handleInsert } = {}) {
*/
const uploadcareMediaLibrary = { name: 'uploadcare', init };
export const NetlifyCmsMediaLibraryUploadcare = uploadcareMediaLibrary;
export default uploadcareMediaLibrary;

View File

@ -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"
}
}

View File

@ -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,
};

View File

@ -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"
}
}

View File

@ -1 +1,3 @@
export BooleanControl from './BooleanControl';
import controlComponent from './BooleanControl';
export const NetlifyCmsWidgetBoolean = { controlComponent };
export { controlComponent };

View File

@ -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"
}
}

View File

@ -8,4 +8,5 @@ const Widget = (opts = {}) => ({
...opts,
});
export const NetlifyCmsWidgetDate = { Widget, controlComponent, previewComponent };
export { Widget as default, controlComponent, previewComponent };

View File

@ -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();

View File

@ -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"
}
}

View File

@ -8,4 +8,5 @@ const Widget = (opts = {}) => ({
...opts,
});
export const NetlifyCmsWidgetDatetime = { Widget, controlComponent, previewComponent };
export { Widget as default, controlComponent, previewComponent };

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
]
}
}

View File

@ -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,

View File

@ -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 };

View File

@ -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": {

View File

@ -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 };

View File

@ -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();

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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,

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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(
<RelationController value={value}>
{({ handleOnChange, value, query, queryHits, setQueryHits }) => {
renderArgs = { value, onChangeSpy: handleOnChange, setQueryHitsSpy: setQueryHits };
return (
<RelationControl
field={field}
value={value}
query={query}
queryHits={queryHits}
onChange={handleOnChange}
forID="relation-field"
classNameWrapper=""
setActiveStyle={setActiveSpy}
setInactiveStyle={setInactiveSpy}
/>
);
}}
</RelationController>,
);
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(
<RelationController value={value}>
{({ handleOnChange, value, query, queryHits, setQueryHits }) => {
renderArgs = { value, onChangeSpy: handleOnChange, setQueryHitsSpy: setQueryHits };
return (
<RelationControl
field={field}
value={value}
query={query}
queryHits={queryHits}
onChange={handleOnChange}
forID="relation-field"
classNameWrapper=""
setActiveStyle={setActiveSpy}
setInactiveStyle={setInactiveSpy}
/>
);
}}
</RelationController>,
);
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);
});
});
});
});

View File

@ -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 };

View File

@ -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": {

View File

@ -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' },

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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 };

View File

@ -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"
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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 };

View File

@ -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);

View File

@ -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()]);

View File

@ -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',
},
},
];

108
scripts/externals.js Normal file
View File

@ -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',
},
},
};

View File

@ -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(),

View File

@ -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",

View File

@ -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==