sandboxApp.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* global __dirname */
  2. /* jshint strict:false */
  3. "use strict";
  4. var express = require('express');
  5. var bodyParser = require('body-parser');
  6. var slug = require('slug');
  7. var beautify = require("json-beautify");
  8. var _ = require('lodash');
  9. var path = require('path');
  10. var Mustache = require('mustache');
  11. var app = express();
  12. var fs = require('fs');
  13. var Promise = require('bluebird'); Promise.promisifyAll(fs);
  14. var sandboxTpml = fs.readFileSync(__dirname + '/html/template.mustache.html').toString();
  15. var exampleTmpl = require('./lib/exampleTmpl.json');
  16. var ExampleStore = require('./lib/ExampleStore');
  17. var examplesDir = __dirname + '/exemples';
  18. // var examplesDir = __dirname + '/test/integration/test-examples';
  19. var exStore = new ExampleStore(examplesDir);
  20. var {
  21. readFileAsync,
  22. readFilesAsync
  23. } = require('./lib/fsio');
  24. var {
  25. getAcceptLanguage,
  26. getIndexBare,
  27. getIndexRepo,
  28. getIndexExample
  29. } = require('./lib/indexHandlers')(exStore, examplesDir);
  30. var {
  31. // getIndexBare,
  32. getPartsRepo,
  33. getPartsExample
  34. } = require('./lib/partHandlers')(exStore, examplesDir);
  35. /**
  36. * Initialize example store
  37. */
  38. exStore.init();
  39. // .then(() => console.log(exStore.getMenu()));
  40. /**
  41. * Initialize Express app:
  42. * - root folder as static
  43. * - body parsers
  44. * - browser language detection middleware
  45. */
  46. app.use(express.static(__dirname));
  47. app.use(bodyParser.json());
  48. app.use(bodyParser.urlencoded({ extended: true }));
  49. app.use(getAcceptLanguage);
  50. function addExample(slug, title) {
  51. return fs.writeFileAsync(examplesJSON, beautify(examples, null, 2, 100));
  52. }
  53. function readConfigJson(exampleSlug) {
  54. console.log(exampleSlug);
  55. return require('./exemples/jquery/' + exampleSlug + '/config.json');
  56. }
  57. function mapObjToArray(obj, key, value) {
  58. var arr = [];
  59. for(var p in obj) {
  60. arr.push({
  61. [key]: p,
  62. [value]: obj[p]
  63. });
  64. }
  65. return arr;
  66. }
  67. /**
  68. * Get repo parts
  69. */
  70. app.get('/parts/:repoSlug', getPartsRepo);
  71. /**
  72. * Get example parts
  73. */
  74. app.get('/parts/:repoSlug/:exampleSlug', getPartsExample);
  75. /**
  76. * Index page: render with only repo list in menu
  77. */
  78. app.get('/', getIndexBare);
  79. /**
  80. * Repo page: render with repo list and selected repo's example list in menu
  81. */
  82. app.get('/:repoSlug', getIndexRepo);
  83. /**
  84. * Example page: render with repo list and selected repo's example list in menu,
  85. * and the editor with the selected example
  86. */
  87. app.get('/:repoSlug/:exampleSlug', getIndexExample);
  88. /**
  89. * Create a new example for specified repo
  90. */
  91. app.post('/:repoSlug/examples', function(req, res) {
  92. // Check for title and extract params
  93. if(! req.body || ! req.body.title) {
  94. res.status(400).send('Le titre ne peut pas être vide !');
  95. }
  96. const { title } = req.body;
  97. const { repoSlug } = req.params;
  98. // Get repo from store
  99. var repo = exStore.getRepo(repoSlug);
  100. if(! repo) {
  101. res.status(404).send("Repo " + repoSlug + "not found");
  102. }
  103. // Prevent duplicate title
  104. var existingTitle = _.find(repo.examples, { title: title });
  105. if(existingTitle) {
  106. res.status(400).send("L'exemple '" + title + "' existe déjà !");
  107. }
  108. var exampleSlug = slug(req.body.title.toLowerCase());
  109. // Prepare config
  110. var config = Object.assign({
  111. slug: exampleSlug,
  112. title,
  113. category: repo.defaultCategory
  114. }, exampleTmpl);
  115. // Prepare files to write
  116. var targetDir = __dirname + '/exemples/' + repoSlug + '/' + exampleSlug;
  117. var files = mapObjToArray({
  118. 'example.html': '<!-- ' + title + '-->\n',
  119. 'script.js': '// ' + title,
  120. 'config.json': beautify(config, null, 2, 100)
  121. }, 'file', 'content');
  122. fs.mkdirAsync(targetDir)
  123. .then(() => Promise.map(
  124. files, ({ file, content }) => fs.writeFileAsync(targetDir + '/' + file, content)
  125. ))
  126. .then(files => repo.examples.push(config))
  127. .then(() => res.json(config));
  128. });
  129. app.get('/examples/:slug', function(req, res) {
  130. const { slug } = req.params;
  131. const config = readConfigJson(slug);
  132. const { title, html, js, css, libsCss, libsJs } = config;
  133. readFileAsync(__dirname + '/exemples/' + slug + '/example.html')
  134. .then(body =>
  135. Mustache.render(sandboxTpml, { body, slug, title, js, css, libsCss, libsJs })
  136. )
  137. .then(html => res.send(html));
  138. });
  139. app.get('/menu', (rea, res) => {
  140. res.send(exStore.getMenu());
  141. });
  142. app.get('/list/:repoPath', function(req, res) {
  143. const { repoPath } = req.params;
  144. const repo = exStore.getList(repoPath);
  145. if(! repo) {
  146. return res.status(404).send('Repo ' + repoPath + ' not found');
  147. }
  148. console.log('found repo', repo);
  149. const data = repo.examples.map(e => (
  150. { slug: e.slug, title: e.title }
  151. ));
  152. res.json(data);
  153. });
  154. app.put('/examples/:slug', function(req, res) {
  155. var slug = req.params.slug;
  156. var existing = _.find(examples, { slug: slug });
  157. if(! existing) {
  158. res.status(404).send("L'exemple avec l'identifiant '" + slug + "' est introuvable !");
  159. }
  160. var targetDir = __dirname + '/exemples/' + slug;
  161. if(req.body.html) {
  162. fs.writeFileSync(targetDir + '/contenu.html', req.body.html);
  163. }
  164. if(req.body.javascript) {
  165. fs.writeFileSync(targetDir + '/script.js', req.body.javascript);
  166. }
  167. var theDate = new Date();
  168. console.log(theDate.getHours() + ':' + theDate.getMinutes() + " - Sauvegarde de l'exemple '" + existing.title + " effectuée'");
  169. res.json({ success: true });
  170. });
  171. module.exports = app;