From 346858a5528a95e0fe869f4fd0269aa43b31cae0 Mon Sep 17 00:00:00 2001 From: Brent Vatne Date: Tue, 29 Nov 2016 15:25:10 -0800 Subject: [PATCH] Add StyleSheet.setStyleAttributePreprocessor Summary: **Motivation** On Exponent we load fonts dynamically and assign their native names by appending a session id, so that fonts from one Exponent "experience" do not clash with each other. So, before sending the `fontFamily` to native, we want to change it to the Exponent-scoped `fontFamily`. Example: ```js // Before rendering your app StyleSheet.setStyleAttributePreprocessor('fontFamily', _processFontFamily); function _processFontFamily(name) { // Pass system fonts through if (!name || Constants.systemFonts.indexOf(name) >= 0) { return name; } if (!Font.isLoaded(name)) { if (__DEV__) { console.error(`${name} is not a system font and has not been loaded through Exponent.Font.loadAsync. If you intended to use a system font, make sure you typed the name correctly and that it is supported by the current operating system. If this is a custom font, be sure to load it with Exponent.Font.loadAsync`); } else { return 'system'; } } return `ExponentFont- Closes https://github.com/facebook/react-native/pull/11138 Differential Revision: D4245518 Pulled By: mkonicek fbshipit-source-id: bd2452b1129d6675aa7b88e41351f8bb61fa20a3 --- .../ReactNativeAttributePayload-test.js | 22 +++++++++++++ Libraries/StyleSheet/StyleSheet.js | 31 ++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 Libraries/Renderer/src/renderers/native/__tests__/ReactNativeAttributePayload-test.js diff --git a/Libraries/Renderer/src/renderers/native/__tests__/ReactNativeAttributePayload-test.js b/Libraries/Renderer/src/renderers/native/__tests__/ReactNativeAttributePayload-test.js new file mode 100644 index 000000000..57d9f958c --- /dev/null +++ b/Libraries/Renderer/src/renderers/native/__tests__/ReactNativeAttributePayload-test.js @@ -0,0 +1,22 @@ +jest.disableAutomock(); + +const ReactNativeAttributePayload = require('ReactNativeAttributePayload'); +const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); +const StyleSheet = require('StyleSheet'); + +describe('ReactNativeAttributePayload', () => { + + describe('create', () => { + it('works with custom style processors', () => { + StyleSheet.setStyleAttributePreprocessor('fontFamily', (nextValue) => 'Wingdings'); + + const updatePayload = ReactNativeAttributePayload.create( + {style: {fontFamily: 'Comic Sans'}}, + {style: ReactNativeStyleAttributes}, + ); + + expect(updatePayload.fontFamily).toEqual('Wingdings'); + }); + }); + +}); diff --git a/Libraries/StyleSheet/StyleSheet.js b/Libraries/StyleSheet/StyleSheet.js index f4959870d..468c157b1 100644 --- a/Libraries/StyleSheet/StyleSheet.js +++ b/Libraries/StyleSheet/StyleSheet.js @@ -13,6 +13,7 @@ var PixelRatio = require('PixelRatio'); var ReactNativePropRegistry = require('ReactNativePropRegistry'); +var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); var StyleSheetValidation = require('StyleSheetValidation'); var flatten = require('flattenStyle'); @@ -162,6 +163,34 @@ module.exports = { */ flatten, + /** + * WARNING: EXPERIMENTAL. Breaking changes will probably happen a lot and will + * not be reliably announced. The whole thing might be deleted, who knows? Use + * at your own risk. + * + * Sets a function to use to pre-process a style property value. This is used + * internally to process color and transform values. You should not use this + * unless you really know what you are doing and have exhausted other options. + */ + setStyleAttributePreprocessor(property: string, process: (nextProp: mixed) => mixed) { + let value; + + if (typeof ReactNativeStyleAttributes[property] === 'string') { + value = {}; + } else if (typeof ReactNativeStyleAttributes[property] === 'object') { + value = ReactNativeStyleAttributes[property]; + } else { + console.error(`${property} is not a valid style attribute`); + return; + } + + if (__DEV__ && typeof value.process === 'function') { + console.warn(`Overwriting ${property} style attribute preprocessor`); + } + + ReactNativeStyleAttributes[property] = { ...value, process }; + }, + /** * Creates a StyleSheet style reference from the given object. */ @@ -172,5 +201,5 @@ module.exports = { result[key] = ReactNativePropRegistry.register(obj[key]); } return result; - } + }, };