[change] babel-plugin option for style runtime

This commit is contained in:
Nicolas Gallagher
2023-04-11 16:15:47 -07:00
parent 7cb5800e25
commit cca0fb1645
5 changed files with 393 additions and 136 deletions

View File

@@ -1,74 +1,57 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Rewrite react-native to react-native-web export from "react-native": export from "react-native" 1`] = `
exports[`[commonjs] Rewrite react-native to react-native-web export from "react-native": export from "react-native" 1`] = `
export { View } from 'react-native';
export { StyleSheet, Text, unstable_createElement } from 'react-native';
↓ ↓ ↓ ↓ ↓ ↓
export { default as View } from 'react-native-web/dist/exports/View';
export { default as StyleSheet } from 'react-native-web/dist/exports/StyleSheet';
export { default as Text } from 'react-native-web/dist/exports/Text';
export { default as unstable_createElement } from 'react-native-web/dist/exports/createElement';
export { default as View } from 'react-native-web/dist/cjs/exports/View';
export { default as StyleSheet } from 'react-native-web/dist/cjs/exports/StyleSheet';
export { default as Text } from 'react-native-web/dist/cjs/exports/Text';
export { default as unstable_createElement } from 'react-native-web/dist/cjs/exports/createElement';
`;
exports[`Rewrite react-native to react-native-web export from "react-native-web": export from "react-native-web" 1`] = `
exports[`[commonjs] Rewrite react-native to react-native-web export from "react-native-web": export from "react-native-web" 1`] = `
export { View } from 'react-native-web';
export { StyleSheet, Text, unstable_createElement } from 'react-native-web';
↓ ↓ ↓ ↓ ↓ ↓
export { default as View } from 'react-native-web/dist/exports/View';
export { default as StyleSheet } from 'react-native-web/dist/exports/StyleSheet';
export { default as Text } from 'react-native-web/dist/exports/Text';
export { default as unstable_createElement } from 'react-native-web/dist/exports/createElement';
export { default as View } from 'react-native-web/dist/cjs/exports/View';
export { default as StyleSheet } from 'react-native-web/dist/cjs/exports/StyleSheet';
export { default as Text } from 'react-native-web/dist/cjs/exports/Text';
export { default as unstable_createElement } from 'react-native-web/dist/cjs/exports/createElement';
`;
exports[`Rewrite react-native to react-native-web import from "react-native": import from "react-native" 1`] = `
exports[`[commonjs] Rewrite react-native to react-native-web import from "react-native": import from "react-native" 1`] = `
import ReactNative from 'react-native';
import { View } from 'react-native';
import { StyleSheet, View } from 'react-native';
import { Invalid, View as MyView } from 'react-native';
import { useLocaleContext } from 'react-native';
import * as ReactNativeModules from 'react-native';
↓ ↓ ↓ ↓ ↓ ↓
import ReactNative from 'react-native-web/dist/index';
import View from 'react-native-web/dist/exports/View';
import { Invalid } from 'react-native-web/dist/index';
import MyView from 'react-native-web/dist/exports/View';
import useLocaleContext from 'react-native-web/dist/exports/useLocaleContext';
import * as ReactNativeModules from 'react-native-web/dist/index';
`;
exports[`Rewrite react-native to react-native-web import from "react-native": import from "react-native" 2`] = `
import ReactNative from 'react-native';
import { View } from 'react-native';
import { Invalid, View as MyView } from 'react-native';
import * as ReactNativeModules from 'react-native';
↓ ↓ ↓ ↓ ↓ ↓
import ReactNative from 'react-native-web/dist/cjs/index';
import StyleSheet from 'react-native-web/dist/cjs/exports/StyleSheet';
import View from 'react-native-web/dist/cjs/exports/View';
import { Invalid } from 'react-native-web/dist/cjs/index';
import MyView from 'react-native-web/dist/cjs/exports/View';
import useLocaleContext from 'react-native-web/dist/cjs/exports/useLocaleContext';
import * as ReactNativeModules from 'react-native-web/dist/cjs/index';
`;
exports[`Rewrite react-native to react-native-web import from "react-native-web": import from "react-native-web" 1`] = `
exports[`[commonjs] Rewrite react-native to react-native-web import from "react-native-web": import from "react-native-web" 1`] = `
import { unstable_createElement } from 'react-native-web';
import { StyleSheet, View, Pressable, processColor } from 'react-native-web';
@@ -76,33 +59,17 @@ import * as ReactNativeModules from 'react-native-web';
↓ ↓ ↓ ↓ ↓ ↓
import unstable_createElement from 'react-native-web/dist/exports/createElement';
import StyleSheet from 'react-native-web/dist/exports/StyleSheet';
import View from 'react-native-web/dist/exports/View';
import Pressable from 'react-native-web/dist/exports/Pressable';
import processColor from 'react-native-web/dist/exports/processColor';
import * as ReactNativeModules from 'react-native-web/dist/index';
import unstable_createElement from 'react-native-web/dist/cjs/exports/createElement';
import StyleSheet from 'react-native-web/dist/cjs/exports/StyleSheet';
import View from 'react-native-web/dist/cjs/exports/View';
import Pressable from 'react-native-web/dist/cjs/exports/Pressable';
import processColor from 'react-native-web/dist/cjs/exports/processColor';
import * as ReactNativeModules from 'react-native-web/dist/cjs/index';
`;
exports[`Rewrite react-native to react-native-web require "react-native": require "react-native" 1`] = `
const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, Pressable } = require('react-native');
↓ ↓ ↓ ↓ ↓ ↓
const ReactNative = require('react-native-web/dist/index');
const View = require('react-native-web/dist/exports/View').default;
const StyleSheet = require('react-native-web/dist/exports/StyleSheet').default;
const Pressable = require('react-native-web/dist/exports/Pressable').default;
`;
exports[`Rewrite react-native to react-native-web require "react-native": require "react-native" 2`] = `
exports[`[commonjs] Rewrite react-native to react-native-web require "react-native": require "react-native" 1`] = `
const ReactNative = require('react-native');
const { View } = require('react-native');
@@ -120,7 +87,114 @@ const Pressable =
`;
exports[`Rewrite react-native to react-native-web require "react-native-web": require "react-native-web" 1`] = `
exports[`[commonjs] Rewrite react-native to react-native-web require "react-native-web": require "react-native-web" 1`] = `
const ReactNative = require('react-native-web');
const { unstable_createElement } = require('react-native-web');
const { StyleSheet, View, Pressable, processColor } = require('react-native-web');
↓ ↓ ↓ ↓ ↓ ↓
const ReactNative = require('react-native-web/dist/cjs/index');
const unstable_createElement =
require('react-native-web/dist/cjs/exports/createElement').default;
const StyleSheet =
require('react-native-web/dist/cjs/exports/StyleSheet').default;
const View = require('react-native-web/dist/cjs/exports/View').default;
const Pressable =
require('react-native-web/dist/cjs/exports/Pressable').default;
const processColor =
require('react-native-web/dist/cjs/exports/processColor').default;
`;
exports[`[legacy] Rewrite react-native to react-native-web export from "react-native": export from "react-native" 1`] = `
export { View } from 'react-native';
export { StyleSheet, Text, unstable_createElement } from 'react-native';
↓ ↓ ↓ ↓ ↓ ↓
export { default as View } from 'react-native-web/dist/exports/View';
export { default as StyleSheet } from 'react-native-web/dist/exports/StyleSheet';
export { default as Text } from 'react-native-web/dist/exports/Text';
export { default as unstable_createElement } from 'react-native-web/dist/exports/createElement';
`;
exports[`[legacy] Rewrite react-native to react-native-web export from "react-native-web": export from "react-native-web" 1`] = `
export { View } from 'react-native-web';
export { StyleSheet, Text, unstable_createElement } from 'react-native-web';
↓ ↓ ↓ ↓ ↓ ↓
export { default as View } from 'react-native-web/dist/exports/View';
export { default as StyleSheet } from 'react-native-web/dist/exports/StyleSheet';
export { default as Text } from 'react-native-web/dist/exports/Text';
export { default as unstable_createElement } from 'react-native-web/dist/exports/createElement';
`;
exports[`[legacy] Rewrite react-native to react-native-web import from "react-native": import from "react-native" 1`] = `
import ReactNative from 'react-native';
import { StyleSheet, View } from 'react-native';
import { Invalid, View as MyView } from 'react-native';
import { useLocaleContext } from 'react-native';
import * as ReactNativeModules from 'react-native';
↓ ↓ ↓ ↓ ↓ ↓
import ReactNative from 'react-native-web/dist/index';
import StyleSheet from 'react-native-web/dist/exports/StyleSheet';
import View from 'react-native-web/dist/exports/View';
import { Invalid } from 'react-native-web/dist/index';
import MyView from 'react-native-web/dist/exports/View';
import useLocaleContext from 'react-native-web/dist/exports/useLocaleContext';
import * as ReactNativeModules from 'react-native-web/dist/index';
`;
exports[`[legacy] Rewrite react-native to react-native-web import from "react-native-web": import from "react-native-web" 1`] = `
import { unstable_createElement } from 'react-native-web';
import { StyleSheet, View, Pressable, processColor } from 'react-native-web';
import * as ReactNativeModules from 'react-native-web';
↓ ↓ ↓ ↓ ↓ ↓
import unstable_createElement from 'react-native-web/dist/exports/createElement';
import StyleSheet from 'react-native-web/dist/exports/StyleSheet';
import View from 'react-native-web/dist/exports/View';
import Pressable from 'react-native-web/dist/exports/Pressable';
import processColor from 'react-native-web/dist/exports/processColor';
import * as ReactNativeModules from 'react-native-web/dist/index';
`;
exports[`[legacy] Rewrite react-native to react-native-web require "react-native": require "react-native" 1`] = `
const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, Pressable } = require('react-native');
↓ ↓ ↓ ↓ ↓ ↓
const ReactNative = require('react-native-web/dist/index');
const View = require('react-native-web/dist/exports/View').default;
const StyleSheet = require('react-native-web/dist/exports/StyleSheet').default;
const Pressable = require('react-native-web/dist/exports/Pressable').default;
`;
exports[`[legacy] Rewrite react-native to react-native-web require "react-native-web": require "react-native-web" 1`] = `
const ReactNative = require('react-native-web');
const { unstable_createElement } = require('react-native-web');
@@ -138,4 +212,101 @@ const processColor =
require('react-native-web/dist/exports/processColor').default;
`;
exports[`Rewrite react-native to react-native-web export from "react-native": export from "react-native" 1`] = `
export { View } from 'react-native';
export { StyleSheet, Text, unstable_createElement } from 'react-native';
↓ ↓ ↓ ↓ ↓ ↓
export { View } from 'react-native';
export { StyleSheet, Text, unstable_createElement } from 'react-native';
`;
exports[`Rewrite react-native to react-native-web export from "react-native-web": export from "react-native-web" 1`] = `
export { View } from 'react-native-web';
export { StyleSheet, Text, unstable_createElement } from 'react-native-web';
↓ ↓ ↓ ↓ ↓ ↓
export { View } from 'react-native-web';
export { StyleSheet, Text, unstable_createElement } from 'react-native-web';
`;
exports[`Rewrite react-native to react-native-web import from "react-native": import from "react-native" 1`] = `
import ReactNative from 'react-native';
import { StyleSheet, View } from 'react-native';
import { Invalid, View as MyView } from 'react-native';
import { useLocaleContext } from 'react-native';
import * as ReactNativeModules from 'react-native';
↓ ↓ ↓ ↓ ↓ ↓
import ReactNative from 'react-native';
import StyleSheet from 'react-native-web/dist/exports/StyleSheet/runtime';
import { View } from 'react-native';
import { Invalid, View as MyView } from 'react-native';
import { useLocaleContext } from 'react-native';
import * as ReactNativeModules from 'react-native';
`;
exports[`Rewrite react-native to react-native-web import from "react-native-web": import from "react-native-web" 1`] = `
import { unstable_createElement } from 'react-native-web';
import { StyleSheet, View, Pressable, processColor } from 'react-native-web';
import * as ReactNativeModules from 'react-native-web';
↓ ↓ ↓ ↓ ↓ ↓
import { unstable_createElement } from 'react-native-web';
import StyleSheet from 'react-native-web/dist/exports/StyleSheet/runtime';
import { View, Pressable, processColor } from 'react-native';
import * as ReactNativeModules from 'react-native-web';
`;
exports[`Rewrite react-native to react-native-web require "react-native": require "react-native" 1`] = `
const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, Pressable } = require('react-native');
↓ ↓ ↓ ↓ ↓ ↓
const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, Pressable } = require('react-native');
`;
exports[`Rewrite react-native to react-native-web require "react-native-web": require "react-native-web" 1`] = `
const ReactNative = require('react-native-web');
const { unstable_createElement } = require('react-native-web');
const { StyleSheet, View, Pressable, processColor } = require('react-native-web');
↓ ↓ ↓ ↓ ↓ ↓
const ReactNative = require('react-native-web');
const { unstable_createElement } = require('react-native-web');
const {
StyleSheet,
View,
Pressable,
processColor
} = require('react-native-web');
`;

View File

@@ -1,69 +1,86 @@
const plugin = require('..');
const pluginTester = require('babel-plugin-tester').default;
const tests = [
// import react-native
{
title: 'import from "react-native"',
code: `import ReactNative from 'react-native';
import { View } from 'react-native';
function createTests(pluginOptions) {
return [
// import react-native
{
title: 'import from "react-native"',
code: `import ReactNative from 'react-native';
import { StyleSheet, View } from 'react-native';
import { Invalid, View as MyView } from 'react-native';
import { useLocaleContext } from 'react-native';
import * as ReactNativeModules from 'react-native';`,
snapshot: true
},
{
title: 'import from "react-native"',
code: `import ReactNative from 'react-native';
import { View } from 'react-native';
import { Invalid, View as MyView } from 'react-native';
import * as ReactNativeModules from 'react-native';`,
snapshot: true,
pluginOptions: { commonjs: true }
},
{
title: 'import from "react-native-web"',
code: `import { unstable_createElement } from 'react-native-web';
snapshot: true,
pluginOptions
},
{
title: 'import from "react-native-web"',
code: `import { unstable_createElement } from 'react-native-web';
import { StyleSheet, View, Pressable, processColor } from 'react-native-web';
import * as ReactNativeModules from 'react-native-web';`,
snapshot: true
},
{
title: 'export from "react-native"',
code: `export { View } from 'react-native';
snapshot: true,
pluginOptions
},
{
title: 'export from "react-native"',
code: `export { View } from 'react-native';
export { StyleSheet, Text, unstable_createElement } from 'react-native';`,
snapshot: true
},
{
title: 'export from "react-native-web"',
code: `export { View } from 'react-native-web';
snapshot: true,
pluginOptions
},
{
title: 'export from "react-native-web"',
code: `export { View } from 'react-native-web';
export { StyleSheet, Text, unstable_createElement } from 'react-native-web';`,
snapshot: true
},
// require react-native
{
title: 'require "react-native"',
code: `const ReactNative = require('react-native');
snapshot: true,
pluginOptions
},
// require react-native
{
title: 'require "react-native"',
code: `const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, Pressable } = require('react-native');`,
snapshot: true
},
{
title: 'require "react-native"',
code: `const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, Pressable } = require('react-native');`,
snapshot: true,
pluginOptions: { commonjs: true }
},
{
title: 'require "react-native-web"',
code: `const ReactNative = require('react-native-web');
snapshot: true,
pluginOptions
},
{
title: 'require "react-native-web"',
code: `const ReactNative = require('react-native-web');
const { unstable_createElement } = require('react-native-web');
const { StyleSheet, View, Pressable, processColor } = require('react-native-web');`,
snapshot: true
}
];
snapshot: true,
pluginOptions
}
];
}
pluginTester({
babelOptions: {
generatorOpts: {
jsescOption: {
quotes: 'single'
}
}
},
plugin,
pluginName: '[legacy] Rewrite react-native to react-native-web',
tests: createTests({})
});
pluginTester({
babelOptions: {
generatorOpts: {
jsescOption: {
quotes: 'single'
}
}
},
plugin,
pluginName: '[commonjs] Rewrite react-native to react-native-web',
tests: createTests({ commonjs: true })
});
pluginTester({
babelOptions: {
@@ -75,5 +92,5 @@ pluginTester({
},
plugin,
pluginName: 'Rewrite react-native to react-native-web',
tests
tests: createTests({ legacy: false })
});

View File

@@ -42,36 +42,64 @@ module.exports = function ({ types: t }) {
ImportDeclaration(path, state) {
const { specifiers } = path.node;
if (isReactNativeModule(path.node)) {
const imports = specifiers
.map((specifier) => {
if (t.isImportSpecifier(specifier)) {
const importName = specifier.imported.name;
const distLocation = getDistLocation(importName, state.opts);
if (state.opts.legacy !== false) {
const imports = specifiers
.map((specifier) => {
if (t.isImportSpecifier(specifier)) {
const importName = specifier.imported.name;
const distLocation = getDistLocation(importName, state.opts);
if (distLocation) {
return t.importDeclaration(
[
t.importDefaultSpecifier(
t.identifier(specifier.local.name)
)
],
t.stringLiteral(distLocation)
);
if (distLocation) {
return t.importDeclaration(
[
t.importDefaultSpecifier(
t.identifier(specifier.local.name)
)
],
t.stringLiteral(distLocation)
);
}
}
}
return t.importDeclaration(
[specifier],
t.stringLiteral(getDistLocation('index', state.opts))
);
})
.filter(Boolean);
return t.importDeclaration(
[specifier],
t.stringLiteral(getDistLocation('index', state.opts))
);
})
.filter(Boolean);
path.replaceWithMultiple(imports);
path.replaceWithMultiple(imports);
} else {
const styleSheetSpecifierIndex = specifiers.findIndex(
(specifier) =>
specifier.imported && specifier.imported.name === 'StyleSheet'
);
if (styleSheetSpecifierIndex !== -1) {
const otherSpecifiers = [
...specifiers.slice(0, styleSheetSpecifierIndex),
...specifiers.slice(styleSheetSpecifierIndex + 1)
];
const newImports = [
t.importDeclaration(
[t.importDefaultSpecifier(t.identifier('StyleSheet'))],
t.stringLiteral(
'react-native-web/dist/exports/StyleSheet/runtime'
)
),
t.importDeclaration(
otherSpecifiers,
t.stringLiteral('react-native')
)
];
path.replaceWithMultiple(newImports);
}
}
}
},
ExportNamedDeclaration(path, state) {
const { specifiers } = path.node;
if (isReactNativeModule(path.node)) {
if (isReactNativeModule(path.node) && state.opts.legacy !== false) {
const exports = specifiers
.map((specifier) => {
if (t.isExportSpecifier(specifier)) {
@@ -104,7 +132,7 @@ module.exports = function ({ types: t }) {
}
},
VariableDeclaration(path, state) {
if (isReactNativeRequire(t, path.node)) {
if (isReactNativeRequire(t, path.node) && state.opts.legacy !== false) {
const { id } = path.node.declarations[0];
if (t.isObjectPattern(id)) {
const imports = id.properties

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) Nicolas Gallagher.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import { localizeStyle } from 'styleq/transform-localize-style';
import { styleq } from 'styleq';
type StyleProps = [string, { [key: string]: mixed } | null];
type Options = { writingDirection: 'ltr' | 'rtl' };
function customStyleq(styles, isRTL) {
return styleq.factory({
transform(style) {
return localizeStyle(style, isRTL);
}
})(styles);
}
export default function StyleSheet(
styles: $ReadOnlyArray<any>,
options?: Options
): StyleProps {
const isRTL = options != null && options.writingDirection === 'rtl';
const styleProps: StyleProps = customStyleq(styles, isRTL);
// inline styles are not processed in any way
return styleProps;
}

View File

@@ -15,9 +15,18 @@ import AnimatedTransform from './AnimatedTransform';
import AnimatedWithChildren from './AnimatedWithChildren';
import NativeAnimatedHelper from '../NativeAnimatedHelper';
import StyleSheet from '../../../../exports/StyleSheet';
const flattenStyle = StyleSheet.flatten;
function flattenStyle(...styles: any): { [key: string]: any } {
const flatArray = styles.flat(Infinity);
const result = {};
for (let i = 0; i < flatArray.length; i++) {
const style = flatArray[i];
if (style != null && typeof style === 'object') {
// $FlowFixMe
Object.assign(result, style);
}
}
return result;
}
function createAnimatedStyle(inputStyle: any): Object {
const style = flattenStyle(inputStyle);