amd2common.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. var glob = require('glob');
  2. var fsExtra = require('fs-extra');
  3. var esprima = require('esprima');
  4. function run(cb) {
  5. glob('**/*.js', {
  6. cwd: __dirname + '/../src/'
  7. }, function (err, files) {
  8. files.forEach(function (filePath) {
  9. var code = parse(fsExtra.readFileSync(
  10. __dirname + '/../src/' + filePath, 'utf-8'));
  11. code = code.replace(/require\(([\'"])zrender\//g, 'require($1zrender/lib/');
  12. fsExtra.outputFileSync(
  13. __dirname + '/../lib/' + filePath,
  14. code, 'utf-8');
  15. });
  16. cb && cb();
  17. });
  18. }
  19. if (require.main === module) {
  20. run();
  21. }
  22. else {
  23. module.exports = run;
  24. }
  25. var MAGIC_DEPS = {
  26. 'exports' : true,
  27. 'module' : true,
  28. 'require' : true
  29. };
  30. var SIMPLIFIED_CJS = ['require', 'exports', 'module'];
  31. // Convert AMD-style JavaScript string into node.js compatible module
  32. function parse (raw){
  33. var output = '';
  34. var ast = esprima.parse(raw, {
  35. range: true,
  36. raw: true
  37. });
  38. var defines = ast.body.filter(isDefine);
  39. if ( defines.length > 1 ){
  40. throw new Error('Each file can have only a single define call. Found "'+ defines.length +'"');
  41. } else if (!defines.length){
  42. return raw;
  43. }
  44. var def = defines[0];
  45. var args = def.expression['arguments'];
  46. var factory = getFactory( args );
  47. var useStrict = getUseStrict( factory );
  48. // do replacements in-place to avoid modifying the code more than needed
  49. if (useStrict) {
  50. output += useStrict.expression.raw +';\n';
  51. }
  52. output += raw.substring( 0, def.range[0] ); // anything before define
  53. output += getRequires(args, factory); // add requires
  54. output += getBody(raw, factory.body, useStrict); // module body
  55. output += raw.substring( def.range[1], raw.length ); // anything after define
  56. return output;
  57. }
  58. function getRequires(args, factory){
  59. var requires = [];
  60. var deps = getDependenciesNames( args );
  61. var params = factory.params.map(function(param, i){
  62. return {
  63. name : param.name,
  64. // simplified cjs doesn't have deps
  65. dep : (deps.length)? deps[i] : SIMPLIFIED_CJS[i]
  66. };
  67. });
  68. params.forEach(function(param){
  69. if ( MAGIC_DEPS[param.dep] && !MAGIC_DEPS[param.name] ) {
  70. // if user remaped magic dependency we declare a var
  71. requires.push( 'var '+ param.name +' = '+ param.dep +';' );
  72. } else if ( param.dep && !MAGIC_DEPS[param.dep] ) {
  73. // only do require for params that have a matching dependency also
  74. // skip "magic" dependencies
  75. requires.push( 'var '+ param.name +' = require(\''+ param.dep +'\');' );
  76. }
  77. });
  78. return requires.join('\n');
  79. }
  80. function getDependenciesNames(args){
  81. var deps = [];
  82. var arr = args.filter(function(arg){
  83. return arg.type === 'ArrayExpression';
  84. })[0];
  85. if (arr) {
  86. deps = arr.elements.map(function(el){
  87. return el.value;
  88. });
  89. }
  90. return deps;
  91. }
  92. function isDefine(node){
  93. return node.type === 'ExpressionStatement' &&
  94. node.expression.type === 'CallExpression' &&
  95. node.expression.callee.type === 'Identifier' &&
  96. node.expression.callee.name === 'define';
  97. }
  98. function getFactory(args){
  99. return args.filter(function(arg){
  100. return arg.type === 'FunctionExpression';
  101. })[0];
  102. }
  103. function getBody(raw, factoryBody, useStrict){
  104. var returnStatement = factoryBody.body.filter(function(node){
  105. return node.type === 'ReturnStatement';
  106. })[0];
  107. var body = '';
  108. var bodyStart = useStrict ? useStrict.expression.range[1] + 1 : factoryBody.range[0] + 1;
  109. if (returnStatement) {
  110. body += raw.substring( bodyStart, returnStatement.range[0] );
  111. // "return ".length === 7 so we add "6" to returnStatement start
  112. body += 'module.exports ='+ raw.substring( returnStatement.range[0] + 6, factoryBody.range[1] - 1 );
  113. } else {
  114. // if using exports or module.exports or just a private module we
  115. // simply return the factoryBody content
  116. body = raw.substring( bodyStart, factoryBody.range[1] - 1 );
  117. }
  118. return body;
  119. }
  120. function getUseStrict(factory){
  121. return factory.body.body.filter(isUseStrict)[0];
  122. }
  123. function isUseStrict(node){
  124. return node.type === 'ExpressionStatement' &&
  125. node.expression.type === 'Literal' &&
  126. node.expression.value === 'use strict';
  127. }