gulp-processTypescriptDeclaration.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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. // Recreate the file.
  30. str = lines.join('\n');
  31. // First let s deal with internal aliased imports.
  32. if (options.moduleSpecifics) {
  33. // Find all imported classes and aliased classes.
  34. var babylonRegex = new RegExp(`import {(.*)} from ['"](.*)['"];`, "g");
  35. var match = babylonRegex.exec(str);
  36. let aliasedClasses = new Set();
  37. while (match != null) {
  38. if (match[1]) {
  39. match[1].split(",").forEach(element => {
  40. // Filter only aliased classes
  41. if (element.indexOf(" as ") > -1) {
  42. aliasedClasses.add(element.trim() + " as " + match[2]);
  43. }
  44. });
  45. }
  46. match = babylonRegex.exec(str);
  47. }
  48. str = str.replace(babylonRegex, '');
  49. // For every aliased.
  50. aliasedClasses.forEach(cls => {
  51. const tokens = cls.split(" as ");
  52. const className = tokens[0];
  53. const alias = tokens[1];
  54. const package = tokens[2];
  55. // Use the default module name.
  56. let namespace = options.moduleName;
  57. // If they are part of a specific module.
  58. options.moduleSpecifics.forEach(function(specific) {
  59. if (package.indexOf(specific.path) > -1) {
  60. namespace = specific.namespace;
  61. }
  62. });
  63. // Replace
  64. const rg = new RegExp(`([ <])(${alias})([^\\w])`, "g")
  65. str = str.replace(rg, `$1${namespace}.${className}$3`);
  66. });
  67. }
  68. // Let s clean up all the import * from BABYLON or the package itself as we know it is part of
  69. // the same namespace... Should be
  70. str = str.replace("import * as BABYLON from 'babylonjs';", "");
  71. let regexp = new RegExp(`import {(.*)} from ['"]${options.packageName}(.*)['"];`, 'g');
  72. str = str.replace(regexp, '');
  73. // Let s clean other chosen imports from the mix.
  74. if (options.importsToRemove) {
  75. while (options.importsToRemove.length) {
  76. let remove = options.importsToRemove.pop();
  77. str = str.replace(new RegExp(`import '${remove}';`), '');
  78. }
  79. }
  80. // Find all other imported classes (Part of BABYLON or Loaders for instance)
  81. // and suffix them by the namespace.
  82. if ((options.classMap)) {
  83. // Replace import { foo, bar } from ...
  84. Object.keys(options.classMap).forEach(package => {
  85. var babylonRegex = new RegExp(`import {(.*)} from ['"](${package})['"];`, "g");
  86. var match = babylonRegex.exec(str);
  87. let classes = new Set();
  88. while (match != null) {
  89. if (match[1]) {
  90. match[1].split(",").forEach(element => {
  91. classes.add(element.trim());
  92. });
  93. }
  94. match = babylonRegex.exec(str);
  95. }
  96. str = str.replace(babylonRegex, '');
  97. classes.forEach(cls => {
  98. let className = cls;
  99. let alias = cls;
  100. // Deal with import { foo as A, bar as B } from ...
  101. if (cls.indexOf(" as ") > -1) {
  102. const tokens = cls.split(" as ");
  103. className = tokens[0];
  104. alias = tokens[1];
  105. }
  106. const rg = new RegExp(`([ <])(${alias})([^\\w])`, "g")
  107. str = str.replace(rg, `$1${options.classMap[package]}.${className}$3`);
  108. });
  109. });
  110. // Replace import * as ...
  111. Object.keys(options.classMap).forEach(package => {
  112. var babylonRegex = new RegExp(`import \\* as (.*) from ['"](${package})['"];`, "g");
  113. var match = babylonRegex.exec(str);
  114. let localNamespace = "";
  115. if (match && match[1]) {
  116. localNamespace = match[1].trim();
  117. str = str.replace(babylonRegex, '');
  118. let rg = new RegExp(`([ <])(${localNamespace}.)([A-Za-z])`, "g")
  119. str = str.replace(rg, `$1${options.classMap[package]}.$3`);
  120. }
  121. });
  122. }
  123. // Clean up export.
  124. str = str.replace(/export {(.*)};/g, '');
  125. // Clean up left import.
  126. str = str.replace(/import (.*);/g, "");
  127. // Rearrange the d.ts.
  128. str = str.split("\n").filter(line => line.trim()).filter(line => line.indexOf("export * from") === -1).join("\n");
  129. // Remove empty module declaration
  130. var cleanEmptyNamespace = function(str, moduleName) {
  131. let emptyDeclareRegexp = new RegExp("declare module " + moduleName + " {\n}\n", "g");
  132. str = str.replace(emptyDeclareRegexp, "");
  133. emptyDeclareRegexp = new RegExp("declare module " + moduleName + " {\r\n}\r\n", "g");
  134. str = str.replace(emptyDeclareRegexp, "");
  135. return str;
  136. }
  137. str = cleanEmptyNamespace(str, options.moduleName);
  138. // Remove empty module declaration of specific modules
  139. if (options.moduleSpecifics) {
  140. options.moduleSpecifics.forEach(function(specific) {
  141. str = cleanEmptyNamespace(str, specific.namespace);
  142. });
  143. }
  144. return str;
  145. }
  146. module.exports = function(fileLocation, options, cb) {
  147. options = options || { };
  148. fs.readFile(fileLocation, function(err, data) {
  149. if (err) throw err;
  150. data += "";
  151. // For Raanan, litteral import hack TO BETTER INTEGRATE
  152. data = data.replace('import "../sass/main.scss";', "");
  153. if (options.prependText) {
  154. data = options.prependText + '\n' + data.toString();
  155. }
  156. var newData = "";
  157. if (options) {
  158. newData = processData(data, options);
  159. fs.writeFileSync(fileLocation.replace('.module', ''), newData);
  160. }
  161. if (options.doNotAppendNamespace) {
  162. fs.writeFileSync(fileLocation, data);
  163. }
  164. else {
  165. fs.writeFileSync(fileLocation, data + "\n" + newData);
  166. }
  167. cb && cb();
  168. });
  169. }