1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | 'use strict';
|
8 |
|
9 | const appc = require('node-appc');
|
10 | const DOMParser = require('xmldom').DOMParser;
|
11 | const fs = require('fs-extra');
|
12 | const path = require('path');
|
13 |
|
14 | const plist = appc.plist;
|
15 | const version = appc.version;
|
16 | const xml = appc.xml;
|
17 | const __ = appc.i18n(__dirname).__;
|
18 |
|
19 | const defaultDOMParserArgs = { errorHandler: function () {} };
|
20 |
|
21 | module.exports = tiapp;
|
22 |
|
23 | function toXml(dom, parent, name, value) {
|
24 |
|
25 | if (name === 'properties') {
|
26 | Object.keys(value).forEach(function (v) {
|
27 | dom.create('property', {
|
28 | name: v,
|
29 | type: value[v].type || 'string',
|
30 | nodeValue: value[v].value
|
31 | }, parent);
|
32 | });
|
33 | return;
|
34 | }
|
35 |
|
36 | var node = dom.create(name, null, parent);
|
37 |
|
38 | switch (name) {
|
39 | case 'deployment-targets':
|
40 | Object.keys(value).forEach(function (v) {
|
41 | dom.create('target', {
|
42 | device: v,
|
43 | nodeValue: value[v]
|
44 | }, node);
|
45 | });
|
46 | break;
|
47 |
|
48 | case 'code-processor':
|
49 | Object.keys(value).forEach(function (key) {
|
50 | if (key === 'plugins') {
|
51 | if (Array.isArray(value[key]) && value[key].length) {
|
52 | dom.create('plugins', null, node, function (plugins) {
|
53 | value[key].forEach(function (p) {
|
54 | dom.create('plugin', { nodeValue: p }, plugins);
|
55 | });
|
56 | });
|
57 | }
|
58 | } else if (key === 'options') {
|
59 | if (Object.prototype.toString.call(value[key]) === '[object Object]') {
|
60 | dom.create('options', null, node, function (options) {
|
61 | Object.keys(value[key]).forEach(function (opt) {
|
62 | dom.create(opt, { nodeValue: value[key][opt] }, options);
|
63 | });
|
64 | });
|
65 | }
|
66 | } else {
|
67 | dom.create(key, { nodeValue: value[key] }, node);
|
68 | }
|
69 | });
|
70 | break;
|
71 |
|
72 | case 'ios':
|
73 | if (Object.prototype.hasOwnProperty.call(value, 'exclude-dir-from-asset-catalog')) {
|
74 | dom.create('exclude-dir-from-asset-catalog', { nodeValue: !!value['exclude-dir-from-asset-catalog'] }, node);
|
75 | }
|
76 |
|
77 | if (Object.prototype.hasOwnProperty.call(value, 'enable-launch-screen-storyboard')) {
|
78 | dom.create('enable-launch-screen-storyboard', { nodeValue: !!value['enable-launch-screen-storyboard'] }, node);
|
79 | }
|
80 |
|
81 | if (Object.prototype.hasOwnProperty.call(value, 'enablecoverage')) {
|
82 | dom.create('enablecoverage', { nodeValue: !!value['enablecoverage'] }, node);
|
83 | }
|
84 |
|
85 | if (Object.prototype.hasOwnProperty.call(value, 'enablemdfind')) {
|
86 | dom.create('enablemdfind', { nodeValue: !!value['enablemdfind'] }, node);
|
87 | }
|
88 |
|
89 | if (Object.prototype.hasOwnProperty.call(value, 'min-ios-ver')) {
|
90 | dom.create('min-ios-ver', { nodeValue: version.format(value['min-ios-ver'], 2) }, node);
|
91 | }
|
92 |
|
93 | if (Object.prototype.hasOwnProperty.call(value, 'default-background-color')) {
|
94 | dom.create('default-background-color', { nodeValue: value['default-background-color'] }, node);
|
95 | }
|
96 |
|
97 | if (Object.prototype.hasOwnProperty.call(value, 'team-id')) {
|
98 | dom.create('team-id', { nodeValue: value['team-id'] }, node);
|
99 | }
|
100 |
|
101 | if (Object.prototype.hasOwnProperty.call(value, 'use-jscore-framework')) {
|
102 | dom.create('use-jscore-framework', { nodeValue: !!value['use-jscore-framework'] }, node);
|
103 | }
|
104 |
|
105 | if (Object.prototype.hasOwnProperty.call(value, 'run-on-main-thread')) {
|
106 | dom.create('run-on-main-thread', { nodeValue: !!value['run-on-main-thread'] }, node);
|
107 | }
|
108 |
|
109 | if (Object.prototype.hasOwnProperty.call(value, 'use-autolayout')) {
|
110 | dom.create('use-autolayout', { nodeValue: !!value['use-autolayout'] }, node);
|
111 | }
|
112 |
|
113 | if (Object.prototype.hasOwnProperty.call(value, 'use-new-build-system')) {
|
114 | dom.create('use-new-build-system', { nodeValue: !!value['use-new-build-system'] }, node);
|
115 | }
|
116 |
|
117 | if (Object.prototype.hasOwnProperty.call(value, 'use-app-thinning')) {
|
118 | dom.create('use-app-thinning', { nodeValue: !!value['use-app-thinning'] }, node);
|
119 | }
|
120 |
|
121 | if (Object.prototype.hasOwnProperty.call(value, 'log-server-port')) {
|
122 | dom.create('log-server-port', { nodeValue: value['log-server-port'] }, node);
|
123 | }
|
124 |
|
125 | if (value.capabilities) {
|
126 | var capNode = dom.create('capabilities', null, node);
|
127 | Object.keys(value.capabilities).forEach(function (cap) {
|
128 | if (cap === 'app-groups') {
|
129 | var appGroupNode = dom.create(cap, null, capNode);
|
130 | value.capabilities[cap].forEach(function (group) {
|
131 | dom.create('group', { nodeValue: group }, appGroupNode);
|
132 | });
|
133 | appGroupNode.appendChild(dom.createTextNode('\r\n\t\t\t'));
|
134 | capNode.appendChild(dom.createTextNode('\r\n\t\t'));
|
135 | }
|
136 | });
|
137 | }
|
138 |
|
139 | if (value.entitlements) {
|
140 | const enNode = dom.create('entitlements', null, node);
|
141 | const pl = new plist();
|
142 | appc.util.mix(pl, value.entitlements);
|
143 | const doc = pl.toXml(3);
|
144 | enNode.appendChild(dom.createTextNode('\r\n\t\t\t'));
|
145 | xml.forEachElement(doc, function (elem) {
|
146 | enNode.appendChild(elem);
|
147 | });
|
148 | enNode.appendChild(dom.createTextNode('\r\n\t\t'));
|
149 | }
|
150 |
|
151 | if (value.plist) {
|
152 | const plNode = dom.create('plist', null, node);
|
153 | const pl = new plist();
|
154 | appc.util.mix(pl, value.plist);
|
155 | const doc = pl.toXml(3);
|
156 | plNode.appendChild(dom.createTextNode('\r\n\t\t\t'));
|
157 | xml.forEachElement(doc, function (elem) {
|
158 | plNode.appendChild(elem);
|
159 | });
|
160 | plNode.appendChild(dom.createTextNode('\r\n\t\t'));
|
161 | }
|
162 |
|
163 | if (Array.isArray(value.extensions)) {
|
164 | var extsNode = dom.create('extentions', null, node);
|
165 | value.extensions.forEach(function (ext) {
|
166 | var extNode = dom.create('extention', { projectPath: ext.projectPath }, extsNode);
|
167 | Array.isArray(ext.targets) && ext.targets.forEach(function (target) {
|
168 | var targetNode = dom.create('target', { name: target.name }, extNode);
|
169 | if (target.ppUUIDs && typeof target.ppUUIDs === 'object' && Object.keys(target.ppUUIDs).length) {
|
170 | var ppUUIDsNode = dom.create('provisioning-profiles', null, targetNode);
|
171 | Object.keys(target.ppUUIDs).forEach(function (type) {
|
172 | dom.create(type, { nodeValue: target.ppUUIDs[type] }, ppUUIDsNode);
|
173 | });
|
174 | ppUUIDsNode.appendChild(dom.createTextNode('\r\n\t\t\t\t\t'));
|
175 | }
|
176 | targetNode.appendChild(dom.createTextNode('\r\n\t\t\t\t'));
|
177 | });
|
178 | extNode.appendChild(dom.createTextNode('\r\n\t\t\t'));
|
179 | });
|
180 | extsNode.appendChild(dom.createTextNode('\r\n\t\t'));
|
181 | }
|
182 | break;
|
183 |
|
184 | case 'iphone':
|
185 | value.orientations && Object.keys(value.orientations).forEach(function (o) {
|
186 | dom.create('orientations', { device: o }, node, function (orientations) {
|
187 | value.orientations[o].forEach(function (p) {
|
188 | dom.create('orientation', { nodeValue: p }, orientations);
|
189 | });
|
190 | });
|
191 | });
|
192 |
|
193 | value.backgroundModes && dom.create('background', null, node, function (background) {
|
194 | value.backgroundModes.forEach(function (mode) {
|
195 | dom.create('mode', { nodeValue: mode }, background);
|
196 | });
|
197 | });
|
198 |
|
199 | value.requiredFeatures && dom.create('requires', null, node, function (requires) {
|
200 | value.requiredFeatures.forEach(function (feature) {
|
201 | dom.create('feature', { nodeValue: feature }, requires);
|
202 | });
|
203 | });
|
204 |
|
205 | value.types && dom.create('types', null, node, function (types) {
|
206 | value.types.forEach(function (typeObj) {
|
207 | dom.create('type', null, types, function (typeNode) {
|
208 | dom.create('name', { nodeValue: typeObj.name }, typeNode);
|
209 | dom.create('icon', { nodeValue: typeObj.icon }, typeNode);
|
210 | dom.create('uti', { nodeValue: typeObj.uti.join(',') }, typeNode);
|
211 | dom.create('owner', { nodeValue: !!typeObj.owner }, typeNode);
|
212 | });
|
213 | });
|
214 | });
|
215 | break;
|
216 |
|
217 | case 'android':
|
218 | node.setAttribute('xmlns:android', 'http://schemas.android.com/apk/res/android');
|
219 |
|
220 | if (value.manifest) {
|
221 | node.appendChild(dom.createTextNode('\r\n' + new Array(3).join('\t')));
|
222 | const opts = defaultDOMParserArgs;
|
223 | opts.xmlns = { android: 'http://schemas.android.com/apk/res/android' };
|
224 | node.appendChild(new DOMParser(opts).parseFromString(value.manifest));
|
225 | }
|
226 |
|
227 | if (Object.prototype.hasOwnProperty.call(value, 'tool-api-level')) {
|
228 | dom.create('tool-api-level', { nodeValue: value['tool-api-level'] }, node);
|
229 | }
|
230 |
|
231 | if (Object.prototype.hasOwnProperty.call(value, 'abi')) {
|
232 | dom.create('abi', { nodeValue: Array.isArray(value.abi) ? value.abi.join(',') : value.abi }, node);
|
233 | }
|
234 |
|
235 | if (value.activities) {
|
236 | dom.create('activities', null, node, function (node) {
|
237 | Object.keys(value.activities).forEach(function (url) {
|
238 | var attrs = {};
|
239 | Object.keys(value.activities[url]).forEach(function (attr) {
|
240 | attr !== 'classname' && (attrs[attr] = value.activities[url][attr]);
|
241 | });
|
242 | dom.create('activity', attrs, node);
|
243 | });
|
244 | });
|
245 | }
|
246 |
|
247 | if (value.services) {
|
248 | dom.create('services', null, node, function (node) {
|
249 | Object.keys(value.services).forEach(function (url) {
|
250 | var attrs = {};
|
251 | Object.keys(value.services[url]).forEach(function (attr) {
|
252 | attr !== 'classname' && (attrs[attr] = value.services[url][attr]);
|
253 | });
|
254 | dom.create('service', attrs, node);
|
255 | });
|
256 | });
|
257 | }
|
258 | break;
|
259 |
|
260 | case 'mobileweb':
|
261 | Object.keys(value).forEach(function (prop) {
|
262 | switch (prop) {
|
263 | case 'build':
|
264 | dom.create('build', null, node, function (build) {
|
265 | Object.keys(value.build).forEach(function (name) {
|
266 | dom.create(name, null, build, function (deployment) {
|
267 | Object.keys(value.build[name]).forEach(function (d) {
|
268 | var val = value.build[name][d];
|
269 | switch (d) {
|
270 | case 'js':
|
271 | case 'css':
|
272 | case 'html':
|
273 | dom.create(d, null, deployment, function (type) {
|
274 | Object.keys(val).forEach(function (v) {
|
275 | dom.create(v, { nodeValue: val[v] }, type);
|
276 | });
|
277 | });
|
278 | break;
|
279 |
|
280 | default:
|
281 | dom.create(d, { nodeValue: val }, deployment);
|
282 | }
|
283 | });
|
284 | });
|
285 | });
|
286 | });
|
287 | break;
|
288 |
|
289 | case 'analytics':
|
290 | case 'filesystem':
|
291 | case 'map':
|
292 | case 'splash':
|
293 | case 'unsupported-platforms':
|
294 | dom.create(prop, null, node, function (section) {
|
295 | Object.keys(value[prop]).forEach(function (key) {
|
296 | dom.create(key, { nodeValue: value[prop][key] }, section);
|
297 | });
|
298 | });
|
299 | break;
|
300 |
|
301 | case 'precache':
|
302 | dom.create('precache', null, node, function (precache) {
|
303 | Object.keys(value[prop]).forEach(function (type) {
|
304 | value[prop][type].forEach(function (n) {
|
305 | dom.create(type, { nodeValue: n }, precache);
|
306 | });
|
307 | });
|
308 | });
|
309 | break;
|
310 |
|
311 | default:
|
312 | dom.create(prop, { nodeValue: value[prop] }, node);
|
313 | }
|
314 | });
|
315 | break;
|
316 |
|
317 | case 'tizen':
|
318 | node.setAttribute('xmlns:tizen', 'http://ti.appcelerator.org');
|
319 |
|
320 | value.appid && node.setAttribute('appid', value.appid);
|
321 |
|
322 | var tizenSection = new DOMParser(defaultDOMParserArgs).parseFromString('<?xml version="1.0" encoding="UTF-8"?>\n<tizen xmlns:tizen="http://ti.appcelerator.org" appid="' + value.appid + '"> ' + value.configXml + ' </tizen>', 'text/xml').documentElement,
|
323 | child = tizenSection.firstChild,
|
324 | nextSibl;
|
325 | while (child) {
|
326 |
|
327 |
|
328 | nextSibl = child.nextSibling;
|
329 | node.appendChild(child);
|
330 | child = nextSibl;
|
331 | }
|
332 | break;
|
333 |
|
334 | case 'windows':
|
335 | Object.keys(value).forEach(function (prop) {
|
336 | switch (prop) {
|
337 | default:
|
338 | dom.create(prop, { nodeValue: value[prop] }, node);
|
339 | }
|
340 | });
|
341 | break;
|
342 |
|
343 | case 'windows-phone':
|
344 | Object.keys(value).forEach(function (prop) {
|
345 | switch (prop) {
|
346 | default:
|
347 | dom.create(prop, { nodeValue: value[prop] }, node);
|
348 | }
|
349 | });
|
350 | break;
|
351 |
|
352 | case 'webpack':
|
353 | if (value.type) {
|
354 | dom.create('type', { nodeValue: value.type }, node);
|
355 | }
|
356 | if (Array.isArray(value.transpileDependencies)) {
|
357 | dom.create('transpile-dependencies', null, node, depsNode => {
|
358 | for (const dep of value.transpileDependencies) {
|
359 | dom.create('dep', { nodeValue: dep }, depsNode);
|
360 | }
|
361 | });
|
362 | }
|
363 | break;
|
364 |
|
365 | case 'modules':
|
366 | value.forEach(function (mod) {
|
367 | dom.create('module', {
|
368 | platform: mod.platform,
|
369 | version: mod.version ? version.format(mod.version, 2) : null,
|
370 | 'deploy-type': mod.deployType || null,
|
371 | nodeValue: mod.id
|
372 | }, node);
|
373 | });
|
374 | break;
|
375 |
|
376 | case 'plugins':
|
377 | value.forEach(function (plugin) {
|
378 | dom.create('plugin', {
|
379 | version: version.format(plugin.version, 2),
|
380 | nodeValue: plugin.id
|
381 | }, node);
|
382 | });
|
383 | break;
|
384 |
|
385 | default:
|
386 | node.appendChild(dom.createTextNode(value));
|
387 | return;
|
388 | }
|
389 |
|
390 | node.appendChild(dom.createTextNode('\r\n' + new Array(2).join('\t')));
|
391 | }
|
392 |
|
393 | function toJS(obj, doc) {
|
394 | var node = doc.firstChild;
|
395 | while (node) {
|
396 | if (node.nodeType === xml.ELEMENT_NODE) {
|
397 | switch (node.tagName) {
|
398 | case 'property':
|
399 | var name = xml.getAttr(node, 'name'),
|
400 | type = xml.getAttr(node, 'type') || 'string',
|
401 | value = xml.getValue(node);
|
402 | if (name) {
|
403 | obj.properties || (obj.properties = {});
|
404 | obj.properties[name] = {
|
405 | type: type,
|
406 | value: type === 'bool' ? !!value
|
407 | : type === 'int' ? (parseInt(value) || 0)
|
408 | : type === 'double' ? (parseFloat(value) || 0)
|
409 | : '' + value
|
410 | };
|
411 | }
|
412 | break;
|
413 |
|
414 | case 'deployment-targets':
|
415 | var targets = obj['deployment-targets'] = {};
|
416 | xml.forEachElement(node, function (elem) {
|
417 | var dev = xml.getAttr(elem, 'device');
|
418 | dev && (targets[dev] = xml.getValue(elem));
|
419 | });
|
420 | break;
|
421 |
|
422 | case 'code-processor':
|
423 | var codeProcessor = obj['code-processor'] = {};
|
424 | xml.forEachElement(node, function (elem) {
|
425 | switch (elem.tagName) {
|
426 | case 'plugins':
|
427 | codeProcessor.plugins = [];
|
428 | xml.forEachElement(elem, function (elem) {
|
429 | if (elem.tagName === 'plugin') {
|
430 | codeProcessor.plugins.push(xml.getValue(elem));
|
431 | }
|
432 | });
|
433 | break;
|
434 | case 'options':
|
435 | codeProcessor.options = {};
|
436 | xml.forEachElement(elem, function (elem) {
|
437 | codeProcessor.options[elem.tagName] = xml.getValue(elem);
|
438 | });
|
439 | break;
|
440 | default:
|
441 | codeProcessor[elem.tagName] = xml.getValue(elem);
|
442 | }
|
443 | });
|
444 | break;
|
445 |
|
446 | case 'ios':
|
447 | var ios = obj.ios = {};
|
448 | xml.forEachElement(node, function (elem) {
|
449 | switch (elem.tagName) {
|
450 | case 'exclude-dir-from-asset-catalog':
|
451 | case 'enable-launch-screen-storyboard':
|
452 | case 'enablecoverage':
|
453 | case 'enablemdfind':
|
454 | case 'default-background-color':
|
455 | case 'team-id':
|
456 | case 'use-jscore-framework':
|
457 | case 'run-on-main-thread':
|
458 | case 'use-autolayout':
|
459 | case 'use-app-thinning':
|
460 | case 'use-new-build-system':
|
461 | case 'log-server-port':
|
462 | ios[elem.tagName] = xml.getValue(elem);
|
463 | break;
|
464 |
|
465 | case 'min-ios-ver':
|
466 | if (elem.firstChild) {
|
467 | ios['min-ios-ver'] = parseFloat(elem.firstChild.data) || 0;
|
468 | }
|
469 | break;
|
470 |
|
471 | case 'capabilities':
|
472 | ios.capabilities = {};
|
473 | xml.forEachElement(elem, function (elem) {
|
474 | if (elem.tagName === 'app-groups') {
|
475 | var appGroups = ios.capabilities[elem.tagName] = [];
|
476 | xml.forEachElement(elem, function (elem) {
|
477 | if (elem.tagName === 'group') {
|
478 | var group = xml.getValue(elem);
|
479 | group && appGroups.push(group);
|
480 | }
|
481 | });
|
482 | }
|
483 | });
|
484 | break;
|
485 |
|
486 | case 'entitlements':
|
487 | ios.entitlements = {};
|
488 | xml.forEachElement(elem, function (elem) {
|
489 | if (elem.tagName === 'dict') {
|
490 | const pl = new plist().parse('<plist version="1.0">' + elem.toString() + '</plist>');
|
491 | Object.keys(pl).forEach(prop => ios.entitlements[prop] = pl[prop]);
|
492 | }
|
493 | });
|
494 | break;
|
495 |
|
496 | case 'plist':
|
497 | ios.plist = {};
|
498 | xml.forEachElement(elem, function (elem) {
|
499 | if (elem.tagName === 'dict') {
|
500 | var pl = new plist().parse('<plist version="1.0">' + elem.toString() + '</plist>');
|
501 | Object.keys(pl).forEach(function (prop) {
|
502 | if (!/^CFBundle(DisplayName|Executable|IconFile|Identifier|InfoDictionaryVersion|Name|PackageType|Signature)|LSRequiresIPhoneOS$/.test(prop)) {
|
503 | ios.plist[prop] = pl[prop];
|
504 | }
|
505 | });
|
506 | }
|
507 | });
|
508 | break;
|
509 |
|
510 | case 'extensions':
|
511 | var extensions = ios.extensions = [];
|
512 | xml.forEachElement(elem, function (elem) {
|
513 | if (elem.tagName !== 'extension') {
|
514 | return;
|
515 | }
|
516 |
|
517 | var ext = {
|
518 | projectPath: elem.getAttribute('projectPath') || null,
|
519 | targets: []
|
520 | };
|
521 | extensions.push(ext);
|
522 |
|
523 | xml.forEachElement(elem, function (elem) {
|
524 | if (elem.tagName !== 'target') {
|
525 | return;
|
526 | }
|
527 |
|
528 | var target = {
|
529 | name: elem.getAttribute('name'),
|
530 | ppUUIDs: {}
|
531 | };
|
532 | ext.targets.push(target);
|
533 |
|
534 | xml.forEachElement(elem, function (elem) {
|
535 | if (elem.tagName === 'provisioning-profiles') {
|
536 | xml.forEachElement(elem, function (elem) {
|
537 | target.ppUUIDs[elem.tagName] = xml.getValue(elem);
|
538 | });
|
539 | }
|
540 | });
|
541 | });
|
542 | });
|
543 | break;
|
544 | }
|
545 | });
|
546 | break;
|
547 |
|
548 | case 'blackberry':
|
549 | var blackberry = obj.blackberry = {};
|
550 | obj.blackberry.other = '';
|
551 | xml.forEachElement(node, function (elem) {
|
552 | switch (elem.tagName) {
|
553 | case 'permissions':
|
554 | const permissions = blackberry.permissions = {};
|
555 | xml.forEachElement(elem, (e) => permissions[xml.getValue(e)] = true);
|
556 | break;
|
557 |
|
558 | case 'build-id':
|
559 | case 'orientation':
|
560 | blackberry[elem.tagName] = xml.getValue(elem);
|
561 | break;
|
562 |
|
563 | default:
|
564 | obj.blackberry.other += elem.toString() + '\n';
|
565 | }
|
566 | });
|
567 | break;
|
568 |
|
569 | case 'iphone':
|
570 | var iphone = obj.iphone = {},
|
571 | dev;
|
572 | xml.forEachElement(node, function (elem) {
|
573 | switch (elem.tagName) {
|
574 | case 'orientations':
|
575 | iphone.orientations || (iphone.orientations = {});
|
576 | if (dev = xml.getAttr(elem, 'device')) {
|
577 | iphone.orientations[dev] || (iphone.orientations[dev] = []);
|
578 | xml.forEachElement(elem, function (elem) {
|
579 | iphone.orientations[dev].push(xml.getValue(elem));
|
580 | });
|
581 | }
|
582 | break;
|
583 |
|
584 | case 'background':
|
585 | xml.forEachElement(elem, function (elem) {
|
586 | if (elem.tagName === 'mode') {
|
587 | iphone.backgroundModes || (iphone.backgroundModes = []);
|
588 | iphone.backgroundModes.push(xml.getValue(elem));
|
589 | }
|
590 | });
|
591 | break;
|
592 |
|
593 | case 'requires':
|
594 | xml.forEachElement(elem, function (elem) {
|
595 | if (elem.tagName === 'feature') {
|
596 | iphone.requiredFeatures || (iphone.requiredFeatures = []);
|
597 | iphone.requiredFeatures.push(xml.getValue(elem));
|
598 | }
|
599 | });
|
600 | break;
|
601 |
|
602 | case 'types':
|
603 | xml.forEachElement(elem, function (elem) {
|
604 | if (elem.tagName === 'type') {
|
605 | iphone.types || (iphone.types = []);
|
606 | var type = {
|
607 | name: '',
|
608 | icon: '',
|
609 | uti: [],
|
610 | owner: false
|
611 | };
|
612 | xml.forEachElement(elem, function (elem) {
|
613 | var v = xml.getValue(elem);
|
614 | type[elem.tagName] = elem.tagName === 'uti' ? v.split(',').map(s => s.trim()) : v;
|
615 | });
|
616 | iphone.types.push(type);
|
617 | }
|
618 | });
|
619 | break;
|
620 | }
|
621 | });
|
622 | break;
|
623 |
|
624 | case 'android':
|
625 | var android = obj.android = {},
|
626 | formatUrl = (url) => {
|
627 | return appc.string.capitalize(url.replace(/^app:\/\//, '').replace(/\.js$/, '').replace(/\//g, '_')).replace(/[/ .$&@]/g, '_');
|
628 | };
|
629 |
|
630 | xml.forEachElement(node, function (elem) {
|
631 | switch (elem.tagName) {
|
632 | case 'manifest':
|
633 |
|
634 |
|
635 |
|
636 | android.manifest = elem.toString().replace(/ xmlns:android="http:\/\/schemas\.android\.com\/apk\/res\/android"/, '');
|
637 | break;
|
638 |
|
639 | case 'abi':
|
640 | android[elem.tagName] = xml.getValue(elem).split(',').map(s => s.trim());
|
641 | break;
|
642 |
|
643 | case 'tool-api-level':
|
644 | android[elem.tagName] = xml.getValue(elem);
|
645 | break;
|
646 |
|
647 | case 'activities':
|
648 | case 'services':
|
649 | var type = elem.tagName,
|
650 | dest = android[type] = {};
|
651 |
|
652 | xml.forEachElement(elem, function (elem) {
|
653 | if ((type === 'activities' && elem.tagName === 'activity') || (type === 'services' && elem.tagName === 'service')) {
|
654 | var url = xml.getAttr(elem, 'url') || xml.getValue(elem) || '';
|
655 | if (url) {
|
656 | var a = dest[url] = {};
|
657 | xml.forEachAttr(elem, function (attr) {
|
658 | a[attr.name] = xml.parse(attr.value);
|
659 | });
|
660 | a['classname'] = formatUrl(url) + (type === 'activities' ? 'Activity' : 'Service');
|
661 | if (type === 'services') {
|
662 | a['type'] = xml.getAttr(elem, 'type') || 'standard';
|
663 | }
|
664 | a['url'] = url;
|
665 | xml.forEachElement(elem, function (elem) {
|
666 | if (elem.tagName === 'intent-filter') {
|
667 | var intentFilter = null;
|
668 | xml.forEachElement(elem, function (elem) {
|
669 | if (elem.tagName === 'action' || elem.tagName === 'category' || elem.tagName === 'data') {
|
670 | intentFilter || (intentFilter = {});
|
671 | intentFilter[elem.tagName] || (intentFilter[elem.tagName] = []);
|
672 | if (elem.tagName === 'data') {
|
673 | var a = {};
|
674 | xml.forEachAttr(elem, function (attr) {
|
675 | a[attr.name.replace(/^android:/, '')] = xml.parse(attr.value);
|
676 | });
|
677 | intentFilter[elem.tagName].push(a);
|
678 | } else {
|
679 | intentFilter[elem.tagName].push(xml.getAttr(elem, 'android:name'));
|
680 | }
|
681 | }
|
682 | });
|
683 | if (intentFilter) {
|
684 | a['intent-filter'] || (a['intent-filter'] = []);
|
685 | a['intent-filter'].push(intentFilter);
|
686 | }
|
687 | } else if (elem.tagName === 'meta-data') {
|
688 | var obj = {};
|
689 | xml.forEachAttr(elem, function (attr) {
|
690 | obj[attr.name.replace(/^android:/, '')] = xml.parse(attr.value);
|
691 | });
|
692 | if (obj.name) {
|
693 | a['meta-data'] || (a['meta-data'] = {});
|
694 | a['meta-data'][obj.name] = obj;
|
695 | }
|
696 | }
|
697 | });
|
698 | }
|
699 | }
|
700 | });
|
701 | break;
|
702 | }
|
703 | });
|
704 | break;
|
705 |
|
706 | case 'mobileweb':
|
707 | var mobileweb = obj.mobileweb = {};
|
708 | xml.forEachElement(node, function (elem) {
|
709 | switch (elem.tagName) {
|
710 | case 'build':
|
711 | var build = mobileweb.build = {};
|
712 | xml.forEachElement(elem, function (elem) {
|
713 | var profile = build[elem.tagName] = {};
|
714 | xml.forEachElement(elem, function (elem) {
|
715 | switch (elem.tagName) {
|
716 | case 'js':
|
717 | case 'css':
|
718 | case 'html':
|
719 | var filetype = profile[elem.tagName] = {};
|
720 | xml.forEachElement(elem, function (elem) {
|
721 | filetype[elem.tagName] = xml.getValue(elem);
|
722 | });
|
723 | break;
|
724 |
|
725 | default:
|
726 | profile[elem.tagName] = xml.getValue(elem);
|
727 | }
|
728 | });
|
729 | });
|
730 | break;
|
731 |
|
732 | case 'analytics':
|
733 | case 'filesystem':
|
734 | case 'map':
|
735 | case 'splash':
|
736 | case 'unsupported-platforms':
|
737 | mobileweb[elem.tagName] = {};
|
738 | xml.forEachElement(elem, function (subelem) {
|
739 | mobileweb[elem.tagName][subelem.tagName] = xml.getValue(subelem);
|
740 | });
|
741 | break;
|
742 |
|
743 | case 'precache':
|
744 | var precache = mobileweb.precache = {};
|
745 | xml.forEachElement(elem, function (elem) {
|
746 | precache[elem.tagName] || (precache[elem.tagName] = []);
|
747 | precache[elem.tagName].push(xml.getValue(elem));
|
748 | });
|
749 | break;
|
750 |
|
751 | default:
|
752 | mobileweb[elem.tagName] = xml.getValue(elem);
|
753 | }
|
754 | });
|
755 | break;
|
756 |
|
757 | case 'tizen':
|
758 | var tizen = obj.tizen = {
|
759 | appid: undefined,
|
760 | configXml: undefined
|
761 | };
|
762 |
|
763 | tizen.appid = xml.getAttr(node, 'appid');
|
764 | xml.forEachElement(node, function (elem) {
|
765 | tizen.configXml ? tizen.configXml = tizen.configXml + '\n' + elem.toString() : tizen.configXml = elem.toString();
|
766 | });
|
767 | break;
|
768 |
|
769 | case 'windows':
|
770 | var windows = obj.windows = {};
|
771 | xml.forEachElement(node, function (elem) {
|
772 | windows[elem.tagName] = xml.getValue(elem);
|
773 | });
|
774 | break;
|
775 |
|
776 | case 'windows-phone':
|
777 | var wp = obj['windows-phone'] = {};
|
778 | xml.forEachElement(node, function (elem) {
|
779 | switch (elem.tagName) {
|
780 | case 'target-sdk':
|
781 | wp[elem.tagName] = elem.firstChild && elem.firstChild.data.replace(/\n/g, '').trim() || '';
|
782 | break;
|
783 | default:
|
784 | wp[elem.tagName] = xml.getValue(elem);
|
785 | }
|
786 | });
|
787 | break;
|
788 |
|
789 | case 'modules':
|
790 | var modules = obj.modules = [];
|
791 | xml.forEachElement(node, function (elem) {
|
792 | var opts = {
|
793 | id: xml.getValue(elem),
|
794 | platform: xml.getAttr(elem, 'platform')
|
795 | },
|
796 | version = elem.getAttribute('version'),
|
797 | deployType = xml.getAttr(elem, 'deploy-type');
|
798 | version && (opts.version = version);
|
799 | deployType && (opts.deployType = deployType);
|
800 | modules.push(opts);
|
801 | });
|
802 | break;
|
803 |
|
804 | case 'plugins':
|
805 | var plugins = obj.plugins = [];
|
806 | xml.forEachElement(node, function (elem) {
|
807 | var opts = {
|
808 | id: xml.getValue(elem)
|
809 | },
|
810 | version = elem.getAttribute('version');
|
811 | version && (opts.version = version);
|
812 | plugins.push(opts);
|
813 | });
|
814 | break;
|
815 |
|
816 | case 'version':
|
817 | obj[node.tagName] = node.firstChild && node.firstChild.data.replace(/\n/g, '').trim() || '';
|
818 | break;
|
819 |
|
820 | case 'name':
|
821 | case 'guid':
|
822 | case 'id':
|
823 | case 'icon':
|
824 |
|
825 | obj[node.tagName] = '' + xml.getValue(node);
|
826 | if (typeof obj[node.tagName] === 'string') {
|
827 | obj[node.tagName] = obj[node.tagName].replace(/\n/g, '');
|
828 | }
|
829 | break;
|
830 |
|
831 | case 'webpack':
|
832 | const webpack = obj.webpack = {};
|
833 | xml.forEachElement(node, elem => {
|
834 | switch (elem.tagName) {
|
835 | case 'type': {
|
836 | webpack[elem.tagName] = xml.getValue(elem);
|
837 | break;
|
838 | }
|
839 | case 'transpile-dependencies': {
|
840 | const transpileDependencies = webpack.transpileDependencies = [];
|
841 | xml.forEachElement(elem, dep => {
|
842 | transpileDependencies.push(xml.getValue(dep));
|
843 | });
|
844 | break;
|
845 | }
|
846 | }
|
847 | });
|
848 | break;
|
849 |
|
850 | default:
|
851 | obj[node.tagName] = xml.getValue(node);
|
852 | }
|
853 | }
|
854 | node = node.nextSibling;
|
855 | }
|
856 | }
|
857 |
|
858 | function tiapp(filename) {
|
859 | Object.defineProperty(this, 'load', {
|
860 | value: function (file) {
|
861 | if (!fs.existsSync(file)) {
|
862 | throw new Error(__('tiapp.xml file does not exist'));
|
863 | }
|
864 | toJS(this, (new DOMParser(defaultDOMParserArgs).parseFromString(fs.readFileSync(file).toString(), 'text/xml')).documentElement);
|
865 | return this;
|
866 | }
|
867 | });
|
868 |
|
869 | Object.defineProperty(this, 'parse', {
|
870 | value: function (str) {
|
871 | toJS(this, (new DOMParser(defaultDOMParserArgs).parseFromString(str, 'text/xml')).documentElement);
|
872 | return this;
|
873 | }
|
874 | });
|
875 |
|
876 | Object.defineProperty(this, 'toString', {
|
877 | value: function (fmt) {
|
878 | if (fmt === 'xml') {
|
879 | var dom = new DOMParser(defaultDOMParserArgs).parseFromString('<ti:app xmlns:ti="http://ti.appcelerator.org"/>', 'text/xml');
|
880 |
|
881 | dom.create = function (tag, attrs, parent, callback) {
|
882 | var node = dom.createElement(tag),
|
883 | i = 0,
|
884 | p = parent;
|
885 |
|
886 | attrs && Object.keys(attrs).forEach(function (attr) {
|
887 | if (attr === 'nodeValue') {
|
888 | node.appendChild(dom.createTextNode('' + attrs[attr]));
|
889 | } else {
|
890 | attrs[attr] != undefined && node.setAttribute(attr, '' + attrs[attr]);
|
891 | }
|
892 | });
|
893 |
|
894 | if (p) {
|
895 | while (p.parentNode) {
|
896 | i++;
|
897 | p = p.parentNode;
|
898 | }
|
899 | parent.appendChild(dom.createTextNode('\r\n' + new Array(i + 1).join('\t')));
|
900 | }
|
901 |
|
902 | parent && parent.appendChild(node);
|
903 | if (callback) {
|
904 | callback(node);
|
905 | node.appendChild(dom.createTextNode('\r\n' + new Array(i + 1).join('\t')));
|
906 | }
|
907 | return node;
|
908 | };
|
909 |
|
910 | Object.keys(this).forEach(function (key) {
|
911 | toXml(dom, dom.documentElement, key, this[key]);
|
912 | }, this);
|
913 |
|
914 | dom.documentElement.appendChild(dom.createTextNode('\r\n'));
|
915 |
|
916 | var xml = dom.documentElement.toString();
|
917 | return '<?xml version="1.0" encoding="UTF-8"?>\n' + xml.replace(/uses-sdk xmlns:android="http:\/\/schemas\.android\.com\/apk\/res\/android"/, 'uses-sdk');
|
918 | } else if (fmt === 'pretty-json') {
|
919 | return JSON.stringify(this, null, '\t');
|
920 | } else if (fmt === 'json') {
|
921 | return JSON.stringify(this);
|
922 | }
|
923 | return Object.prototype.toString.call(this);
|
924 | }
|
925 | });
|
926 |
|
927 | Object.defineProperty(this, 'save', {
|
928 | value: function (file) {
|
929 | if (file) {
|
930 | fs.ensureDirSync(path.dirname(file));
|
931 | fs.writeFileSync(file, this.toString('xml'));
|
932 | }
|
933 | return this;
|
934 | }
|
935 | });
|
936 |
|
937 | filename && this.load(filename);
|
938 | }
|