From 0c21fc215b4e6f0d4b415aabb9f8297635b7d148 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 15 Jan 2019 15:53:19 +0800 Subject: [PATCH] Add new package for editor configuration, initially containing just feature flags --- docs/manifest.json | 6 ++ lib/packages-dependencies.php | 1 + package.json | 1 + packages/editor-configuration/.npmrc | 1 + packages/editor-configuration/CHANGELOG.md | 5 ++ packages/editor-configuration/README.md | 73 +++++++++++++++++++ packages/editor-configuration/package.json | 27 +++++++ .../src/config/development.js | 3 + .../editor-configuration/src/config/plugin.js | 3 + .../src/config/production.js | 3 + packages/editor-configuration/src/index.js | 20 +++++ .../editor-configuration/src/utils/index.js | 15 ++++ .../src/utils/test/index.js | 21 ++++++ 13 files changed, 179 insertions(+) create mode 100644 packages/editor-configuration/.npmrc create mode 100644 packages/editor-configuration/CHANGELOG.md create mode 100644 packages/editor-configuration/README.md create mode 100644 packages/editor-configuration/package.json create mode 100644 packages/editor-configuration/src/config/development.js create mode 100644 packages/editor-configuration/src/config/plugin.js create mode 100644 packages/editor-configuration/src/config/production.js create mode 100644 packages/editor-configuration/src/index.js create mode 100644 packages/editor-configuration/src/utils/index.js create mode 100644 packages/editor-configuration/src/utils/test/index.js diff --git a/docs/manifest.json b/docs/manifest.json index 4dc762893f571b..67cc8698d099ec 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -515,6 +515,12 @@ "markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/packages/edit-post/README.md", "parent": "packages" }, + { + "title": "@wordpress/editor-configuration", + "slug": "packages-editor-configuration", + "markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/packages/editor-configuration/README.md", + "parent": "packages" + }, { "title": "@wordpress/editor", "slug": "packages-editor", diff --git a/lib/packages-dependencies.php b/lib/packages-dependencies.php index 34c70851ff727c..5dbc8032673b8a 100644 --- a/lib/packages-dependencies.php +++ b/lib/packages-dependencies.php @@ -160,6 +160,7 @@ 'wp-viewport', 'wp-wordcount', ), + 'wp-editor-configuration' => array(), 'wp-element' => array( 'lodash', 'react', diff --git a/package.json b/package.json index 95ce65ad2682f3..85f72dbf9c2b6e 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@wordpress/dom-ready": "file:packages/dom-ready", "@wordpress/edit-post": "file:packages/edit-post", "@wordpress/editor": "file:packages/editor", + "@wordpress/editor-configuration": "file:packages/editor-configuration", "@wordpress/element": "file:packages/element", "@wordpress/escape-html": "file:packages/escape-html", "@wordpress/format-library": "file:packages/format-library", diff --git a/packages/editor-configuration/.npmrc b/packages/editor-configuration/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/editor-configuration/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/editor-configuration/CHANGELOG.md b/packages/editor-configuration/CHANGELOG.md new file mode 100644 index 00000000000000..c9970e2e618b50 --- /dev/null +++ b/packages/editor-configuration/CHANGELOG.md @@ -0,0 +1,5 @@ +## 1.0.0 (Unreleased) + +### New Features + +- Initial release. diff --git a/packages/editor-configuration/README.md b/packages/editor-configuration/README.md new file mode 100644 index 00000000000000..797981dc712bc1 --- /dev/null +++ b/packages/editor-configuration/README.md @@ -0,0 +1,73 @@ +# Editor configuration + +Editor configuration is a package that stores configuration values for Gutenberg. + +The package contains three different configuration files per environment: +- `config/development.js` - configuration values for local development environments and testing. +- `config/plugin.js` - configuration values for the Gutenberg plugin. +- `config/production.js` - configuration values for the block editor in Wordpress Core. + +## Installation + +Install the module + +```bash +npm install @wordpress/editor-configuration --save +``` + +_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for ES2015+ such as lower versions of IE then using [core-js](https://github.com/zloirock/core-js) or [@babel/polyfill](https://babeljs.io/docs/en/next/babel-polyfill) will add support for these methods. Learn more about it in [Babel docs](https://babeljs.io/docs/en/next/caveats)._ + +## Usage + +### Feature flags + +Feature flags (also known as 'feature toggles') are boolean values that indicate whether a specific feature is active. + +By defining a per-environment flag for a feature, fine-grain control can be achieved over when a feature is released. Generally a feature will initally only be enabled in `development` environments. Once it reaches a certain maturity, it can be enabled in the plugin. Finally, once a feature is ready for release, it can be enabled in production. + +An advantage of feature flags is that a pull request implementing a new feature no longer needs to be held back from being merged into `master`. As long as the code passes review, a feature can be merged but disabled until it's ready to be released. + +### Adding a feature flag + +For each configuration file, add a new item in the `features` object. Add new flags in alphabetical order to make it easier to browse them: + +development.js +```javascript +export default { + features: { + // ... + 'editor/my-first-feature': true, + // ... + } +} +``` + +plugin.js / production.js +```javascript +export default { + features: { + // ... + 'editor/my-first-feature': false, + // ... + } +} +``` + +In the file(s) the feature is implemented, import the `getFeatureFlag` function from this package, and use it to determine whether the feature is active: +```javascript +import { getFeatureFlag } from '@wordpress/editor-configuration'; + +const isMyFirstFeatureActive = getFeatureFlag( 'editor/my-first-feature' ); +``` + +Finally, avoid executing code that implements the feature at the earliest possible point: +```javascript +function myFirstFeature() { + if ( ! isMyFirstFeatureActive ) { + return; + } + + // ... implementation of feature +} + +``` diff --git a/packages/editor-configuration/package.json b/packages/editor-configuration/package.json new file mode 100644 index 00000000000000..bed1ff4fd60053 --- /dev/null +++ b/packages/editor-configuration/package.json @@ -0,0 +1,27 @@ +{ + "name": "@wordpress/editor-configuration", + "version": "1.0.0", + "description": "Configuration for the WordPress block editor.", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "config", + "configuration" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/editor-configuration/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "react-native": "src/index", + "dependencies": {}, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/editor-configuration/src/config/development.js b/packages/editor-configuration/src/config/development.js new file mode 100644 index 00000000000000..6ed10e3b2a47cb --- /dev/null +++ b/packages/editor-configuration/src/config/development.js @@ -0,0 +1,3 @@ +export default { + features: {}, +}; diff --git a/packages/editor-configuration/src/config/plugin.js b/packages/editor-configuration/src/config/plugin.js new file mode 100644 index 00000000000000..6ed10e3b2a47cb --- /dev/null +++ b/packages/editor-configuration/src/config/plugin.js @@ -0,0 +1,3 @@ +export default { + features: {}, +}; diff --git a/packages/editor-configuration/src/config/production.js b/packages/editor-configuration/src/config/production.js new file mode 100644 index 00000000000000..6ed10e3b2a47cb --- /dev/null +++ b/packages/editor-configuration/src/config/production.js @@ -0,0 +1,3 @@ +export default { + features: {}, +}; diff --git a/packages/editor-configuration/src/index.js b/packages/editor-configuration/src/index.js new file mode 100644 index 00000000000000..1c27b8750ecba8 --- /dev/null +++ b/packages/editor-configuration/src/index.js @@ -0,0 +1,20 @@ +/** + * Internal dependencies + */ +import development from './config/development'; +import plugin from './config/plugin'; +import production from './config/production'; + +import { + getFeatureFlag as unboundGetFeatureFlag, +} from './utils'; + +const configMap = { + development, + plugin, + production, +}; + +const activeConfig = configMap[ process.env.NODE_ENV ] || development; + +export const getFeatureFlag = unboundGetFeatureFlag.bind( null, activeConfig ); diff --git a/packages/editor-configuration/src/utils/index.js b/packages/editor-configuration/src/utils/index.js new file mode 100644 index 00000000000000..cb5e5ddaa421f2 --- /dev/null +++ b/packages/editor-configuration/src/utils/index.js @@ -0,0 +1,15 @@ + +/** + * Get the value of a feature flag by its name. + * + * Note, when this function is exported from `@wordpress/editor-configurations, + * it is pre-bound and only requires the `featureName` argument. + * + * @param {Object} config The configuration object. + * @param {string} featureName The name of the feature. + * + * @return {boolean} Whether the feature is enabled (`true`) or disabled (`false`). + */ +export function getFeatureFlag( config, featureName ) { + return !! config.features[ featureName ]; +} diff --git a/packages/editor-configuration/src/utils/test/index.js b/packages/editor-configuration/src/utils/test/index.js new file mode 100644 index 00000000000000..6066444f6cee99 --- /dev/null +++ b/packages/editor-configuration/src/utils/test/index.js @@ -0,0 +1,21 @@ +import { getFeatureFlag } from '../'; + +describe( 'getFeatureFlag', () => { + it( 'returns false for an unknown feature flag', () => { + const config = { + features: {}, + }; + expect( getFeatureFlag( config, 'foo' ) ).toBe( false ); + } ); + + it( 'returns the truthiness of the value set in the config for a known feature flag', () => { + const config = { + features: { + foo: true, + bar: false, + }, + }; + expect( getFeatureFlag( config, 'foo' ) ).toBe( true ); + expect( getFeatureFlag( config, 'bar' ) ).toBe( false ); + } ); +} );