gulp-processModuleDeclarationToNamespace.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Gulp Tools
  2. var fs = require("fs");
  3. var processData = function(data, options) {
  4. var str = "" + data;
  5. // Start process by extracting all lines.
  6. let lines = str.split('\n');
  7. // var firstIndex = lines.findIndex((line => { return line.indexOf(`'${options.packageName}/`) !== -1 }));
  8. // var lastIndex = lines.findIndex(((line, idx) => { return line.trim() === '}' && idx > firstIndex }));
  9. // lines.splice(firstIndex, lastIndex - firstIndex + 1);
  10. // Let's go line by line and check if we have special folder replacements
  11. // Replaces declare module 'babylonjs'; by declare module BABYLON for instance
  12. for (var index = 0; index < lines.length; index++) {
  13. var namespace = options.moduleName;
  14. var regex = /declare module ["'](.*)["'] {/g;
  15. if (options.moduleSpecifics) {
  16. var match = regex.exec(lines[index]);
  17. if (!match) {
  18. continue;
  19. }
  20. var module = match[1];
  21. options.moduleSpecifics.forEach(function(specific) {
  22. if (module.indexOf(specific.path) > -1) {
  23. namespace = specific.namespace;
  24. }
  25. });
  26. }
  27. lines[index] = lines[index].replace(regex, `declare module ${namespace} {`);
  28. }
  29. // Replace module augmentation blocks
  30. for (var index = 0; index < lines.length; index++) {
  31. var namespace = options.moduleName;
  32. var regex = /\smodule ["'](.*)["'] {/g;
  33. var match = regex.exec(lines[index]);
  34. if (!match) {
  35. continue;
  36. }
  37. lines[index] = "";
  38. // Find matching closing curly }
  39. var opened = 0;
  40. for (let endIndex = index; endIndex < lines.length; endIndex++) {
  41. let scanLine = lines[endIndex].trim();
  42. if (scanLine.length === 0) {
  43. continue;
  44. }
  45. // Skip comments
  46. if (scanLine[0] === "*" || scanLine[0] === "/") {
  47. continue;
  48. }
  49. // Count open curly
  50. if (scanLine.indexOf("{") != -1) {
  51. opened++;
  52. }
  53. // And closing ones
  54. if (scanLine.indexOf("}") != -1) {
  55. opened--;
  56. // until the closing module
  57. if (opened < 0) {
  58. lines[endIndex] = "";
  59. index = endIndex;
  60. break;
  61. }
  62. }
  63. }
  64. }
  65. // Recreate the file.
  66. str = lines.join('\n');
  67. // First let s deal with internal aliased imports.
  68. if (options.moduleSpecifics) {
  69. // Find all imported classes and aliased classes.
  70. var babylonRegex = new RegExp(`import {(.*)} from ['"](.*)['"];`, "g");
  71. var match = babylonRegex.exec(str);
  72. let aliasedClasses = new Set();
  73. while (match != null) {
  74. if (match[1]) {
  75. match[1].split(",").forEach(element => {
  76. // Filter only aliased classes
  77. if (element.indexOf(" as ") > -1) {
  78. aliasedClasses.add(element.trim() + " as " + match[2]);
  79. }
  80. });
  81. }
  82. match = babylonRegex.exec(str);
  83. }
  84. str = str.replace(babylonRegex, '');
  85. // For every aliased.
  86. aliasedClasses.forEach(cls => {
  87. const tokens = cls.split(" as ");
  88. const className = tokens[0];
  89. const alias = tokens[1];
  90. const package = tokens[2];
  91. // Use the default module name.
  92. let namespace = options.moduleName;
  93. // If they are part of a specific module.
  94. options.moduleSpecifics.forEach(function(specific) {
  95. if (package.indexOf(specific.path) > -1) {
  96. namespace = specific.namespace;
  97. }
  98. });
  99. // Replace
  100. const rg = new RegExp(`([ <])(${alias})([^\\w])`, "g")
  101. str = str.replace(rg, `$1${namespace}.${className}$3`);
  102. });
  103. }
  104. // Let s clean up all the import * from BABYLON or the package itself as we know it is part of
  105. // the same namespace... Should be
  106. str = str.replace("import * as BABYLON from 'babylonjs';", "");
  107. let regexp = new RegExp(`import {(.*)} from ['"]${options.packageName}(.*)['"];`, 'g');
  108. str = str.replace(regexp, '');
  109. // Let s clean other chosen imports from the mix.
  110. if (options.importsToRemove) {
  111. while (options.importsToRemove.length) {
  112. let remove = options.importsToRemove.pop();
  113. str = str.replace(new RegExp(`import '${remove}';`), '');
  114. }
  115. }
  116. // Find all other imported classes (Part of BABYLON or Loaders for instance)
  117. // and suffix them by the namespace.
  118. if ((options.classMap)) {
  119. // Replace import { foo, bar } from ...
  120. Object.keys(options.classMap).forEach(package => {
  121. var babylonRegex = new RegExp(`import {(.*)} from ['"](${package})['"];`, "g");
  122. var match = babylonRegex.exec(str);
  123. let classes = new Set();
  124. while (match != null) {
  125. if (match[1]) {
  126. match[1].split(",").forEach(element => {
  127. classes.add(element.trim());
  128. });
  129. }
  130. match = babylonRegex.exec(str);
  131. }
  132. str = str.replace(babylonRegex, '');
  133. classes.forEach(cls => {
  134. let className = cls;
  135. let alias = cls;
  136. // Deal with import { foo as A, bar as B } from ...
  137. if (cls.indexOf(" as ") > -1) {
  138. const tokens = cls.split(" as ");
  139. className = tokens[0];
  140. alias = tokens[1];
  141. }
  142. const rg = new RegExp(`([ <])(${alias})([^\\w])`, "g")
  143. str = str.replace(rg, `$1${options.classMap[package]}.${className}$3`);
  144. });
  145. });
  146. // Replace import * as ...
  147. Object.keys(options.classMap).forEach(package => {
  148. var babylonRegex = new RegExp(`import \\* as (.*) from ['"](${package})['"];`, "g");
  149. var match = babylonRegex.exec(str);
  150. let localNamespace = "";
  151. if (match && match[1]) {
  152. localNamespace = match[1].trim();
  153. str = str.replace(babylonRegex, '');
  154. let rg = new RegExp(`([ <])(${localNamespace}.)([A-Za-z])`, "g")
  155. str = str.replace(rg, `$1${options.classMap[package]}.$3`);
  156. }
  157. });
  158. }
  159. // Clean up named export.
  160. str = str.replace(/export {(.*)};/g, '');
  161. // Clean up left import.
  162. str = str.replace(/import (.*);/g, "");
  163. // Clean up export * from.
  164. str = str.split("\n").filter(line => line.trim()).filter(line => line.indexOf("export * from") === -1).join("\n");
  165. // Remove empty module declaration
  166. var cleanEmptyNamespace = function(str, moduleName) {
  167. let emptyDeclareRegexp = new RegExp("declare module " + moduleName + " {\\s*}\\s*", "gm");
  168. str = str.replace(emptyDeclareRegexp, "");
  169. return str;
  170. }
  171. str = cleanEmptyNamespace(str, options.moduleName);
  172. // Remove empty module declaration of specific modules
  173. if (options.moduleSpecifics) {
  174. options.moduleSpecifics.forEach(function(specific) {
  175. str = cleanEmptyNamespace(str, specific.namespace);
  176. });
  177. }
  178. // Remove Empty Lines
  179. str = str.replace(/^\s*$/g, "");
  180. // Remove Inlined Import
  181. str = str.replace(/import\("[A-Za-z0-9\/]*"\)\./g, "");
  182. return str;
  183. }
  184. module.exports = function(fileLocation, options, cb) {
  185. options = options || { };
  186. fs.readFile(fileLocation, function(err, data) {
  187. if (err) throw err;
  188. data += "";
  189. // For Raanan, litteral import hack TO BETTER INTEGRATE
  190. data = data.replace('import "../sass/main.scss";', "");
  191. if (options.prependText) {
  192. data = options.prependText + '\n' + data.toString();
  193. }
  194. var newData = "";
  195. if (options) {
  196. newData = processData(data, options);
  197. var namespaceData = newData;
  198. if (options.prependToNamespaceText) {
  199. namespaceData = options.prependToNamespaceText + '\n' + namespaceData;
  200. }
  201. fs.writeFileSync(fileLocation.replace('.module', ''), namespaceData);
  202. }
  203. if (options.doNotAppendNamespace) {
  204. fs.writeFileSync(fileLocation, data);
  205. }
  206. else {
  207. fs.writeFileSync(fileLocation, data + "\n" + newData);
  208. }
  209. cb && cb();
  210. });
  211. }