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