compile.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /**
  2. * Module dependencies.
  3. */
  4. var fs = require('fs');
  5. /**
  6. * Arguments.
  7. */
  8. var args = process.argv.slice(2)
  9. , pending = args.length
  10. , files = {};
  11. console.log('');
  12. // parse arguments
  13. args.forEach(function(file){
  14. var mod = file.replace('lib/', '');
  15. fs.readFile(file, 'utf8', function(err, js){
  16. if (err) throw err;
  17. console.log(' \033[90mcompile : \033[0m\033[36m%s\033[0m', file);
  18. files[file] = parse(js);
  19. --pending || compile();
  20. });
  21. });
  22. /**
  23. * Parse the given `js`.
  24. */
  25. function parse(js) {
  26. return parseInheritance(parseConditionals(js));
  27. }
  28. /**
  29. * Parse __proto__.
  30. */
  31. function parseInheritance(js) {
  32. return js
  33. .replace(/^ *(\w+)\.prototype\.__proto__ * = *(\w+)\.prototype *;?/gm, function(_, child, parent){
  34. return child + '.prototype = new ' + parent + ';\n'
  35. + child + '.prototype.constructor = '+ child + ';\n';
  36. });
  37. }
  38. /**
  39. * Parse the given `js`, currently supporting:
  40. *
  41. * 'if' ['node' | 'browser']
  42. * 'end'
  43. *
  44. */
  45. function parseConditionals(js) {
  46. var lines = js.split('\n')
  47. , len = lines.length
  48. , buffer = true
  49. , browser = false
  50. , buf = []
  51. , line
  52. , cond;
  53. for (var i = 0; i < len; ++i) {
  54. line = lines[i];
  55. if (/^ *\/\/ *if *(node|browser)/gm.exec(line)) {
  56. cond = RegExp.$1;
  57. buffer = browser = 'browser' == cond;
  58. } else if (/^ *\/\/ *end/.test(line)) {
  59. buffer = true;
  60. browser = false;
  61. } else if (browser) {
  62. buf.push(line.replace(/^( *)\/\//, '$1'));
  63. } else if (buffer) {
  64. buf.push(line);
  65. }
  66. }
  67. return buf.join('\n');
  68. }
  69. /**
  70. * Compile the files.
  71. */
  72. function compile() {
  73. var buf = '';
  74. buf += 'ejs = (function(){\n';
  75. buf += '\n// CommonJS require()\n\n';
  76. buf += browser.require + '\n\n';
  77. buf += 'require.modules = {};\n\n';
  78. buf += 'require.resolve = ' + browser.resolve + ';\n\n';
  79. buf += 'require.register = ' + browser.register + ';\n\n';
  80. buf += 'require.relative = ' + browser.relative + ';\n\n';
  81. args.forEach(function(file){
  82. var js = files[file];
  83. file = file.replace('lib/', '');
  84. buf += '\nrequire.register("' + file + '", function(module, exports, require){\n';
  85. buf += js;
  86. buf += '\n}); // module: ' + file + '\n';
  87. });
  88. buf += '\n return require("ejs");\n})();';
  89. fs.writeFile('ejs.js', buf, function(err){
  90. if (err) throw err;
  91. console.log(' \033[90m create : \033[0m\033[36m%s\033[0m', 'ejs.js');
  92. console.log();
  93. });
  94. }
  95. // refactored version of weepy's
  96. // https://github.com/weepy/brequire/blob/master/browser/brequire.js
  97. var browser = {
  98. /**
  99. * Require a module.
  100. */
  101. require: function require(p){
  102. if ('fs' == p) return {};
  103. if ('path' == p) return {};
  104. var path = require.resolve(p)
  105. , mod = require.modules[path];
  106. if (!mod) throw new Error('failed to require "' + p + '"');
  107. if (!mod.exports) {
  108. mod.exports = {};
  109. mod.call(mod.exports, mod, mod.exports, require.relative(path));
  110. }
  111. return mod.exports;
  112. },
  113. /**
  114. * Resolve module path.
  115. */
  116. resolve: function(path){
  117. var orig = path
  118. , reg = path + '.js'
  119. , index = path + '/index.js';
  120. return require.modules[reg] && reg
  121. || require.modules[index] && index
  122. || orig;
  123. },
  124. /**
  125. * Return relative require().
  126. */
  127. relative: function(parent) {
  128. return function(p){
  129. if ('.' != p.substr(0, 1)) return require(p);
  130. var path = parent.split('/')
  131. , segs = p.split('/');
  132. path.pop();
  133. for (var i = 0; i < segs.length; i++) {
  134. var seg = segs[i];
  135. if ('..' == seg) path.pop();
  136. else if ('.' != seg) path.push(seg);
  137. }
  138. return require(path.join('/'));
  139. };
  140. },
  141. /**
  142. * Register a module.
  143. */
  144. register: function(path, fn){
  145. require.modules[path] = fn;
  146. }
  147. };