indexHandlers.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /* global __dirname */
  2. "use strict";
  3. var _ = require('lodash');
  4. var Mustache = require('mustache');
  5. var path = require('path');
  6. var fs = require('fs');
  7. var chokidar = require('chokidar');
  8. var indexTmplPath = path.normalize(__dirname + '/../html/index.mustache.html');
  9. var indexTpml;
  10. var {
  11. readFilesAsync
  12. } = require('../lib/fsio');
  13. var translator = require('../lib/translator');
  14. var passLog = require('../lib/passLog');
  15. indexTpml = fs.readFileSync(indexTmplPath).toString();
  16. // One-liner for current directory, ignores .dotfiles
  17. chokidar.watch('./html', {ignored: /(^|[\/\\])\../}).on('all', (event, path) => {
  18. // console.log(event, path);
  19. if(path === 'html/index.mustache.html') {
  20. console.log('reload index html');
  21. indexTpml = fs.readFileSync(indexTmplPath).toString();
  22. }
  23. });
  24. module.exports = function(exStore, exDir, testMode) {
  25. function readExampleFiles(repoSlug, exampleSlug, config) {
  26. const exampleDir = exDir + '/' + repoSlug + '/' + exampleSlug;
  27. const libsCssDir = path.normalize(__dirname + '/../css/vendor');
  28. const libsJsDir = path.normalize(__dirname + '/../js/vendor');
  29. const { html, js, css } = config; // libsCss, libsJs
  30. const files = [].concat(html, js, css);
  31. return readFilesAsync(exampleDir, files);
  32. }
  33. function renderIndex(req, withRepo, withExample) {
  34. // Extract repoSlug and exampleSlug from req.params
  35. const { locale, params: { repoSlug, exampleSlug } } = req;
  36. let repo;
  37. let menuExample;
  38. let statusCode;
  39. const menuRepo = exStore.getRepoMenu();
  40. const translations = translator.getAll(locale);
  41. // Initialize view data
  42. let data = {
  43. menuRepo,
  44. reposJSON: JSON.stringify(menuRepo),
  45. repoJSON: 'null',
  46. exampleJSON: 'null',
  47. testMode,
  48. testRun: testMode && req.query.testing,
  49. appPath: req.path,
  50. _: translations,
  51. _JSON: JSON.stringify(translations)
  52. };
  53. // Fetch example repository if needed
  54. if(withRepo) {
  55. data.repo = exStore.getRepo(repoSlug);
  56. data.repoJSON = JSON.stringify(data.repo);
  57. if(! data.repo) {
  58. // return res.status(404).send('Repo ' + req.params.repoSlug + ' not found');
  59. data.errorMessage = translator.getOne(locale, "repoNotFound", [repoSlug]); //'Repo ' + params.repoSlug + ' not found';
  60. statusCode = 404;
  61. }
  62. else {
  63. data.menuExample = exStore.getExampleMenu(data.repo.path);
  64. data.showControls = true;
  65. }
  66. }
  67. // Fetch example if needed
  68. if(withExample && data.repo) {
  69. data.example = _.find(data.repo.examples, { slug: exampleSlug });
  70. data.exampleJSON = JSON.stringify(data.example);
  71. if(! data.example) {
  72. // return res.status(404).send('Example ' + req.params.repoSlug + '/' + req.params.exampleSlug + ' not found');
  73. data.errorMessage = translator.getOne(locale, "exampleNotFound", [repoSlug, exampleSlug]);
  74. statusCode = 404;
  75. }
  76. else {
  77. data.showEditor = true;
  78. }
  79. }
  80. data.showShortcutExample = data.repo && ! data.example;
  81. // Mustache.render(indexTpml, data);
  82. return (
  83. exampleSlug && data.example ?
  84. readExampleFiles(repoSlug, exampleSlug, data.example) : Promise.resolve([])
  85. ).then(files =>
  86. ({ files, filesJSON: JSON.stringify(files) })
  87. )
  88. .then(({ files, filesJSON }) => Object.assign(data, { files, filesJSON }))
  89. .then(passLog('data before rendering, path: ' + req.path))
  90. .then(data => ({
  91. html: Mustache.render(indexTpml, data),
  92. code: statusCode ? statusCode : 200
  93. }))
  94. .catch(err => {
  95. console.error('#### Error', err);
  96. return { code: 500, html: err.message };
  97. });
  98. }
  99. return {
  100. /**
  101. * Extract language header from req
  102. */
  103. getAcceptLanguage: function (req, res, next) {
  104. const acceptLanguageHdr = req.headers["accept-language"];
  105. const re = /[a-z]{2}\-[A-Z]{2}/;
  106. const matches = re.exec(acceptLanguageHdr);
  107. if(matches) {
  108. req.locale = matches[0];
  109. }
  110. next();
  111. },
  112. /**
  113. * Get bare index without repo or examples
  114. */
  115. getIndexBare: function(req, res) {
  116. renderIndex(req)
  117. .then(({ html, code }) => res.send(html));
  118. },
  119. /**
  120. * Get index with repo selected only
  121. */
  122. getIndexRepo: function(req, res) {
  123. renderIndex(req, true)
  124. .then(({ html, code }) => res.status(code).send(html));
  125. },
  126. /**
  127. * Get index with selected repo&example
  128. */
  129. getIndexExample: function(req, res) {
  130. renderIndex(req, true, true)
  131. .then(({ html, code }) => res.status(code).send(html));
  132. }
  133. };
  134. };