1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | var path = require('path');
|
29 | var fs = require('fs');
|
30 | var xml_helpers = require('../util/xml-helpers');
|
31 | var CordovaError = require('../CordovaError/CordovaError');
|
32 |
|
33 | function PluginInfo (dirname) {
|
34 | var self = this;
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | self.getPreferences = getPreferences;
|
44 | function getPreferences (platform) {
|
45 | return _getTags(self._et, 'preference', platform, _parsePreference)
|
46 | .reduce(function (preferences, pref) {
|
47 | preferences[pref.preference] = pref.default;
|
48 | return preferences;
|
49 | }, {});
|
50 | }
|
51 |
|
52 | function _parsePreference (prefTag) {
|
53 | var name = prefTag.attrib.name.toUpperCase();
|
54 | var def = prefTag.attrib.default || null;
|
55 | return {preference: name, default: def};
|
56 | }
|
57 |
|
58 |
|
59 | self.getAssets = getAssets;
|
60 | function getAssets (platform) {
|
61 | var assets = _getTags(self._et, 'asset', platform, _parseAsset);
|
62 | return assets;
|
63 | }
|
64 |
|
65 | function _parseAsset (tag) {
|
66 | var src = tag.attrib.src;
|
67 | var target = tag.attrib.target;
|
68 |
|
69 | if (!src || !target) {
|
70 | var msg =
|
71 | 'Malformed <asset> tag. Both "src" and "target" attributes'
|
72 | + 'must be specified in\n'
|
73 | + self.filepath
|
74 | ;
|
75 | throw new Error(msg);
|
76 | }
|
77 |
|
78 | var asset = {
|
79 | itemType: 'asset',
|
80 | src: src,
|
81 | target: target
|
82 | };
|
83 | return asset;
|
84 | }
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 | self.getDependencies = getDependencies;
|
93 | function getDependencies (platform) {
|
94 | var deps = _getTags(
|
95 | self._et,
|
96 | 'dependency',
|
97 | platform,
|
98 | _parseDependency
|
99 | );
|
100 | return deps;
|
101 | }
|
102 |
|
103 | function _parseDependency (tag) {
|
104 | var dep =
|
105 | { id: tag.attrib.id,
|
106 | version: tag.attrib.version || '',
|
107 | url: tag.attrib.url || '',
|
108 | subdir: tag.attrib.subdir || '',
|
109 | commit: tag.attrib.commit
|
110 | };
|
111 |
|
112 | dep.git_ref = dep.commit;
|
113 |
|
114 | if (!dep.id) {
|
115 | var msg =
|
116 | '<dependency> tag is missing id attribute in '
|
117 | + self.filepath
|
118 | ;
|
119 | throw new CordovaError(msg);
|
120 | }
|
121 | return dep;
|
122 | }
|
123 |
|
124 |
|
125 | self.getConfigFiles = getConfigFiles;
|
126 | function getConfigFiles (platform) {
|
127 | var configFiles = _getTags(self._et, 'config-file', platform, _parseConfigFile);
|
128 | return configFiles;
|
129 | }
|
130 |
|
131 | function _parseConfigFile (tag) {
|
132 | var configFile =
|
133 | { target: tag.attrib['target'],
|
134 | parent: tag.attrib['parent'],
|
135 | after: tag.attrib['after'],
|
136 | xmls: tag.getchildren(),
|
137 |
|
138 | versions: tag.attrib['versions'],
|
139 | deviceTarget: tag.attrib['device-target']
|
140 | };
|
141 | return configFile;
|
142 | }
|
143 |
|
144 | self.getEditConfigs = getEditConfigs;
|
145 | function getEditConfigs (platform) {
|
146 | var editConfigs = _getTags(self._et, 'edit-config', platform, _parseEditConfigs);
|
147 | return editConfigs;
|
148 | }
|
149 |
|
150 | function _parseEditConfigs (tag) {
|
151 | var editConfig =
|
152 | { file: tag.attrib['file'],
|
153 | target: tag.attrib['target'],
|
154 | mode: tag.attrib['mode'],
|
155 | xmls: tag.getchildren()
|
156 | };
|
157 | return editConfig;
|
158 | }
|
159 |
|
160 |
|
161 |
|
162 | self.getInfo = getInfo;
|
163 | function getInfo (platform) {
|
164 | var infos = _getTags(
|
165 | self._et,
|
166 | 'info',
|
167 | platform,
|
168 | function (elem) { return elem.text; }
|
169 | );
|
170 |
|
171 | infos = infos.filter(Boolean);
|
172 | return infos;
|
173 | }
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 | self.getSourceFiles = getSourceFiles;
|
180 | function getSourceFiles (platform) {
|
181 | var sourceFiles = _getTagsInPlatform(self._et, 'source-file', platform, _parseSourceFile);
|
182 | return sourceFiles;
|
183 | }
|
184 |
|
185 | function _parseSourceFile (tag) {
|
186 | return {
|
187 | itemType: 'source-file',
|
188 | src: tag.attrib.src,
|
189 | framework: isStrTrue(tag.attrib.framework),
|
190 | weak: isStrTrue(tag.attrib.weak),
|
191 | compilerFlags: tag.attrib['compiler-flags'],
|
192 | targetDir: tag.attrib['target-dir']
|
193 | };
|
194 | }
|
195 |
|
196 |
|
197 |
|
198 |
|
199 | self.getHeaderFiles = getHeaderFiles;
|
200 | function getHeaderFiles (platform) {
|
201 | var headerFiles = _getTagsInPlatform(self._et, 'header-file', platform, function (tag) {
|
202 | return {
|
203 | itemType: 'header-file',
|
204 | src: tag.attrib.src,
|
205 | targetDir: tag.attrib['target-dir']
|
206 | };
|
207 | });
|
208 | return headerFiles;
|
209 | }
|
210 |
|
211 |
|
212 |
|
213 |
|
214 | self.getResourceFiles = getResourceFiles;
|
215 | function getResourceFiles (platform) {
|
216 | var resourceFiles = _getTagsInPlatform(self._et, 'resource-file', platform, function (tag) {
|
217 | return {
|
218 | itemType: 'resource-file',
|
219 | src: tag.attrib.src,
|
220 | target: tag.attrib.target,
|
221 | versions: tag.attrib.versions,
|
222 | deviceTarget: tag.attrib['device-target'],
|
223 | arch: tag.attrib.arch,
|
224 | reference: tag.attrib.reference
|
225 | };
|
226 | });
|
227 | return resourceFiles;
|
228 | }
|
229 |
|
230 |
|
231 |
|
232 |
|
233 | self.getLibFiles = getLibFiles;
|
234 | function getLibFiles (platform) {
|
235 | var libFiles = _getTagsInPlatform(self._et, 'lib-file', platform, function (tag) {
|
236 | return {
|
237 | itemType: 'lib-file',
|
238 | src: tag.attrib.src,
|
239 | arch: tag.attrib.arch,
|
240 | Include: tag.attrib.Include,
|
241 | versions: tag.attrib.versions,
|
242 | deviceTarget: tag.attrib['device-target'] || tag.attrib.target
|
243 | };
|
244 | });
|
245 | return libFiles;
|
246 | }
|
247 |
|
248 |
|
249 |
|
250 |
|
251 | self.getHookScripts = getHookScripts;
|
252 | function getHookScripts (hook, platforms) {
|
253 | var scriptElements = self._et.findall('./hook');
|
254 |
|
255 | if (platforms) {
|
256 | platforms.forEach(function (platform) {
|
257 | scriptElements = scriptElements.concat(self._et.findall('./platform[@name="' + platform + '"]/hook'));
|
258 | });
|
259 | }
|
260 |
|
261 | function filterScriptByHookType (el) {
|
262 | return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
|
263 | }
|
264 |
|
265 | return scriptElements.filter(filterScriptByHookType);
|
266 | }
|
267 |
|
268 | self.getJsModules = getJsModules;
|
269 | function getJsModules (platform) {
|
270 | var modules = _getTags(self._et, 'js-module', platform, _parseJsModule);
|
271 | return modules;
|
272 | }
|
273 |
|
274 | function _parseJsModule (tag) {
|
275 | var ret = {
|
276 | itemType: 'js-module',
|
277 | name: tag.attrib.name,
|
278 | src: tag.attrib.src,
|
279 | clobbers: tag.findall('clobbers').map(function (tag) { return { target: tag.attrib.target }; }),
|
280 | merges: tag.findall('merges').map(function (tag) { return { target: tag.attrib.target }; }),
|
281 | runs: tag.findall('runs').length > 0
|
282 | };
|
283 |
|
284 | return ret;
|
285 | }
|
286 |
|
287 | self.getEngines = function () {
|
288 | return self._et.findall('engines/engine').map(function (n) {
|
289 | return {
|
290 | name: n.attrib.name,
|
291 | version: n.attrib.version,
|
292 | platform: n.attrib.platform,
|
293 | scriptSrc: n.attrib.scriptSrc
|
294 | };
|
295 | });
|
296 | };
|
297 |
|
298 | self.getPlatforms = function () {
|
299 | return self._et.findall('platform').map(function (n) {
|
300 | return { name: n.attrib.name };
|
301 | });
|
302 | };
|
303 |
|
304 | self.getPlatformsArray = function () {
|
305 | return self._et.findall('platform').map(function (n) {
|
306 | return n.attrib.name;
|
307 | });
|
308 | };
|
309 |
|
310 | self.getFrameworks = function (platform, options) {
|
311 | return _getTags(self._et, 'framework', platform, function (el) {
|
312 | var src = el.attrib.src;
|
313 | if (options) {
|
314 | var vars = options.cli_variables || {};
|
315 |
|
316 | if (Object.keys(vars).length === 0) {
|
317 |
|
318 | vars = self.getPreferences(platform);
|
319 | }
|
320 | var regExp;
|
321 |
|
322 |
|
323 | Object.keys(vars).forEach(function (name) {
|
324 | if (vars[name]) {
|
325 | regExp = new RegExp('\\$' + name, 'g');
|
326 | src = src.replace(regExp, vars[name]);
|
327 | }
|
328 | });
|
329 | }
|
330 | var ret = {
|
331 | itemType: 'framework',
|
332 | type: el.attrib.type,
|
333 | parent: el.attrib.parent,
|
334 | custom: isStrTrue(el.attrib.custom),
|
335 | embed: isStrTrue(el.attrib.embed),
|
336 | src: src,
|
337 | spec: el.attrib.spec,
|
338 | weak: isStrTrue(el.attrib.weak),
|
339 | versions: el.attrib.versions,
|
340 | targetDir: el.attrib['target-dir'],
|
341 | deviceTarget: el.attrib['device-target'] || el.attrib.target,
|
342 | arch: el.attrib.arch,
|
343 | implementation: el.attrib.implementation
|
344 | };
|
345 | return ret;
|
346 | });
|
347 | };
|
348 |
|
349 | self.getFilesAndFrameworks = getFilesAndFrameworks;
|
350 | function getFilesAndFrameworks (platform, options) {
|
351 |
|
352 |
|
353 | var items = [].concat(
|
354 | self.getSourceFiles(platform),
|
355 | self.getHeaderFiles(platform),
|
356 | self.getResourceFiles(platform),
|
357 | self.getFrameworks(platform, options),
|
358 | self.getLibFiles(platform)
|
359 | );
|
360 | return items;
|
361 | }
|
362 |
|
363 |
|
364 |
|
365 | self.filepath = path.join(dirname, 'plugin.xml');
|
366 | if (!fs.existsSync(self.filepath)) {
|
367 | throw new CordovaError('Cannot find plugin.xml for plugin "' + path.basename(dirname) + '". Please try adding it again.');
|
368 | }
|
369 |
|
370 | self.dir = dirname;
|
371 | var et = self._et = xml_helpers.parseElementtreeSync(self.filepath);
|
372 | var pelem = et.getroot();
|
373 | self.id = pelem.attrib.id;
|
374 | self.version = pelem.attrib.version;
|
375 |
|
376 |
|
377 | self.name = pelem.findtext('name');
|
378 | self.description = pelem.findtext('description');
|
379 | self.license = pelem.findtext('license');
|
380 | self.repo = pelem.findtext('repo');
|
381 | self.issue = pelem.findtext('issue');
|
382 | self.keywords = pelem.findtext('keywords');
|
383 | self.info = pelem.findtext('info');
|
384 | if (self.keywords) {
|
385 | self.keywords = self.keywords.split(',').map(function (s) { return s.trim(); });
|
386 | }
|
387 | self.getKeywordsAndPlatforms = function () {
|
388 | var ret = self.keywords || [];
|
389 | return ret.concat('ecosystem:cordova').concat(addCordova(self.getPlatformsArray()));
|
390 | };
|
391 | }
|
392 |
|
393 |
|
394 |
|
395 | function addCordova (someArray) {
|
396 | var newArray = someArray.map(function (element) {
|
397 | return 'cordova-' + element;
|
398 | });
|
399 | return newArray;
|
400 | }
|
401 |
|
402 |
|
403 |
|
404 |
|
405 |
|
406 | function _getTags (pelem, tag, platform, transform) {
|
407 | var platformTag = pelem.find('./platform[@name="' + platform + '"]');
|
408 | var tagsInRoot = pelem.findall(tag);
|
409 | tagsInRoot = tagsInRoot || [];
|
410 | var tagsInPlatform = platformTag ? platformTag.findall(tag) : [];
|
411 | var tags = tagsInRoot.concat(tagsInPlatform);
|
412 | if (typeof transform === 'function') {
|
413 | tags = tags.map(transform);
|
414 | }
|
415 | return tags;
|
416 | }
|
417 |
|
418 |
|
419 | function _getTagsInPlatform (pelem, tag, platform, transform) {
|
420 | var platformTag = pelem.find('./platform[@name="' + platform + '"]');
|
421 | var tags = platformTag ? platformTag.findall(tag) : [];
|
422 | if (typeof transform === 'function') {
|
423 | tags = tags.map(transform);
|
424 | }
|
425 | return tags;
|
426 | }
|
427 |
|
428 |
|
429 | function isStrTrue (x) {
|
430 | return String(x).toLowerCase() === 'true';
|
431 | }
|
432 |
|
433 | module.exports = PluginInfo;
|
434 |
|
435 | PluginInfo.PluginInfo = PluginInfo;
|
436 | PluginInfo.loadPluginsDir = function (dir) {
|
437 | var PluginInfoProvider = require('./PluginInfoProvider');
|
438 | return new PluginInfoProvider().getAllWithinSearchPath(dir);
|
439 | };
|