iosWKWebViewEngineSupport.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. Helper class to work with Swift.
  3. Mainly, it has only two method: to activate and to deactivate swift support in the project.
  4. */
  5. var path = require('path');
  6. var fs = require('fs');
  7. var strFormat = require('util').format;
  8. var COMMENT_KEY = /_comment$/;
  9. var WKWEBVIEW_PLUGIN_NAME = 'cordova-plugin-wkwebview-engine';
  10. var WKWEBVIEW_MACRO = 'WK_WEBVIEW_ENGINE_IS_USED';
  11. var isWkWebViewEngineUsed = 0;
  12. var context;
  13. var projectRoot;
  14. var projectName;
  15. var iosPlatformPath;
  16. module.exports = {
  17. setWKWebViewEngineMacro: setWKWebViewEngineMacro
  18. };
  19. /**
  20. * Define preprocessor macro for WKWebViewEngine.
  21. *
  22. * @param {Object} cordovaContext - cordova context
  23. */
  24. function setWKWebViewEngineMacro(cordovaContext) {
  25. init(cordovaContext);
  26. // injecting options in project file
  27. var projectFile = loadProjectFile();
  28. setMacro(projectFile.xcode);
  29. projectFile.write();
  30. }
  31. // region General private methods
  32. /**
  33. * Initialize before execution.
  34. *
  35. * @param {Object} ctx - cordova context instance
  36. */
  37. function init(ctx) {
  38. context = ctx;
  39. projectRoot = ctx.opts.projectRoot;
  40. projectName = getProjectName(ctx, projectRoot);
  41. iosPlatformPath = path.join(projectRoot, 'platforms', 'ios');
  42. var wkWebViewPluginPath = path.join(projectRoot, 'plugins', WKWEBVIEW_PLUGIN_NAME);
  43. isWkWebViewEngineUsed = isDirectoryExists(wkWebViewPluginPath) ? 1 : 0;
  44. }
  45. function isDirectoryExists(dir) {
  46. var exists = false;
  47. try {
  48. fs.accessSync(dir, fs.F_OK);
  49. exists = true;
  50. } catch(err) {
  51. }
  52. return exists;
  53. }
  54. /**
  55. * Load iOS project file from platform specific folder.
  56. *
  57. * @return {Object} projectFile - project file information
  58. */
  59. function loadProjectFile() {
  60. try {
  61. return loadProjectFile_cordova_7_and_above();
  62. } catch(e) {
  63. }
  64. try {
  65. return loadProjectFile_cordova_5_and_6();
  66. } catch(e) {
  67. }
  68. try {
  69. return loadProjectFile_cordova_pre_5();
  70. } catch (e) {
  71. }
  72. throw new Error('Failed to load iOS project file. Maybe your Cordova version is not supported?');
  73. }
  74. function loadProjectFile_cordova_pre_5() {
  75. var platformIos = context.requireCordovaModule('cordova-lib/src/plugman/platforms')['ios'];
  76. return platformIos.parseProjectFile(iosPlatformPath);
  77. }
  78. function loadProjectFile_cordova_5_and_6() {
  79. var platformIos = context.requireCordovaModule('cordova-lib/src/plugman/platforms/ios');
  80. return platformIos.parseProjectFile(iosPlatformPath);
  81. }
  82. function loadProjectFile_cordova_7_and_above() {
  83. var pbxPath = path.join(iosPlatformPath, projectName + '.xcodeproj', 'project.pbxproj');
  84. var xcodeproj = context.requireCordovaModule('xcode').project(pbxPath);
  85. xcodeproj.parseSync();
  86. var saveProj = function() {
  87. fs.writeFileSync(pbxPath, xcodeproj.writeSync());
  88. };
  89. return {
  90. xcode: xcodeproj,
  91. write: saveProj
  92. };
  93. }
  94. /**
  95. * Get name of the current project.
  96. *
  97. * @param {Object} ctx - cordova context instance
  98. * @param {String} projectRoot - current root of the project
  99. *
  100. * @return {String} name of the project
  101. */
  102. function getProjectName(ctx, projectRoot) {
  103. var cordova_util = ctx.requireCordovaModule('cordova-lib/src/cordova/util');
  104. var xml = cordova_util.projectConfig(projectRoot);
  105. var ConfigParser;
  106. // If we are running Cordova 5.4 or abova - use parser from cordova-common.
  107. // Otherwise - from cordova-lib.
  108. try {
  109. ConfigParser = ctx.requireCordovaModule('cordova-common/src/ConfigParser/ConfigParser');
  110. } catch (e) {
  111. ConfigParser = ctx.requireCordovaModule('cordova-lib/src/configparser/ConfigParser')
  112. }
  113. return new ConfigParser(xml).name();
  114. }
  115. /**
  116. * Remove comments from the file.
  117. *
  118. * @param {Object} obj - file object
  119. * @return {Object} file object without comments
  120. */
  121. function nonComments(obj) {
  122. var keys = Object.keys(obj);
  123. var newObj = {};
  124. for (var i = 0, len = keys.length; i < len; i++) {
  125. if (!COMMENT_KEY.test(keys[i])) {
  126. newObj[keys[i]] = obj[keys[i]];
  127. }
  128. }
  129. return newObj;
  130. }
  131. // endregion
  132. // region Macros injection
  133. /**
  134. * Inject WKWebView macro into project configuration file.
  135. *
  136. * @param {Object} xcodeProject - xcode project file instance
  137. */
  138. function setMacro(xcodeProject) {
  139. var configurations = nonComments(xcodeProject.pbxXCBuildConfigurationSection());
  140. var config;
  141. var buildSettings;
  142. for (config in configurations) {
  143. buildSettings = configurations[config].buildSettings;
  144. var preprocessorDefs = buildSettings['GCC_PREPROCESSOR_DEFINITIONS'] ? buildSettings['GCC_PREPROCESSOR_DEFINITIONS'] : [];
  145. if (!preprocessorDefs.length && !isWkWebViewEngineUsed) {
  146. continue;
  147. }
  148. if (!Array.isArray(preprocessorDefs)) {
  149. preprocessorDefs = [preprocessorDefs];
  150. }
  151. var isModified = false;
  152. var injectedDefinition = strFormat('"%s=%d"', WKWEBVIEW_MACRO, isWkWebViewEngineUsed);
  153. preprocessorDefs.forEach(function(item, idx) {
  154. if (item.indexOf(WKWEBVIEW_MACRO) !== -1) {
  155. preprocessorDefs[idx] = injectedDefinition;
  156. isModified = true;
  157. }
  158. });
  159. if (!isModified) {
  160. preprocessorDefs.push(injectedDefinition);
  161. }
  162. if (preprocessorDefs.length === 1) {
  163. buildSettings['GCC_PREPROCESSOR_DEFINITIONS'] = preprocessorDefs[0];
  164. } else {
  165. buildSettings['GCC_PREPROCESSOR_DEFINITIONS'] = preprocessorDefs;
  166. }
  167. }
  168. }
  169. // endregion