Authored by 张丽霞

add files

Showing 66 changed files with 4629 additions and 0 deletions

Too many changes to show.

To preserve performance only 66 of 66+ files are displayed.

{
"rules": {
// This folder currently runs through babel and doesn't need to be
// compatible with node 4
"comma-dangle": 0,
"lint/extra-arrow-initializer": 0,
"no-alert": 0,
"no-console-disallow": 0
},
"env": {
"node": true
}
}
... ...
/**
* 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';
// beeper@1.1.0 has a return statement outside of a function
// and therefore doesn't parse. Let's mock it so that we can
// run the tests.
module.exports = function () {};
... ...
/**
* 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.
*
* @format
*/
'use strict';
const asyncify = require('async/asyncify');
const {EventEmitter} = require('events');
const {dirname} = require.requireActual('path');
const fs = jest.genMockFromModule('fs');
const invariant = require('fbjs/lib/invariant');
const path = require('path');
const stream = require.requireActual('stream');
const noop = () => {};
function asyncCallback(cb) {
return function() {
setImmediate(() => cb.apply(this, arguments));
};
}
const mtime = {
getTime: () => Math.ceil(Math.random() * 10000000),
};
fs.realpath.mockImplementation((filepath, callback) => {
callback = asyncCallback(callback);
let node;
try {
node = getToNode(filepath);
} catch (e) {
return callback(e);
}
if (node && typeof node === 'object' && node.SYMLINK != null) {
return callback(null, node.SYMLINK);
}
return callback(null, filepath);
});
fs.readdirSync.mockImplementation(filepath => Object.keys(getToNode(filepath)));
fs.readdir.mockImplementation((filepath, callback) => {
callback = asyncCallback(callback);
let node;
try {
node = getToNode(filepath);
if (node && typeof node === 'object' && node.SYMLINK != null) {
node = getToNode(node.SYMLINK);
}
} catch (e) {
return callback(e);
}
if (!(node && typeof node === 'object' && node.SYMLINK == null)) {
return callback(new Error(filepath + ' is not a directory.'));
}
return callback(null, Object.keys(node));
});
fs.readFile.mockImplementation(asyncify(fs.readFileSync));
fs.readFileSync.mockImplementation(function(filepath, encoding) {
filepath = path.normalize(filepath);
const node = getToNode(filepath);
if (isDirNode(node)) {
throw new Error('Error readFileSync a dir: ' + filepath);
}
if (Buffer.isBuffer(node) && typeof encoding !== 'undefined') {
return node.toString();
}
return node;
});
fs.writeFile.mockImplementation(asyncify(fs.writeFileSync));
fs.writeFileSync.mockImplementation((filePath, content, options) => {
filePath = path.normalize(filePath);
if (options == null || typeof options === 'string') {
options = {encoding: options};
}
invariant(
options.encoding == null || options.encoding === 'utf8',
'`options` argument supports only `null` or `"utf8"`',
);
const dirPath = path.dirname(filePath);
const node = getToNode(dirPath);
if (!isDirNode(node)) {
throw fsError('ENOTDIR', 'not a directory: ' + dirPath);
}
node[path.basename(filePath)] = content;
});
const openFds = new Map();
let nextFd = 3;
fs.openSync.mockImplementation((filePath, flags) => {
const dirPath = path.dirname(filePath);
const node = getToNode(dirPath);
if (!isDirNode(node)) {
throw fsError('ENOTDIR', 'not a directory: ' + dirPath);
}
node[path.basename(filePath)] = '';
openFds.set(nextFd, {filePath, flags, node});
return nextFd++;
});
fs.writeSync.mockImplementation((fd, str) => {
invariant(typeof str === 'string', 'only strings supported');
const data = openFds.get(fd);
if (data == null || data.flags !== 'w') {
throw fsError('EBADF', 'bad file descriptor, write');
}
data.node[path.basename(data.filePath)] += str;
});
fs.closeSync.mockImplementation(fd => {
openFds.delete(fd);
});
fs.mkdir.mockImplementation(asyncify(fs.mkdirSync));
fs.mkdirSync.mockImplementation((dirPath, mode) => {
const parentPath = path.dirname(dirPath);
const node = getToNode(parentPath);
if (!isDirNode(node)) {
throw fsError('ENOTDIR', 'not a directory: ' + parentPath);
}
if (node[path.basename(dirPath)] == null) {
node[path.basename(dirPath)] = {};
}
});
function fsError(code, message) {
const error = new Error(code + ': ' + message);
error.code = code;
return error;
}
function isDirNode(node) {
return (
node &&
typeof node === 'object' &&
node.SYMLINK == null &&
Buffer.isBuffer(node) === false
);
}
function readlinkSync(filepath) {
const node = getToNode(filepath);
if (node !== null && typeof node === 'object' && !!node.SYMLINK) {
return node.SYMLINK;
} else {
throw new Error(`EINVAL: invalid argument, readlink '${filepath}'`);
}
}
fs.readlink.mockImplementation((filepath, callback) => {
callback = asyncCallback(callback);
let result;
try {
result = readlinkSync(filepath);
} catch (e) {
callback(e);
return;
}
callback(null, result);
});
fs.readlinkSync.mockImplementation(readlinkSync);
function existsSync(filepath) {
try {
const node = getToNode(filepath);
return node !== null;
} catch (e) {
return false;
}
}
fs.exists.mockImplementation((filepath, callback) => {
callback = asyncCallback(callback);
let result;
try {
result = existsSync(filepath);
} catch (e) {
callback(e);
return;
}
callback(null, result);
});
fs.existsSync.mockImplementation(existsSync);
function makeStatResult(node) {
const isSymlink = node != null && node.SYMLINK != null;
return {
isBlockDevice: () => false,
isCharacterDevice: () => false,
isDirectory: () => node != null && typeof node === 'object' && !isSymlink,
isFIFO: () => false,
isFile: () => node != null && typeof node === 'string',
isSocket: () => false,
isSymbolicLink: () => isSymlink,
mtime,
};
}
function statSync(filepath) {
const node = getToNode(filepath);
if (node != null && node.SYMLINK) {
return statSync(node.SYMLINK);
}
return makeStatResult(node);
}
fs.stat.mockImplementation((filepath, callback) => {
callback = asyncCallback(callback);
let result;
try {
result = statSync(filepath);
} catch (e) {
callback(e);
return;
}
callback(null, result);
});
fs.statSync.mockImplementation(statSync);
function lstatSync(filepath) {
const node = getToNode(filepath);
return makeStatResult(node);
}
fs.lstat.mockImplementation((filepath, callback) => {
callback = asyncCallback(callback);
let result;
try {
result = lstatSync(filepath);
} catch (e) {
callback(e);
return;
}
callback(null, result);
});
fs.lstatSync.mockImplementation(lstatSync);
fs.open.mockImplementation(function(filepath) {
const callback = arguments[arguments.length - 1] || noop;
let data, error, fd;
try {
data = getToNode(filepath);
} catch (e) {
error = e;
}
if (error || data == null) {
error = Error(`ENOENT: no such file or directory: \`${filepath}\``);
}
if (data != null) {
/* global Buffer: true */
fd = {buffer: new Buffer(data, 'utf8'), position: 0};
}
callback(error, fd);
});
fs.read.mockImplementation(
(fd, buffer, writeOffset, length, position, callback = noop) => {
let bytesWritten;
try {
if (position == null || position < 0) {
({position} = fd);
}
bytesWritten = fd.buffer.copy(
buffer,
writeOffset,
position,
position + length,
);
fd.position = position + bytesWritten;
} catch (e) {
callback(Error('invalid argument'));
return;
}
callback(null, bytesWritten, buffer);
},
);
fs.close.mockImplementation((fd, callback = noop) => {
try {
fd.buffer = fs.position = undefined;
} catch (e) {
callback(Error('invalid argument'));
return;
}
callback(null);
});
let filesystem = {};
fs.mock = {
clear() {
filesystem = {};
},
};
fs.createReadStream.mockImplementation(filepath => {
if (!filepath.startsWith('/')) {
throw Error('Cannot open file ' + filepath);
}
const parts = filepath.split('/').slice(1);
let file = filesystem;
for (const part of parts) {
file = file[part];
if (!file) {
break;
}
}
if (typeof file !== 'string') {
throw Error('Cannot open file ' + filepath);
}
return new stream.Readable({
read() {
this.push(file, 'utf8');
this.push(null);
},
});
});
fs.createWriteStream.mockImplementation(filePath => {
let node;
const writeStream = new stream.Writable({
write(chunk, encoding, callback) {
this.__chunks.push(chunk);
node[path.basename(filePath)] = this.__chunks.join('');
callback();
},
});
writeStream.__file = filePath;
writeStream.__chunks = [];
writeStream.end = jest.fn(writeStream.end);
fs.createWriteStream.mock.returned.push(writeStream);
try {
const dirPath = dirname(filePath);
node = getToNode(dirPath);
if (!isDirNode(node)) {
throw fsError('ENOTDIR', 'not a directory: ' + dirPath);
}
// Truncate the file on opening.
node[path.basename(filePath)] = '';
} catch (error) {
process.nextTick(() => writeStream.emit('error', error));
}
return writeStream;
});
fs.createWriteStream.mock.returned = [];
fs.__setMockFilesystem = object => (filesystem = object);
const watcherListByPath = new Map();
fs.watch.mockImplementation((filename, options, listener) => {
if (options.recursive) {
throw new Error('recursive watch not implemented');
}
let watcherList = watcherListByPath.get(filename);
if (watcherList == null) {
watcherList = [];
watcherListByPath.set(filename, watcherList);
}
const fsWatcher = new EventEmitter();
fsWatcher.on('change', listener);
fsWatcher.close = () => {
watcherList.splice(watcherList.indexOf(fsWatcher), 1);
fsWatcher.close = () => {
throw new Error('FSWatcher is already closed');
};
};
watcherList.push(fsWatcher);
});
fs.__triggerWatchEvent = (eventType, filename) => {
const directWatchers = watcherListByPath.get(filename) || [];
directWatchers.forEach(wtc => wtc.emit('change', eventType));
const dirPath = path.dirname(filename);
const dirWatchers = watcherListByPath.get(dirPath) || [];
dirWatchers.forEach(wtc =>
wtc.emit('change', eventType, path.relative(dirPath, filename)),
);
};
function getToNode(filepath) {
// Ignore the drive for Windows paths.
if (filepath.match(/^[a-zA-Z]:\\/)) {
filepath = filepath.substring(2);
}
if (filepath.endsWith(path.sep)) {
filepath = filepath.slice(0, -1);
}
const parts = filepath.split(/[\/\\]/);
if (parts[0] !== '') {
throw new Error('Make sure all paths are absolute.');
}
let node = filesystem;
parts.slice(1).forEach(part => {
if (node && node.SYMLINK) {
node = getToNode(node.SYMLINK);
}
node = node[part];
if (node == null) {
const err = new Error(
`ENOENT: no such file or directory: \`${filepath}\``,
);
err.code = 'ENOENT';
throw err;
}
});
return node;
}
module.exports = fs;
... ...
/**
* 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.
*
* @emails oncall+javascript_foundation
* @flow
* @format
*/
'use strict';
declare var jest: any;
declare var describe: any;
declare var beforeEach: any;
declare var expect: any;
declare var it: any;
jest.mock('fs');
const fs = require('fs');
describe('fs mock', () => {
beforeEach(() => {
(fs: $FlowFixMe).mock.clear();
});
describe('writeFileSync()', () => {
it('stores content correctly', () => {
fs.writeFileSync('/test', 'foobar', 'utf8');
const content = fs.readFileSync('/test', 'utf8');
/* $FlowFixMe(>=0.56.0 site=react_native_oss) This comment suppresses an
* error found when Flow v0.56 was deployed. To see the error delete this
* comment and run Flow. */
expect(content).toEqual('foobar');
});
it('fails on missing path', () => {
/* $FlowFixMe(>=0.56.0 site=react_native_oss) This comment suppresses an
* error found when Flow v0.56 was deployed. To see the error delete this
* comment and run Flow. */
expect(() =>
fs.writeFileSync('/dir/test', 'foobar', 'utf8'),
).toThrowError('ENOENT: no such file or directory');
});
it('properly normalizes paths', () => {
fs.writeFileSync('/test/foo/../bar/../../tadam', 'beep', 'utf8');
const content = fs.readFileSync('/glo/../tadam', 'utf8');
expect(content).toEqual('beep');
});
});
describe('mkdirSync()', () => {
it('creates folders that we can write files in', () => {
fs.mkdirSync('/dir', 0o777);
fs.writeFileSync('/dir/test', 'foobar', 'utf8');
const content = fs.readFileSync('/dir/test', 'utf8');
/* $FlowFixMe(>=0.56.0 site=react_native_oss) This comment suppresses an
* error found when Flow v0.56 was deployed. To see the error delete this
* comment and run Flow. */
expect(content).toEqual('foobar');
});
it('does not erase directories', () => {
fs.mkdirSync('/dir', 0o777);
fs.writeFileSync('/dir/test', 'foobar', 'utf8');
fs.mkdirSync('/dir', 0o777);
const content = fs.readFileSync('/dir/test', 'utf8');
/* $FlowFixMe(>=0.56.0 site=react_native_oss) This comment suppresses an
* error found when Flow v0.56 was deployed. To see the error delete this
* comment and run Flow. */
expect(content).toEqual('foobar');
});
});
describe('createWriteStream()', () => {
it('writes content', done => {
const stream = fs.createWriteStream('/test');
stream.write('hello, ');
stream.write('world');
stream.end('!');
process.nextTick(() => {
const content = fs.readFileSync('/test', 'utf8');
expect(content).toEqual('hello, world!');
done();
});
});
});
describe('writeSync()', () => {
it('writes content', () => {
const fd = fs.openSync('/test', 'w');
fs.writeSync(fd, 'hello, world!');
fs.closeSync(fd);
const content = fs.readFileSync('/test', 'utf8');
expect(content).toEqual('hello, world!');
});
});
});
... ...
/**
* 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';
function sign(source) {
return source;
}
module.exports = sign;
... ...
/**
* 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.
*
* @emails oncall+javascript_foundation
*/
'use strict';
jest
.dontMock('../filterPlatformAssetScales')
.dontMock('../assetPathUtils');
const filterPlatformAssetScales = require('../filterPlatformAssetScales');
describe('filterPlatformAssetScales', () => {
it('removes everything but 2x and 3x for iOS', () => {
expect(filterPlatformAssetScales('ios', [1, 1.5, 2, 3, 4])).toEqual([1, 2, 3]);
expect(filterPlatformAssetScales('ios', [3, 4])).toEqual([3]);
});
it('keeps closest largest one if nothing matches', () => {
expect(filterPlatformAssetScales('ios', [0.5, 4, 100])).toEqual([4]);
expect(filterPlatformAssetScales('ios', [0.5, 100])).toEqual([100]);
expect(filterPlatformAssetScales('ios', [0.5])).toEqual([0.5]);
expect(filterPlatformAssetScales('ios', [])).toEqual([]);
});
it('keeps all scales for unknown platform', () => {
expect(filterPlatformAssetScales('freebsd', [1, 1.5, 2, 3.7])).toEqual([1, 1.5, 2, 3.7]);
});
});
... ...
/**
* 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.
*
* @emails oncall+javascript_foundation
*/
'use strict';
jest
.dontMock('../getAssetDestPathAndroid')
.dontMock('../assetPathUtils');
const getAssetDestPathAndroid = require('../getAssetDestPathAndroid');
describe('getAssetDestPathAndroid', () => {
it('should use the right destination folder', () => {
const asset = {
name: 'icon',
type: 'png',
httpServerLocation: '/assets/test',
};
const expectDestPathForScaleToStartWith = (scale, path) => {
if (!getAssetDestPathAndroid(asset, scale).startsWith(path)) {
throw new Error(`asset for scale ${scale} should start with path '${path}'`);
}
};
expectDestPathForScaleToStartWith(1, 'drawable-mdpi');
expectDestPathForScaleToStartWith(1.5, 'drawable-hdpi');
expectDestPathForScaleToStartWith(2, 'drawable-xhdpi');
expectDestPathForScaleToStartWith(3, 'drawable-xxhdpi');
expectDestPathForScaleToStartWith(4, 'drawable-xxxhdpi');
});
it('should lowercase path', () => {
const asset = {
name: 'Icon',
type: 'png',
httpServerLocation: '/assets/App/Test',
};
expect(getAssetDestPathAndroid(asset, 1)).toBe(
'drawable-mdpi/app_test_icon.png'
);
});
it('should remove `assets/` prefix', () => {
const asset = {
name: 'icon',
type: 'png',
httpServerLocation: '/assets/RKJSModules/Apps/AndroidSample/Assets',
};
expect(
getAssetDestPathAndroid(asset, 1).startsWith('assets_')
).toBeFalsy();
});
it('should put non-drawable resources to `raw/`', () => {
const asset = {
name: 'video',
type: 'mp4',
httpServerLocation: '/assets/app/test',
};
expect(getAssetDestPathAndroid(asset, 1)).toBe(
'raw/app_test_video.mp4'
);
});
});
... ...
/**
* 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.
*
* @emails oncall+javascript_foundation
*/
'use strict';
jest.dontMock('../getAssetDestPathIOS');
const getAssetDestPathIOS = require('../getAssetDestPathIOS');
describe('getAssetDestPathIOS', () => {
it('should build correct path', () => {
const asset = {
name: 'icon',
type: 'png',
httpServerLocation: '/assets/test',
};
expect(getAssetDestPathIOS(asset, 1)).toBe('assets/test/icon.png');
});
it('should consider scale', () => {
const asset = {
name: 'icon',
type: 'png',
httpServerLocation: '/assets/test',
};
expect(getAssetDestPathIOS(asset, 2)).toBe('assets/test/icon@2x.png');
expect(getAssetDestPathIOS(asset, 3)).toBe('assets/test/icon@3x.png');
});
});
... ...
/**
* 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.
*
* @flow
*/
'use strict';
import type {PackagerAsset} from '../../Libraries/Image/AssetRegistry';
/**
* FIXME: using number to represent discrete scale numbers is fragile in essence because of
* floating point numbers imprecision.
*/
function getAndroidAssetSuffix(scale: number): string {
switch (scale) {
case 0.75: return 'ldpi';
case 1: return 'mdpi';
case 1.5: return 'hdpi';
case 2: return 'xhdpi';
case 3: return 'xxhdpi';
case 4: return 'xxxhdpi';
}
throw new Error('no such scale');
}
// See https://developer.android.com/guide/topics/resources/drawable-resource.html
const drawableFileTypes = new Set([
'gif',
'jpeg',
'jpg',
'png',
'svg',
'webp',
'xml',
]);
function getAndroidResourceFolderName(asset: PackagerAsset, scale: number) {
if (!drawableFileTypes.has(asset.type)) {
return 'raw';
}
var suffix = getAndroidAssetSuffix(scale);
if (!suffix) {
throw new Error(
'Don\'t know which android drawable suffix to use for asset: ' +
JSON.stringify(asset)
);
}
const androidFolder = 'drawable-' + suffix;
return androidFolder;
}
function getAndroidResourceIdentifier(asset: PackagerAsset) {
var folderPath = getBasePath(asset);
return (folderPath + '/' + asset.name)
.toLowerCase()
.replace(/\//g, '_') // Encode folder structure in file name
.replace(/([^a-z0-9_])/g, '') // Remove illegal chars
.replace(/^assets_/, ''); // Remove "assets_" prefix
}
function getBasePath(asset: PackagerAsset) {
var basePath = asset.httpServerLocation;
if (basePath[0] === '/') {
basePath = basePath.substr(1);
}
return basePath;
}
module.exports = {
getAndroidAssetSuffix: getAndroidAssetSuffix,
getAndroidResourceFolderName: getAndroidResourceFolderName,
getAndroidResourceIdentifier: getAndroidResourceIdentifier,
getBasePath: getBasePath
};
... ...
/**
* 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.
*
* @flow
*/
'use strict';
const log = require('../util/log').out('bundle');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const Server = require('metro/src/Server');
const {Terminal} = require('metro-core');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const TerminalReporter = require('metro/src/lib/TerminalReporter');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const TransformCaching = require('metro/src/lib/TransformCaching');
const {defaults} = require('metro');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const outputBundle = require('metro/src/shared/output/bundle');
const path = require('path');
const saveAssets = require('./saveAssets');
const {ASSET_REGISTRY_PATH} = require('../core/Constants');
import type {RequestOptions, OutputOptions} from './types.flow';
import type {ConfigT} from 'metro';
const defaultAssetExts = defaults.assetExts;
const defaultSourceExts = defaults.sourceExts;
const defaultPlatforms = defaults.platforms;
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const defaultProvidesModuleNodeModules = defaults.providesModuleNodeModules;
async function buildBundle(
args: OutputOptions & {
assetsDest: mixed,
entryFile: string,
maxWorkers: number,
resetCache: boolean,
transformer: string,
minify: boolean,
},
config: ConfigT,
output = outputBundle,
) {
// This is used by a bazillion of npm modules we don't control so we don't
// have other choice than defining it as an env variable here.
process.env.NODE_ENV = args.dev ? 'development' : 'production';
let sourceMapUrl = args.sourcemapOutput;
if (sourceMapUrl && !args.sourcemapUseAbsolutePath) {
sourceMapUrl = path.basename(sourceMapUrl);
}
const requestOpts: RequestOptions = {
entryFile: args.entryFile,
sourceMapUrl,
dev: args.dev,
minify: args.minify !== undefined ? args.minify : !args.dev,
platform: args.platform,
};
const assetExts = (config.getAssetExts && config.getAssetExts()) || [];
const sourceExts = (config.getSourceExts && config.getSourceExts()) || [];
const platforms = (config.getPlatforms && config.getPlatforms()) || [];
const transformModulePath = args.transformer
? path.resolve(args.transformer)
: config.getTransformModulePath();
const providesModuleNodeModules =
typeof config.getProvidesModuleNodeModules === 'function'
? config.getProvidesModuleNodeModules()
: defaultProvidesModuleNodeModules;
const terminal = new Terminal(process.stdout);
const server = new Server({
assetExts: defaultAssetExts.concat(assetExts),
assetRegistryPath: ASSET_REGISTRY_PATH,
blacklistRE: config.getBlacklistRE(),
dynamicDepsInPackages: config.dynamicDepsInPackages,
extraNodeModules: config.extraNodeModules,
getModulesRunBeforeMainModule: config.getModulesRunBeforeMainModule,
getPolyfills: config.getPolyfills,
getTransformOptions: config.getTransformOptions,
globalTransformCache: null,
hasteImplModulePath: config.hasteImplModulePath,
maxWorkers: args.maxWorkers,
platforms: defaultPlatforms.concat(platforms),
postMinifyProcess: config.postMinifyProcess,
postProcessModules: config.postProcessModules,
postProcessBundleSourcemap: config.postProcessBundleSourcemap,
projectRoots: config.getProjectRoots(),
providesModuleNodeModules: providesModuleNodeModules,
resetCache: args.resetCache,
reporter: new TerminalReporter(terminal),
sourceExts: defaultSourceExts.concat(sourceExts),
transformCache: TransformCaching.useTempDir(),
transformModulePath: transformModulePath,
watch: false,
workerPath: config.getWorkerPath && config.getWorkerPath(),
});
const bundle = await output.build(server, requestOpts);
await output.save(bundle, args, log);
// Save the assets of the bundle
const outputAssets = await server.getAssets({
...Server.DEFAULT_BUNDLE_OPTIONS,
...requestOpts,
bundleType: 'todo',
});
// When we're done saving bundle output and the assets, we're done.
const assets = await saveAssets(
outputAssets,
args.platform,
args.assetsDest,
);
server.end();
return assets;
}
module.exports = buildBundle;
... ...
/**
* 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';
const buildBundle = require('./buildBundle');
const bundleCommandLineArgs = require('./bundleCommandLineArgs');
const outputBundle = require('metro/src/shared/output/bundle');
/**
* Builds the bundle starting to look for dependencies at the given entry path.
*/
function bundleWithOutput(argv, config, args, output) {
if (!output) {
output = outputBundle;
}
return buildBundle(args, config, output);
}
module.exports = {
name: 'bundle',
description: 'builds the javascript bundle for offline use',
func: bundleWithOutput,
options: bundleCommandLineArgs,
// not used by the CLI itself
withOutput: bundleWithOutput,
};
... ...
/**
* 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';
module.exports = [
{
command: '--entry-file <path>',
description: 'Path to the root JS file, either absolute or relative to JS root',
}, {
command: '--platform [string]',
description: 'Either "ios" or "android"',
default: 'ios',
}, {
command: '--transformer [string]',
description: 'Specify a custom transformer to be used',
}, {
command: '--dev [boolean]',
description: 'If false, warnings are disabled and the bundle is minified',
parse: (val) => val === 'false' ? false : true,
default: true,
}, {
command: '--minify [boolean]',
description: 'Allows overriding whether bundle is minified. This defaults to ' +
'false if dev is true, and true if dev is false. Disabling minification ' +
'can be useful for speeding up production builds for testing purposes.',
parse: (val) => val === 'false' ? false : true,
}, {
command: '--bundle-output <string>',
description: 'File name where to store the resulting bundle, ex. /tmp/groups.bundle',
}, {
command: '--bundle-encoding [string]',
description: 'Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer).',
default: 'utf8',
}, {
command: '--max-workers [number]',
description: 'Specifies the maximum number of workers the worker-pool ' +
'will spawn for transforming files. This defaults to the number of the ' +
'cores available on your machine.',
parse: (workers: string) => Number(workers),
}, {
command: '--sourcemap-output [string]',
description: 'File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map',
}, {
command: '--sourcemap-sources-root [string]',
description: 'Path to make sourcemap\'s sources entries relative to, ex. /root/dir',
}, {
command: '--sourcemap-use-absolute-path',
description: 'Report SourceMapURL using its full path',
default: false,
}, {
command: '--assets-dest [string]',
description: 'Directory name where to store assets referenced in the bundle',
}, {
command: '--verbose',
description: 'Enables logging',
default: false,
}, {
command: '--reset-cache',
description: 'Removes cached files',
default: false,
}, {
command: '--read-global-cache',
description: 'Try to fetch transformed JS code from the global cache, if configured.',
default: false,
},
];
... ...
/**
* 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.
*
* @flow
* @format
*/
'use strict';
const ALLOWED_SCALES = {
ios: [1, 2, 3],
};
function filterPlatformAssetScales(
platform: string,
scales: $ReadOnlyArray<number>,
): $ReadOnlyArray<number> {
const whitelist = ALLOWED_SCALES[platform];
if (!whitelist) {
return scales;
}
const result = scales.filter(scale => whitelist.indexOf(scale) > -1);
if (result.length === 0 && scales.length > 0) {
// No matching scale found, but there are some available. Ideally we don't
// want to be in this situation and should throw, but for now as a fallback
// let's just use the closest larger image
const maxScale = whitelist[whitelist.length - 1];
for (const scale of scales) {
if (scale > maxScale) {
result.push(scale);
break;
}
}
// There is no larger scales available, use the largest we have
if (result.length === 0) {
result.push(scales[scales.length - 1]);
}
}
return result;
}
module.exports = filterPlatformAssetScales;
... ...
/**
* 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.
*
* @flow
*/
'use strict';
const assetPathUtils = require('./assetPathUtils');
const path = require('path');
import type {PackagerAsset} from '../../Libraries/Image/AssetRegistry';
function getAssetDestPathAndroid(asset: PackagerAsset, scale: number): string {
const androidFolder = assetPathUtils.getAndroidResourceFolderName(asset, scale);
const fileName = assetPathUtils.getAndroidResourceIdentifier(asset);
return path.join(androidFolder, fileName + '.' + asset.type);
}
module.exports = getAssetDestPathAndroid;
... ...
/**
* 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.
*
* @flow
*/
'use strict';
const path = require('path');
import type {PackagerAsset} from '../../Libraries/Image/AssetRegistry';
function getAssetDestPathIOS(asset: PackagerAsset, scale: number): string {
const suffix = scale === 1 ? '' : '@' + scale + 'x';
const fileName = asset.name + suffix + '.' + asset.type;
return path.join(asset.httpServerLocation.substr(1), fileName);
}
module.exports = getAssetDestPathIOS;
... ...
/**
* 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';
const filterPlatformAssetScales = require('./filterPlatformAssetScales');
const fs = require('fs');
const getAssetDestPathAndroid = require('./getAssetDestPathAndroid');
const getAssetDestPathIOS = require('./getAssetDestPathIOS');
const log = require('../util/log').out('bundle');
const mkdirp = require('mkdirp');
const path = require('path');
function saveAssets(
assets,
platform,
assetsDest
) {
if (!assetsDest) {
console.warn('Assets destination folder is not set, skipping...');
return Promise.resolve();
}
const getAssetDestPath = platform === 'android'
? getAssetDestPathAndroid
: getAssetDestPathIOS;
const filesToCopy = Object.create(null); // Map src -> dest
assets
.forEach(asset => {
const validScales = new Set(filterPlatformAssetScales(platform, asset.scales));
asset.scales.forEach((scale, idx) => {
if (!validScales.has(scale)) {
return;
}
const src = asset.files[idx];
const dest = path.join(assetsDest, getAssetDestPath(asset, scale));
filesToCopy[src] = dest;
});
});
return copyAll(filesToCopy);
}
function copyAll(filesToCopy) {
const queue = Object.keys(filesToCopy);
if (queue.length === 0) {
return Promise.resolve();
}
log('Copying ' + queue.length + ' asset files');
return new Promise((resolve, reject) => {
const copyNext = (error) => {
if (error) {
return reject(error);
}
if (queue.length === 0) {
log('Done copying assets');
resolve();
} else {
const src = queue.shift();
const dest = filesToCopy[src];
copy(src, dest, copyNext);
}
};
copyNext();
});
}
function copy(src, dest, callback) {
const destDir = path.dirname(dest);
mkdirp(destDir, err => {
if (err) {
return callback(err);
}
fs.createReadStream(src)
.pipe(fs.createWriteStream(dest))
.on('finish', callback);
});
}
module.exports = saveAssets;
... ...
/**
* 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.
*
* @flow
*/
'use strict';
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
export type {OutputOptions, RequestOptions} from 'metro/src/shared/types.flow';
... ...
/**
* 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';
const bundleWithOutput = require('./bundle').withOutput;
const bundleCommandLineArgs = require('./bundleCommandLineArgs');
const outputUnbundle = require('metro/src/shared/output/unbundle');
/**
* Builds the bundle starting to look for dependencies at the given entry path.
*/
function unbundle(argv, config, args) {
return bundleWithOutput(argv, config, args, outputUnbundle);
}
module.exports = {
name: 'unbundle',
description: 'builds javascript as "unbundle" for offline use',
func: unbundle,
options: bundleCommandLineArgs.concat({
command: '--indexed-unbundle',
description: 'Force indexed unbundle file format, even when building for android',
default: false,
}),
};
... ...
/**
* 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';
// gracefulify() has to be called before anything else runs
require('graceful-fs').gracefulify(require('fs'));
// This file must be able to run in node 0.12 without babel so we can show that
// it is not supported. This is why the rest of the cli code is in `cliEntry.js`.
require('./server/checkNodeVersion')();
require('../setupBabel')();
var cliEntry = require('./cliEntry');
if (require.main === module) {
cliEntry.run();
}
module.exports = cliEntry;
... ...
/**
* 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.
*
* @flow
*/
'use strict';
const config = require('./core');
const assertRequiredOptions = require('./util/assertRequiredOptions');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const chalk = require('chalk');
const childProcess = require('child_process');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const commander = require('commander');
const commands = require('./commands');
const init = require('./init/init');
const path = require('path');
const pkg = require('../package.json');
import type {CommandT} from './commands';
import type {RNConfig} from './core';
commander.version(pkg.version);
const defaultOptParser = (val) => val;
const handleError = (err) => {
console.error();
console.error(err.message || err);
console.error();
process.exit(1);
};
// Custom printHelpInformation command inspired by internal Commander.js
// one modified to suit our needs
function printHelpInformation() {
let cmdName = this._name;
if (this._alias) {
cmdName = cmdName + '|' + this._alias;
}
const sourceInformation = this.pkg
? [
` ${chalk.bold('Source:')} ${this.pkg.name}@${this.pkg.version}`,
'',
]
: [];
let output = [
'',
chalk.bold(chalk.cyan((` react-native ${cmdName} ${this.usage()}`))),
` ${this._description}`,
'',
...sourceInformation,
` ${chalk.bold('Options:')}`,
'',
this.optionHelp().replace(/^/gm, ' '),
'',
];
if (this.examples && this.examples.length > 0) {
const formattedUsage = this.examples.map(
example => ` ${example.desc}: \n ${chalk.cyan(example.cmd)}`,
).join('\n\n');
output = output.concat([
chalk.bold(' Example usage:'),
'',
formattedUsage,
]);
}
return output.concat([
'',
'',
]).join('\n');
}
function printUnknownCommand(cmdName) {
console.log([
'',
cmdName
? chalk.red(` Unrecognized command '${cmdName}'`)
: chalk.red(' You didn\'t pass any command'),
` Run ${chalk.cyan('react-native --help')} to see list of all available commands`,
'',
].join('\n'));
}
const addCommand = (command: CommandT, cfg: RNConfig) => {
const options = command.options || [];
const cmd = commander
.command(command.name, undefined, {
noHelp: !command.description,
})
.description(command.description)
.action(function runAction() {
const passedOptions = this.opts();
const argv: Array<string> = Array.from(arguments).slice(0, -1);
Promise.resolve()
.then(() => {
assertRequiredOptions(options, passedOptions);
return command.func(argv, cfg, passedOptions);
})
.catch(handleError);
});
cmd.helpInformation = printHelpInformation.bind(cmd);
cmd.examples = command.examples;
cmd.pkg = command.pkg;
options
.forEach(opt => cmd.option(
opt.command,
opt.description,
opt.parse || defaultOptParser,
typeof opt.default === 'function' ? opt.default(cfg) : opt.default,
));
// Placeholder option for --config, which is parsed before any other option,
// but needs to be here to avoid "unknown option" errors when specified
cmd.option('--config [string]', 'Path to the CLI configuration file');
};
function run() {
const setupEnvScript = /^win/.test(process.platform)
? 'setup_env.bat'
: 'setup_env.sh';
childProcess.execFileSync(path.join(__dirname, setupEnvScript));
commands.forEach(cmd => addCommand(cmd, config));
commander.parse(process.argv);
const isValidCommand = commands.find(cmd => cmd.name.split(' ')[0] === process.argv[2]);
if (!isValidCommand) {
printUnknownCommand(process.argv[2]);
return;
}
if (!commander.args.length) {
commander.help();
}
}
module.exports = {
run: run,
init: init,
};
... ...
/**
* 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.
*
* @flow
*/
'use strict';
const { getProjectCommands } = require('./core');
import type { RNConfig } from './core';
export type CommandT = {
name: string,
description?: string,
usage?: string,
func: (argv: Array<string>, config: RNConfig, args: Object) => ?Promise<void>,
options?: Array<{
command: string,
description?: string,
parse?: (val: string) => any,
default?: ((config: RNConfig) => mixed) | mixed,
}>,
examples?: Array<{
desc: string,
cmd: string,
}>,
pkg?: {
version: string,
name: string,
},
};
const documentedCommands = [
require('./server/server'),
require('./runIOS/runIOS'),
require('./runAndroid/runAndroid'),
require('./library/library'),
require('./bundle/bundle'),
require('./bundle/unbundle'),
require('./eject/eject'),
require('./link/link'),
require('./link/unlink'),
require('./install/install'),
require('./install/uninstall'),
require('./upgrade/upgrade'),
require('./logAndroid/logAndroid'),
require('./logIOS/logIOS'),
require('./dependencies/dependencies'),
require('./info/info'),
];
// The user should never get here because projects are inited by
// using `react-native-cli` from outside a project directory.
const undocumentedCommands = [
{
name: 'init',
func: () => {
console.log([
'Looks like React Native project already exists in the current',
'folder. Run this command from a different folder or remove node_modules/react-native',
].join('\n'));
},
},
];
const commands: Array<CommandT> = [
...documentedCommands,
...undocumentedCommands,
...getProjectCommands(),
];
module.exports = commands;
... ...
/**
* Copyright (c) 2016-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.
*
* @flow
* @format
*/
'use strict';
const ASSET_REGISTRY_PATH = 'react-native/Libraries/Image/AssetRegistry';
const ASSET_SOURCE_RESOLVER_PATH =
'react-native/Libraries/Image/AssetSourceResolver';
module.exports = {
ASSET_REGISTRY_PATH,
ASSET_SOURCE_RESOLVER_PATH,
};
... ...
const fs = require.requireActual('fs');
const path = require('path');
const manifest = fs.readFileSync(path.join(__dirname, './files/AndroidManifest.xml'));
const mainJavaClass = fs.readFileSync(path.join(__dirname, './files/Main.java'));
function generateValidFileStructure(classFileName) {
return {
src: {
'AndroidManifest.xml': manifest,
main: {
com: {
some: {
example: {
'Main.java': mainJavaClass,
[classFileName]: fs.readFileSync(path.join(__dirname, `./files/${classFileName}`)),
},
},
},
},
},
};
}
exports.valid = generateValidFileStructure('ReactPackage.java');
exports.validKotlin = generateValidFileStructure('ReactPackage.kt');
exports.userConfigManifest = {
src: {
main: {
'AndroidManifest.xml': manifest,
com: {
some: {
example: {
'Main.java': mainJavaClass,
'ReactPackage.java': fs.readFileSync(path.join(__dirname, './files/ReactPackage.java')),
},
},
},
},
debug: {
'AndroidManifest.xml': fs.readFileSync(path.join(__dirname, './files/AndroidManifest-debug.xml')),
},
},
};
exports.corrupted = {
src: {
'AndroidManifest.xml': manifest,
main: {
com: {
some: {
example: {},
},
},
},
},
};
exports.noPackage = {
src: {
'AndroidManifest.xml': manifest,
main: {
com: {
some: {
example: {
'Main.java': mainJavaClass,
},
},
},
},
},
};
... ...
exports.single = {
func: () => {},
description: 'Test action',
name: 'test',
};
exports.multiple = [{
func: () => {},
description: 'Test action #1',
name: 'test1',
}, {
func: () => {},
description: 'Test action #2',
name: 'test2',
}];
... ...
const fs = require.requireActual('fs');
const path = require('path');
const android = require('./android');
const pjson = fs.readFileSync(path.join(__dirname, 'files', 'package.json'));
module.exports = {
valid: {
'package.json': pjson,
android: android.valid,
},
withAssets: {
'package.json': pjson,
android: android.valid,
fonts: {
'A.ttf': '',
'B.ttf': '',
},
images: {
'C.jpg': '',
},
},
noPackage: {
'package.json': pjson,
android: android.noPackage,
},
};
... ...
<manifest
xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
... ...
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.some.example">
</manifest>
... ...
package com.some.example;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SomeExamplePackage {}
... ...
package com.some.example;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SomeExampleJavaPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new SomeExampleModule(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
... ...
package com.some.example;
import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager
import java.util.*
class SomeExampleKotlinPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule>
= mutableListOf(MaterialPaletteModule(reactContext))
override fun createViewManagers(reactContext: ReactApplicationContext?):
MutableList<ViewManager<View, ReactShadowNode>> = Collections.emptyList()
}
... ...
{
"name": "react-native-vector-icons",
"version": "1.0.0",
"description": "Customizable Icons for React Native with support for NavBar/TabBar, image source and full styling. Choose from 3000+ bundled icons or use your own.",
"main": "index.js",
"bin": {
"generate-icon": "./generate-icon.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rm -rf {Fonts,Entypo.js,EvilIcons.js,FontAwesome.js,Foundation.js,Ionicons.js,MaterialIcons.js,Octicons.js,Zocial.js} && mkdir Fonts && npm run build-entypo && npm run build-evilicons && npm run build-fontawesome && npm run build-foundation && npm run build-ionicons && npm run build-materialicons && npm run build-octicons && npm run build-zocial",
"build-entypo": "mkdir -p tmp/svg && curl https://dl.dropboxusercontent.com/u/4339492/entypo.zip > tmp/entypo.zip && unzip -j tmp/entypo.zip *.svg -x __MACOSX/* -d tmp/svg && fontcustom compile tmp/svg -o tmp -n Entypo -t css -h && node generate-icon tmp/Entypo.css --componentName=Entypo --fontFamily=Entypo > Entypo.js && cp tmp/Entypo.ttf Fonts && rm -rf {tmp,.fontcustom-manifest.json}",
"build-evilicons": "fontcustom compile node_modules/evil-icons/assets/icons -o tmp -n EvilIcons -t css -h && node generate-icon tmp/EvilIcons.css --prefix=.icon-ei- --componentName=EvilIcons --fontFamily=EvilIcons > EvilIcons.js && cp tmp/EvilIcons.ttf Fonts && rm -rf {tmp,.fontcustom-manifest.json}",
"build-fontawesome": "node generate-icon node_modules/font-awesome/css/font-awesome.css --prefix=.fa- --componentName=FontAwesome --fontFamily=FontAwesome > FontAwesome.js && cp node_modules/font-awesome/fonts/fontawesome-webfont.ttf Fonts/FontAwesome.ttf",
"build-foundation": "node generate-icon bower_components/foundation-icon-fonts/foundation-icons.css --prefix=.fi- --componentName=Foundation --fontFamily=fontcustom > Foundation.js && cp bower_components/foundation-icon-fonts/foundation-icons.ttf Fonts/Foundation.ttf",
"build-ionicons": "node generate-icon bower_components/ionicons/css/ionicons.css --prefix=.ion- --componentName=Ionicons --fontFamily=Ionicons > Ionicons.js && cp bower_components/ionicons/fonts/ionicons.ttf Fonts/Ionicons.ttf",
"build-materialicons": "mkdir -p tmp/svg && for f in ./node_modules/material-design-icons/*/svg/production/ic_*_48px.svg; do t=${f/*\\/ic_/}; t=${t/_48px/}; cp \"$f\" \"./tmp/svg/${t//_/-}\"; done && fontcustom compile tmp/svg -o tmp -n MaterialIcons -t css -h && node generate-icon tmp/MaterialIcons.css --componentName=MaterialIcons --fontFamily=MaterialIcons > MaterialIcons.js && cp tmp/MaterialIcons.ttf Fonts && rm -rf {tmp,.fontcustom-manifest.json}",
"build-octicons": "node generate-icon bower_components/octicons/octicons/octicons.css --prefix=.octicon- --componentName=Octicons --fontFamily=octicons > Octicons.js && cp bower_components/octicons/octicons/octicons.ttf Fonts/Octicons.ttf",
"build-zocial": "node generate-icon bower_components/css-social-buttons/css/zocial.css --prefix=.zocial. --componentName=Zocial --fontFamily=zocial > Zocial.js && cp bower_components/css-social-buttons/css/zocial.ttf Fonts/Zocial.ttf"
},
"keywords": [
"react-native",
"react-component",
"react-native-component",
"react",
"mobile",
"ios",
"android",
"ui",
"icon",
"icons",
"vector",
"retina",
"font"
],
"author": {
"name": "Joel Arvidsson",
"email": "joel@oblador.se"
},
"homepage": "https://github.com/oblador/react-native-vector-icons",
"bugs": {
"url": "https://github.com/oblador/react-native-vector-icons/issues"
},
"repository": {
"type": "git",
"url": "git://github.com/oblador/react-native-vector-icons.git"
},
"license": "MIT",
"peerDependencies": {
"react-native": ">=0.4.0 || 0.5.0-rc1 || 0.6.0-rc || 0.7.0-rc || 0.7.0-rc.2 || 0.8.0-rc || 0.8.0-rc.2 || 0.9.0-rc || 0.10.0-rc || 0.11.0-rc || 0.12.0-rc || 0.13.0-rc || 0.14.0-rc || 0.15.0-rc || 0.16.0-rc"
},
"dependencies": {
"lodash": "^3.8.0",
"yargs": "^3.30.0",
"rnpm-plugin-test": "*"
},
"devDependencies": {
"evil-icons": "^1.7.6",
"font-awesome": "^4.4.0",
"material-design-icons": "^2.1.1"
}
}
... ...
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
00E356F31AD99517003FC87E /* androidTestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* androidTestTests.m */; };
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
672DE8B31B124B8088D0D29F /* libBVLinearGradient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B5255B7628A54AC2A9B4B2A0 /* libBVLinearGradient.a */; };
68FEB18F24414EF981BD7940 /* libCodePush.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 53C67FE8F7294B7A83790610 /* libCodePush.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
C6C437D070BA42D6BE39198B /* libRCTVideo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A7396DFBAFA4CA092E367F5 /* libRCTVideo.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTActionSheet;
};
00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTGeolocation;
};
00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
remoteInfo = RCTImage;
};
00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58B511DB1A9E6C8500147676;
remoteInfo = RCTNetwork;
};
00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
remoteInfo = RCTVibration;
};
00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
remoteInfo = androidTest;
};
139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTSettings;
};
139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
remoteInfo = RCTWebSocket;
};
146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
remoteInfo = React;
};
78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTLinking;
};
832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
remoteInfo = RCTText;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = "<group>"; };
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = "<group>"; };
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = "<group>"; };
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = "<group>"; };
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
00E356EE1AD99517003FC87E /* androidTestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = androidTestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
00E356F21AD99517003FC87E /* androidTestTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = androidTestTests.m; sourceTree = "<group>"; };
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* androidTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = androidTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = androidTest/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = androidTest/AppDelegate.m; sourceTree = "<group>"; };
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = androidTest/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = androidTest/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = androidTest/main.m; sourceTree = "<group>"; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
53C67FE8F7294B7A83790610 /* libCodePush.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libCodePush.a; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
B5255B7628A54AC2A9B4B2A0 /* libBVLinearGradient.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libBVLinearGradient.a; sourceTree = "<group>"; };
467A6CBCB2164E7D9B673D4C /* CodePush.xcodeproj */ = {isa = PBXFileReference; name = "CodePush.xcodeproj"; path = "../node_modules/react-native-code-push/CodePush.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
FD7121847BA447D8B737F22A /* BVLinearGradient.xcodeproj */ = {isa = PBXFileReference; name = "BVLinearGradient.xcodeproj"; path = "../node_modules/react-native-linear-gradient/BVLinearGradient.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
409DA945815C46DEB4F254DB /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; name = "RCTVideo.xcodeproj"; path = "../node_modules/react-native-video/RCTVideo.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
3A7396DFBAFA4CA092E367F5 /* libRCTVideo.a */ = {isa = PBXFileReference; name = "libRCTVideo.a"; path = "libRCTVideo.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
00E356EB1AD99517003FC87E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
146834051AC3E58100842450 /* libReact.a in Frameworks */,
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
672DE8B31B124B8088D0D29F /* libBVLinearGradient.a in Frameworks */,
68FEB18F24414EF981BD7940 /* libCodePush.a in Frameworks */,
C6C437D070BA42D6BE39198B /* libRCTVideo.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
00C302A81ABCB8CE00DB3ED1 /* Products */ = {
isa = PBXGroup;
children = (
00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */,
);
name = Products;
sourceTree = "<group>";
};
00C302B61ABCB90400DB3ED1 /* Products */ = {
isa = PBXGroup;
children = (
00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */,
);
name = Products;
sourceTree = "<group>";
};
00C302BC1ABCB91800DB3ED1 /* Products */ = {
isa = PBXGroup;
children = (
00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
);
name = Products;
sourceTree = "<group>";
};
00C302D41ABCB9D200DB3ED1 /* Products */ = {
isa = PBXGroup;
children = (
00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
);
name = Products;
sourceTree = "<group>";
};
00C302E01ABCB9EE00DB3ED1 /* Products */ = {
isa = PBXGroup;
children = (
00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */,
);
name = Products;
sourceTree = "<group>";
};
00E356EF1AD99517003FC87E /* androidTestTests */ = {
isa = PBXGroup;
children = (
00E356F21AD99517003FC87E /* androidTestTests.m */,
00E356F01AD99517003FC87E /* Supporting Files */,
);
path = androidTestTests;
sourceTree = "<group>";
};
00E356F01AD99517003FC87E /* Supporting Files */ = {
isa = PBXGroup;
children = (
00E356F11AD99517003FC87E /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
139105B71AF99BAD00B5F7CC /* Products */ = {
isa = PBXGroup;
children = (
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
);
name = Products;
sourceTree = "<group>";
};
139FDEE71B06529A00C62182 /* Products */ = {
isa = PBXGroup;
children = (
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
};
13B07FAE1A68108700A75B9A /* androidTest */ = {
isa = PBXGroup;
children = (
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
);
name = androidTest;
sourceTree = "<group>";
};
146834001AC3E56700842450 /* Products */ = {
isa = PBXGroup;
children = (
146834041AC3E56700842450 /* libReact.a */,
);
name = Products;
sourceTree = "<group>";
};
78C398B11ACF4ADC00677621 /* Products */ = {
isa = PBXGroup;
children = (
78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
);
name = Products;
sourceTree = "<group>";
};
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
146833FF1AC3E56700842450 /* React.xcodeproj */,
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
467A6CBCB2164E7D9B673D4C /* CodePush.xcodeproj */,
FD7121847BA447D8B737F22A /* BVLinearGradient.xcodeproj */,
409DA945815C46DEB4F254DB /* RCTVideo.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
};
832341B11AAA6A8300B99B32 /* Products */ = {
isa = PBXGroup;
children = (
832341B51AAA6A8300B99B32 /* libRCTText.a */,
);
name = Products;
sourceTree = "<group>";
};
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
13B07FAE1A68108700A75B9A /* androidTest */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* androidTestTests */,
83CBBA001A601CBA00E9B192 /* Products */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
83CBBA001A601CBA00E9B192 /* Products */ = {
isa = PBXGroup;
children = (
13B07F961A680F5B00A75B9A /* androidTest.app */,
00E356EE1AD99517003FC87E /* androidTestTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
00E356ED1AD99517003FC87E /* androidTestTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "androidTestTests" */;
buildPhases = (
00E356EA1AD99517003FC87E /* Sources */,
00E356EB1AD99517003FC87E /* Frameworks */,
00E356EC1AD99517003FC87E /* Resources */,
);
buildRules = (
);
dependencies = (
00E356F51AD99517003FC87E /* PBXTargetDependency */,
);
name = androidTestTests;
productName = androidTestTests;
productReference = 00E356EE1AD99517003FC87E /* androidTestTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
13B07F861A680F5B00A75B9A /* androidTest */ = {
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "androidTest" */;
buildPhases = (
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
);
buildRules = (
);
dependencies = (
);
name = androidTest;
productName = "Hello World";
productReference = 13B07F961A680F5B00A75B9A /* androidTest.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 610;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
00E356ED1AD99517003FC87E = {
CreatedOnToolsVersion = 6.2;
TestTargetID = 13B07F861A680F5B00A75B9A;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "androidTest" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 83CBB9F61A601CBA00E9B192;
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
},
{
ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
},
{
ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;
ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
},
{
ProductGroup = 78C398B11ACF4ADC00677621 /* Products */;
ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
},
{
ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
},
{
ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */;
ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
},
{
ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
},
{
ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */;
ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
},
{
ProductGroup = 139FDEE71B06529A00C62182 /* Products */;
ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 146834001AC3E56700842450 /* Products */;
ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
},
);
projectRoot = "";
targets = (
13B07F861A680F5B00A75B9A /* androidTest */,
00E356ED1AD99517003FC87E /* androidTestTests */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTActionSheet.a;
remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTGeolocation.a;
remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTImage.a;
remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTNetwork.a;
remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTVibration.a;
remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTSettings.a;
remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocket.a;
remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
146834041AC3E56700842450 /* libReact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libReact.a;
remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTLinking.a;
remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTText.a;
remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
00E356EC1AD99517003FC87E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
13B07F8E1A680F5B00A75B9A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Bundle React Native code and images";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../node_modules/react-native/scripts/react-native-xcode.sh";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
00E356EA1AD99517003FC87E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
00E356F31AD99517003FC87E /* androidTestTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
13B07F871A680F5B00A75B9A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 13B07F861A680F5B00A75B9A /* androidTest */;
targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
13B07FB21A68108700A75B9A /* Base */,
);
name = LaunchScreen.xib;
path = androidTest;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
00E356F61AD99517003FC87E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = androidTestTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/androidTest.app/androidTest";
};
name = Debug;
};
00E356F71AD99517003FC87E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = androidTestTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/androidTest.app/androidTest";
};
name = Release;
};
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEAD_CODE_STRIPPING = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)",
"$(SRCROOT)/../node_modules/react-native-code-push",
"$(SRCROOT)/../node_modules/react-native-linear-gradient/**",
"$(SRCROOT)/../node_modules/react-native-video",
);
INFOPLIST_FILE = androidTest/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = androidTest;
};
name = Debug;
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)",
"$(SRCROOT)/../node_modules/react-native-code-push",
"$(SRCROOT)/../node_modules/react-native-linear-gradient/**",
"$(SRCROOT)/../node_modules/react-native-video",
);
INFOPLIST_FILE = androidTest/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = androidTest;
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)",
"$(SRCROOT)/../node_modules/react-native-code-push",
"$(SRCROOT)/../node_modules/react-native-linear-gradient/**",
"$(SRCROOT)/../node_modules/react-native-video",
);
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
83CBBA211A601CBA00E9B192 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)",
"$(SRCROOT)/../node_modules/react-native-code-push",
"$(SRCROOT)/../node_modules/react-native-linear-gradient/**",
"$(SRCROOT)/../node_modules/react-native-video",
);
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "androidTestTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
00E356F61AD99517003FC87E /* Debug */,
00E356F71AD99517003FC87E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "androidTest" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */,
13B07F951A680F5B00A75B9A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "androidTest" */ = {
isa = XCConfigurationList;
buildConfigurations = (
83CBBA201A601CBA00E9B192 /* Debug */,
83CBBA211A601CBA00E9B192 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
}
... ...
const fs = require.requireActual('fs');
const path = require('path');
exports.valid = {
'demoProject.xcodeproj': {
'project.pbxproj': fs.readFileSync(path.join(__dirname, './files/project.pbxproj')),
},
'TestPod.podspec': 'empty'
};
exports.validTestName = {
'MyTestProject.xcodeproj': {
'project.pbxproj': fs.readFileSync(path.join(__dirname, './files/project.pbxproj')),
},
};
exports.pod = {
'TestPod.podspec': 'empty'
};
... ...
const android = require('./android');
const ios = require('./ios');
const flat = {
android: android.valid,
ios: ios.valid,
Podfile: 'empty'
};
const nested = {
android: {
app: android.valid,
},
ios: ios.valid,
};
const withExamples = {
Examples: flat,
ios: ios.valid,
android: android.valid,
};
const withPods = {
Podfile: 'content',
ios: ios.pod
};
module.exports = { flat, nested, withExamples, withPods };
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const fs = require('fs');
const findAndroidAppFolder = require('../../android/findAndroidAppFolder');
const mocks = require('../../__fixtures__/android');
describe('android::findAndroidAppFolder', () => {
beforeAll(() => {
fs.__setMockFilesystem({
empty: {},
nested: {
android: {
app: mocks.valid,
},
},
flat: {
android: mocks.valid,
},
});
});
it('returns an android app folder if it exists in the given folder', () => {
expect(findAndroidAppFolder('/flat')).toBe('android');
expect(findAndroidAppFolder('/nested')).toBe('android/app');
});
it('returns `null` if there is no android app folder', () => {
expect(findAndroidAppFolder('/empty')).toBeNull();
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const findManifest = require('../../android/findManifest');
const fs = require('fs');
const mocks = require('../../__fixtures__/android');
describe('android::findManifest', () => {
beforeAll(() => {
fs.__setMockFilesystem({
empty: {},
flat: {
android: mocks.valid,
},
});
});
it('returns a manifest path if file exists in the folder', () => {
expect(typeof findManifest('/flat')).toBe('string');
});
it('returns `null` if there is no manifest in the folder', () => {
expect(findManifest('/empty')).toBeNull();
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const findPackageClassName = require('../../android/findPackageClassName');
const fs = require('fs');
const mocks = require('../../__fixtures__/android');
describe('android::findPackageClassName', () => {
beforeAll(() => {
fs.__setMockFilesystem({
empty: {},
flatJava: {
android: mocks.valid,
},
flatKotlin: {
android: mocks.validKotlin,
},
});
});
it('returns manifest content if file exists in the folder', () => {
expect(typeof findPackageClassName('/flatJava')).toBe('string');
});
it('returns the name of the java class implementing ReactPackage', () => {
expect(findPackageClassName('/flatJava')).toBe('SomeExampleJavaPackage');
});
it('returns the name of the kotlin class implementing ReactPackage', () => {
expect(findPackageClassName('/flatKotlin')).toBe(
'SomeExampleKotlinPackage',
);
});
it('returns `null` if there are no matches', () => {
expect(findPackageClassName('/empty')).toBeNull();
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const getDependencyConfig = require('../../android').dependencyConfig;
const fs = require('fs');
const mocks = require('../../__fixtures__/android');
const userConfig = {};
describe('android::getDependencyConfig', () => {
beforeAll(() => {
fs.__setMockFilesystem({
empty: {},
nested: {
android: {
app: mocks.valid,
},
},
corrupted: {
android: {
app: mocks.corrupted,
},
},
noPackage: {
android: {},
},
});
});
it('returns an object with android project configuration', () => {
expect(getDependencyConfig('/nested', userConfig)).not.toBeNull();
expect(typeof getDependencyConfig('/nested', userConfig)).toBe('object');
});
it('returns `null` if manifest file has not been found', () => {
expect(getDependencyConfig('/empty', userConfig)).toBeNull();
});
it('returns `null` if android project was not found', () => {
expect(getDependencyConfig('/empty', userConfig)).toBeNull();
});
it('returns `null` if android project does not contain ReactPackage', () => {
expect(getDependencyConfig('/noPackage', userConfig)).toBeNull();
});
it('returns `null` if it cannot find a packageClassName', () => {
expect(getDependencyConfig('/corrupted', userConfig)).toBeNull();
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const getProjectConfig = require('../../android').projectConfig;
const fs = require('fs');
const mocks = require('../../__fixtures__/android');
describe('android::getProjectConfig', () => {
beforeAll(() => {
fs.__setMockFilesystem({
empty: {},
nested: {
android: {
app: mocks.valid,
},
},
flat: {
android: mocks.valid,
},
multiple: {
android: mocks.userConfigManifest,
},
noManifest: {
android: {},
},
});
});
it("returns `null` if manifest file hasn't been found", () => {
const userConfig = {};
const folder = '/noManifest';
expect(getProjectConfig(folder, userConfig)).toBeNull();
});
describe('returns an object with android project configuration for', () => {
it('nested structure', () => {
const userConfig = {};
const folder = '/nested';
expect(getProjectConfig(folder, userConfig)).not.toBeNull();
expect(typeof getProjectConfig(folder, userConfig)).toBe('object');
});
it('flat structure', () => {
const userConfig = {};
const folder = '/flat';
expect(getProjectConfig(folder, userConfig)).not.toBeNull();
expect(typeof getProjectConfig(folder, userConfig)).toBe('object');
});
it('multiple', () => {
const userConfig = {
manifestPath: 'src/main/AndroidManifest.xml',
};
const folder = '/multiple';
expect(getProjectConfig(folder, userConfig)).not.toBeNull();
expect(typeof getProjectConfig(folder, userConfig)).toBe('object');
});
});
it('should return `null` if android project was not found', () => {
const userConfig = {};
const folder = '/empty';
expect(getProjectConfig(folder, userConfig)).toBeNull();
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const findManifest = require('../../android/findManifest');
const readManifest = require('../../android/readManifest');
const fs = require('fs');
const mocks = require('../../__fixtures__/android');
describe('android::readManifest', () => {
beforeAll(() => {
fs.__setMockFilesystem({
empty: {},
nested: {
android: {
app: mocks.valid,
},
},
});
});
it('returns manifest content if file exists in the folder', () => {
const manifestPath = findManifest('/nested');
expect(readManifest(manifestPath)).not.toBeNull();
expect(typeof readManifest(manifestPath)).toBe('object');
});
it('throws an error if there is no manifest in the folder', () => {
const fakeManifestPath = findManifest('/empty');
expect(() => {
readManifest(fakeManifestPath);
}).toThrow();
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const findAssets = require('../findAssets');
const dependencies = require('../__fixtures__/dependencies');
const fs = require('fs');
describe('findAssets', () => {
beforeEach(() => {
fs.__setMockFilesystem({testDir: dependencies.withAssets});
});
it('returns an array of all files in given folders', () => {
const assets = findAssets('/testDir', ['fonts', 'images']);
expect(Array.isArray(assets)).toBeTruthy();
expect(assets).toHaveLength(3);
});
it('prepends assets paths with the folder path', () => {
const assets = findAssets('/testDir', ['fonts', 'images']);
assets.forEach(assetPath => {
expect(assetPath).toContain('testDir');
});
});
it('returns an empty array if given assets are null', () => {
expect(findAssets('/testDir', null)).toHaveLength(0);
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
const findPlugins = require('../findPlugins');
const path = require('path');
const ROOT = path.join(__dirname, '..', '..', '..');
const pjsonPath = path.join(ROOT, 'package.json');
describe('findPlugins', () => {
beforeEach(() => {
jest.resetModules();
});
it('returns an array of dependencies', () => {
jest.mock(pjsonPath, () => ({
dependencies: {'rnpm-plugin-test': '*'},
}));
expect(findPlugins([ROOT])).toHaveProperty('commands');
expect(findPlugins([ROOT])).toHaveProperty('platforms');
expect(findPlugins([ROOT]).commands).toHaveLength(1);
expect(findPlugins([ROOT]).commands[0]).toBe('rnpm-plugin-test');
expect(findPlugins([ROOT]).platforms).toHaveLength(0);
});
it('returns an empty array if there are no plugins in this folder', () => {
jest.mock(pjsonPath, () => ({}));
expect(findPlugins([ROOT])).toHaveProperty('commands');
expect(findPlugins([ROOT])).toHaveProperty('platforms');
expect(findPlugins([ROOT]).commands).toHaveLength(0);
expect(findPlugins([ROOT]).platforms).toHaveLength(0);
});
it('returns an object with empty arrays if there is no package.json in the supplied folder', () => {
expect(findPlugins(['fake-path'])).toHaveProperty('commands');
expect(findPlugins(['fake-path'])).toHaveProperty('platforms');
expect(findPlugins(['fake-path']).commands).toHaveLength(0);
expect(findPlugins(['fake-path']).platforms).toHaveLength(0);
});
it('returns plugins from both dependencies and dev dependencies', () => {
jest.mock(pjsonPath, () => ({
dependencies: {'rnpm-plugin-test': '*'},
devDependencies: {'rnpm-plugin-test-2': '*'},
}));
expect(findPlugins([ROOT])).toHaveProperty('commands');
expect(findPlugins([ROOT])).toHaveProperty('platforms');
expect(findPlugins([ROOT]).commands).toHaveLength(2);
expect(findPlugins([ROOT]).platforms).toHaveLength(0);
});
it('returns unique list of plugins', () => {
jest.mock(pjsonPath, () => ({
dependencies: {'rnpm-plugin-test': '*'},
devDependencies: {'rnpm-plugin-test': '*'},
}));
expect(findPlugins([ROOT]).commands).toHaveLength(1);
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* All rights reserved.
*
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const findPodfilePath = require('../../ios/findPodfilePath');
const fs = require('fs');
const projects = require('../../__fixtures__/projects');
const ios = require('../../__fixtures__/ios');
describe('ios::findPodfilePath', () => {
it('returns null if there is no Podfile', () => {
fs.__setMockFilesystem(ios.valid);
expect(findPodfilePath('')).toBeNull();
});
it('returns Podfile path if it exists', () => {
fs.__setMockFilesystem(projects.withPods);
expect(findPodfilePath('/ios')).toContain('Podfile');
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* All rights reserved.
*
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const findPodspecName = require('../../ios/findPodspecName');
const fs = require('fs');
const projects = require('../../__fixtures__/projects');
const ios = require('../../__fixtures__/ios');
describe('ios::findPodspecName', () => {
it('returns null if there is not podspec file', () => {
fs.__setMockFilesystem(projects.flat);
expect(findPodspecName('')).toBeNull();
});
it('returns podspec name if only one exists', () => {
fs.__setMockFilesystem(ios.pod);
expect(findPodspecName('/')).toBe('TestPod');
});
it('returns podspec name that match packet directory', () => {
fs.__setMockFilesystem({
user: {
PacketName: {
'Another.podspec': 'empty',
'PacketName.podspec': 'empty'
}
}
});
expect(findPodspecName('/user/PacketName')).toBe('PacketName');
});
it('returns first podspec name if not match in directory', () => {
fs.__setMockFilesystem({
user: {
packet: {
'Another.podspec': 'empty',
'PacketName.podspec': 'empty'
}
}
});
expect(findPodspecName('/user/packet')).toBe('Another');
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const findProject = require('../../ios/findProject');
const fs = require('fs');
const projects = require('../../__fixtures__/projects');
const ios = require('../../__fixtures__/ios');
describe('ios::findProject', () => {
it('returns path to xcodeproj if found', () => {
fs.__setMockFilesystem(projects.flat);
expect(findProject('/')).not.toBeNull();
});
it('returns null if there are no projects', () => {
fs.__setMockFilesystem({testDir: projects});
expect(findProject('/')).toBeNull();
});
it('returns ios project regardless of its name', () => {
fs.__setMockFilesystem({ios: ios.validTestName});
expect(findProject('/')).not.toBeNull();
});
it('ignores node_modules', () => {
fs.__setMockFilesystem({node_modules: projects.flat});
expect(findProject('/')).toBeNull();
});
it('ignores Pods', () => {
fs.__setMockFilesystem({Pods: projects.flat});
expect(findProject('/')).toBeNull();
});
it('ignores Pods inside `ios` folder', () => {
fs.__setMockFilesystem({
ios: {
Pods: projects.flat,
DemoApp: projects.flat.ios,
},
});
expect(findProject('/')).toBe('ios/DemoApp/demoProject.xcodeproj');
});
it('ignores xcodeproj from example folders', () => {
fs.__setMockFilesystem({
examples: projects.flat,
Examples: projects.flat,
example: projects.flat,
KeychainExample: projects.flat,
Zpp: projects.flat,
});
expect(findProject('/').toLowerCase()).not.toContain('example');
});
it('ignores xcodeproj from sample folders', () => {
fs.__setMockFilesystem({
samples: projects.flat,
Samples: projects.flat,
sample: projects.flat,
KeychainSample: projects.flat,
Zpp: projects.flat,
});
expect(findProject('/').toLowerCase()).not.toContain('sample');
});
it('ignores xcodeproj from test folders at any level', () => {
fs.__setMockFilesystem({
test: projects.flat,
IntegrationTests: projects.flat,
tests: projects.flat,
Zpp: {
tests: projects.flat,
src: projects.flat,
},
});
expect(findProject('/').toLowerCase()).not.toContain('test');
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
jest.mock('fs');
const getProjectConfig = require('../../ios').projectConfig;
const fs = require('fs');
const projects = require('../../__fixtures__/projects');
describe('ios::getProjectConfig', () => {
const userConfig = {};
beforeEach(() => {
fs.__setMockFilesystem({testDir: projects});
});
it('returns an object with ios project configuration', () => {
const folder = '/testDir/nested';
expect(getProjectConfig(folder, userConfig)).not.toBeNull();
expect(typeof getProjectConfig(folder, userConfig)).toBe('object');
});
it('returns `null` if ios project was not found', () => {
const folder = '/testDir/empty';
expect(getProjectConfig(folder, userConfig)).toBeNull();
});
it('returns normalized shared library names', () => {
const projectConfig = getProjectConfig('/testDir/nested', {
sharedLibraries: ['libc++', 'libz.tbd', 'HealthKit', 'HomeKit.framework'],
});
expect(projectConfig.sharedLibraries).toEqual([
'libc++.tbd',
'libz.tbd',
'HealthKit.framework',
'HomeKit.framework',
]);
});
});
... ...
/**
* Copyright (c) 2013-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.
*
* @format
* @emails oncall+javascript_foundation
*/
'use strict';
let spawnError = false;
jest.setMock('child_process', {
spawn: () => ({
on: (event, cb) => cb(spawnError),
}),
});
const makeCommand = require('../makeCommand');
describe('makeCommand', () => {
const command = makeCommand('echo');
it('generates a function around shell command', () => {
expect(typeof command).toBe('function');
});
it('throws an error if there is no callback provided', () => {
expect(command).toThrow();
});
it('invokes a callback after command execution', () => {
const spy = jest.fn();
command(spy);
expect(spy.mock.calls).toHaveLength(1);
});
it('throws an error if spawn ended up with error', () => {
spawnError = true;
const cb = jest.fn();
expect(() => {
command(cb);
}).toThrow();
});
});
... ...
/**
* 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';
const fs = require('fs');
const path = require('path');
/**
* @param {String} folder Folder to seek in
* @return {String}
*/
module.exports = function findAndroidAppFolder(folder) {
const flat = 'android';
const nested = path.join('android', 'app');
if (fs.existsSync(path.join(folder, nested))) {
return nested;
}
if (fs.existsSync(path.join(folder, flat))) {
return flat;
}
return null;
};
... ...
/**
* 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';
const glob = require('glob');
const path = require('path');
/**
* Find an android application path in the folder
*
* @param {String} folder Name of the folder where to seek
* @return {String}
*/
module.exports = function findManifest(folder) {
const manifestPath = glob.sync(path.join('**', 'AndroidManifest.xml'), {
cwd: folder,
ignore: ['node_modules/**', '**/build/**', 'Examples/**', 'examples/**'],
})[0];
return manifestPath ? path.join(folder, manifestPath) : null;
};
... ...
/**
* 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';
const fs = require('fs');
const glob = require('glob');
const path = require('path');
/**
* Gets package's class name (class that implements ReactPackage)
* by searching for its declaration in all Java/Kotlin files present in the folder
*
* @param {String} folder Folder to find java/kt files
*/
module.exports = function getPackageClassName(folder) {
const files = glob.sync('**/+(*.java|*.kt)', { cwd: folder });
const packages = files
.map(filePath => fs.readFileSync(path.join(folder, filePath), 'utf8'))
.map(file => file.match(/class (.*) +(implements|:) ReactPackage/))
.filter(match => match);
return packages.length ? packages[0][1] : null;
};
... ...
/**
* 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';
const findAndroidAppFolder = require('./findAndroidAppFolder');
const findManifest = require('./findManifest');
const findPackageClassName = require('./findPackageClassName');
const path = require('path');
const readManifest = require('./readManifest');
const getPackageName = (manifest) => manifest.attr.package;
/**
* Gets android project config by analyzing given folder and taking some
* defaults specified by user into consideration
*/
exports.projectConfig = function projectConfigAndroid(folder, userConfig) {
const src = userConfig.sourceDir || findAndroidAppFolder(folder);
if (!src) {
return null;
}
const sourceDir = path.join(folder, src);
const isFlat = sourceDir.indexOf('app') === -1;
const manifestPath = userConfig.manifestPath
? path.join(sourceDir, userConfig.manifestPath)
: findManifest(sourceDir);
if (!manifestPath) {
return null;
}
const manifest = readManifest(manifestPath);
const packageName = userConfig.packageName || getPackageName(manifest);
if (!packageName) {
throw new Error(`Package name not found in ${manifestPath}`);
}
const packageFolder = userConfig.packageFolder ||
packageName.replace(/\./g, path.sep);
const mainFilePath = path.join(
sourceDir,
userConfig.mainFilePath || `src/main/java/${packageFolder}/MainApplication.java`
);
const stringsPath = path.join(
sourceDir,
userConfig.stringsPath || 'src/main/res/values/strings.xml'
);
const settingsGradlePath = path.join(
folder,
'android',
userConfig.settingsGradlePath || 'settings.gradle'
);
const assetsPath = path.join(
sourceDir,
userConfig.assetsPath || 'src/main/assets'
);
const buildGradlePath = path.join(
sourceDir,
userConfig.buildGradlePath || 'build.gradle'
);
return {
sourceDir,
isFlat,
folder,
stringsPath,
manifestPath,
buildGradlePath,
settingsGradlePath,
assetsPath,
mainFilePath,
};
};
/**
* Same as projectConfigAndroid except it returns
* different config that applies to packages only
*/
exports.dependencyConfig = function dependencyConfigAndroid(folder, userConfig) {
const src = userConfig.sourceDir || findAndroidAppFolder(folder);
if (!src) {
return null;
}
const sourceDir = path.join(folder, src);
const manifestPath = userConfig.manifestPath
? path.join(sourceDir, userConfig.manifestPath)
: findManifest(sourceDir);
if (!manifestPath) {
return null;
}
const manifest = readManifest(manifestPath);
const packageName = userConfig.packageName || getPackageName(manifest);
const packageClassName = findPackageClassName(sourceDir);
/**
* This module has no package to export
*/
if (!packageClassName) {
return null;
}
const packageImportPath = userConfig.packageImportPath ||
`import ${packageName}.${packageClassName};`;
const packageInstance = userConfig.packageInstance ||
`new ${packageClassName}()`;
return { sourceDir, folder, manifest, packageImportPath, packageInstance };
};
exports.linkConfig = require('../../link/android');
... ...
/**
* 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';
const fs = require('fs');
const xml = require('xmldoc');
/**
* @param {String} manifestPath
* @return {XMLDocument} Parsed manifest's content
*/
module.exports = function readManifest(manifestPath) {
return new xml.XmlDocument(fs.readFileSync(manifestPath, 'utf8'));
};
... ...
/**
* 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';
const glob = require('glob');
const path = require('path');
const findAssetsInFolder = (folder) =>
glob.sync(path.join(folder, '**'), { nodir: true });
/**
* Given an array of assets folders, e.g. ['Fonts', 'Images'],
* it globs in them to find all files that can be copied.
*
* It returns an array of absolute paths to files found.
*/
module.exports = function findAssets(folder, assets) {
return (assets || [])
.map(assetsFolder => path.join(folder, assetsFolder))
.reduce((_assets, assetsFolder) =>
_assets.concat(findAssetsInFolder(assetsFolder)),
[]
);
};
... ...
/**
* 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';
const path = require('path');
const union = require('lodash').union;
const uniq = require('lodash').uniq;
const flatten = require('lodash').flatten;
/**
* Filter dependencies by name pattern
* @param {String} dependency Name of the dependency
* @return {Boolean} If dependency is a rnpm plugin
*/
const isRNPMPlugin = (dependency) => dependency.indexOf('rnpm-plugin-') === 0;
const isReactNativePlugin = (dependency) => dependency.indexOf('react-native-') === 0;
const readPackage = (folder) => {
try {
return require(path.join(folder, 'package.json'));
} catch (e) {
return null;
}
};
const findPluginsInReactNativePackage = (pjson) => {
if (!pjson.rnpm || !pjson.rnpm.plugin) {
return [];
}
return path.join(pjson.name, pjson.rnpm.plugin);
};
const findPlatformsInPackage = (pjson) => {
if (!pjson.rnpm || !pjson.rnpm.platform) {
return [];
}
return path.join(pjson.name, pjson.rnpm.platform);
};
const findPluginInFolder = (folder) => {
const pjson = readPackage(folder);
if (!pjson) {
return {commands: [], platforms: []};
}
const deps = union(
Object.keys(pjson.dependencies || {}),
Object.keys(pjson.devDependencies || {})
);
return deps.reduce(
(acc, pkg) => {
let commands = acc.commands;
let platforms = acc.platforms;
if (isRNPMPlugin(pkg)) {
commands = commands.concat(pkg);
}
if (isReactNativePlugin(pkg)) {
const pkgJson = readPackage(path.join(folder, 'node_modules', pkg));
if (pkgJson) {
commands = commands.concat(findPluginsInReactNativePackage(pkgJson));
platforms = platforms.concat(findPlatformsInPackage(pkgJson));
}
}
return {commands: commands, platforms: platforms};
},
{commands: [], platforms: []}
);
};
/**
* Find plugins in package.json of the given folder
* @param {String} folder Path to the folder to get the package.json from
* @type {Object} Object of commands and platform plugins
*/
module.exports = function findPlugins(folders) {
const plugins = folders.map(findPluginInFolder);
return {
commands: uniq(flatten(plugins.map(p => p.commands))),
platforms: uniq(flatten(plugins.map(p => p.platforms)))
};
};
... ...
/**
* 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.
*
* @flow
*/
'use strict';
const android = require('./android');
const Config = require('../util/Config');
const findPlugins = require('./findPlugins');
const findAssets = require('./findAssets');
const ios = require('./ios');
const wrapCommands = require('./wrapCommands');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const flatten = require('lodash').flatten;
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const minimist = require('minimist');
const path = require('path');
import type {CommandT} from '../commands';
import type {ConfigT} from 'metro';
export type RNConfig = {
...ConfigT,
/**
* Returns an object with all platform configurations.
*/
getPlatformConfig(): Object,
/**
* Returns an array of project commands used by the CLI to load
*/
getProjectCommands(): Array<CommandT>,
/**
* Returns project config from the current working directory
*/
getProjectConfig(): Object,
/**
* Returns dependency config from <node_modules>/packageName
*/
getDependencyConfig(pkgName: string): Object,
};
const getRNPMConfig = (folder) =>
// $FlowFixMe non-literal require
require(path.join(folder, './package.json')).rnpm || {};
const attachPackage = (command, pkg) => Array.isArray(command)
? command.map(cmd => attachPackage(cmd, pkg))
: { ...command, pkg };
const appRoot = process.cwd();
const plugins = findPlugins([appRoot]);
const pluginPlatforms = plugins
.platforms
.reduce((acc, pathToPlatforms) => {
// $FlowFixMe non-literal require
return Object.assign(acc, require(path.join(appRoot, 'node_modules', pathToPlatforms)));
},
{});
const defaultRNConfig = {
getProjectCommands(): Array<CommandT> {
const commands = plugins
.commands
.map(pathToCommands => {
const name = pathToCommands.split(path.sep)[0];
return attachPackage(
// $FlowFixMe non-literal require
require(path.join(appRoot, 'node_modules', pathToCommands)),
// $FlowFixMe non-literal require
require(path.join(appRoot, 'node_modules', name, 'package.json'))
);
});
return flatten(commands);
},
getPlatformConfig(): Object {
return {
ios,
android,
...pluginPlatforms
};
},
getProjectConfig(): Object {
const platforms = this.getPlatformConfig();
const folder = process.cwd();
const rnpm = getRNPMConfig(folder);
let config = Object.assign({}, rnpm, {
assets: findAssets(folder, rnpm.assets),
});
Object.keys(platforms).forEach(key => {
config[key] = platforms[key].projectConfig(folder, rnpm[key] || {});
});
return config;
},
getDependencyConfig(packageName: string) {
const platforms = this.getPlatformConfig();
const folder = path.join(process.cwd(), 'node_modules', packageName);
const rnpm = getRNPMConfig(
path.join(process.cwd(), 'node_modules', packageName)
);
let config = Object.assign({}, rnpm, {
assets: findAssets(folder, rnpm.assets),
commands: wrapCommands(rnpm.commands),
params: rnpm.params || [],
});
Object.keys(platforms).forEach(key => {
config[key] = platforms[key].dependencyConfig(folder, rnpm[key] || {});
});
return config;
},
};
/**
* Loads the CLI configuration
*/
function getCliConfig(): RNConfig {
const cliArgs = minimist(process.argv.slice(2));
const config = cliArgs.config != null
? Config.load(path.resolve(__dirname, cliArgs.config))
: Config.findOptional(__dirname);
return {...defaultRNConfig, ...config};
}
module.exports = getCliConfig();
... ...
'use strict';
const fs = require('fs');
const path = require('path');
module.exports = function findPodfilePath(projectFolder) {
const podFilePath = path.join(projectFolder, '..', 'Podfile');
const podFileExists = fs.existsSync(podFilePath);
return podFileExists ? podFilePath : null;
};
... ...
'use strict';
const glob = require('glob');
const path = require('path');
module.exports = function findPodspecName(folder) {
const podspecs = glob.sync('*.podspec', { cwd: folder });
let podspecFile = null;
if (podspecs.length === 0) {
return null;
}
else if (podspecs.length === 1) {
podspecFile = podspecs[0];
}
else {
const folderParts = folder.split(path.sep);
const currentFolder = folderParts[folderParts.length - 1];
const toSelect = podspecs.indexOf(currentFolder + '.podspec');
if (toSelect === -1) {
podspecFile = podspecs[0];
}
else {
podspecFile = podspecs[toSelect];
}
}
return podspecFile.replace('.podspec', '');
};
... ...
/**
* 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';
const glob = require('glob');
const path = require('path');
/**
* Glob pattern to look for xcodeproj
*/
const GLOB_PATTERN = '**/*.xcodeproj';
/**
* Regexp matching all test projects
*/
const TEST_PROJECTS = /test|example|sample/i;
/**
* Base iOS folder
*/
const IOS_BASE = 'ios';
/**
* These folders will be excluded from search to speed it up
*/
const GLOB_EXCLUDE_PATTERN = ['**/@(Pods|node_modules)/**'];
/**
* Finds iOS project by looking for all .xcodeproj files
* in given folder.
*
* Returns first match if files are found or null
*
* Note: `./ios/*.xcodeproj` are returned regardless of the name
*/
module.exports = function findProject(folder) {
const projects = glob
.sync(GLOB_PATTERN, {
cwd: folder,
ignore: GLOB_EXCLUDE_PATTERN,
})
.filter(project => {
return path.dirname(project) === IOS_BASE || !TEST_PROJECTS.test(project);
})
.sort((projectA, projectB) => {
return path.dirname(projectA) === IOS_BASE ? -1 : 1;
});
if (projects.length === 0) {
return null;
}
return projects[0];
};
... ...
/**
* 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';
const findProject = require('./findProject');
const findPodfilePath = require('./findPodfilePath');
const findPodspecName = require('./findPodspecName');
const path = require('path');
/**
* For libraries specified without an extension, add '.tbd' for those that
* start with 'lib' and '.framework' to the rest.
*/
const mapSharedLibaries = (libraries) => {
return libraries.map(name => {
if (path.extname(name)) {
return name;
}
return name + (name.indexOf('lib') === 0 ? '.tbd' : '.framework');
});
};
/**
* Returns project config by analyzing given folder and applying some user defaults
* when constructing final object
*/
exports.projectConfig = function projectConfigIOS(folder, userConfig) {
const project = userConfig.project || findProject(folder);
/**
* No iOS config found here
*/
if (!project) {
return null;
}
const projectPath = path.join(folder, project);
return {
sourceDir: path.dirname(projectPath),
folder: folder,
pbxprojPath: path.join(projectPath, 'project.pbxproj'),
podfile: findPodfilePath(projectPath),
podspec: findPodspecName(folder),
projectPath: projectPath,
projectName: path.basename(projectPath),
libraryFolder: userConfig.libraryFolder || 'Libraries',
sharedLibraries: mapSharedLibaries(userConfig.sharedLibraries || []),
plist: userConfig.plist || [],
};
};
exports.dependencyConfig = exports.projectConfig;
exports.linkConfig = require('../../link/ios');
... ...
/**
* 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';
const spawn = require('child_process').spawn;
module.exports = function makeCommand(command) {
return (cb) => {
if (!cb) {
throw new Error(`You missed a callback function for the ${command} command`);
}
const args = command.split(' ');
const cmd = args.shift();
const commandProcess = spawn(cmd, args, {
stdio: 'inherit',
stdin: 'inherit',
});
commandProcess.on('close', function prelink(code) {
if (code) {
throw new Error(`Error occurred during executing "${command}" command`);
}
cb();
});
};
};
... ...
/**
* 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';
const makeCommand = require('./makeCommand');
module.exports = function wrapCommands(commands) {
const mappedCommands = {};
Object.keys(commands || []).forEach((k) => {
mappedCommands[k] = makeCommand(commands[k]);
});
return mappedCommands;
};
... ...
/**
* 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';
const Metro = require('metro');
const denodeify = require('denodeify');
const fs = require('fs');
const path = require('path');
const {ASSET_REGISTRY_PATH} = require('../core/Constants');
function dependencies(argv, config, args, packagerInstance) {
const rootModuleAbsolutePath = args.entryFile;
if (!fs.existsSync(rootModuleAbsolutePath)) {
return Promise.reject(new Error(`File ${rootModuleAbsolutePath} does not exist`));
}
const transformModulePath =
args.transformer ? path.resolve(args.transformer) :
typeof config.getTransformModulePath === 'function' ? config.getTransformModulePath() :
undefined;
const packageOpts = {
assetRegistryPath: ASSET_REGISTRY_PATH,
projectRoots: config.getProjectRoots(),
blacklistRE: config.getBlacklistRE(),
dynamicDepsInPackages: config.dynamicDepsInPackages,
getPolyfills: config.getPolyfills,
getTransformOptions: config.getTransformOptions,
hasteImplModulePath: config.hasteImplModulePath,
postMinifyProcess: config.postMinifyProcess,
transformModulePath: transformModulePath,
extraNodeModules: config.extraNodeModules,
verbose: config.verbose,
workerPath: config.getWorkerPath(),
};
const relativePath = packageOpts.projectRoots.map(root =>
path.relative(
root,
rootModuleAbsolutePath
)
)[0];
const options = {
platform: args.platform,
entryFile: relativePath,
dev: args.dev,
minify: false,
generateSourceMaps: !args.dev,
};
const writeToFile = args.output;
const outStream = writeToFile
? fs.createWriteStream(args.output)
: process.stdout;
return Promise.resolve((packagerInstance ?
packagerInstance.getOrderedDependencyPaths(options) :
Metro.getOrderedDependencyPaths(packageOpts, options)).then(
deps => {
deps.forEach(modulePath => {
// Temporary hack to disable listing dependencies not under this directory.
// Long term, we need either
// (a) JS code to not depend on anything outside this directory, or
// (b) Come up with a way to declare this dependency in Buck.
const isInsideProjectRoots = packageOpts.projectRoots.filter(
root => modulePath.startsWith(root)
).length > 0;
if (isInsideProjectRoots) {
outStream.write(modulePath + '\n');
}
});
return writeToFile
? denodeify(outStream.end).bind(outStream)()
: Promise.resolve();
}
));
}
module.exports = {
name: 'dependencies',
func: dependencies,
options: [
{
command: '--entry-file <path>',
description: 'Absolute path to the root JS file',
}, {
command: '--output [path]',
description: 'File name where to store the output, ex. /tmp/dependencies.txt',
}, {
command: '--platform [extension]',
description: 'The platform extension used for selecting modules',
}, {
command: '--transformer [path]',
description: 'Specify a custom transformer to be used'
}, {
command: '--max-workers [number]',
description: 'Specifies the maximum number of workers the worker-pool ' +
'will spawn for transforming files. This defaults to the number of the ' +
'cores available on your machine.',
parse: (workers: string) => Number(workers),
}, {
command: '--dev [boolean]',
description: 'If false, skip all dev-only code path',
parse: (val) => val === 'false' ? false : true,
default: true,
}, {
command: '--verbose',
description: 'Enables logging',
default: false,
},
],
};
... ...
/**
* 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';
const copyProjectTemplateAndReplace = require('../generator/copyProjectTemplateAndReplace');
const path = require('path');
const fs = require('fs');
/**
* The eject command re-creates the `android` and `ios` native folders. Because native code can be
* difficult to maintain, this new script allows an `app.json` to be defined for the project, which
* is used to configure the native app.
*
* The `app.json` config may contain the following keys:
*
* - `name` - The short name used for the project, should be TitleCase
* - `displayName` - The app's name on the home screen
*/
function eject() {
const doesIOSExist = fs.existsSync(path.resolve('ios'));
const doesAndroidExist = fs.existsSync(path.resolve('android'));
if (doesIOSExist && doesAndroidExist) {
console.error(
'Both the iOS and Android folders already exist! Please delete `ios` and/or `android` ' +
'before ejecting.'
);
process.exit(1);
}
let appConfig = null;
try {
appConfig = require(path.resolve('app.json'));
} catch (e) {
console.error(
'Eject requires an `app.json` config file to be located at ' +
`${path.resolve('app.json')}, and it must at least specify a \`name\` for the project ` +
'name, and a `displayName` for the app\'s home screen label.'
);
process.exit(1);
}
const appName = appConfig.name;
if (!appName) {
console.error(
'App `name` must be defined in the `app.json` config file to define the project name. ' +
'It must not contain any spaces or dashes.'
);
process.exit(1);
}
const displayName = appConfig.displayName;
if (!displayName) {
console.error(
'App `displayName` must be defined in the `app.json` config file, to define the label ' +
'of the app on the home screen.'
);
process.exit(1);
}
const templateOptions = { displayName };
if (!doesIOSExist) {
console.log('Generating the iOS folder.');
copyProjectTemplateAndReplace(
path.resolve('node_modules', 'react-native', 'local-cli', 'templates', 'HelloWorld', 'ios'),
path.resolve('ios'),
appName,
templateOptions
);
}
if (!doesAndroidExist) {
console.log('Generating the Android folder.');
copyProjectTemplateAndReplace(
path.resolve('node_modules', 'react-native', 'local-cli', 'templates', 'HelloWorld', 'android'),
path.resolve('android'),
appName,
templateOptions
);
}
}
module.exports = {
name: 'eject',
description: 'Re-create the iOS and Android folders and native code',
func: eject,
options: [],
};
... ...
/**
* 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';
const chalk = require('chalk');
const copyAndReplace = require('../util/copyAndReplace');
const path = require('path');
const prompt = require('./promptSync')();
const walk = require('../util/walk');
/**
* Util for creating a new React Native project.
* Copy the project from a template and use the correct project name in
* all files.
* @param srcPath e.g. '/Users/martin/AwesomeApp/node_modules/react-native/local-cli/templates/HelloWorld'
* @param destPath e.g. '/Users/martin/AwesomeApp'
* @param newProjectName e.g. 'AwesomeApp'
* @param options e.g. {
* upgrade: true,
* force: false,
* displayName: 'Hello World',
* ignorePaths: ['template/file/to/ignore.md'],
* }
*/
function copyProjectTemplateAndReplace(srcPath, destPath, newProjectName, options) {
if (!srcPath) { throw new Error('Need a path to copy from'); }
if (!destPath) { throw new Error('Need a path to copy to'); }
if (!newProjectName) { throw new Error('Need a project name'); }
options = options || {};
walk(srcPath).forEach(absoluteSrcFilePath => {
// 'react-native upgrade'
if (options.upgrade) {
// Don't upgrade these files
const fileName = path.basename(absoluteSrcFilePath);
// This also includes __tests__/index.*.js
if (fileName === 'index.ios.js') { return; }
if (fileName === 'index.android.js') { return; }
if (fileName === 'index.js') { return; }
if (fileName === 'App.js') { return; }
}
const relativeFilePath = path.relative(srcPath, absoluteSrcFilePath);
const relativeRenamedPath = dotFilePath(relativeFilePath)
.replace(/HelloWorld/g, newProjectName)
.replace(/helloworld/g, newProjectName.toLowerCase());
// Templates may contain files that we don't want to copy.
// Examples:
// - Dummy package.json file included in the template only for publishing to npm
// - Docs specific to the template (.md files)
if (options.ignorePaths) {
if (!Array.isArray(options.ignorePaths)) {
throw new Error('options.ignorePaths must be an array');
}
if (options.ignorePaths.some(ignorePath => ignorePath === relativeFilePath)) {
// Skip copying this file
return;
}
}
let contentChangedCallback = null;
if (options.upgrade && (!options.force)) {
contentChangedCallback = (_, contentChanged) => {
return upgradeFileContentChangedCallback(
absoluteSrcFilePath,
relativeRenamedPath,
contentChanged,
);
};
}
copyAndReplace(
absoluteSrcFilePath,
path.resolve(destPath, relativeRenamedPath),
{
'Hello App Display Name': options.displayName || newProjectName,
'HelloWorld': newProjectName,
'helloworld': newProjectName.toLowerCase(),
},
contentChangedCallback,
);
});
}
/**
* There are various dotfiles in the templates folder in the RN repo. We want
* these to be ignored by tools when working with React Native itself.
* Example: _babelrc file is ignored by Babel, renamed to .babelrc inside
* a real app folder.
* This is especially important for .gitignore because npm has some special
* behavior of automatically renaming .gitignore to .npmignore.
*/
function dotFilePath(path) {
if (!path) {return path;}
return path
.replace('_gitignore', '.gitignore')
.replace('_gitattributes', '.gitattributes')
.replace('_babelrc', '.babelrc')
.replace('_flowconfig', '.flowconfig')
.replace('_buckconfig', '.buckconfig')
.replace('_watchmanconfig', '.watchmanconfig');
}
function upgradeFileContentChangedCallback(
absoluteSrcFilePath,
relativeDestPath,
contentChanged
) {
if (contentChanged === 'new') {
console.log(chalk.bold('new') + ' ' + relativeDestPath);
return 'overwrite';
} else if (contentChanged === 'changed') {
console.log(chalk.bold(relativeDestPath) + ' ' +
'has changed in the new version.\nDo you want to keep your ' +
relativeDestPath + ' or replace it with the ' +
'latest version?\nIf you ever made any changes ' +
'to this file, you\'ll probably want to keep it.\n' +
'You can see the new version here: ' + absoluteSrcFilePath + '\n' +
'Do you want to replace ' + relativeDestPath + '? ' +
'Answer y to replace, n to keep your version: ');
const answer = prompt();
if (answer === 'y') {
console.log('Replacing ' + relativeDestPath);
return 'overwrite';
} else {
console.log('Keeping your ' + relativeDestPath);
return 'keep';
}
} else if (contentChanged === 'identical') {
return 'keep';
} else {
throw new Error(`Unknown file changed state: ${relativeDestPath}, ${contentChanged}`);
}
}
module.exports = copyProjectTemplateAndReplace;
... ...
/**
* 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 chalk = require('chalk');
var path = require('path');
function printRunInstructions(projectDir, projectName) {
const absoluteProjectDir = path.resolve(projectDir);
// iOS
const xcodeProjectPath = path.resolve(projectDir, 'ios', projectName) + '.xcodeproj';
const relativeXcodeProjectPath = path.relative(process.cwd(), xcodeProjectPath);
console.log(chalk.white.bold('To run your app on iOS:'));
console.log(' cd ' + absoluteProjectDir);
console.log(' react-native run-ios');
console.log(' - or -');
console.log(' Open ' + relativeXcodeProjectPath + ' in Xcode');
console.log(' Hit the Run button');
// Android
console.log(chalk.white.bold('To run your app on Android:'));
console.log(' cd ' + absoluteProjectDir);
console.log(' Have an Android emulator running (quickest way to get started), or a device connected');
console.log(' react-native run-android');
}
module.exports = printRunInstructions;
... ...
// Simplified version of:
// https://github.com/0x00A/prompt-sync/blob/master/index.js
'use strict';
var fs = require('fs');
var term = 13; // carriage return
function create() {
return prompt;
function prompt(ask, value, opts) {
var insert = 0, savedinsert = 0, res, i, savedstr;
opts = opts || {};
if (Object(ask) === ask) {
opts = ask;
ask = opts.ask;
} else if (Object(value) === value) {
opts = value;
value = opts.value;
}
ask = ask || '';
var echo = opts.echo;
var masked = 'echo' in opts;
var fd = (process.platform === 'win32') ?
process.stdin.fd :
fs.openSync('/dev/tty', 'rs');
var wasRaw = process.stdin.isRaw;
if (!wasRaw) { process.stdin.setRawMode(true); }
var buf = new Buffer(3);
var str = '', character, read;
savedstr = '';
if (ask) {
process.stdout.write(ask);
}
var cycle = 0;
var prevComplete;
while (true) {
read = fs.readSync(fd, buf, 0, 3);
if (read > 1) { // received a control sequence
if (buf.toString()) {
str = str + buf.toString();
str = str.replace(/\0/g, '');
insert = str.length;
process.stdout.write('\u001b[2K\u001b[0G' + ask + str);
process.stdout.write('\u001b[' + (insert + ask.length + 1) + 'G');
buf = new Buffer(3);
}
continue; // any other 3 character sequence is ignored
}
// if it is not a control character seq, assume only one character is read
character = buf[read - 1];
// catch a ^C and return null
if (character == 3){
process.stdout.write('^C\n');
fs.closeSync(fd);
process.exit(130);
process.stdin.setRawMode(wasRaw);
return null;
}
// catch the terminating character
if (character == term) {
fs.closeSync(fd);
break;
}
if (character == 127 || (process.platform == 'win32' && character == 8)) { //backspace
if (!insert) {continue;}
str = str.slice(0, insert - 1) + str.slice(insert);
insert--;
process.stdout.write('\u001b[2D');
} else {
if ((character < 32 ) || (character > 126))
{continue;}
str = str.slice(0, insert) + String.fromCharCode(character) + str.slice(insert);
insert++;
}
if (masked) {
process.stdout.write('\u001b[2K\u001b[0G' + ask + Array(str.length + 1).join(echo));
} else {
process.stdout.write('\u001b[s');
if (insert == str.length) {
process.stdout.write('\u001b[2K\u001b[0G' + ask + str);
} else {
if (ask) {
process.stdout.write('\u001b[2K\u001b[0G' + ask + str);
} else {
process.stdout.write('\u001b[2K\u001b[0G' + str + '\u001b[' + (str.length - insert) + 'D');
}
}
process.stdout.write('\u001b[u');
process.stdout.write('\u001b[1C');
}
}
process.stdout.write('\n');
process.stdin.setRawMode(wasRaw);
return str || value || '';
}
}
module.exports = create;
... ...