amd2common.js 5.2 KB

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