UNPKG

6.79 kBJavaScriptView Raw
1/**
2 * Copyright 2015-present Desmond Yao
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Created by desmond on 4/16/17.
17 * @flow
18 */
19
20
21'use strict';
22const fs = require('fs');
23const path = require('path');
24const MODULE_REGEX = /require\s?\(([0-9]+)[^)]*\)/g;
25const EXPR_STMT = 'ExpressionStatement';
26const EMPTY_STMT = 'EmptyStatement';
27const IF_STMT = 'IfStatement';
28
29const BINARY_EXPR = 'BinaryExpression';
30const LOGICAL_EXPR = 'LogicalExpression';
31const UNARY_EXPR = 'UnaryExpression';
32const CALL_EXPR = 'CallExpression';
33const FUNC_EXPR = 'FunctionExpression';
34const COND_EXPR = 'ConditionalExpression';
35const IDENTIFIER = 'Identifier';
36const LITERAL_NUM = 'NumericLiteral';
37const LITERAL_STR = 'StringLiteral';
38
39import type {Config} from '../flow/types';
40
41const DEFAULT_ASSET_EXTS = [
42 'bmp', 'gif', 'jpg', 'jpeg', 'png', 'psd', 'svg', 'webp', // Image formats
43 'm4v', 'mov', 'mp4', 'mpeg', 'mpg', 'webm', // Video formats
44 'aac', 'aiff', 'caf', 'm4a', 'mp3', 'wav', // Audio formats
45 'html', 'pdf', // Document formats
46];
47
48export function isReactNativeEntry(moduleName : string) : boolean {
49 return moduleName === 'react-native-implementation' ||
50 moduleName === 'react-native/Libraries/react-native/react-native.js';
51}
52
53export function isAssetModule(moduleName : string) : boolean {
54 let ext = moduleName.substring(moduleName.lastIndexOf('.') + 1);
55 return DEFAULT_ASSET_EXTS.indexOf(ext) > 0;
56}
57
58export function isEmptyStmt(node : any) : boolean {
59 try {
60 return node.type === EMPTY_STMT;
61 } catch (e) {
62 return false;
63 }
64}
65
66export function getAssetConfig(node: any) : any {
67 const func = node.expression.arguments[0];
68 const rhs = func.body.body[0].expression.right; //require(240).registerAsset({...})
69 const propNode = rhs.arguments[0].properties; // {...}
70 const assetConfig = {
71 code: {
72 start : rhs.arguments[0].start,
73 end: rhs.arguments[0].end
74 }
75 };
76 propNode.forEach(prop => {
77 let key = prop.key.value ? prop.key.value : prop.key.name;
78 if (key === 'scales') {
79 let value = [];
80 prop.value.elements.forEach(scaleNode => {
81 value.push(scaleNode.value);
82 });
83 assetConfig[key] = value;
84 } else {
85 assetConfig[key] = prop.value.value;
86 }
87 });
88 return assetConfig;
89}
90
91export function isModuleCall(node : any) : boolean {
92 try {
93 return node.type === EXPR_STMT
94 && node.expression.type === CALL_EXPR
95 && node.expression.callee.type === IDENTIFIER
96 && node.expression.callee.name === 'require'
97 && node.expression.arguments.length === 1
98 && node.expression.arguments[0].type === LITERAL_NUM;
99 } catch (e) {
100 return false;
101 }
102}
103
104export function isRequirePolyfillCondition(node: any, dev: boolean) : boolean {
105 if (node.type === IF_STMT
106 && node.test.type === LOGICAL_EXPR
107 && node.test.left.name === '__DEV__'
108 && node.test.operator === '&&'
109 && node.test.right.type === BINARY_EXPR) {
110 let binaryExpr = node.test.right;
111 if (dev) {
112 return binaryExpr.left.operator === 'typeof'
113 && binaryExpr.operator === '==='
114 && binaryExpr.right.type === LITERAL_STR;
115 } else {
116 return binaryExpr.left.type === LITERAL_STR
117 && binaryExpr.operator === '=='
118 && binaryExpr.right.operator === 'typeof';
119 }
120 }
121}
122
123export function isPolyfillCall(node : any, dev : boolean) : boolean {
124 try {
125 let isPolyfillCallExpr = (expr: any) => {
126 return expr.type === CALL_EXPR
127 && expr.callee.type === FUNC_EXPR
128 && expr.callee.params.length === 1
129 && expr.callee.params[0].type === IDENTIFIER
130 && expr.arguments.length === 1
131 && expr.arguments[0].type === COND_EXPR;
132 };
133 if (dev) {
134 return node.type === EXPR_STMT && isPolyfillCallExpr(node.expression);
135 } else {
136 return node.type === EXPR_STMT
137 && node.expression.type === UNARY_EXPR
138 && isPolyfillCallExpr(node.expression.argument);
139 }
140 } catch (e) {
141 return false;
142 }
143}
144
145export function isModuleDeclaration(node : any) : boolean {
146 try {
147 return node.type === EXPR_STMT
148 && node.expression.type === CALL_EXPR
149 && node.expression.callee.type === IDENTIFIER
150 && node.expression.callee.name === '__d';
151 } catch (e) {
152 return false;
153 }
154}
155
156export function replaceModuleIdWithName(codeBlob : string, modules : any) : string {
157 let dependencies = getModuleDependencyCodeRange(codeBlob, 0, codeBlob.length);
158 if (dependencies) {
159 dependencies.forEach(deps => {
160 let moduleName = modules[deps.module].name;
161 codeBlob = codeBlob.replace(deps.code, 'require(\"' + moduleName + '\")');
162 });
163 }
164 return codeBlob;
165}
166
167export function getModuleDependency(codeBlob : string, start : number, end : number) : Array<number> {
168 const dependency = [];
169 const bodyString = codeBlob.substring(start, end);
170 let result;
171 while(result = MODULE_REGEX.exec(bodyString)) {
172 dependency.push(parseInt(result[1]));
173 }
174 return dependency;
175}
176
177export function getModuleDependencyCodeRange(codeBlob : string, start : number, end : number) : Array<any> {
178 const dependency = [];
179 const bodyString = codeBlob.substring(start, end);
180 let result;
181 while(result = MODULE_REGEX.exec(bodyString)) {
182 dependency.push({
183 code: result[0],
184 module: parseInt(result[1])
185 });
186 }
187 return dependency;
188}
189
190export function ensureFolder(dir : string) {
191 try {
192 fs.accessSync(dir, fs.F_OK);
193 return true;
194 } catch (e) {
195 fs.mkdirSync(dir);
196 return false;
197 }
198}
199
200/**
201 * 递归创建目录 同步方法
202 */
203export function mkdirsSync(dirname) {
204 //console.log(dirname);
205 if (fs.existsSync(dirname)) {
206 return true;
207 } else {
208 if (mkdirsSync(path.dirname(dirname))) {
209 fs.mkdirSync(dirname);
210 return true;
211 }
212 }
213}
214
215// export function resolvePathArrays(root: string, array : Array<any>, val ?: string) : Array<any> {
216// const newArr = [];
217// array.forEach(item => {
218// if (val) {
219// let newItem = Object.assign({}, item);
220// newItem[val] = path.resolve(root, item[val]);
221// newArr.push(newItem);
222// } else if (typeof item === 'string') {
223// newArr.push(path.resolve(root, item));
224// }
225// });
226// return newArr;
227// }
228
229