mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-25 15:42:24 +00:00
Monorepo
Introduces a monorepo structure, relies on yarn workspaces to share
dependencies, and lerna for syncing versions across the monorepo.
* Create 2 workspaces:
'packages' and 'website'
* Create 2 public packages:
'babel-plugin-react-native-web' and 'react-native-web'
* Create 1 private package:
'benchmarks'
A simple release script runs the tests, builds the package assets,
increments the package version numbers, git commits and tags, publishes
the package to npm, pushes the changes to github, and releases the
website update.
Close #657
This commit is contained in:
+161
@@ -0,0 +1,161 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`1. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
import { View } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
import View from 'react-native-web/dist/components/View';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`2. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
import { Switch, Text, View as MyView, ViewPropTypes } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
import Switch from 'react-native-web/dist/components/Switch';
|
||||
import Text from 'react-native-web/dist/components/Text';
|
||||
import MyView from 'react-native-web/dist/components/View';
|
||||
import ViewPropTypes from 'react-native-web/dist/components/View/ViewPropTypes';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`3. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
import { createElement, Switch, StyleSheet } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
import createElement from 'react-native-web/dist/modules/createElement';
|
||||
import Switch from 'react-native-web/dist/components/Switch';
|
||||
import StyleSheet from 'react-native-web/dist/apis/StyleSheet';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`4. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
import { InvalidThing, TouchableOpacity } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
import { InvalidThing } from 'react-native-web';
|
||||
import TouchableOpacity from 'react-native-web/dist/components/Touchable/TouchableOpacity';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`5. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
import * as RNW from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
import * as RNW from 'react-native-web';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`6. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
const { View } = require('react-native');
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
const View = require('react-native-web/dist/components/View');
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`7. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
let { Switch, Text, View: MyView } = require('react-native');
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
let Switch = require('react-native-web/dist/components/Switch');
|
||||
|
||||
let Text = require('react-native-web/dist/components/Text');
|
||||
|
||||
let MyView = require('react-native-web/dist/components/View');
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`8. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
var { createElement, Switch, StyleSheet } = require('react-native');
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
var createElement = require('react-native-web/dist/modules/createElement');
|
||||
|
||||
var Switch = require('react-native-web/dist/components/Switch');
|
||||
|
||||
var StyleSheet = require('react-native-web/dist/apis/StyleSheet');
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`9. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
const { InvalidThing, TouchableOpacity } = require('react-native');
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
const TouchableOpacity = require('react-native-web/dist/components/Touchable/TouchableOpacity');
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`10. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
export { View } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
export { default as View } from 'react-native-web/dist/components/View';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`11. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
export { Switch, Text, View as MyView, ViewPropTypes } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
export { default as Switch } from 'react-native-web/dist/components/Switch';
|
||||
export { default as Text } from 'react-native-web/dist/components/Text';
|
||||
export { default as MyView } from 'react-native-web/dist/components/View';
|
||||
export { default as ViewPropTypes } from 'react-native-web/dist/components/View/ViewPropTypes';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`12. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
export { createElement, Switch, StyleSheet } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
export { default as createElement } from 'react-native-web/dist/modules/createElement';
|
||||
export { default as Switch } from 'react-native-web/dist/components/Switch';
|
||||
export { default as StyleSheet } from 'react-native-web/dist/apis/StyleSheet';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`13. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
export { InvalidThing, TouchableOpacity } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
export { InvalidThing } from 'react-native-web';
|
||||
export { default as TouchableOpacity } from 'react-native-web/dist/components/Touchable/TouchableOpacity';
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`14. Rewrite react-native paths for react-native-web 1`] = `
|
||||
"
|
||||
export { default as RNW } from 'react-native';
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
export { default as RNW } from 'react-native-web';
|
||||
"
|
||||
`;
|
||||
@@ -0,0 +1,46 @@
|
||||
const plugin = require('..');
|
||||
const pluginTester = require('babel-plugin-tester');
|
||||
|
||||
pluginTester({
|
||||
plugin,
|
||||
snapshot: true,
|
||||
tests: [
|
||||
// import react-native
|
||||
"import { View } from 'react-native';",
|
||||
"import { Switch, Text, View as MyView, ViewPropTypes } from 'react-native';",
|
||||
"import { createElement, Switch, StyleSheet } from 'react-native';",
|
||||
"import { InvalidThing, TouchableOpacity } from 'react-native';",
|
||||
"import * as RNW from 'react-native';",
|
||||
|
||||
// import react-native-web
|
||||
// "import { View } from 'react-native-web';",
|
||||
// "import { Switch, Text, View as MyView } from 'react-native-web';",
|
||||
// "import { createElement, Switch, StyleSheet } from 'react-native-web';",
|
||||
// "import { InvalidThing, TouchableOpacity } from 'react-native-web';",
|
||||
// "import * as RNW from 'react-native-web';",
|
||||
|
||||
// require react-native
|
||||
"const { View } = require('react-native');",
|
||||
"let { Switch, Text, View: MyView } = require('react-native');",
|
||||
"var { createElement, Switch, StyleSheet } = require('react-native');",
|
||||
"const { InvalidThing, TouchableOpacity } = require('react-native');",
|
||||
|
||||
// require react-native-web
|
||||
// "const { View } = require('react-native-web');",
|
||||
// "let { Switch, Text, View: MyView } = require('react-native-web');",
|
||||
// "var { createElement, Switch, StyleSheet } = require('react-native-web');",
|
||||
// "const { InvalidThing, TouchableOpacity } = require('react-native-web');",
|
||||
|
||||
// export react-native
|
||||
"export { View } from 'react-native';",
|
||||
"export { Switch, Text, View as MyView, ViewPropTypes } from 'react-native';",
|
||||
"export { createElement, Switch, StyleSheet } from 'react-native';",
|
||||
"export { InvalidThing, TouchableOpacity } from 'react-native';",
|
||||
"export { default as RNW } from 'react-native';",
|
||||
{
|
||||
code: "const RNW = require('react-native');",
|
||||
output: "const RNW = require('react-native');",
|
||||
snapshot: false
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -0,0 +1,182 @@
|
||||
const getDistLocation = importName => {
|
||||
const root = 'react-native-web/dist';
|
||||
|
||||
switch (importName) {
|
||||
// apis
|
||||
case 'Animated':
|
||||
case 'AppRegistry':
|
||||
case 'AppState':
|
||||
case 'AsyncStorage':
|
||||
case 'BackHandler':
|
||||
case 'Clipboard':
|
||||
case 'Dimensions':
|
||||
case 'Easing':
|
||||
case 'I18nManager':
|
||||
case 'InteractionManager':
|
||||
case 'Keyboard':
|
||||
case 'Linking':
|
||||
case 'NetInfo':
|
||||
case 'PanResponder':
|
||||
case 'PixelRatio':
|
||||
case 'Platform':
|
||||
case 'StyleSheet':
|
||||
case 'UIManager':
|
||||
case 'Vibration': {
|
||||
return `${root}/apis/${importName}`;
|
||||
}
|
||||
|
||||
// components
|
||||
case 'ActivityIndicator':
|
||||
case 'ART':
|
||||
case 'Button':
|
||||
case 'FlatList':
|
||||
case 'Image':
|
||||
case 'KeyboardAvoidingView':
|
||||
case 'ListView':
|
||||
case 'Modal':
|
||||
case 'Picker':
|
||||
case 'ProgressBar':
|
||||
case 'RefreshControl':
|
||||
case 'ScrollView':
|
||||
case 'SectionList':
|
||||
case 'Slider':
|
||||
case 'StatusBar':
|
||||
case 'Switch':
|
||||
case 'Text':
|
||||
case 'TextInput':
|
||||
case 'View':
|
||||
case 'VirtualizedList': {
|
||||
return `${root}/components/${importName}`;
|
||||
}
|
||||
|
||||
case 'Touchable':
|
||||
case 'TouchableHighlight':
|
||||
case 'TouchableNativeFeedback':
|
||||
case 'TouchableOpacity':
|
||||
case 'TouchableWithoutFeedback': {
|
||||
return `${root}/components/Touchable/${importName}`;
|
||||
}
|
||||
|
||||
// modules
|
||||
case 'createElement':
|
||||
case 'findNodeHandle':
|
||||
case 'NativeModules':
|
||||
case 'processColor':
|
||||
case 'render':
|
||||
case 'unmountComponentAtNode': {
|
||||
return `${root}/modules/${importName}`;
|
||||
}
|
||||
|
||||
// propTypes
|
||||
case 'ColorPropType':
|
||||
case 'EdgeInsetsPropType':
|
||||
case 'PointPropType': {
|
||||
return `${root}/propTypes/${importName}`;
|
||||
}
|
||||
case 'TextPropTypes': {
|
||||
return `${root}/components/Text/${importName}`;
|
||||
}
|
||||
case 'ViewPropTypes': {
|
||||
return `${root}/components/View/${importName}`;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const isReactNativeRequire = (t, node) => {
|
||||
const { declarations } = node;
|
||||
if (declarations.length > 1) {
|
||||
return false;
|
||||
}
|
||||
const { id, init } = declarations[0];
|
||||
return (
|
||||
t.isObjectPattern(id) &&
|
||||
t.isCallExpression(init) &&
|
||||
t.isIdentifier(init.callee) &&
|
||||
init.callee.name === 'require' &&
|
||||
init.arguments.length === 1 &&
|
||||
init.arguments[0].value === 'react-native'
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = function({ types: t }) {
|
||||
return {
|
||||
name: 'Rewrite react-native paths for react-native-web',
|
||||
visitor: {
|
||||
ImportDeclaration(path) {
|
||||
const { source, specifiers } = path.node;
|
||||
if (source && source.value === 'react-native' && specifiers.length) {
|
||||
const imports = specifiers
|
||||
.map(specifier => {
|
||||
if (t.isImportSpecifier(specifier)) {
|
||||
const importName = specifier.imported.name;
|
||||
const distLocation = getDistLocation(importName);
|
||||
|
||||
if (distLocation) {
|
||||
return t.importDeclaration(
|
||||
[t.importDefaultSpecifier(t.identifier(specifier.local.name))],
|
||||
t.stringLiteral(distLocation)
|
||||
);
|
||||
}
|
||||
}
|
||||
return t.importDeclaration([specifier], t.stringLiteral('react-native-web'));
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
path.replaceWithMultiple(imports);
|
||||
}
|
||||
},
|
||||
ExportNamedDeclaration(path) {
|
||||
const { source, specifiers } = path.node;
|
||||
if (source && source.value === 'react-native' && specifiers.length) {
|
||||
const exports = specifiers
|
||||
.map(specifier => {
|
||||
if (t.isExportSpecifier(specifier)) {
|
||||
const exportName = specifier.exported.name;
|
||||
const localName = specifier.local.name;
|
||||
const distLocation = getDistLocation(localName);
|
||||
|
||||
if (distLocation) {
|
||||
return t.exportNamedDeclaration(
|
||||
null,
|
||||
[t.exportSpecifier(t.identifier('default'), t.identifier(exportName))],
|
||||
t.stringLiteral(distLocation)
|
||||
);
|
||||
}
|
||||
return t.exportNamedDeclaration(
|
||||
null,
|
||||
[specifier],
|
||||
t.stringLiteral('react-native-web')
|
||||
);
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
path.replaceWithMultiple(exports);
|
||||
}
|
||||
},
|
||||
VariableDeclaration(path) {
|
||||
if (isReactNativeRequire(t, path.node)) {
|
||||
const { id } = path.node.declarations[0];
|
||||
const imports = id.properties
|
||||
.map(identifier => {
|
||||
const distLocation = getDistLocation(identifier.key.name);
|
||||
if (distLocation) {
|
||||
return t.variableDeclaration(path.node.kind, [
|
||||
t.variableDeclarator(
|
||||
t.identifier(identifier.value.name),
|
||||
t.callExpression(t.identifier('require'), [t.stringLiteral(distLocation)])
|
||||
)
|
||||
]);
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
path.replaceWithMultiple(imports);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user