Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

PluginInfo.js 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /**
  2. Licensed to the Apache Software Foundation (ASF) under one
  3. or more contributor license agreements. See the NOTICE file
  4. distributed with this work for additional information
  5. regarding copyright ownership. The ASF licenses this file
  6. to you under the Apache License, Version 2.0 (the
  7. "License"); you may not use this file except in compliance
  8. with the License. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing,
  11. software distributed under the License is distributed on an
  12. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  13. KIND, either express or implied. See the License for the
  14. specific language governing permissions and limitations
  15. under the License.
  16. */
  17. /*
  18. A class for holidng the information currently stored in plugin.xml
  19. It should also be able to answer questions like whether the plugin
  20. is compatible with a given engine version.
  21. TODO (kamrik): refactor this to not use sync functions and return promises.
  22. */
  23. var path = require('path');
  24. var fs = require('fs-extra');
  25. var xml_helpers = require('../util/xml-helpers');
  26. var CordovaError = require('../CordovaError/CordovaError');
  27. function PluginInfo (dirname) {
  28. var self = this;
  29. // METHODS
  30. // Defined inside the constructor to avoid the "this" binding problems.
  31. // <preference> tag
  32. // Example: <preference name="API_KEY" />
  33. // Used to require a variable to be specified via --variable when installing the plugin.
  34. // returns { key : default | null}
  35. self.getPreferences = getPreferences;
  36. function getPreferences (platform) {
  37. return _getTags(self._et, 'preference', platform, _parsePreference)
  38. .reduce(function (preferences, pref) {
  39. preferences[pref.preference] = pref.default;
  40. return preferences;
  41. }, {});
  42. }
  43. function _parsePreference (prefTag) {
  44. var name = prefTag.attrib.name.toUpperCase();
  45. var def = prefTag.attrib.default || null;
  46. return { preference: name, default: def };
  47. }
  48. // <asset>
  49. self.getAssets = getAssets;
  50. function getAssets (platform) {
  51. var assets = _getTags(self._et, 'asset', platform, _parseAsset);
  52. return assets;
  53. }
  54. function _parseAsset (tag) {
  55. var src = tag.attrib.src;
  56. var target = tag.attrib.target;
  57. if (!src || !target) {
  58. var msg =
  59. 'Malformed <asset> tag. Both "src" and "target" attributes'
  60. + 'must be specified in\n'
  61. + self.filepath
  62. ;
  63. throw new Error(msg);
  64. }
  65. var asset = {
  66. itemType: 'asset',
  67. src: src,
  68. target: target
  69. };
  70. return asset;
  71. }
  72. // <dependency>
  73. // Example:
  74. // <dependency id="com.plugin.id"
  75. // url="https://github.com/myuser/someplugin"
  76. // commit="428931ada3891801"
  77. // subdir="some/path/here" />
  78. self.getDependencies = getDependencies;
  79. function getDependencies (platform) {
  80. var deps = _getTags(
  81. self._et,
  82. 'dependency',
  83. platform,
  84. _parseDependency
  85. );
  86. return deps;
  87. }
  88. function _parseDependency (tag) {
  89. var dep =
  90. { id: tag.attrib.id,
  91. version: tag.attrib.version || '',
  92. url: tag.attrib.url || '',
  93. subdir: tag.attrib.subdir || '',
  94. commit: tag.attrib.commit
  95. };
  96. dep.git_ref = dep.commit;
  97. if (!dep.id) {
  98. var msg =
  99. '<dependency> tag is missing id attribute in '
  100. + self.filepath
  101. ;
  102. throw new CordovaError(msg);
  103. }
  104. return dep;
  105. }
  106. // <config-file> tag
  107. self.getConfigFiles = getConfigFiles;
  108. function getConfigFiles (platform) {
  109. var configFiles = _getTags(self._et, 'config-file', platform, _parseConfigFile);
  110. return configFiles;
  111. }
  112. function _parseConfigFile (tag) {
  113. var configFile =
  114. { target: tag.attrib['target'],
  115. parent: tag.attrib['parent'],
  116. after: tag.attrib['after'],
  117. xmls: tag.getchildren(),
  118. // To support demuxing via versions
  119. versions: tag.attrib['versions'],
  120. deviceTarget: tag.attrib['device-target']
  121. };
  122. return configFile;
  123. }
  124. self.getEditConfigs = getEditConfigs;
  125. function getEditConfigs (platform) {
  126. var editConfigs = _getTags(self._et, 'edit-config', platform, _parseEditConfigs);
  127. return editConfigs;
  128. }
  129. function _parseEditConfigs (tag) {
  130. var editConfig =
  131. { file: tag.attrib['file'],
  132. target: tag.attrib['target'],
  133. mode: tag.attrib['mode'],
  134. xmls: tag.getchildren()
  135. };
  136. return editConfig;
  137. }
  138. // <info> tags, both global and within a <platform>
  139. // TODO (kamrik): Do we ever use <info> under <platform>? Example wanted.
  140. self.getInfo = getInfo;
  141. function getInfo (platform) {
  142. var infos = _getTags(
  143. self._et,
  144. 'info',
  145. platform,
  146. function (elem) { return elem.text; }
  147. );
  148. // Filter out any undefined or empty strings.
  149. infos = infos.filter(Boolean);
  150. return infos;
  151. }
  152. // <source-file>
  153. // Examples:
  154. // <source-file src="src/ios/someLib.a" framework="true" />
  155. // <source-file src="src/ios/someLib.a" compiler-flags="-fno-objc-arc" />
  156. self.getSourceFiles = getSourceFiles;
  157. function getSourceFiles (platform) {
  158. var sourceFiles = _getTagsInPlatform(self._et, 'source-file', platform, _parseSourceFile);
  159. return sourceFiles;
  160. }
  161. function _parseSourceFile (tag) {
  162. return {
  163. itemType: 'source-file',
  164. src: tag.attrib.src,
  165. framework: isStrTrue(tag.attrib.framework),
  166. weak: isStrTrue(tag.attrib.weak),
  167. compilerFlags: tag.attrib['compiler-flags'],
  168. targetDir: tag.attrib['target-dir']
  169. };
  170. }
  171. // <header-file>
  172. // Example:
  173. // <header-file src="CDVFoo.h" />
  174. self.getHeaderFiles = getHeaderFiles;
  175. function getHeaderFiles (platform) {
  176. var headerFiles = _getTagsInPlatform(self._et, 'header-file', platform, function (tag) {
  177. return {
  178. itemType: 'header-file',
  179. src: tag.attrib.src,
  180. targetDir: tag.attrib['target-dir'],
  181. type: tag.attrib['type']
  182. };
  183. });
  184. return headerFiles;
  185. }
  186. // <resource-file>
  187. // Example:
  188. // <resource-file src="FooPluginStrings.xml" target="res/values/FooPluginStrings.xml" device-target="win" arch="x86" versions="&gt;=8.1" />
  189. self.getResourceFiles = getResourceFiles;
  190. function getResourceFiles (platform) {
  191. var resourceFiles = _getTagsInPlatform(self._et, 'resource-file', platform, function (tag) {
  192. return {
  193. itemType: 'resource-file',
  194. src: tag.attrib.src,
  195. target: tag.attrib.target,
  196. versions: tag.attrib.versions,
  197. deviceTarget: tag.attrib['device-target'],
  198. arch: tag.attrib.arch,
  199. reference: tag.attrib.reference
  200. };
  201. });
  202. return resourceFiles;
  203. }
  204. // <lib-file>
  205. // Example:
  206. // <lib-file src="src/BlackBerry10/native/device/libfoo.so" arch="device" />
  207. self.getLibFiles = getLibFiles;
  208. function getLibFiles (platform) {
  209. var libFiles = _getTagsInPlatform(self._et, 'lib-file', platform, function (tag) {
  210. return {
  211. itemType: 'lib-file',
  212. src: tag.attrib.src,
  213. arch: tag.attrib.arch,
  214. Include: tag.attrib.Include,
  215. versions: tag.attrib.versions,
  216. deviceTarget: tag.attrib['device-target'] || tag.attrib.target
  217. };
  218. });
  219. return libFiles;
  220. }
  221. // <podspec>
  222. // Example:
  223. // <podspec>
  224. // <config>
  225. // <source url="https://github.com/brightcove/BrightcoveSpecs.git" />
  226. // <source url="https://github.com/CocoaPods/Specs.git"/>
  227. // </config>
  228. // <pods use-frameworks="true" inhibit-all-warnings="true">
  229. // <pod name="PromiseKit" />
  230. // <pod name="Foobar1" spec="~> 2.0.0" />
  231. // <pod name="Foobar2" git="git@github.com:hoge/foobar1.git" />
  232. // <pod name="Foobar3" git="git@github.com:hoge/foobar2.git" branch="next" />
  233. // <pod name="Foobar4" swift-version="4.1" />
  234. // <pod name="Foobar5" swift-version="3.0" />
  235. // </pods>
  236. // </podspec>
  237. self.getPodSpecs = getPodSpecs;
  238. function getPodSpecs (platform) {
  239. var podSpecs = _getTagsInPlatform(self._et, 'podspec', platform, function (tag) {
  240. var declarations = null;
  241. var sources = null;
  242. var libraries = null;
  243. var config = tag.find('config');
  244. var pods = tag.find('pods');
  245. if (config != null) {
  246. sources = config.findall('source').map(function (t) {
  247. return {
  248. url: t.attrib.url
  249. };
  250. }).reduce(function (acc, val) {
  251. return Object.assign({}, acc, { [val.url]: { source: val.url } });
  252. }, {});
  253. }
  254. if (pods != null) {
  255. declarations = Object.keys(pods.attrib).reduce(function (acc, key) {
  256. return pods.attrib[key] === undefined ? acc : Object.assign({}, acc, { [key]: pods.attrib[key] });
  257. }, {});
  258. libraries = pods.findall('pod').map(function (t) {
  259. return Object.keys(t.attrib).reduce(function (acc, key) {
  260. return t.attrib[key] === undefined ? acc : Object.assign({}, acc, { [key]: t.attrib[key] });
  261. }, {});
  262. }).reduce(function (acc, val) {
  263. return Object.assign({}, acc, { [val.name]: val });
  264. }, {});
  265. }
  266. return {
  267. declarations: declarations,
  268. sources: sources,
  269. libraries: libraries
  270. };
  271. });
  272. return podSpecs;
  273. }
  274. // <hook>
  275. // Example:
  276. // <hook type="before_build" src="scripts/beforeBuild.js" />
  277. self.getHookScripts = getHookScripts;
  278. function getHookScripts (hook, platforms) {
  279. var scriptElements = self._et.findall('./hook');
  280. if (platforms) {
  281. platforms.forEach(function (platform) {
  282. scriptElements = scriptElements.concat(self._et.findall('./platform[@name="' + platform + '"]/hook'));
  283. });
  284. }
  285. function filterScriptByHookType (el) {
  286. return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
  287. }
  288. return scriptElements.filter(filterScriptByHookType);
  289. }
  290. self.getJsModules = getJsModules;
  291. function getJsModules (platform) {
  292. var modules = _getTags(self._et, 'js-module', platform, _parseJsModule);
  293. return modules;
  294. }
  295. function _parseJsModule (tag) {
  296. var ret = {
  297. itemType: 'js-module',
  298. name: tag.attrib.name,
  299. src: tag.attrib.src,
  300. clobbers: tag.findall('clobbers').map(function (tag) { return { target: tag.attrib.target }; }),
  301. merges: tag.findall('merges').map(function (tag) { return { target: tag.attrib.target }; }),
  302. runs: tag.findall('runs').length > 0
  303. };
  304. return ret;
  305. }
  306. self.getEngines = function () {
  307. return self._et.findall('engines/engine').map(function (n) {
  308. return {
  309. name: n.attrib.name,
  310. version: n.attrib.version,
  311. platform: n.attrib.platform,
  312. scriptSrc: n.attrib.scriptSrc
  313. };
  314. });
  315. };
  316. self.getPlatforms = function () {
  317. return self._et.findall('platform').map(function (n) {
  318. return { name: n.attrib.name };
  319. });
  320. };
  321. self.getPlatformsArray = function () {
  322. return self._et.findall('platform').map(function (n) {
  323. return n.attrib.name;
  324. });
  325. };
  326. self.getFrameworks = function (platform, options) {
  327. return _getTags(self._et, 'framework', platform, function (el) {
  328. var src = el.attrib.src;
  329. if (options) {
  330. var vars = options.cli_variables || {};
  331. if (Object.keys(vars).length === 0) {
  332. // get variable defaults from plugin.xml for removal
  333. vars = self.getPreferences(platform);
  334. }
  335. var regExp;
  336. // Iterate over plugin variables.
  337. // Replace them in framework src if they exist
  338. Object.keys(vars).forEach(function (name) {
  339. if (vars[name]) {
  340. regExp = new RegExp('\\$' + name, 'g');
  341. src = src.replace(regExp, vars[name]);
  342. }
  343. });
  344. }
  345. var ret = {
  346. itemType: 'framework',
  347. type: el.attrib.type,
  348. parent: el.attrib.parent,
  349. custom: isStrTrue(el.attrib.custom),
  350. embed: isStrTrue(el.attrib.embed),
  351. src: src,
  352. spec: el.attrib.spec,
  353. weak: isStrTrue(el.attrib.weak),
  354. versions: el.attrib.versions,
  355. targetDir: el.attrib['target-dir'],
  356. deviceTarget: el.attrib['device-target'] || el.attrib.target,
  357. arch: el.attrib.arch,
  358. implementation: el.attrib.implementation
  359. };
  360. return ret;
  361. });
  362. };
  363. self.getFilesAndFrameworks = getFilesAndFrameworks;
  364. function getFilesAndFrameworks (platform, options) {
  365. // Please avoid changing the order of the calls below, files will be
  366. // installed in this order.
  367. var items = [].concat(
  368. self.getSourceFiles(platform),
  369. self.getHeaderFiles(platform),
  370. self.getResourceFiles(platform),
  371. self.getFrameworks(platform, options),
  372. self.getLibFiles(platform)
  373. );
  374. return items;
  375. }
  376. /// // End of PluginInfo methods /////
  377. /// // PluginInfo Constructor logic /////
  378. self.filepath = path.join(dirname, 'plugin.xml');
  379. if (!fs.existsSync(self.filepath)) {
  380. throw new CordovaError('Cannot find plugin.xml for plugin "' + path.basename(dirname) + '". Please try adding it again.');
  381. }
  382. self.dir = dirname;
  383. var et = self._et = xml_helpers.parseElementtreeSync(self.filepath);
  384. var pelem = et.getroot();
  385. self.id = pelem.attrib.id;
  386. self.version = pelem.attrib.version;
  387. // Optional fields
  388. self.name = pelem.findtext('name');
  389. self.description = pelem.findtext('description');
  390. self.license = pelem.findtext('license');
  391. self.repo = pelem.findtext('repo');
  392. self.issue = pelem.findtext('issue');
  393. self.keywords = pelem.findtext('keywords');
  394. self.info = pelem.findtext('info');
  395. if (self.keywords) {
  396. self.keywords = self.keywords.split(',').map(function (s) { return s.trim(); });
  397. }
  398. self.getKeywordsAndPlatforms = function () {
  399. var ret = self.keywords || [];
  400. return ret.concat('ecosystem:cordova').concat(addCordova(self.getPlatformsArray()));
  401. };
  402. } // End of PluginInfo constructor.
  403. // Helper function used to prefix every element of an array with cordova-
  404. // Useful when we want to modify platforms to be cordova-platform
  405. function addCordova (someArray) {
  406. var newArray = someArray.map(function (element) {
  407. return 'cordova-' + element;
  408. });
  409. return newArray;
  410. }
  411. // Helper function used by most of the getSomething methods of PluginInfo.
  412. // Get all elements of a given name. Both in root and in platform sections
  413. // for the given platform. If transform is given and is a function, it is
  414. // applied to each element.
  415. function _getTags (pelem, tag, platform, transform) {
  416. var platformTag = pelem.find('./platform[@name="' + platform + '"]');
  417. var tagsInRoot = pelem.findall(tag);
  418. tagsInRoot = tagsInRoot || [];
  419. var tagsInPlatform = platformTag ? platformTag.findall(tag) : [];
  420. var tags = tagsInRoot.concat(tagsInPlatform);
  421. if (typeof transform === 'function') {
  422. tags = tags.map(transform);
  423. }
  424. return tags;
  425. }
  426. // Same as _getTags() but only looks inside a platform section.
  427. function _getTagsInPlatform (pelem, tag, platform, transform) {
  428. var platformTag = pelem.find('./platform[@name="' + platform + '"]');
  429. var tags = platformTag ? platformTag.findall(tag) : [];
  430. if (typeof transform === 'function') {
  431. tags = tags.map(transform);
  432. }
  433. return tags;
  434. }
  435. // Check if x is a string 'true'.
  436. function isStrTrue (x) {
  437. return String(x).toLowerCase() === 'true';
  438. }
  439. module.exports = PluginInfo;
  440. // Backwards compat:
  441. PluginInfo.PluginInfo = PluginInfo;
  442. PluginInfo.loadPluginsDir = function (dir) {
  443. var PluginInfoProvider = require('./PluginInfoProvider');
  444. return new PluginInfoProvider().getAllWithinSearchPath(dir);
  445. };