Updates from Tue 31 Mar

- Bugfix/require module regexp | Amjad Masad
- [ReactNative] RCTView's shadowOffset is of float type, not CGFloat | Kevin Gozali
- Fix WebView automaticallyAdjustContentInsets error | Spencer Ahrens
- [react-native] map view - add onTouch** props | Jiajie Zhu
- [react-native] Fix documentation extraction for View | Ben Alpert
- [ReactNative] Add few hints in the UI | Alex Kotliarskyi
- Adding `scrollWithoutAnimationTo` method for ScrollViews | Felix Oghina
- [ScrollView] Add "bounces" property to ScrollView propTypes | Spencer Ahrens
- Fix a crash in RCTAsyncLocalStorage when the value is not a string. | Spencer Ahrens
- [ReactNative] Remove global MutationObserver to fix Bluebird feature detection | Christopher Chedeau
- [catalyst] fix typo | Jiajie Zhu
- [react-packager] check-in bluebird | Amjad Masad
- [react-native] v0.3.1 | Amjad Masad
- [Pod] Preserve header directory structure | Alex Akers
- [react-native] Bring React.render behavior in line with web | Ben Alpert
- Expose html prop on WebView | Spencer Ahrens
- missing '.' in ListView.DataSource example | Christopher Chedeau
- [react-native] Support returning null from a component | Ben Alpert
- [react-native] Fix race condition in removeSubviewsFromContainerWithID: | Ben Alpert
This commit is contained in:
Christopher Chedeau 2015-03-31 19:01:48 -07:00
parent e90ede3ce2
commit 18cb5d0711
22 changed files with 205 additions and 88 deletions

View File

@ -20,8 +20,11 @@ var SampleApp = React.createClass({
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js{'\n'}
Press Cmd+R to reload
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+Shift+Z for dev menu
</Text>
</View>
);
@ -43,6 +46,7 @@ var styles = StyleSheet.create({
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});

View File

@ -40,7 +40,7 @@ var UIExplorerPage = React.createClass({
ContentWrapper = View;
} else {
ContentWrapper = ScrollView;
wrapperProps.keyboardShouldPeristTaps = true;
wrapperProps.keyboardShouldPersistTaps = true;
wrapperProps.keyboardDismissMode = 'interactive';
}
var title = this.props.title ?

View File

@ -147,6 +147,9 @@ var MapView = React.createClass({
legalLabelInsets={this.props.legalLabelInsets}
onChange={this._onChange}
onTouchStart={this.props.onTouchStart}
onTouchMove={this.props.onTouchMove}
onTouchEnd={this.props.onTouchEnd}
onTouchCancel={this.props.onTouchCancel}
/>
);
},

View File

@ -59,13 +59,20 @@ var ScrollView = React.createClass({
contentOffset: PointPropType, // zeros
onScroll: PropTypes.func,
onScrollAnimationEnd: PropTypes.func,
scrollEnabled: PropTypes.bool, // tre
scrollEnabled: PropTypes.bool, // true
scrollIndicatorInsets: EdgeInsetsPropType, // zeros
showsHorizontalScrollIndicator: PropTypes.bool,
showsVerticalScrollIndicator: PropTypes.bool,
style: StyleSheetPropType(ViewStylePropTypes),
scrollEventThrottle: PropTypes.number, // null
/**
* When true, the scroll view bounces when it reaches the end of the
* content if the content is larger then the scroll view along the axis of
* the scroll direction. When false, it disables all bouncing even if
* the `alwaysBounce*` props are true. The default value is true.
*/
bounces: PropTypes.bool,
/**
* When true, the scroll view bounces horizontally when it reaches the end
* even if the content is smaller than the scroll view itself. The default
@ -195,6 +202,14 @@ var ScrollView = React.createClass({
);
},
scrollWithoutAnimationTo: function(destY?: number, destX?: number) {
RCTUIManager.scrollWithoutAnimationTo(
this.getNodeHandle(),
destX || 0,
destY || 0
);
},
render: function() {
var contentContainerStyle = [
this.props.horizontal && styles.contentContainerHorizontal,
@ -308,6 +323,7 @@ var validAttributes = {
alwaysBounceHorizontal: true,
alwaysBounceVertical: true,
automaticallyAdjustContentInsets: true,
bounces: true,
centerContent: true,
contentInset: {diff: insetsDiffer},
contentOffset: {diff: pointsDiffer},

View File

@ -60,7 +60,8 @@ var WebView = React.createClass({
propTypes: {
renderError: PropTypes.func.isRequired, // view to show if there's an error
renderLoading: PropTypes.func.isRequired, // loading indicator to show
url: PropTypes.string.isRequired,
url: PropTypes.string,
html: PropTypes.string,
automaticallyAdjustContentInsets: PropTypes.bool,
shouldInjectAJAXHandler: PropTypes.bool,
contentInset: EdgeInsetsPropType,
@ -115,6 +116,7 @@ var WebView = React.createClass({
key="webViewKey"
style={webViewStyles}
url={this.props.url}
html={this.props.html}
shouldInjectAJAXHandler={this.props.shouldInjectAJAXHandler}
contentInset={this.props.contentInset}
automaticallyAdjustContentInsets={this.props.automaticallyAdjustContentInsets}
@ -182,6 +184,7 @@ var WebView = React.createClass({
var RCTWebView = createReactIOSNativeComponentClass({
validAttributes: merge(ReactIOSViewAttributes.UIView, {
url: true,
html: true,
contentInset: {diff: insetsDiffer},
automaticallyAdjustContentInsets: true,
shouldInjectAJAXHandler: true

View File

@ -60,6 +60,10 @@ function setupDocumentShim() {
if (GLOBAL.document) {
GLOBAL.document.createElement = null;
}
// There is no DOM so MutationObserver doesn't make sense. It is used
// as feature detection in Bluebird Promise implementation
GLOBAL.MutationObserver = undefined;
}
function handleErrorWithRedBox(e) {

View File

@ -67,8 +67,12 @@ var augmentElement = function(element: ReactElement) {
return element;
};
var render = function(component: ReactComponent, mountInto: number) {
ReactIOSMount.renderComponent(component, mountInto);
var render = function(
element: ReactElement,
mountInto: number,
callback?: ?(() => void)
): ?ReactComponent {
return ReactIOSMount.renderComponent(element, mountInto, callback);
};
var ReactIOS = {

View File

@ -24,6 +24,7 @@ var NodeHandle = require('NodeHandle');
var ReactClass = require('ReactClass');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
var ReactEmptyComponent = require('ReactEmptyComponent');
var ReactInstanceHandles = require('ReactInstanceHandles');
var ReactIOSComponentEnvironment = require('ReactIOSComponentEnvironment');
var ReactIOSComponentMixin = require('ReactIOSComponentMixin');
@ -36,6 +37,8 @@ var ReactUpdates = require('ReactUpdates');
var ResponderEventPlugin = require('ResponderEventPlugin');
var UniversalWorkerNodeHandle = require('UniversalWorkerNodeHandle');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
// Just to ensure this gets packaged, since its only caller is from Native.
require('RCTEventEmitter');
require('RCTLog');
@ -77,6 +80,13 @@ function inject() {
ReactIOSComponentEnvironment
);
// Can't import View here because it depends on React to make its composite
var RCTView = createReactIOSNativeComponentClass({
validAttributes: {},
uiViewClassName: 'RCTView',
});
ReactEmptyComponent.injection.injectEmptyComponent(RCTView);
EventPluginUtils.injection.injectMount(ReactIOSMount);
ReactClass.injection.injectMixin(ReactIOSComponentMixin);

View File

@ -16,13 +16,13 @@ var RCTUIManager = require('NativeModules').UIManager;
var ReactIOSTagHandles = require('ReactIOSTagHandles');
var ReactPerf = require('ReactPerf');
var ReactReconciler = require('ReactReconciler');
var ReactUpdateQueue = require('ReactUpdateQueue');
var ReactUpdates = require('ReactUpdates');
var emptyObject = require('emptyObject');
var instantiateReactComponent = require('instantiateReactComponent');
var invariant = require('invariant');
var TOP_ROOT_NODE_IDS = {};
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
function instanceNumberToChildRootID(rootNodeID, instanceNumber) {
return rootNodeID + '[' + instanceNumber + ']';
@ -85,10 +85,26 @@ var ReactIOSMount = {
* @param {containerTag} containerView Handle to native view tag
*/
renderComponent: function(
descriptor: ReactComponent,
containerTag: number
) {
var instance = instantiateReactComponent(descriptor);
nextElement: ReactElement,
containerTag: number,
callback?: ?(() => void)
): ?ReactComponent {
var topRootNodeID = ReactIOSTagHandles.tagToRootNodeID[containerTag];
if (topRootNodeID) {
var prevComponent = ReactIOSMount._instancesByContainerID[topRootNodeID];
if (prevComponent) {
var prevElement = prevComponent._currentElement;
if (shouldUpdateReactComponent(prevElement, nextElement)) {
ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement);
if (callback) {
ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
}
return prevComponent;
} else {
ReactIOSMount.unmountComponentAtNode(containerTag);
}
}
}
if (!ReactIOSTagHandles.reactTagIsNativeTopRootID(containerTag)) {
console.error('You cannot render into anything but a top root');
@ -100,13 +116,14 @@ var ReactIOSMount = {
topRootNodeID,
containerTag
);
TOP_ROOT_NODE_IDS[topRootNodeID] = true;
var instance = instantiateReactComponent(nextElement);
ReactIOSMount._instancesByContainerID[topRootNodeID] = instance;
var childRootNodeID = instanceNumberToChildRootID(
topRootNodeID,
ReactIOSMount.instanceCount++
);
ReactIOSMount._instancesByContainerID[topRootNodeID] = instance;
// The initial render is synchronous but any updates that happen during
// rendering, in componentWillMount or componentDidMount, will be batched
@ -118,6 +135,11 @@ var ReactIOSMount = {
childRootNodeID,
topRootNodeID
);
var component = instance.getPublicInstance();
if (callback) {
callback.call(component);
}
return component;
},
/**
@ -170,20 +192,18 @@ var ReactIOSMount = {
* component at this time.
*/
unmountComponentAtNode: function(containerTag: number): bool {
var containerID = ReactIOSTagHandles.tagToRootNodeID[containerTag];
if (!ReactIOSTagHandles.reactTagIsNativeTopRootID(containerTag)) {
console.error('You cannot render into anything but a top root');
return;
}
invariant(
TOP_ROOT_NODE_IDS[containerID],
'We only currently support removing components from the root node'
);
var containerID = ReactIOSTagHandles.tagToRootNodeID[containerTag];
var instance = ReactIOSMount._instancesByContainerID[containerID];
if (!instance) {
console.error('Tried to unmount a component that does not exist');
return false;
}
ReactIOSMount.unmountComponentFromNode(instance, containerID);
delete ReactIOSMount._instancesByContainerID[containerID];
delete TOP_ROOT_NODE_IDS[containerID];
return true;
},
@ -200,10 +220,8 @@ var ReactIOSMount = {
instance: ReactComponent,
containerID: string
) {
// call back into native to remove all of the subviews from this container
// TODO: ReactComponent.prototype.unmountComponent is missing from Flow's
// react lib.
(instance: any).unmountComponent();
// Call back into native to remove all of the subviews from this container
ReactReconciler.unmountComponent(instance);
var containerTag =
ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(containerID);
RCTUIManager.removeSubviewsFromContainerWithID(containerTag);

View File

@ -1,77 +1,93 @@
Pod::Spec.new do |s|
s.name = "React"
s.version = "0.1.0"
s.version = "0.3.1"
s.summary = "Build high quality mobile apps using React."
s.description = <<-DESC
React Native apps are built using the React JS framework,
and render directly to native UIKit elements using a fully
asynchronous architecture. There is no browser and no HTML.
We have picked what we think is the best set of features from
these and other technologies to build what we hope to become
the best product development framework available, with an
emphasis on iteration speed, developer delight, continuity
of technology, and absolutely beautiful and fast products
with no compromises in quality or capability.
React Native apps are built using the React JS
framework, and render directly to native UIKit
elements using a fully asynchronous architecture.
There is no browser and no HTML. We have picked what
we think is the best set of features from these and
other technologies to build what we hope to become
the best product development framework available,
with an emphasis on iteration speed, developer
delight, continuity of technology, and absolutely
beautiful and fast products with no compromises in
quality or capability.
DESC
s.homepage = "http://facebook.github.io/react-native/"
s.license = "BSD"
s.author = "Facebook"
s.platform = :ios, "7.0"
s.source = { :git => "https://github.com/facebook/react-native.git", :tag => "v#{s.version}" }
s.source_files = "React/**/*.{c,h,m}"
s.resources = "Resources/*.png"
s.preserve_paths = "cli.js", "Libraries/**/*.js", "lint", "linter.js", "node_modules", "package.json", "packager", "PATENTS", "react-native-cli"
s.exclude_files = "**/__tests__/*", "IntegrationTests/*"
s.frameworks = "JavaScriptCore"
s.default_subspec = 'Core'
s.requires_arc = true
s.platform = :ios, "7.0"
s.prepare_command = 'npm install'
s.libraries = 'icucore'
s.preserve_paths = "cli.js", "Libraries/**/*.js", "lint", "linter.js", "node_modules", "package.json", "packager", "PATENTS", "react-native-cli"
s.header_mappings_dir = "."
s.subspec 'Core' do |ss|
ss.source_files = "React/**/*.{c,h,m}"
ss.exclude_files = "**/__tests__/*", "IntegrationTests/*"
ss.frameworks = "JavaScriptCore"
end
s.subspec 'RCTActionSheet' do |ss|
ss.dependency 'React/Core'
ss.source_files = "Libraries/ActionSheetIOS/*.{h,m}"
ss.preserve_paths = "Libraries/ActionSheetIOS/*.js"
end
s.subspec 'RCTAdSupport' do |ss|
ss.source_files = "Libraries/RCTAdSupport/*.{h,m}"
ss.preserve_paths = "Libraries/RCTAdSupport/*.js"
ss.dependency 'React/Core'
ss.source_files = "Libraries/AdSupport/*.{h,m}"
ss.preserve_paths = "Libraries/AdSupport/*.js"
end
s.subspec 'RCTAnimation' do |ss|
ss.dependency 'React/Core'
ss.source_files = "Libraries/Animation/*.{h,m}"
ss.preserve_paths = "Libraries/Animation/*.js"
end
s.subspec 'RCTGeolocation' do |ss|
ss.dependency 'React/Core'
ss.source_files = "Libraries/Geolocation/*.{h,m}"
ss.preserve_paths = "Libraries/Geolocation/*.js"
end
s.subspec 'RCTImage' do |ss|
ss.dependency 'React/Core'
ss.source_files = "Libraries/Image/*.{h,m}"
ss.preserve_paths = "Libraries/Image/*.js"
end
s.subspec 'RCTNetwork' do |ss|
ss.dependency 'React/Core'
ss.source_files = "Libraries/Network/*.{h,m}"
ss.preserve_paths = "Libraries/Network/*.js"
end
s.subspec 'RCTPushNotification' do |ss|
ss.dependency 'React/Core'
ss.source_files = "Libraries/PushNotificationIOS/*.{h,m}"
ss.preserve_paths = "Libraries/PushNotificationIOS/*.js"
end
s.subspec 'RCTWebSocketDebugger' do |ss|
ss.dependency 'React/Core'
ss.libraries = 'icucore'
ss.source_files = "Libraries/RCTWebSocketDebugger/*.{h,m}"
end
s.subspec 'RCTText' do |ss|
ss.dependency 'React/Core'
ss.source_files = "Libraries/Text/*.{h,m}"
ss.preserve_paths = "Libraries/Text/*.js"
end
s.subspec 'RCTVibration' do |ss|
ss.dependency 'React/Core'
ss.source_files = "Libraries/Vibration/*.{h,m}"
ss.preserve_paths = "Libraries/Vibration/*.js"
end

View File

@ -157,7 +157,7 @@ static dispatch_queue_t RCTFileQueue(void)
return RCTMakeAndLogError(@"Entries must be arrays of the form [key: string, value: string], got: ", entry, nil);
}
if (![entry[1] isKindOfClass:[NSString class]]) {
return RCTMakeAndLogError(@"Values must be strings, got: ", entry[1], entry[0]);
return RCTMakeAndLogError(@"Values must be strings, got: ", entry[1], @{@"key": entry[0]});
}
NSString *key = entry[0];
id errorOut = RCTErrorForKey(key);

View File

@ -507,7 +507,7 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
{
RCT_EXPORT();
id<RCTViewNodeProtocol> container = _viewRegistry[containerID];
id<RCTViewNodeProtocol> container = _shadowViewRegistry[containerID];
RCTAssert(container != nil, @"container view (for ID %@) not found", containerID);
NSUInteger subviewsCount = [[container reactSubviews] count];
@ -1051,7 +1051,21 @@ static void RCTMeasureLayout(RCTShadowView *view,
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){
UIView *view = viewRegistry[reactTag];
if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) {
[(id<RCTScrollableProtocol>)view scrollToOffset:CGPointMake([offsetX floatValue], [offsetY floatValue])];
[(id<RCTScrollableProtocol>)view scrollToOffset:CGPointMake([offsetX floatValue], [offsetY floatValue]) animated:YES];
} else {
RCTLogError(@"tried to scrollToOffset: on non-RCTScrollableProtocol view %@ with tag %@", view, reactTag);
}
}];
}
- (void)scrollWithoutAnimationToOffsetWithView:(NSNumber *)reactTag scrollToOffsetX:(NSNumber *)offsetX offsetY:(NSNumber *)offsetY
{
RCT_EXPORT(scrollWithoutAnimationTo);
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){
UIView *view = viewRegistry[reactTag];
if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) {
[(id<RCTScrollableProtocol>)view scrollToOffset:CGPointMake([offsetX floatValue], [offsetY floatValue]) animated:NO];
} else {
RCTLogError(@"tried to scrollToOffset: on non-RCTScrollableProtocol view %@ with tag %@", view, reactTag);
}

View File

@ -79,7 +79,7 @@ RCT_REMAP_VIEW_PROPERTY(testID, accessibilityIdentifier, NSString)
RCT_REMAP_VIEW_PROPERTY(opacity, alpha, CGFloat)
RCT_REMAP_VIEW_PROPERTY(shadowColor, layer.shadowColor, CGColor);
RCT_REMAP_VIEW_PROPERTY(shadowOffset, layer.shadowOffset, CGSize);
RCT_REMAP_VIEW_PROPERTY(shadowOpacity, layer.shadowOpacity, CGFloat)
RCT_REMAP_VIEW_PROPERTY(shadowOpacity, layer.shadowOpacity, float)
RCT_REMAP_VIEW_PROPERTY(shadowRadius, layer.shadowRadius, CGFloat)
RCT_REMAP_VIEW_PROPERTY(transformMatrix, layer.transform, CATransform3D)
RCT_CUSTOM_VIEW_PROPERTY(overflow, css_overflow, RCTView)

View File

@ -73,6 +73,11 @@
[_webView loadRequest:[NSURLRequest requestWithURL:URL]];
}
- (void)setHTML:(NSString *)HTML
{
[_webView loadHTMLString:HTML baseURL:nil];
}
- (void)layoutSubviews
{
[super layoutSubviews];

View File

@ -22,8 +22,9 @@
}
RCT_REMAP_VIEW_PROPERTY(url, URL, NSURL);
RCT_REMAP_VIEW_PROPERTY(html, HTML, NSString);
RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets);
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, UIEdgeInsets);
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL);
RCT_EXPORT_VIEW_PROPERTY(shouldInjectAJAXHandler, BOOL);
- (NSDictionary *)constantsToExport

View File

@ -1,6 +1,6 @@
{
"name": "react-native",
"version": "0.3.0",
"version": "0.3.1",
"description": "A framework for building native apps using React",
"repository": {
"type": "git",

View File

@ -66,7 +66,7 @@ ws.onopen = function() {
setStatus('Debugger session #' + sessionID + ' active');
ws.send(JSON.stringify({replyID: parseInt(sessionID, 10)}));
} else {
setStatus('Waiting for simulator');
setStatus('Waiting, press ⌘R in simulator to reload and connect');
}
}

View File

@ -14,6 +14,7 @@ jest
.dontMock('path')
.dontMock('absolute-path')
.dontMock('../docblock')
.dontMock('../../requirePattern')
.setMock('../../../ModuleDescriptor', function(data) {return data;});
describe('DependencyGraph', function() {

View File

@ -12,6 +12,7 @@ var ModuleDescriptor = require('../../ModuleDescriptor');
var q = require('q');
var fs = require('fs');
var docblock = require('./docblock');
var requirePattern = require('../requirePattern');
var path = require('path');
var isAbsolutePath = require('absolute-path');
var debug = require('debug')('DependecyGraph');
@ -600,7 +601,6 @@ DependecyGraph.prototype._processAssetChange = function(eventType, file) {
/**
* Extract all required modules from a `code` string.
*/
var requireRe = /\brequire\s*\(\s*[\'"]([^"\']+)["\']\s*\)/g;
var blockCommentRe = /\/\*(.|\n)*?\*\//g;
var lineCommentRe = /\/\/.+(\n|$)/g;
function extractRequires(code) {
@ -609,7 +609,7 @@ function extractRequires(code) {
code
.replace(blockCommentRe, '')
.replace(lineCommentRe, '')
.replace(requireRe, function(match, dep) {
.replace(requirePattern, function(match, _, dep) {
deps.push(dep);
});

View File

@ -10,6 +10,7 @@
jest.dontMock('../')
.dontMock('q')
.dontMock('../requirePattern')
.setMock('../../ModuleDescriptor', function(data) {return data;});
var q = require('q');
@ -226,11 +227,13 @@ describe('HasteDependencyResolver', function() {
});
var depGraph = depResolver._depGraph;
var dependencies = ['x', 'y', 'z'];
var dependencies = ['x', 'y', 'z', 'a', 'b'];
var code = [
'require("x")',
'require("y")',
'require( "z" )',
'require( "a")',
'require("b" )',
].join('\n');
depGraph.resolveDependency.mockImpl(function(fromModule, toModuleName) {
@ -255,7 +258,9 @@ describe('HasteDependencyResolver', function() {
' require, requireDynamic, requireLazy, module, exports) {' +
' require(\'changed\')',
'require(\'y\')',
'require("z")});',
'require("z")',
'require("a")',
'require("b")});',
].join('\n'));
});
});

View File

@ -9,8 +9,8 @@
'use strict';
var path = require('path');
var FileWatcher = require('../../FileWatcher');
var DependencyGraph = require('./DependencyGraph');
var requirePattern = require('./requirePattern');
var ModuleDescriptor = require('../ModuleDescriptor');
var declareOpts = require('../../lib/declareOpts');
@ -25,7 +25,6 @@ var DEFINE_MODULE_CODE = [
].join('');
var DEFINE_MODULE_REPLACE_RE = /_moduleName_|_code_|_deps_/g;
var REL_REQUIRE_STMT = /require\(['"]([\.\/0-9A-Z_$\-]*)['"]\)/gi;
var validateOpts = declareOpts({
projectRoots: {
@ -146,12 +145,12 @@ HasteDependencyResolver.prototype.wrapModule = function(module, code) {
}
var relativizedCode =
code.replace(REL_REQUIRE_STMT, function(codeMatch, depName) {
code.replace(requirePattern, function(codeMatch, _, depName) {
var depId = resolvedDeps[depName];
if (depId != null) {
return 'require(\'' + depId + '\')';
} else {
return codeMatch;
return codeMatch.replace(/\s+/g, '');
}
});

View File

@ -0,0 +1,14 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
var REQUIRE_RE = /\brequire\s*?\(\s*?([\'"])([^"\']+)\1\s*?\)/g;
module.exports = REQUIRE_RE;