From f8f28980957ecb46393981d9b4bdfc820da06c26 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Fri, 26 Aug 2016 11:13:22 -0700 Subject: [PATCH] Use Twitter JavaScript style --- .eslintrc | 215 +++++++++++++- package.json | 12 +- src/apis/Animated/index.js | 14 +- src/apis/AppRegistry/ReactNativeApp.js | 14 +- .../__tests__/renderApplication-test.js | 18 +- src/apis/AppRegistry/index.js | 48 +-- src/apis/AppRegistry/renderApplication.js | 26 +- src/apis/AppState/__tests__/index-test.js | 34 +-- src/apis/AppState/index.js | 42 +-- src/apis/AsyncStorage/__tests__/index-test.js | 4 +- src/apis/AsyncStorage/index.js | 84 +++--- src/apis/Dimensions/__tests__/index-test.js | 4 +- src/apis/Dimensions/index.js | 24 +- src/apis/I18nManager/__tests__/index-test.js | 54 ++-- src/apis/I18nManager/index.js | 36 +-- src/apis/InteractionManager/index.js | 16 +- src/apis/NetInfo/__tests__/index-test.js | 4 +- src/apis/NetInfo/index.js | 54 ++-- src/apis/PixelRatio/__tests__/index-test.js | 4 +- src/apis/PixelRatio/index.js | 14 +- src/apis/Platform/index.js | 4 +- .../__tests__/createReactStyleObject-test.js | 14 +- .../StyleSheet/__tests__/expandStyle-test.js | 32 +- .../StyleSheet/__tests__/i18nStyle-test.js | 56 ++-- src/apis/StyleSheet/__tests__/index-test.js | 52 ++-- .../__tests__/normalizeValue-test.js | 16 +- .../__tests__/processTextShadow-test.js | 12 +- .../__tests__/processTransform-test.js | 18 +- .../__tests__/processVendorPrefixes-test.js | 12 +- src/apis/StyleSheet/createReactStyleObject.js | 26 +- src/apis/StyleSheet/css.js | 24 +- src/apis/StyleSheet/expandStyle.js | 50 ++-- src/apis/StyleSheet/i18nStyle.js | 68 ++--- src/apis/StyleSheet/index.js | 66 ++--- src/apis/StyleSheet/normalizeValue.js | 10 +- src/apis/StyleSheet/processTextShadow.js | 26 +- src/apis/StyleSheet/processTransform.js | 28 +- src/apis/StyleSheet/processVendorPrefixes.js | 14 +- src/apis/UIManager/__tests__/index-test.js | 180 +++++------ src/apis/UIManager/index.js | 56 ++-- src/apis/Vibration/index.js | 14 +- .../ActivityIndicator/__tests__/index-test.js | 4 +- src/components/ActivityIndicator/index.js | 50 ++-- src/components/Image/ImageResizeMode.js | 6 +- src/components/Image/ImageStylePropTypes.js | 16 +- src/components/Image/__tests__/index-test.js | 197 ++++++------- src/components/Image/index.js | 140 +++++---- src/components/Image/resolveAssetSource.js | 4 +- src/components/ListView/ListViewPropTypes.js | 8 +- .../ListView/__tests__/index-test.js | 4 +- src/components/ListView/index.js | 88 +++--- src/components/ScrollView/ScrollViewBase.js | 50 ++-- .../ScrollView/__tests__/index-test.js | 4 +- src/components/ScrollView/index.js | 146 ++++----- .../StaticContainer/__tests__/index-test.js | 4 +- src/components/StaticContainer/index.js | 10 +- .../StaticRenderer/__tests__/index-test.js | 4 +- src/components/StaticRenderer/index.js | 8 +- src/components/Switch/__tests__/index-test.js | 56 ++-- src/components/Switch/index.js | 72 ++--- src/components/Text/TextStylePropTypes.js | 6 +- src/components/Text/__tests__/index-test.js | 50 ++-- src/components/Text/index.js | 28 +- src/components/TextInput/TextInputState.js | 16 +- .../TextInput/__tests__/index-test.js | 279 +++++++++--------- src/components/TextInput/index.js | 152 +++++----- .../Touchable/__tests__/index-test.js | 4 +- src/components/View/ViewStylePropTypes.js | 18 +- src/components/View/__tests__/index-test.js | 68 ++--- src/components/View/index.js | 64 ++-- src/core.js | 30 +- src/index.js | 82 ++--- src/modules/NativeMethodsMixin/index.js | 28 +- src/modules/NativeModules/index.js | 2 +- src/modules/applyLayout/index.js | 42 +-- src/modules/applyNativeMethods/index.js | 12 +- .../createDOMElement/__tests__/index-test.js | 78 ++--- src/modules/createDOMElement/index.js | 18 +- src/modules/dismissKeyboard/index.js | 8 +- src/modules/findNodeHandle/index.js | 6 +- .../flattenStyle/__tests__/index-test.js | 58 ++-- src/modules/injectResponderEventPlugin.js | 54 ++-- .../__tests__/index-test.js | 24 +- src/modules/multiplyStyleLengthValue/index.js | 20 +- src/modules/normalizeNativeEvent.js | 46 +-- src/modules/polyfills/Set.js | 12 +- src/propTypes/BaseComponentPropTypes.js | 8 +- src/propTypes/BorderPropTypes.js | 12 +- src/propTypes/LayoutPropTypes.js | 10 +- src/propTypes/StyleSheetPropType.js | 18 +- src/propTypes/TextPropTypes.js | 18 +- src/propTypes/TransformPropTypes.js | 10 +- src/tests.webpack.js | 4 +- 93 files changed, 1936 insertions(+), 1719 deletions(-) diff --git a/.eslintrc b/.eslintrc index e325acd2..5fd0a1d1 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,14 +1,213 @@ { - // babel parser to support ES features + // babel parser to support ES6/7 features "parser": "babel-eslint", - // based on https://github.com/feross/standard - "extends": [ "standard", "standard-react" ], + "parserOptions": { + "ecmaVersion": 7, + "ecmaFeatures": { + "experimentalObjectRestSpread": true, + "jsx": true + }, + "sourceType": "module" + }, + "plugins": [ + "jsx-a11y", + "promise", + "react" + ], + "env": { + "es6": true, + "node": true + }, + "globals": { + "document": false, + "navigator": false, + "window": false + }, "rules": { - // overrides of the standard style - "space-before-function-paren": [ 2, { "anonymous": "always", "named": "never" } ], - "wrap-iife": [ 2, "outside" ], - // overrides of the standard-react style + "accessor-pairs": 2, + "array-bracket-spacing": ["error", "always"], + "arrow-parens": [2, "always"], + "arrow-spacing": [2, { "before": true, "after": true }], + "block-spacing": [2, "always"], + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "camelcase": 0, + "comma-dangle": [2, "never"], + "comma-spacing": [2, { "before": false, "after": true }], + "comma-style": [2, "last"], + "computed-property-spacing": ["error", "never"], + "constructor-super": 2, + "curly": [2, "all"], + "default-case": [2, { commentPattern: '^no default$' }], + "dot-location": [2, "property"], + "eol-last": 2, + "eqeqeq": [2, "allow-null"], + "generator-star-spacing": [2, { "before": true, "after": true }], + "handle-callback-err": [2, "^(err|error)$" ], + "indent": [2, 2, { "SwitchCase": 1 }], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "keyword-spacing": [2, { "before": true, "after": true }], + "max-len": [2, 120, 4], + "new-cap": [2, { "newIsCap": true, "capIsNew": false }], + "new-parens": 2, + "no-alert": 1, + "no-array-constructor": 2, + "no-caller": 2, + "no-case-declarations": 2, + "no-class-assign": 2, + "no-cond-assign": 2, + "no-const-assign": 2, + "no-control-regex": 2, + "no-debugger": 2, + "no-delete-var": 2, + "no-dupe-args": 2, + "no-dupe-class-members": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-duplicate-imports": 2, + "no-empty-character-class": 2, + "no-empty-pattern": 2, + "no-eval": 2, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-extra-boolean-cast": 2, + "no-extra-parens": [2, "functions"], + "no-extra-semi": 2, + "no-fallthrough": 2, + "no-floating-decimal": 2, + "no-func-assign": 2, + "no-implied-eval": 2, + "no-inner-declarations": [2, "functions"], + "no-invalid-regexp": 2, + "no-irregular-whitespace": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-labels": [2, { "allowLoop": false, "allowSwitch": false }], + "no-lone-blocks": 2, + "no-loop-func": 2, + "no-mixed-spaces-and-tabs": 2, + "no-multi-spaces": 2, + "no-multi-str": 2, + "no-multiple-empty-lines": [2, { "max": 1 }], + "no-native-reassign": 2, + "no-negated-in-lhs": 2, + "no-new": 2, + "no-new-func": 2, + "no-new-object": 2, + "no-new-require": 2, + "no-new-symbol": 2, + "no-new-wrappers": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 2, + "no-path-concat": 2, + "no-proto": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-return-assign": [2, "except-parens"], + "no-script-url": 2, + "no-self-assign": 2, + "no-self-compare": 2, + "no-sequences": 2, + "no-shadow-restricted-names": 2, + "no-spaced-func": 2, + "no-sparse-arrays": 2, + "no-this-before-super": 2, + "no-throw-literal": 2, + "no-trailing-spaces": 2, + "no-undef": 2, + "no-undef-init": 2, + "no-unexpected-multiline": 2, + "no-unmodified-loop-condition": 2, + "no-unneeded-ternary": [2, { "defaultAssignment": false }], + "no-unreachable": 2, + "no-unsafe-finally": 2, + "no-unused-vars": [2, { "vars": "all", "args": "none" }], + "no-useless-call": 2, + "no-useless-computed-key": 2, + "no-useless-concat": 2, + "no-useless-constructor": 2, + "no-useless-escape": 2, + "no-var": 2, + "no-whitespace-before-property": 2, + "no-with": 2, + "object-curly-spacing": ["error", "always"], + "operator-linebreak": [2, "after"], + "padded-blocks": [2, "never"], + "prefer-const": 2, + "prefer-rest-params": 2, + "prefer-template": 2, + "quotes": [2, "single", "avoid-escape"], + "radix": 2, + "rest-spread-spacing": ["error"], + "semi": [2, "always"], + "semi-spacing": [2, { "before": false, "after": true }], + "space-before-blocks": [2, "always"], + "space-before-function-paren": [2, { "anonymous": "always", "named": "never" }], + "space-in-parens": [2, "never"], + "space-infix-ops": 2, + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }], + "template-curly-spacing": [2, "never"], + "use-isnan": 2, + "valid-typeof": 2, + "wrap-iife": [2, "outside"], + "yield-star-spacing": [2, "both"], + "yoda": [2, "never"], + + // promise + "promise/param-names": 2, + + // jsx accessibility + "jsx-a11y/aria-props": 2, + "jsx-a11y/aria-proptypes": 2, + "jsx-a11y/aria-role": 2, + "jsx-a11y/aria-unsupported-elements": 2, + "jsx-a11y/heading-has-content": 2, + "jsx-a11y/href-no-hash": 2, + "jsx-a11y/html-has-lang": 2, + "jsx-a11y/img-has-alt": 2, + "jsx-a11y/img-redundant-alt": 2, + "jsx-a11y/label-has-for": 2, + "jsx-a11y/mouse-events-have-key-events": 2, + "jsx-a11y/no-access-key": 2, + "jsx-a11y/no-marquee": 2, + "jsx-a11y/no-onchange": 0, + "jsx-a11y/onclick-has-focus": 2, + "jsx-a11y/onclick-has-role": 2, + "jsx-a11y/role-has-required-aria-props": 2, + "jsx-a11y/role-supports-aria-props": 2, + "jsx-a11y/scope": 2, + "jsx-a11y/tabindex-no-positive": 2, + + // react + "jsx-quotes": [2, "prefer-single"], + "react/display-name": 0, + "react/jsx-boolean-value": 2, + "react/jsx-handler-names": [2, { + "eventHandlerPrefix": "_handle" + }], + "react/jsx-indent": [2, 2], + "react/jsx-indent-props": [2, 2], + "react/jsx-no-bind": 2, + "react/jsx-no-duplicate-props": 2, + "react/jsx-no-undef": 2, + "react/jsx-pascal-case": 2, "react/jsx-sort-props": 2, - "react/jsx-sort-prop-types": 2 + "react/jsx-uses-react": 2, + "react/jsx-uses-vars": 2, + "react/no-did-mount-set-state": 0, + "react/no-did-update-set-state": 2, + "react/no-direct-mutation-state": 2, + "react/no-multi-comp": 0, + "react/no-string-refs": 2, + "react/no-unknown-property": 2, + "react/prefer-es6-class": 2, + "react/prop-types": 2, + "react/react-in-jsx-scope": 0, + "react/self-closing-comp": 2, + "react/sort-comp": 0, + "react/sort-prop-types": 2, + "react/wrap-multilines": 0 } } diff --git a/package.json b/package.json index db25f336..ac462506 100644 --- a/package.json +++ b/package.json @@ -31,17 +31,15 @@ "@kadira/storybook": "^1.38.0", "babel-cli": "^6.10.1", "babel-core": "^6.10.4", - "babel-eslint": "^6.1.0", + "babel-eslint": "^6.1.2", "babel-loader": "^6.2.4", "babel-preset-react-native": "^1.9.0", "del-cli": "^0.2.0", "enzyme": "^2.3.0", - "eslint": "^2.12.0", - "eslint-config-standard": "^5.3.1", - "eslint-config-standard-react": "^2.4.0", - "eslint-plugin-promise": "^1.3.2", - "eslint-plugin-react": "^5.1.1", - "eslint-plugin-standard": "^1.3.2", + "eslint": "^3.4.0", + "eslint-plugin-jsx-a11y": "^2.2.0", + "eslint-plugin-promise": "^2.0.1", + "eslint-plugin-react": "^6.1.2", "file-loader": "^0.9.0", "karma": "^0.13.22", "karma-browserstack-launcher": "^1.0.1", diff --git a/src/apis/Animated/index.js b/src/apis/Animated/index.js index 21f80b94..7d59efc3 100644 --- a/src/apis/Animated/index.js +++ b/src/apis/Animated/index.js @@ -1,14 +1,14 @@ -import Animated from 'animated' -import StyleSheet from '../StyleSheet' -import Image from '../../components/Image' -import Text from '../../components/Text' -import View from '../../components/View' +import Animated from 'animated'; +import Image from '../../components/Image'; +import StyleSheet from '../StyleSheet'; +import Text from '../../components/Text'; +import View from '../../components/View'; -Animated.inject.FlattenStyle(StyleSheet.flatten) +Animated.inject.FlattenStyle(StyleSheet.flatten); module.exports = { ...Animated, Image: Animated.createAnimatedComponent(Image), Text: Animated.createAnimatedComponent(Text), View: Animated.createAnimatedComponent(View) -} +}; diff --git a/src/apis/AppRegistry/ReactNativeApp.js b/src/apis/AppRegistry/ReactNativeApp.js index eda77dc4..6c74e6a3 100644 --- a/src/apis/AppRegistry/ReactNativeApp.js +++ b/src/apis/AppRegistry/ReactNativeApp.js @@ -1,6 +1,6 @@ -import React, { Component, PropTypes } from 'react' -import StyleSheet from '../StyleSheet' -import View from '../../components/View' +import StyleSheet from '../StyleSheet'; +import View from '../../components/View'; +import React, { Component, PropTypes } from 'react'; class ReactNativeApp extends Component { static propTypes = { @@ -10,13 +10,13 @@ class ReactNativeApp extends Component { }; render() { - const { initialProps, rootComponent: RootComponent, rootTag } = this.props + const { initialProps, rootComponent: RootComponent, rootTag } = this.props; return ( - ) + ); } } @@ -31,6 +31,6 @@ const styles = StyleSheet.create({ right: 0, bottom: 0 } -}) +}); -module.exports = ReactNativeApp +module.exports = ReactNativeApp; diff --git a/src/apis/AppRegistry/__tests__/renderApplication-test.js b/src/apis/AppRegistry/__tests__/renderApplication-test.js index e636181b..7963e6a2 100644 --- a/src/apis/AppRegistry/__tests__/renderApplication-test.js +++ b/src/apis/AppRegistry/__tests__/renderApplication-test.js @@ -1,16 +1,16 @@ /* eslint-env mocha */ -import assert from 'assert' -import { prerenderApplication } from '../renderApplication' -import React from 'react' +import assert from 'assert'; +import { prerenderApplication } from '../renderApplication'; +import React from 'react'; -const component = () =>
+const component = () =>
; suite('apis/AppRegistry/renderApplication', () => { test('prerenderApplication', () => { - const { html, styleElement } = prerenderApplication(component, {}) + const { html, styleElement } = prerenderApplication(component, {}); - assert.ok(html.indexOf('
-1) - assert.equal(styleElement.type, 'style') - }) -}) + assert.ok(html.indexOf('
-1); + assert.equal(styleElement.type, 'style'); + }); +}); diff --git a/src/apis/AppRegistry/index.js b/src/apis/AppRegistry/index.js index 69d3952a..0861e780 100644 --- a/src/apis/AppRegistry/index.js +++ b/src/apis/AppRegistry/index.js @@ -6,12 +6,12 @@ * @flow */ -import { Component } from 'react' -import invariant from 'fbjs/lib/invariant' -import ReactDOM from 'react-dom' -import renderApplication, { prerenderApplication } from './renderApplication' +import { Component } from 'react'; +import invariant from 'fbjs/lib/invariant'; +import ReactDOM from 'react-dom'; +import renderApplication, { prerenderApplication } from './renderApplication'; -const runnables = {} +const runnables = {}; type ComponentProvider = () => Component @@ -26,7 +26,7 @@ type AppConfig = { */ class AppRegistry { static getAppKeys(): Array { - return Object.keys(runnables) + return Object.keys(runnables); } static prerenderApplication(appKey: string, appParameters?: Object): string { @@ -34,59 +34,59 @@ class AppRegistry { runnables[appKey] && runnables[appKey].prerender, `Application ${appKey} has not been registered. ` + 'This is either due to an import error during initialization or failure to call AppRegistry.registerComponent.' - ) + ); - return runnables[appKey].prerender(appParameters) + return runnables[appKey].prerender(appParameters); } static registerComponent(appKey: string, getComponentFunc: ComponentProvider): string { runnables[appKey] = { run: ({ initialProps, rootTag }) => renderApplication(getComponentFunc(), initialProps, rootTag), prerender: ({ initialProps } = {}) => prerenderApplication(getComponentFunc(), initialProps) - } - return appKey + }; + return appKey; } static registerConfig(config: Array) { config.forEach(({ appKey, component, run }) => { if (run) { - AppRegistry.registerRunnable(appKey, run) + AppRegistry.registerRunnable(appKey, run); } else { - invariant(component, 'No component provider passed in') - AppRegistry.registerComponent(appKey, component) + invariant(component, 'No component provider passed in'); + AppRegistry.registerComponent(appKey, component); } - }) + }); } // TODO: fix style sheet creation when using this method static registerRunnable(appKey: string, run: Function): string { - runnables[appKey] = { run } - return appKey + runnables[appKey] = { run }; + return appKey; } static runApplication(appKey: string, appParameters?: Object): void { - const isDevelopment = process.env.NODE_ENV !== 'production' - const params = { ...appParameters } - params.rootTag = `#${params.rootTag.id}` + const isDevelopment = process.env.NODE_ENV !== 'production'; + const params = { ...appParameters }; + params.rootTag = `#${params.rootTag.id}`; console.log( `Running application "${appKey}" with appParams: ${JSON.stringify(params)}. ` + `development-level warnings are ${isDevelopment ? 'ON' : 'OFF'}, ` + `performance optimizations are ${isDevelopment ? 'OFF' : 'ON'}` - ) + ); invariant( runnables[appKey] && runnables[appKey].run, `Application "${appKey}" has not been registered. ` + 'This is either due to an import error during initialization or failure to call AppRegistry.registerComponent.' - ) + ); - runnables[appKey].run(appParameters) + runnables[appKey].run(appParameters); } static unmountApplicationComponentAtRootTag(rootTag) { - ReactDOM.unmountComponentAtNode(rootTag) + ReactDOM.unmountComponentAtNode(rootTag); } } -module.exports = AppRegistry +module.exports = AppRegistry; diff --git a/src/apis/AppRegistry/renderApplication.js b/src/apis/AppRegistry/renderApplication.js index 771f0fac..ce1a42b0 100644 --- a/src/apis/AppRegistry/renderApplication.js +++ b/src/apis/AppRegistry/renderApplication.js @@ -6,15 +6,15 @@ * @flow */ -import invariant from 'fbjs/lib/invariant' -import React, { Component } from 'react' -import ReactDOM from 'react-dom' -import ReactDOMServer from 'react-dom/server' -import ReactNativeApp from './ReactNativeApp' -import StyleSheet from '../../apis/StyleSheet' +import invariant from 'fbjs/lib/invariant'; +import ReactDOM from 'react-dom'; +import ReactDOMServer from 'react-dom/server'; +import ReactNativeApp from './ReactNativeApp'; +import StyleSheet from '../../apis/StyleSheet'; +import React, { Component } from 'react'; export default function renderApplication(RootComponent: Component, initialProps: Object, rootTag: any) { - invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag) + invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag); const component = ( - ) - ReactDOM.render(component, rootTag) + ); + ReactDOM.render(component, rootTag); } export function prerenderApplication(RootComponent: Component, initialProps: Object): string { @@ -32,8 +32,8 @@ export function prerenderApplication(RootComponent: Component, initialProps: Obj initialProps={initialProps} rootComponent={RootComponent} /> - ) - const html = ReactDOMServer.renderToString(component) - const styleElement = StyleSheet.render() - return { html, styleElement } + ); + const html = ReactDOMServer.renderToString(component); + const styleElement = StyleSheet.render(); + return { html, styleElement }; } diff --git a/src/apis/AppState/__tests__/index-test.js b/src/apis/AppState/__tests__/index-test.js index 8c0aa28c..54d51a30 100644 --- a/src/apis/AppState/__tests__/index-test.js +++ b/src/apis/AppState/__tests__/index-test.js @@ -1,31 +1,31 @@ /* eslint-env mocha */ -import AppState from '..' -import assert from 'assert' +import AppState from '..'; +import assert from 'assert'; suite('apis/AppState', () => { - const handler = () => {} + const handler = () => {}; teardown(() => { - try { AppState.removeEventListener('change', handler) } catch (e) {} - }) + try { AppState.removeEventListener('change', handler); } catch (e) {} + }); suite('addEventListener', () => { test('throws if the provided "eventType" is not supported', () => { - assert.throws(() => AppState.addEventListener('foo', handler)) - assert.doesNotThrow(() => AppState.addEventListener('change', handler)) - }) - }) + assert.throws(() => AppState.addEventListener('foo', handler)); + assert.doesNotThrow(() => AppState.addEventListener('change', handler)); + }); + }); suite('removeEventListener', () => { test('throws if the handler is not registered', () => { - assert.throws(() => AppState.removeEventListener('change', handler)) - }) + assert.throws(() => AppState.removeEventListener('change', handler)); + }); test('throws if the provided "eventType" is not supported', () => { - AppState.addEventListener('change', handler) - assert.throws(() => AppState.removeEventListener('foo', handler)) - assert.doesNotThrow(() => AppState.removeEventListener('change', handler)) - }) - }) -}) + AppState.addEventListener('change', handler); + assert.throws(() => AppState.removeEventListener('foo', handler)); + assert.doesNotThrow(() => AppState.removeEventListener('change', handler)); + }); + }); +}); diff --git a/src/apis/AppState/index.js b/src/apis/AppState/index.js index e71d930c..2b0d6aec 100644 --- a/src/apis/AppState/index.js +++ b/src/apis/AppState/index.js @@ -1,54 +1,54 @@ -import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment' -import findIndex from 'lodash/findIndex' -import invariant from 'fbjs/lib/invariant' +import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; +import findIndex from 'lodash/findIndex'; +import invariant from 'fbjs/lib/invariant'; -const EVENT_TYPES = [ 'change' ] -const VISIBILITY_CHANGE_EVENT = 'visibilitychange' +const EVENT_TYPES = [ 'change' ]; +const VISIBILITY_CHANGE_EVENT = 'visibilitychange'; const AppStates = { BACKGROUND: 'background', ACTIVE: 'active' -} +}; -const listeners = [] +const listeners = []; class AppState { static isSupported = ExecutionEnvironment.canUseDOM && document.visibilityState static get currentState() { if (!AppState.isSupported) { - return AppState.ACTIVE + return AppState.ACTIVE; } switch (document.visibilityState) { case 'hidden': case 'prerender': case 'unloaded': - return AppStates.BACKGROUND + return AppStates.BACKGROUND; default: - return AppStates.ACTIVE + return AppStates.ACTIVE; } } static addEventListener(type: string, handler: Function) { if (AppState.isSupported) { - invariant(EVENT_TYPES.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type) - const callback = () => handler(AppState.currentState) - listeners.push([ handler, callback ]) - document.addEventListener(VISIBILITY_CHANGE_EVENT, callback, false) + invariant(EVENT_TYPES.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type); + const callback = () => handler(AppState.currentState); + listeners.push([ handler, callback ]); + document.addEventListener(VISIBILITY_CHANGE_EVENT, callback, false); } } static removeEventListener(type: string, handler: Function) { if (AppState.isSupported) { - invariant(EVENT_TYPES.indexOf(type) !== -1, 'Trying to remove listener for unknown event: "%s"', type) - const listenerIndex = findIndex(listeners, (pair) => pair[0] === handler) - invariant(listenerIndex !== -1, 'Trying to remove AppState listener for unregistered handler') - const callback = listeners[listenerIndex][1] - document.removeEventListener(VISIBILITY_CHANGE_EVENT, callback, false) - listeners.splice(listenerIndex, 1) + invariant(EVENT_TYPES.indexOf(type) !== -1, 'Trying to remove listener for unknown event: "%s"', type); + const listenerIndex = findIndex(listeners, (pair) => pair[0] === handler); + invariant(listenerIndex !== -1, 'Trying to remove AppState listener for unregistered handler'); + const callback = listeners[listenerIndex][1]; + document.removeEventListener(VISIBILITY_CHANGE_EVENT, callback, false); + listeners.splice(listenerIndex, 1); } } } -module.exports = AppState +module.exports = AppState; diff --git a/src/apis/AsyncStorage/__tests__/index-test.js b/src/apis/AsyncStorage/__tests__/index-test.js index 000366ce..826bd7e1 100644 --- a/src/apis/AsyncStorage/__tests__/index-test.js +++ b/src/apis/AsyncStorage/__tests__/index-test.js @@ -1,5 +1,5 @@ /* eslint-env mocha */ suite('apis/AsyncStorage', () => { - test.skip('NO TEST COVERAGE', () => {}) -}) + test.skip('NO TEST COVERAGE', () => {}); +}); diff --git a/src/apis/AsyncStorage/index.js b/src/apis/AsyncStorage/index.js index ae16f5a6..d5a15775 100644 --- a/src/apis/AsyncStorage/index.js +++ b/src/apis/AsyncStorage/index.js @@ -5,12 +5,12 @@ */ const mergeLocalStorageItem = (key, value) => { - const oldValue = window.localStorage.getItem(key) - const oldObject = JSON.parse(oldValue) - const newObject = JSON.parse(value) - const nextValue = JSON.stringify({ ...oldObject, ...newObject }) - window.localStorage.setItem(key, nextValue) -} + const oldValue = window.localStorage.getItem(key); + const oldObject = JSON.parse(oldValue); + const newObject = JSON.parse(value); + const nextValue = JSON.stringify({ ...oldObject, ...newObject }); + window.localStorage.setItem(key, nextValue); +}; class AsyncStorage { /** @@ -19,12 +19,12 @@ class AsyncStorage { static clear() { return new Promise((resolve, reject) => { try { - window.localStorage.clear() - resolve(null) + window.localStorage.clear(); + resolve(null); } catch (err) { - reject(err) + reject(err); } - }) + }); } /** @@ -33,17 +33,17 @@ class AsyncStorage { static getAllKeys() { return new Promise((resolve, reject) => { try { - const numberOfKeys = window.localStorage.length - const keys = [] + const numberOfKeys = window.localStorage.length; + const keys = []; for (let i = 0; i < numberOfKeys; i += 1) { - const key = window.localStorage.key(i) - keys.push(key) + const key = window.localStorage.key(i); + keys.push(key); } - resolve(keys) + resolve(keys); } catch (err) { - reject(err) + reject(err); } - }) + }); } /** @@ -52,12 +52,12 @@ class AsyncStorage { static getItem(key: string) { return new Promise((resolve, reject) => { try { - const value = window.localStorage.getItem(key) - resolve(value) + const value = window.localStorage.getItem(key); + resolve(value); } catch (err) { - reject(err) + reject(err); } - }) + }); } /** @@ -66,12 +66,12 @@ class AsyncStorage { static mergeItem(key: string, value: string) { return new Promise((resolve, reject) => { try { - mergeLocalStorageItem(key, value) - resolve(null) + mergeLocalStorageItem(key, value); + resolve(null); } catch (err) { - reject(err) + reject(err); } - }) + }); } /** @@ -81,12 +81,12 @@ class AsyncStorage { * multiGet(['k1', 'k2']) -> [['k1', 'val1'], ['k2', 'val2']] */ static multiGet(keys: Array) { - const promises = keys.map((key) => AsyncStorage.getItem(key)) + const promises = keys.map((key) => AsyncStorage.getItem(key)); return Promise.all(promises).then( (result) => Promise.resolve(result.map((value, i) => [ keys[i], value ])), (error) => Promise.reject(error) - ) + ); } /** @@ -96,24 +96,24 @@ class AsyncStorage { * multiMerge([['k1', 'val1'], ['k2', 'val2']]) */ static multiMerge(keyValuePairs: Array>) { - const promises = keyValuePairs.map((item) => AsyncStorage.mergeItem(item[0], item[1])) + const promises = keyValuePairs.map((item) => AsyncStorage.mergeItem(item[0], item[1])); return Promise.all(promises).then( () => Promise.resolve(null), (error) => Promise.reject(error) - ) + ); } /** * Delete all the keys in the `keys` array. */ static multiRemove(keys: Array) { - const promises = keys.map((key) => AsyncStorage.removeItem(key)) + const promises = keys.map((key) => AsyncStorage.removeItem(key)); return Promise.all(promises).then( () => Promise.resolve(null), (error) => Promise.reject(error) - ) + ); } /** @@ -121,12 +121,12 @@ class AsyncStorage { * multiSet([['k1', 'val1'], ['k2', 'val2']]) */ static multiSet(keyValuePairs: Array>) { - const promises = keyValuePairs.map((item) => AsyncStorage.setItem(item[0], item[1])) + const promises = keyValuePairs.map((item) => AsyncStorage.setItem(item[0], item[1])); return Promise.all(promises).then( () => Promise.resolve(null), (error) => Promise.reject(error) - ) + ); } /** @@ -135,12 +135,12 @@ class AsyncStorage { static removeItem(key: string) { return new Promise((resolve, reject) => { try { - window.localStorage.removeItem(key) - resolve(null) + window.localStorage.removeItem(key); + resolve(null); } catch (err) { - reject(err) + reject(err); } - }) + }); } /** @@ -149,13 +149,13 @@ class AsyncStorage { static setItem(key: string, value: string) { return new Promise((resolve, reject) => { try { - window.localStorage.setItem(key, value) - resolve(null) + window.localStorage.setItem(key, value); + resolve(null); } catch (err) { - reject(err) + reject(err); } - }) + }); } } -module.exports = AsyncStorage +module.exports = AsyncStorage; diff --git a/src/apis/Dimensions/__tests__/index-test.js b/src/apis/Dimensions/__tests__/index-test.js index 56228914..62b241eb 100644 --- a/src/apis/Dimensions/__tests__/index-test.js +++ b/src/apis/Dimensions/__tests__/index-test.js @@ -1,5 +1,5 @@ /* eslint-env mocha */ suite('apis/Dimensions', () => { - test.skip('NO TEST COVERAGE', () => {}) -}) + test.skip('NO TEST COVERAGE', () => {}); +}); diff --git a/src/apis/Dimensions/index.js b/src/apis/Dimensions/index.js index 430e3ad2..84f01b0c 100644 --- a/src/apis/Dimensions/index.js +++ b/src/apis/Dimensions/index.js @@ -6,18 +6,18 @@ * @flow */ -import debounce from 'lodash/debounce' -import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment' -import invariant from 'fbjs/lib/invariant' +import debounce from 'lodash/debounce'; +import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; +import invariant from 'fbjs/lib/invariant'; -const win = ExecutionEnvironment.canUseDOM ? window : { screen: {} } +const win = ExecutionEnvironment.canUseDOM ? window : { screen: {} }; -const dimensions = {} +const dimensions = {}; class Dimensions { static get(dimension: string): Object { - invariant(dimensions[dimension], 'No dimension set for key ' + dimension) - return dimensions[dimension] + invariant(dimensions[dimension], `No dimension set for key ${dimension}`); + return dimensions[dimension]; } static set(): void { @@ -26,18 +26,18 @@ class Dimensions { height: win.innerHeight, scale: win.devicePixelRatio || 1, width: win.innerWidth - } + }; dimensions.screen = { fontScale: 1, height: win.screen.height, scale: win.devicePixelRatio || 1, width: win.screen.width - } + }; } } -Dimensions.set() -ExecutionEnvironment.canUseDOM && window.addEventListener('resize', debounce(Dimensions.set, 50)) +Dimensions.set(); +ExecutionEnvironment.canUseDOM && window.addEventListener('resize', debounce(Dimensions.set, 50)); -module.exports = Dimensions +module.exports = Dimensions; diff --git a/src/apis/I18nManager/__tests__/index-test.js b/src/apis/I18nManager/__tests__/index-test.js index 0d6c3209..631a87b9 100644 --- a/src/apis/I18nManager/__tests__/index-test.js +++ b/src/apis/I18nManager/__tests__/index-test.js @@ -1,46 +1,46 @@ /* eslint-env mocha */ -import assert from 'assert' -import I18nManager from '..' +import assert from 'assert'; +import I18nManager from '..'; suite('apis/I18nManager', () => { suite('when RTL not enabled', () => { setup(() => { - I18nManager.setPreferredLanguageRTL(false) - }) + I18nManager.setPreferredLanguageRTL(false); + }); test('is "false" by default', () => { - assert.equal(I18nManager.isRTL, false) - assert.equal(document.documentElement.getAttribute('dir'), 'ltr') - }) + assert.equal(I18nManager.isRTL, false); + assert.equal(document.documentElement.getAttribute('dir'), 'ltr'); + }); test('is "true" when forced', () => { - I18nManager.forceRTL(true) - assert.equal(I18nManager.isRTL, true) - assert.equal(document.documentElement.getAttribute('dir'), 'rtl') - I18nManager.forceRTL(false) - }) - }) + I18nManager.forceRTL(true); + assert.equal(I18nManager.isRTL, true); + assert.equal(document.documentElement.getAttribute('dir'), 'rtl'); + I18nManager.forceRTL(false); + }); + }); suite('when RTL is enabled', () => { setup(() => { - I18nManager.setPreferredLanguageRTL(true) - }) + I18nManager.setPreferredLanguageRTL(true); + }); teardown(() => { - I18nManager.setPreferredLanguageRTL(false) - }) + I18nManager.setPreferredLanguageRTL(false); + }); test('is "true" by default', () => { - assert.equal(I18nManager.isRTL, true) - assert.equal(document.documentElement.getAttribute('dir'), 'rtl') - }) + assert.equal(I18nManager.isRTL, true); + assert.equal(document.documentElement.getAttribute('dir'), 'rtl'); + }); test('is "false" when not allowed', () => { - I18nManager.allowRTL(false) - assert.equal(I18nManager.isRTL, false) - assert.equal(document.documentElement.getAttribute('dir'), 'ltr') - I18nManager.allowRTL(true) - }) - }) -}) + I18nManager.allowRTL(false); + assert.equal(I18nManager.isRTL, false); + assert.equal(document.documentElement.getAttribute('dir'), 'ltr'); + I18nManager.allowRTL(true); + }); + }); +}); diff --git a/src/apis/I18nManager/index.js b/src/apis/I18nManager/index.js index a9bbab80..0a860edf 100644 --- a/src/apis/I18nManager/index.js +++ b/src/apis/I18nManager/index.js @@ -1,4 +1,4 @@ -import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment' +import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; type I18nManagerStatus = { allowRTL: (allowRTL: boolean) => {}, @@ -7,39 +7,39 @@ type I18nManagerStatus = { isRTL: boolean } -let isPreferredLanguageRTL = false -let isRTLAllowed = true -let isRTLForced = false +let isPreferredLanguageRTL = false; +let isRTLAllowed = true; +let isRTLForced = false; const isRTL = () => { if (isRTLForced) { - return true + return true; } - return isRTLAllowed && isPreferredLanguageRTL -} + return isRTLAllowed && isPreferredLanguageRTL; +}; const onChange = () => { if (ExecutionEnvironment.canUseDOM) { - document.documentElement.setAttribute('dir', isRTL() ? 'rtl' : 'ltr') + document.documentElement.setAttribute('dir', isRTL() ? 'rtl' : 'ltr'); } -} +}; const I18nManager: I18nManagerStatus = { allowRTL(bool) { - isRTLAllowed = bool - onChange() + isRTLAllowed = bool; + onChange(); }, forceRTL(bool) { - isRTLForced = bool - onChange() + isRTLForced = bool; + onChange(); }, setPreferredLanguageRTL(bool) { - isPreferredLanguageRTL = bool - onChange() + isPreferredLanguageRTL = bool; + onChange(); }, get isRTL() { - return isRTL() + return isRTL(); } -} +}; -module.exports = I18nManager +module.exports = I18nManager; diff --git a/src/apis/InteractionManager/index.js b/src/apis/InteractionManager/index.js index 15fe9aee..2f3a9cb3 100644 --- a/src/apis/InteractionManager/index.js +++ b/src/apis/InteractionManager/index.js @@ -5,8 +5,8 @@ * @flow */ -import keyMirror from 'fbjs/lib/keyMirror' -import invariant from 'fbjs/lib/invariant' +import invariant from 'fbjs/lib/invariant'; +import keyMirror from 'fbjs/lib/keyMirror'; const InteractionManager = { Events: keyMirror({ @@ -21,15 +21,15 @@ const InteractionManager = { invariant( typeof callback === 'function', 'Must specify a function to schedule.' - ) - callback() + ); + callback(); }, /** * Notify manager that an interaction has started. */ createInteractionHandle() { - return 1 + return 1; }, /** @@ -39,10 +39,10 @@ const InteractionManager = { invariant( !!handle, 'Must provide a handle to clear.' - ) + ); }, addListener: () => {} -} +}; -module.exports = InteractionManager +module.exports = InteractionManager; diff --git a/src/apis/NetInfo/__tests__/index-test.js b/src/apis/NetInfo/__tests__/index-test.js index 958b2724..46ff365e 100644 --- a/src/apis/NetInfo/__tests__/index-test.js +++ b/src/apis/NetInfo/__tests__/index-test.js @@ -1,5 +1,5 @@ /* eslint-env mocha */ suite('apis/NetInfo', () => { - test.skip('NO TEST COVERAGE', () => {}) -}) + test.skip('NO TEST COVERAGE', () => {}); +}); diff --git a/src/apis/NetInfo/index.js b/src/apis/NetInfo/index.js index d0fcf20c..bcae6907 100644 --- a/src/apis/NetInfo/index.js +++ b/src/apis/NetInfo/index.js @@ -6,16 +6,16 @@ * @flow */ -import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment' -import invariant from 'fbjs/lib/invariant' +import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; +import invariant from 'fbjs/lib/invariant'; const connection = ExecutionEnvironment.canUseDOM && ( window.navigator.connection || window.navigator.mozConnection || window.navigator.webkitConnection -) +); -const eventTypes = [ 'change' ] +const eventTypes = [ 'change' ]; /** * Navigator online: https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine @@ -23,63 +23,63 @@ const eventTypes = [ 'change' ] */ const NetInfo = { addEventListener(type: string, handler: Function): { remove: () => void } { - invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type) + invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type); if (!connection) { - console.error('Network Connection API is not supported. Not listening for connection type changes.') + console.error('Network Connection API is not supported. Not listening for connection type changes.'); return { remove: () => {} - } + }; } - connection.addEventListener(type, handler) + connection.addEventListener(type, handler); return { remove: () => NetInfo.removeEventListener(type, handler) - } + }; }, removeEventListener(type: string, handler: Function): void { - invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type) - if (!connection) { return } - connection.removeEventListener(type, handler) + invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type); + if (!connection) { return; } + connection.removeEventListener(type, handler); }, fetch(): Promise { return new Promise((resolve, reject) => { try { - resolve(connection.type) + resolve(connection.type); } catch (err) { - resolve('unknown') + resolve('unknown'); } - }) + }); }, isConnected: { addEventListener(type: string, handler: Function): { remove: () => void } { - invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type) - window.addEventListener('online', handler.bind(null, true), false) - window.addEventListener('offline', handler.bind(null, false), false) + invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type); + window.addEventListener('online', handler.bind(null, true), false); + window.addEventListener('offline', handler.bind(null, false), false); return { remove: () => NetInfo.isConnected.removeEventListener(type, handler) - } + }; }, removeEventListener(type: string, handler: Function): void { - invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type) - window.removeEventListener('online', handler.bind(null, true), false) - window.removeEventListener('offline', handler.bind(null, false), false) + invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type); + window.removeEventListener('online', handler.bind(null, true), false); + window.removeEventListener('offline', handler.bind(null, false), false); }, fetch(): Promise { return new Promise((resolve, reject) => { try { - resolve(window.navigator.onLine) + resolve(window.navigator.onLine); } catch (err) { - resolve(true) + resolve(true); } - }) + }); } } -} +}; -module.exports = NetInfo +module.exports = NetInfo; diff --git a/src/apis/PixelRatio/__tests__/index-test.js b/src/apis/PixelRatio/__tests__/index-test.js index 1b52c460..5ee4655a 100644 --- a/src/apis/PixelRatio/__tests__/index-test.js +++ b/src/apis/PixelRatio/__tests__/index-test.js @@ -1,5 +1,5 @@ /* eslint-env mocha */ suite('apis/PixelRatio', () => { - test.skip('NO TEST COVERAGE', () => {}) -}) + test.skip('NO TEST COVERAGE', () => {}); +}); diff --git a/src/apis/PixelRatio/index.js b/src/apis/PixelRatio/index.js index 3ff1627e..aa24d893 100644 --- a/src/apis/PixelRatio/index.js +++ b/src/apis/PixelRatio/index.js @@ -6,7 +6,7 @@ * @flow */ -import Dimensions from '../Dimensions' +import Dimensions from '../Dimensions'; /** * PixelRatio gives access to the device pixel density. @@ -16,14 +16,14 @@ class PixelRatio { * Returns the device pixel density. */ static get(): number { - return Dimensions.get('window').scale + return Dimensions.get('window').scale; } /** * No equivalent for Web */ static getFontScale(): number { - return Dimensions.get('window').fontScale || PixelRatio.get() + return Dimensions.get('window').fontScale || PixelRatio.get(); } /** @@ -31,7 +31,7 @@ class PixelRatio { * Guaranteed to return an integer number. */ static getPixelSizeForLayoutSize(layoutSize: number): number { - return Math.round(layoutSize * PixelRatio.get()) + return Math.round(layoutSize * PixelRatio.get()); } /** @@ -41,9 +41,9 @@ class PixelRatio { * exactly (8.33 * 3) = 25 pixels. */ static roundToNearestPixel(layoutSize: number): number { - const ratio = PixelRatio.get() - return Math.round(layoutSize * ratio) / ratio + const ratio = PixelRatio.get(); + return Math.round(layoutSize * ratio) / ratio; } } -module.exports = PixelRatio +module.exports = PixelRatio; diff --git a/src/apis/Platform/index.js b/src/apis/Platform/index.js index bdb5b2e6..950ce698 100644 --- a/src/apis/Platform/index.js +++ b/src/apis/Platform/index.js @@ -1,6 +1,6 @@ const Platform = { OS: 'web', select: (obj: Object) => obj.web -} +}; -module.exports = Platform +module.exports = Platform; diff --git a/src/apis/StyleSheet/__tests__/createReactStyleObject-test.js b/src/apis/StyleSheet/__tests__/createReactStyleObject-test.js index f876432b..10b66ce4 100644 --- a/src/apis/StyleSheet/__tests__/createReactStyleObject-test.js +++ b/src/apis/StyleSheet/__tests__/createReactStyleObject-test.js @@ -1,13 +1,13 @@ /* eslint-env mocha */ -import assert from 'assert' -import createReactStyleObject from '../createReactStyleObject' +import assert from 'assert'; +import createReactStyleObject from '../createReactStyleObject'; suite('apis/StyleSheet/createReactStyleObject', () => { test('converts ReactNative style to ReactDOM style', () => { - const reactNativeStyle = { display: 'flex', marginVertical: 0, opacity: 0 } - const expectedStyle = { display: 'flex', marginTop: '0px', marginBottom: '0px', opacity: 0 } + const reactNativeStyle = { display: 'flex', marginVertical: 0, opacity: 0 }; + const expectedStyle = { display: 'flex', marginTop: '0px', marginBottom: '0px', opacity: 0 }; - assert.deepEqual(createReactStyleObject(reactNativeStyle), expectedStyle) - }) -}) + assert.deepEqual(createReactStyleObject(reactNativeStyle), expectedStyle); + }); +}); diff --git a/src/apis/StyleSheet/__tests__/expandStyle-test.js b/src/apis/StyleSheet/__tests__/expandStyle-test.js index b0b7f61c..77628b67 100644 --- a/src/apis/StyleSheet/__tests__/expandStyle-test.js +++ b/src/apis/StyleSheet/__tests__/expandStyle-test.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ -import assert from 'assert' -import expandStyle from '../expandStyle' +import assert from 'assert'; +import expandStyle from '../expandStyle'; suite('apis/StyleSheet/expandStyle', () => { test('shortform -> longform', () => { @@ -14,7 +14,7 @@ suite('apis/StyleSheet/expandStyle', () => { marginTop: 50, marginVertical: 25, margin: 10 - } + }; const expected = { borderBottomStyle: 'solid', @@ -31,36 +31,36 @@ suite('apis/StyleSheet/expandStyle', () => { marginBottom: '25px', marginLeft: '10px', marginRight: '10px' - } + }; - assert.deepEqual(expandStyle(initial), expected) - }) + assert.deepEqual(expandStyle(initial), expected); + }); test('textAlignVertical', () => { const initial = { textAlignVertical: 'center' - } + }; const expected = { verticalAlign: 'middle' - } + }; - assert.deepEqual(expandStyle(initial), expected) - }) + assert.deepEqual(expandStyle(initial), expected); + }); test('flex', () => { - const value = 10 + const value = 10; const initial = { flex: value - } + }; const expected = { flexGrow: value, flexShrink: 1, flexBasis: 'auto' - } + }; - assert.deepEqual(expandStyle(initial), expected) - }) -}) + assert.deepEqual(expandStyle(initial), expected); + }); +}); diff --git a/src/apis/StyleSheet/__tests__/i18nStyle-test.js b/src/apis/StyleSheet/__tests__/i18nStyle-test.js index 058dab68..7ee84c15 100644 --- a/src/apis/StyleSheet/__tests__/i18nStyle-test.js +++ b/src/apis/StyleSheet/__tests__/i18nStyle-test.js @@ -1,8 +1,8 @@ /* eslint-env mocha */ -import assert from 'assert' -import I18nManager from '../../I18nManager' -import i18nStyle from '../i18nStyle' +import assert from 'assert'; +import I18nManager from '../../I18nManager'; +import i18nStyle from '../i18nStyle'; const initial = { borderLeftColor: 'red', @@ -24,13 +24,13 @@ const initial = { textAlign: 'left', textShadowOffset: { width: '1rem', height: 10 }, writingDirection: 'ltr' -} +}; const initialNoI18n = Object.keys(initial).reduce((acc, prop) => { - const newProp = `${prop}$noI18n` - acc[newProp] = initial[prop] - return acc -}, {}) + const newProp = `${prop}$noI18n`; + acc[newProp] = initial[prop]; + return acc; +}, {}); const expected = { borderLeftColor: 'blue', @@ -52,40 +52,40 @@ const expected = { textAlign: 'right', textShadowOffset: { width: '-1rem', height: 10 }, writingDirection: 'rtl' -} +}; suite('apis/StyleSheet/i18nStyle', () => { suite('LTR mode', () => { setup(() => { - I18nManager.allowRTL(false) - }) + I18nManager.allowRTL(false); + }); teardown(() => { - I18nManager.allowRTL(true) - }) + I18nManager.allowRTL(true); + }); test('does not auto-flip', () => { - assert.deepEqual(i18nStyle(initial), initial) - }) + assert.deepEqual(i18nStyle(initial), initial); + }); test('normalizes properties', () => { - assert.deepEqual(i18nStyle(initialNoI18n), initial) - }) - }) + assert.deepEqual(i18nStyle(initialNoI18n), initial); + }); + }); suite('RTL mode', () => { setup(() => { - I18nManager.forceRTL(true) - }) + I18nManager.forceRTL(true); + }); teardown(() => { - I18nManager.forceRTL(false) - }) + I18nManager.forceRTL(false); + }); test('does auto-flip', () => { - assert.deepEqual(i18nStyle(initial), expected) - }) + assert.deepEqual(i18nStyle(initial), expected); + }); test('normalizes properties', () => { - assert.deepEqual(i18nStyle(initialNoI18n), initial) - }) - }) -}) + assert.deepEqual(i18nStyle(initialNoI18n), initial); + }); + }); +}); diff --git a/src/apis/StyleSheet/__tests__/index-test.js b/src/apis/StyleSheet/__tests__/index-test.js index b72e6419..7f89d641 100644 --- a/src/apis/StyleSheet/__tests__/index-test.js +++ b/src/apis/StyleSheet/__tests__/index-test.js @@ -1,52 +1,52 @@ /* eslint-env mocha */ -import assert from 'assert' -import { getDefaultStyleSheet } from '../css' -import isPlainObject from 'lodash/isPlainObject' -import StyleSheet from '..' +import assert from 'assert'; +import { getDefaultStyleSheet } from '../css'; +import isPlainObject from 'lodash/isPlainObject'; +import StyleSheet from '..'; suite('apis/StyleSheet', () => { setup(() => { - StyleSheet._reset() - }) + StyleSheet._reset(); + }); test('absoluteFill', () => { - assert(Number.isInteger(StyleSheet.absoluteFill) === true) - }) + assert(Number.isInteger(StyleSheet.absoluteFill) === true); + }); test('absoluteFillObject', () => { - assert.ok(isPlainObject(StyleSheet.absoluteFillObject) === true) - }) + assert.ok(isPlainObject(StyleSheet.absoluteFillObject) === true); + }); suite('create', () => { test('replaces styles with numbers', () => { - const style = StyleSheet.create({ root: { opacity: 1 } }) - assert(Number.isInteger(style.root) === true) - }) + const style = StyleSheet.create({ root: { opacity: 1 } }); + assert(Number.isInteger(style.root) === true); + }); test('renders a style sheet in the browser', () => { - StyleSheet.create({ root: { color: 'red' } }) + StyleSheet.create({ root: { color: 'red' } }); assert.equal( document.getElementById('__react-native-style').textContent, getDefaultStyleSheet() - ) - }) - }) + ); + }); + }); test('flatten', () => { - assert(typeof StyleSheet.flatten === 'function') - }) + assert(typeof StyleSheet.flatten === 'function'); + }); test('hairlineWidth', () => { - assert(Number.isInteger(StyleSheet.hairlineWidth) === true) - }) + assert(Number.isInteger(StyleSheet.hairlineWidth) === true); + }); test('render', () => { assert.equal( StyleSheet.render().props.dangerouslySetInnerHTML.__html, getDefaultStyleSheet() - ) - }) + ); + }); test('resolve', () => { assert.deepEqual( @@ -66,6 +66,6 @@ suite('apis/StyleSheet', () => { pointerEvents: null } } - ) - }) -}) + ); + }); +}); diff --git a/src/apis/StyleSheet/__tests__/normalizeValue-test.js b/src/apis/StyleSheet/__tests__/normalizeValue-test.js index 42d91cf2..c42168e0 100644 --- a/src/apis/StyleSheet/__tests__/normalizeValue-test.js +++ b/src/apis/StyleSheet/__tests__/normalizeValue-test.js @@ -1,14 +1,14 @@ /* eslint-env mocha */ -import assert from 'assert' -import normalizeValue from '../normalizeValue' +import assert from 'assert'; +import normalizeValue from '../normalizeValue'; suite('apis/StyleSheet/normalizeValue', () => { test('normalizes property values requiring units', () => { - assert.deepEqual(normalizeValue('margin', 0), '0px') - }) + assert.deepEqual(normalizeValue('margin', 0), '0px'); + }); test('ignores unitless property values', () => { - assert.deepEqual(normalizeValue('flexGrow', 1), 1) - assert.deepEqual(normalizeValue('scale', 2), 2) - }) -}) + assert.deepEqual(normalizeValue('flexGrow', 1), 1); + assert.deepEqual(normalizeValue('scale', 2), 2); + }); +}); diff --git a/src/apis/StyleSheet/__tests__/processTextShadow-test.js b/src/apis/StyleSheet/__tests__/processTextShadow-test.js index 3ffcb6c2..3d016f75 100644 --- a/src/apis/StyleSheet/__tests__/processTextShadow-test.js +++ b/src/apis/StyleSheet/__tests__/processTextShadow-test.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ -import assert from 'assert' -import processTextShadow from '../processTextShadow' +import assert from 'assert'; +import processTextShadow from '../processTextShadow'; suite('apis/StyleSheet/processTextShadow', () => { test('textShadowOffset', () => { @@ -9,7 +9,7 @@ suite('apis/StyleSheet/processTextShadow', () => { textShadowColor: 'red', textShadowOffset: { width: 2, height: 2 }, textShadowRadius: 5 - } + }; assert.deepEqual( processTextShadow(style), @@ -19,6 +19,6 @@ suite('apis/StyleSheet/processTextShadow', () => { textShadowOffset: null, textShadowRadius: null } - ) - }) -}) + ); + }); +}); diff --git a/src/apis/StyleSheet/__tests__/processTransform-test.js b/src/apis/StyleSheet/__tests__/processTransform-test.js index 46e1ff49..fe7fa161 100644 --- a/src/apis/StyleSheet/__tests__/processTransform-test.js +++ b/src/apis/StyleSheet/__tests__/processTransform-test.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ -import assert from 'assert' -import processTransform from '../processTransform' +import assert from 'assert'; +import processTransform from '../processTransform'; suite('apis/StyleSheet/processTransform', () => { test('transform', () => { @@ -11,18 +11,18 @@ suite('apis/StyleSheet/processTransform', () => { { translateX: 20 }, { rotate: '20deg' } ] - } + }; assert.deepEqual( processTransform(style), { transform: 'scaleX(20) translateX(20px) rotate(20deg)' } - ) - }) + ); + }); test('transformMatrix', () => { const style = { transformMatrix: [ 1, 2, 3, 4, 5, 6 ] - } + }; assert.deepEqual( processTransform(style), @@ -30,6 +30,6 @@ suite('apis/StyleSheet/processTransform', () => { transform: 'matrix3d(1,2,3,4,5,6)', transformMatrix: null } - ) - }) -}) + ); + }); +}); diff --git a/src/apis/StyleSheet/__tests__/processVendorPrefixes-test.js b/src/apis/StyleSheet/__tests__/processVendorPrefixes-test.js index c6c2ac9b..1a04c666 100644 --- a/src/apis/StyleSheet/__tests__/processVendorPrefixes-test.js +++ b/src/apis/StyleSheet/__tests__/processVendorPrefixes-test.js @@ -1,17 +1,17 @@ /* eslint-env mocha */ -import assert from 'assert' -import processVendorPrefixes from '../processVendorPrefixes' +import assert from 'assert'; +import processVendorPrefixes from '../processVendorPrefixes'; suite('apis/StyleSheet/processVendorPrefixes', () => { test('handles array values', () => { const style = { display: [ '-webkit-flex', 'flex' ] - } + }; assert.deepEqual( processVendorPrefixes(style), { display: 'flex' } - ) - }) -}) + ); + }); +}); diff --git a/src/apis/StyleSheet/createReactStyleObject.js b/src/apis/StyleSheet/createReactStyleObject.js index 1657a6f6..f0ce3159 100644 --- a/src/apis/StyleSheet/createReactStyleObject.js +++ b/src/apis/StyleSheet/createReactStyleObject.js @@ -1,20 +1,20 @@ -import expandStyle from './expandStyle' -import flattenStyle from '../../modules/flattenStyle' -import i18nStyle from './i18nStyle' -import processTextShadow from './processTextShadow' -import processTransform from './processTransform' -import processVendorPrefixes from './processVendorPrefixes' +import expandStyle from './expandStyle'; +import flattenStyle from '../../modules/flattenStyle'; +import i18nStyle from './i18nStyle'; +import processTextShadow from './processTextShadow'; +import processTransform from './processTransform'; +import processVendorPrefixes from './processVendorPrefixes'; -const plugins = [ +const processors = [ processTextShadow, processTransform, processVendorPrefixes -] +]; -const applyPlugins = (style) => { - return plugins.reduce((style, plugin) => plugin(style), style) -} +const applyProcessors = (style) => processors.reduce((style, processor) => processor(style), style); -const createReactDOMStyleObject = (reactNativeStyle) => applyPlugins(expandStyle(i18nStyle(flattenStyle(reactNativeStyle)))) +const createReactDOMStyleObject = (reactNativeStyle) => applyProcessors( + expandStyle(i18nStyle(flattenStyle(reactNativeStyle))) +); -module.exports = createReactDOMStyleObject +module.exports = createReactDOMStyleObject; diff --git a/src/apis/StyleSheet/css.js b/src/apis/StyleSheet/css.js index 635d2a1e..455cc243 100644 --- a/src/apis/StyleSheet/css.js +++ b/src/apis/StyleSheet/css.js @@ -1,23 +1,25 @@ -const DISPLAY_FLEX_CLASSNAME = '__style_df' -const POINTER_EVENTS_AUTO_CLASSNAME = '__style_pea' -const POINTER_EVENTS_BOX_NONE_CLASSNAME = '__style_pebn' -const POINTER_EVENTS_BOX_ONLY_CLASSNAME = '__style_pebo' -const POINTER_EVENTS_NONE_CLASSNAME = '__style_pen' +const DISPLAY_FLEX_CLASSNAME = '__style_df'; +const POINTER_EVENTS_AUTO_CLASSNAME = '__style_pea'; +const POINTER_EVENTS_BOX_NONE_CLASSNAME = '__style_pebn'; +const POINTER_EVENTS_BOX_ONLY_CLASSNAME = '__style_pebo'; +const POINTER_EVENTS_NONE_CLASSNAME = '__style_pen'; +/* eslint-disable max-len */ const CSS_RESET = // reset unwanted styles '/* React Native */\n' + 'html {font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}\n' + 'body {margin:0}\n' + 'button::-moz-focus-inner, input::-moz-focus-inner {border:0;padding:0}\n' + -'input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {display:none}' +'input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {display:none}'; const CSS_HELPERS = // vendor prefix 'display:flex' until React supports fallback values for inline styles `.${DISPLAY_FLEX_CLASSNAME} {display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}\n` + // implement React Native's pointer event values `.${POINTER_EVENTS_AUTO_CLASSNAME}, .${POINTER_EVENTS_BOX_ONLY_CLASSNAME}, .${POINTER_EVENTS_BOX_NONE_CLASSNAME} * {pointer-events:auto}\n` + -`.${POINTER_EVENTS_NONE_CLASSNAME}, .${POINTER_EVENTS_BOX_ONLY_CLASSNAME} *, .${POINTER_EVENTS_NONE_CLASSNAME} {pointer-events:none}` +`.${POINTER_EVENTS_NONE_CLASSNAME}, .${POINTER_EVENTS_BOX_ONLY_CLASSNAME} *, .${POINTER_EVENTS_NONE_CLASSNAME} {pointer-events:none}`; +/* eslint-enable max-len */ const styleAsClassName = { display: { @@ -29,10 +31,10 @@ const styleAsClassName = { 'box-only': POINTER_EVENTS_BOX_ONLY_CLASSNAME, 'none': POINTER_EVENTS_NONE_CLASSNAME } -} +}; -export const getDefaultStyleSheet = () => `${CSS_RESET}\n${CSS_HELPERS}` +export const getDefaultStyleSheet = () => `${CSS_RESET}\n${CSS_HELPERS}`; export const getStyleAsHelperClassName = (prop, value) => { - return styleAsClassName[prop] && styleAsClassName[prop][value] -} + return styleAsClassName[prop] && styleAsClassName[prop][value]; +}; diff --git a/src/apis/StyleSheet/expandStyle.js b/src/apis/StyleSheet/expandStyle.js index f382d252..410d702a 100644 --- a/src/apis/StyleSheet/expandStyle.js +++ b/src/apis/StyleSheet/expandStyle.js @@ -9,9 +9,9 @@ * longfrom equivalents. */ -import normalizeValue from './normalizeValue' +import normalizeValue from './normalizeValue'; -const emptyObject = {} +const emptyObject = {}; const styleShortFormProperties = { borderColor: [ 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor' ], borderRadius: [ 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius' ], @@ -26,48 +26,48 @@ const styleShortFormProperties = { paddingVertical: [ 'paddingTop', 'paddingBottom' ], textDecorationLine: [ 'textDecoration' ], writingDirection: [ 'direction' ] -} +}; const alphaSort = (arr) => arr.sort((a, b) => { - if (a < b) { return -1 } - if (a > b) { return 1 } - return 0 -}) + if (a < b) { return -1; } + if (a > b) { return 1; } + return 0; +}); const createStyleReducer = (originalStyle) => { - const originalStyleProps = Object.keys(originalStyle) + const originalStyleProps = Object.keys(originalStyle); return (style, prop) => { - const value = normalizeValue(prop, originalStyle[prop]) - const longFormProperties = styleShortFormProperties[prop] + const value = normalizeValue(prop, originalStyle[prop]); + const longFormProperties = styleShortFormProperties[prop]; // React Native treats `flex:1` like `flex:1 1 auto` if (prop === 'flex') { - style.flexGrow = value - style.flexShrink = 1 - style.flexBasis = 'auto' + style.flexGrow = value; + style.flexShrink = 1; + style.flexBasis = 'auto'; // React Native accepts 'center' as a value } else if (prop === 'textAlignVertical') { - style.verticalAlign = (value === 'center' ? 'middle' : value) + style.verticalAlign = (value === 'center' ? 'middle' : value); } else if (longFormProperties) { longFormProperties.forEach((longForm, i) => { // the value of any longform property in the original styles takes // precedence over the shortform's value if (originalStyleProps.indexOf(longForm) === -1) { - style[longForm] = value + style[longForm] = value; } - }) + }); } else { - style[prop] = value + style[prop] = value; } - return style - } -} + return style; + }; +}; const expandStyle = (style = emptyObject) => { - const sortedStyleProps = alphaSort(Object.keys(style)) - const styleReducer = createStyleReducer(style) - return sortedStyleProps.reduce(styleReducer, {}) -} + const sortedStyleProps = alphaSort(Object.keys(style)); + const styleReducer = createStyleReducer(style); + return sortedStyleProps.reduce(styleReducer, {}); +}; -module.exports = expandStyle +module.exports = expandStyle; diff --git a/src/apis/StyleSheet/i18nStyle.js b/src/apis/StyleSheet/i18nStyle.js index e43706fc..e28d783d 100644 --- a/src/apis/StyleSheet/i18nStyle.js +++ b/src/apis/StyleSheet/i18nStyle.js @@ -1,5 +1,5 @@ -import I18nManager from '../I18nManager' -import multiplyStyleLengthValue from '../../modules/multiplyStyleLengthValue' +import I18nManager from '../I18nManager'; +import multiplyStyleLengthValue from '../../modules/multiplyStyleLengthValue'; /** * Map of property names to their BiDi equivalent. @@ -21,86 +21,86 @@ const PROPERTIES_TO_SWAP = { 'paddingLeft': 'paddingRight', 'paddingRight': 'paddingLeft', 'right': 'left' -} +}; const PROPERTIES_SWAP_LEFT_RIGHT = { 'clear': true, 'float': true, 'textAlign': true -} +}; const PROPERTIES_SWAP_LTR_RTL = { 'writingDirection': true -} +}; /** * Invert the sign of a numeric-like value */ -const additiveInverse = (value: String | Number) => multiplyStyleLengthValue(value, -1) +const additiveInverse = (value: String | Number) => multiplyStyleLengthValue(value, -1); /** * BiDi flip the given property. */ const flipProperty = (prop:String): String => { - return PROPERTIES_TO_SWAP.hasOwnProperty(prop) ? PROPERTIES_TO_SWAP[prop] : prop -} + return PROPERTIES_TO_SWAP.hasOwnProperty(prop) ? PROPERTIES_TO_SWAP[prop] : prop; +}; /** * BiDi flip translateX */ const flipTransform = (transform: Object): Object => { - const translateX = transform.translateX + const translateX = transform.translateX; if (translateX != null) { - transform.translateX = additiveInverse(translateX) + transform.translateX = additiveInverse(translateX); } - return transform -} + return transform; +}; const swapLeftRight = (value:String): String => { - return value === 'left' ? 'right' : value === 'right' ? 'left' : value -} + return value === 'left' ? 'right' : value === 'right' ? 'left' : value; +}; const swapLtrRtl = (value:String): String => { - return value === 'ltr' ? 'rtl' : value === 'rtl' ? 'ltr' : value -} + return value === 'ltr' ? 'rtl' : value === 'rtl' ? 'ltr' : value; +}; const i18nStyle = (style = {}) => { - const newStyle = {} + const newStyle = {}; for (const prop in style) { if (style.hasOwnProperty(prop)) { - const indexOfNoFlip = prop.indexOf('$noI18n') + const indexOfNoFlip = prop.indexOf('$noI18n'); if (I18nManager.isRTL) { if (PROPERTIES_TO_SWAP[prop]) { - const newProp = flipProperty(prop) - newStyle[newProp] = style[prop] + const newProp = flipProperty(prop); + newStyle[newProp] = style[prop]; } else if (PROPERTIES_SWAP_LEFT_RIGHT[prop]) { - newStyle[prop] = swapLeftRight(style[prop]) + newStyle[prop] = swapLeftRight(style[prop]); } else if (PROPERTIES_SWAP_LTR_RTL[prop]) { - newStyle[prop] = swapLtrRtl(style[prop]) + newStyle[prop] = swapLtrRtl(style[prop]); } else if (prop === 'textShadowOffset') { - newStyle[prop] = style[prop] - newStyle[prop].width = additiveInverse(style[prop].width) + newStyle[prop] = style[prop]; + newStyle[prop].width = additiveInverse(style[prop].width); } else if (prop === 'transform') { - newStyle[prop] = style[prop].map(flipTransform) + newStyle[prop] = style[prop].map(flipTransform); } else if (indexOfNoFlip > -1) { - const newProp = prop.substring(0, indexOfNoFlip) - newStyle[newProp] = style[prop] + const newProp = prop.substring(0, indexOfNoFlip); + newStyle[newProp] = style[prop]; } else { - newStyle[prop] = style[prop] + newStyle[prop] = style[prop]; } } else { if (indexOfNoFlip > -1) { - const newProp = prop.substring(0, indexOfNoFlip) - newStyle[newProp] = style[prop] + const newProp = prop.substring(0, indexOfNoFlip); + newStyle[newProp] = style[prop]; } else { - newStyle[prop] = style[prop] + newStyle[prop] = style[prop]; } } } } - return newStyle -} + return newStyle; +}; -module.exports = i18nStyle +module.exports = i18nStyle; diff --git a/src/apis/StyleSheet/index.js b/src/apis/StyleSheet/index.js index 1cfffc43..50555a73 100644 --- a/src/apis/StyleSheet/index.js +++ b/src/apis/StyleSheet/index.js @@ -1,32 +1,32 @@ -import * as css from './css' -import createReactStyleObject from './createReactStyleObject' -import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment' -import flattenStyle from '../../modules/flattenStyle' -import React from 'react' -import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry' -import StyleSheetValidation from './StyleSheetValidation' +import * as css from './css'; +import createReactStyleObject from './createReactStyleObject'; +import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; +import flattenStyle from '../../modules/flattenStyle'; +import React from 'react'; +import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry'; +import StyleSheetValidation from './StyleSheetValidation'; -let styleElement -let shouldInsertStyleSheet = ExecutionEnvironment.canUseDOM +let styleElement; +let shouldInsertStyleSheet = ExecutionEnvironment.canUseDOM; -const STYLE_SHEET_ID = '__react-native-style' +const STYLE_SHEET_ID = '__react-native-style'; -const absoluteFillObject = { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 } +const absoluteFillObject = { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }; -const defaultStyleSheet = css.getDefaultStyleSheet() +const defaultStyleSheet = css.getDefaultStyleSheet(); const insertStyleSheet = () => { // check if the server rendered the style sheet - styleElement = document.getElementById(STYLE_SHEET_ID) + styleElement = document.getElementById(STYLE_SHEET_ID); // if not, inject the style sheet if (!styleElement) { document.head.insertAdjacentHTML( 'afterbegin', `` - ) - shouldInsertStyleSheet = false + ); + shouldInsertStyleSheet = false; } -} +}; module.exports = { /** @@ -35,9 +35,9 @@ module.exports = { */ _reset() { if (styleElement) { - document.head.removeChild(styleElement) - styleElement = null - shouldInsertStyleSheet = true + document.head.removeChild(styleElement); + styleElement = null; + shouldInsertStyleSheet = true; } }, @@ -47,15 +47,15 @@ module.exports = { create(styles) { if (shouldInsertStyleSheet) { - insertStyleSheet() + insertStyleSheet(); } - const result = {} + const result = {}; for (const key in styles) { - StyleSheetValidation.validateStyle(key, styles) - result[key] = ReactNativePropRegistry.register(styles[key]) + StyleSheetValidation.validateStyle(key, styles); + result[key] = ReactNativePropRegistry.register(styles[key]); } - return result + return result; }, hairlineWidth: 1, @@ -64,7 +64,7 @@ module.exports = { /* @platform web */ render() { - return