Built files from Bizgaze WebServer
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

precompiler.js 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /* eslint-disable no-console */
  2. import Async from 'neo-async';
  3. import fs from 'fs';
  4. import * as Handlebars from './handlebars';
  5. import { basename } from 'path';
  6. import { SourceMapConsumer, SourceNode } from 'source-map';
  7. module.exports.loadTemplates = function(opts, callback) {
  8. loadStrings(opts, function(err, strings) {
  9. if (err) {
  10. callback(err);
  11. } else {
  12. loadFiles(opts, function(err, files) {
  13. if (err) {
  14. callback(err);
  15. } else {
  16. opts.templates = strings.concat(files);
  17. callback(undefined, opts);
  18. }
  19. });
  20. }
  21. });
  22. };
  23. function loadStrings(opts, callback) {
  24. let strings = arrayCast(opts.string),
  25. names = arrayCast(opts.name);
  26. if (names.length !== strings.length && strings.length > 1) {
  27. return callback(
  28. new Handlebars.Exception(
  29. 'Number of names did not match the number of string inputs'
  30. )
  31. );
  32. }
  33. Async.map(
  34. strings,
  35. function(string, callback) {
  36. if (string !== '-') {
  37. callback(undefined, string);
  38. } else {
  39. // Load from stdin
  40. let buffer = '';
  41. process.stdin.setEncoding('utf8');
  42. process.stdin.on('data', function(chunk) {
  43. buffer += chunk;
  44. });
  45. process.stdin.on('end', function() {
  46. callback(undefined, buffer);
  47. });
  48. }
  49. },
  50. function(err, strings) {
  51. strings = strings.map((string, index) => ({
  52. name: names[index],
  53. path: names[index],
  54. source: string
  55. }));
  56. callback(err, strings);
  57. }
  58. );
  59. }
  60. function loadFiles(opts, callback) {
  61. // Build file extension pattern
  62. let extension = (opts.extension || 'handlebars').replace(
  63. /[\\^$*+?.():=!|{}\-[\]]/g,
  64. function(arg) {
  65. return '\\' + arg;
  66. }
  67. );
  68. extension = new RegExp('\\.' + extension + '$');
  69. let ret = [],
  70. queue = (opts.files || []).map(template => ({ template, root: opts.root }));
  71. Async.whilst(
  72. () => queue.length,
  73. function(callback) {
  74. let { template: path, root } = queue.shift();
  75. fs.stat(path, function(err, stat) {
  76. if (err) {
  77. return callback(
  78. new Handlebars.Exception(`Unable to open template file "${path}"`)
  79. );
  80. }
  81. if (stat.isDirectory()) {
  82. opts.hasDirectory = true;
  83. fs.readdir(path, function(err, children) {
  84. /* istanbul ignore next : Race condition that being too lazy to test */
  85. if (err) {
  86. return callback(err);
  87. }
  88. children.forEach(function(file) {
  89. let childPath = path + '/' + file;
  90. if (
  91. extension.test(childPath) ||
  92. fs.statSync(childPath).isDirectory()
  93. ) {
  94. queue.push({ template: childPath, root: root || path });
  95. }
  96. });
  97. callback();
  98. });
  99. } else {
  100. fs.readFile(path, 'utf8', function(err, data) {
  101. /* istanbul ignore next : Race condition that being too lazy to test */
  102. if (err) {
  103. return callback(err);
  104. }
  105. if (opts.bom && data.indexOf('\uFEFF') === 0) {
  106. data = data.substring(1);
  107. }
  108. // Clean the template name
  109. let name = path;
  110. if (!root) {
  111. name = basename(name);
  112. } else if (name.indexOf(root) === 0) {
  113. name = name.substring(root.length + 1);
  114. }
  115. name = name.replace(extension, '');
  116. ret.push({
  117. path: path,
  118. name: name,
  119. source: data
  120. });
  121. callback();
  122. });
  123. }
  124. });
  125. },
  126. function(err) {
  127. if (err) {
  128. callback(err);
  129. } else {
  130. callback(undefined, ret);
  131. }
  132. }
  133. );
  134. }
  135. module.exports.cli = function(opts) {
  136. if (opts.version) {
  137. console.log(Handlebars.VERSION);
  138. return;
  139. }
  140. if (!opts.templates.length && !opts.hasDirectory) {
  141. throw new Handlebars.Exception(
  142. 'Must define at least one template or directory.'
  143. );
  144. }
  145. if (opts.simple && opts.min) {
  146. throw new Handlebars.Exception('Unable to minimize simple output');
  147. }
  148. const multiple = opts.templates.length !== 1 || opts.hasDirectory;
  149. if (opts.simple && multiple) {
  150. throw new Handlebars.Exception(
  151. 'Unable to output multiple templates in simple mode'
  152. );
  153. }
  154. // Force simple mode if we have only one template and it's unnamed.
  155. if (
  156. !opts.amd &&
  157. !opts.commonjs &&
  158. opts.templates.length === 1 &&
  159. !opts.templates[0].name
  160. ) {
  161. opts.simple = true;
  162. }
  163. // Convert the known list into a hash
  164. let known = {};
  165. if (opts.known && !Array.isArray(opts.known)) {
  166. opts.known = [opts.known];
  167. }
  168. if (opts.known) {
  169. for (let i = 0, len = opts.known.length; i < len; i++) {
  170. known[opts.known[i]] = true;
  171. }
  172. }
  173. const objectName = opts.partial ? 'Handlebars.partials' : 'templates';
  174. let output = new SourceNode();
  175. if (!opts.simple) {
  176. if (opts.amd) {
  177. output.add(
  178. "define(['" +
  179. opts.handlebarPath +
  180. 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];'
  181. );
  182. } else if (opts.commonjs) {
  183. output.add('var Handlebars = require("' + opts.commonjs + '");');
  184. } else {
  185. output.add('(function() {\n');
  186. }
  187. output.add(' var template = Handlebars.template, templates = ');
  188. if (opts.namespace) {
  189. output.add(opts.namespace);
  190. output.add(' = ');
  191. output.add(opts.namespace);
  192. output.add(' || ');
  193. }
  194. output.add('{};\n');
  195. }
  196. opts.templates.forEach(function(template) {
  197. let options = {
  198. knownHelpers: known,
  199. knownHelpersOnly: opts.o
  200. };
  201. if (opts.map) {
  202. options.srcName = template.path;
  203. }
  204. if (opts.data) {
  205. options.data = true;
  206. }
  207. let precompiled = Handlebars.precompile(template.source, options);
  208. // If we are generating a source map, we have to reconstruct the SourceNode object
  209. if (opts.map) {
  210. let consumer = new SourceMapConsumer(precompiled.map);
  211. precompiled = SourceNode.fromStringWithSourceMap(
  212. precompiled.code,
  213. consumer
  214. );
  215. }
  216. if (opts.simple) {
  217. output.add([precompiled, '\n']);
  218. } else {
  219. if (!template.name) {
  220. throw new Handlebars.Exception('Name missing for template');
  221. }
  222. if (opts.amd && !multiple) {
  223. output.add('return ');
  224. }
  225. output.add([
  226. objectName,
  227. "['",
  228. template.name,
  229. "'] = template(",
  230. precompiled,
  231. ');\n'
  232. ]);
  233. }
  234. });
  235. // Output the content
  236. if (!opts.simple) {
  237. if (opts.amd) {
  238. if (multiple) {
  239. output.add(['return ', objectName, ';\n']);
  240. }
  241. output.add('});');
  242. } else if (!opts.commonjs) {
  243. output.add('})();');
  244. }
  245. }
  246. if (opts.map) {
  247. output.add('\n//# sourceMappingURL=' + opts.map + '\n');
  248. }
  249. output = output.toStringWithSourceMap();
  250. output.map = output.map + '';
  251. if (opts.min) {
  252. output = minify(output, opts.map);
  253. }
  254. if (opts.map) {
  255. fs.writeFileSync(opts.map, output.map, 'utf8');
  256. }
  257. output = output.code;
  258. if (opts.output) {
  259. fs.writeFileSync(opts.output, output, 'utf8');
  260. } else {
  261. console.log(output);
  262. }
  263. };
  264. function arrayCast(value) {
  265. value = value != null ? value : [];
  266. if (!Array.isArray(value)) {
  267. value = [value];
  268. }
  269. return value;
  270. }
  271. /**
  272. * Run uglify to minify the compiled template, if uglify exists in the dependencies.
  273. *
  274. * We are using `require` instead of `import` here, because es6-modules do not allow
  275. * dynamic imports and uglify-js is an optional dependency. Since we are inside NodeJS here, this
  276. * should not be a problem.
  277. *
  278. * @param {string} output the compiled template
  279. * @param {string} sourceMapFile the file to write the source map to.
  280. */
  281. function minify(output, sourceMapFile) {
  282. try {
  283. // Try to resolve uglify-js in order to see if it does exist
  284. require.resolve('uglify-js');
  285. } catch (e) {
  286. if (e.code !== 'MODULE_NOT_FOUND') {
  287. // Something else seems to be wrong
  288. throw e;
  289. }
  290. // it does not exist!
  291. console.error(
  292. 'Code minimization is disabled due to missing uglify-js dependency'
  293. );
  294. return output;
  295. }
  296. return require('uglify-js').minify(output.code, {
  297. sourceMap: {
  298. content: output.map,
  299. url: sourceMapFile
  300. }
  301. });
  302. }