sandboxApp.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 fs = require('fs');
  10. var Promise = require('bluebird');
  11. var Mustache = require('mustache');
  12. var app = express();
  13. // var examplesJSON = __dirname + '/exemples/liste.json';
  14. var sandboxTpml = fs.readFileSync(__dirname + '/html/template.mustache.html').toString();
  15. // var examples = require(examplesJSON);
  16. Promise.promisifyAll(fs);
  17. // Initialize Express app: root folder as static, body parsers
  18. app.use(express.static(__dirname));
  19. app.use(bodyParser.json());
  20. app.use(bodyParser.urlencoded({ extended: true }));
  21. function scandir(path, excludes) {
  22. excludes = excludes || [];
  23. return fs.readdirAsync(path)
  24. .then(dirContent => {
  25. excludes.forEach(file => {
  26. var idxInContent = dirContent.indexOf(file);
  27. if(idxInContent !== -1) {
  28. dirContent.splice(idxInContent, 1);
  29. }
  30. });
  31. return dirContent;
  32. })
  33. }
  34. function ExampleStore(path) {
  35. this.rootPath = path;
  36. this.repos = [];
  37. }
  38. ExampleStore.prototype.init = function() {
  39. const loadRepository = this.loadRepository.bind(this);
  40. return scandir(this.rootPath, ['.gitkeep'])
  41. .then(repositories => Promise.map(
  42. repositories, loadRepository
  43. ));
  44. };
  45. ExampleStore.prototype.loadRepository = function(repoPath) {
  46. const loadExample = this.loadExample.bind(this);
  47. const fullPath = this.rootPath + '/' + repoPath;
  48. const repoConfig = require(fullPath + '/repo-config.json');
  49. const repoDescriptor = {
  50. title: repoConfig.title,
  51. path: repoPath,
  52. fullPath,
  53. examples: []
  54. };
  55. this.repos.push(repoDescriptor);
  56. return scandir(fullPath, ['.gitkeep', 'repo-config.json'])
  57. .then(examples => Promise.map(
  58. examples, example => loadExample(repoDescriptor, example)
  59. ))
  60. .then(() => console.log(this.repos[0]))
  61. };
  62. ExampleStore.prototype.loadExample = function(repo, slug) {
  63. const exampleConfig = require(repo.fullPath + '/' + slug + '/config.json');
  64. repo.examples.push(Object.assign({ slug }, exampleConfig));
  65. return exampleConfig;
  66. };
  67. ExampleStore.prototype.getList = function(path) {
  68. return _.find(this.repos, { path });
  69. }
  70. ExampleStore.prototype.getMenu = function(path) {
  71. const self = this;
  72. return '<ul>' + self.repos.reduce((menu, repo) => {
  73. return '<li>'+ repo.title + '<ul>' + repo.examples.reduce((submenu, example) =>
  74. (submenu + '<li><a href="#' + repo.path + '/' + example.slug + '">' + example.title + '</a></li>'),
  75. '') + '</ul></li>';
  76. }, '') + '</ul>';
  77. }
  78. var es = new ExampleStore(__dirname + '/exemples');
  79. es.init()
  80. .then(() => console.log(es.getMenu()));
  81. function addExample(slug, title) {
  82. examples.push({ slug: slug, title: title });
  83. return fs.writeFileAsync(examplesJSON, beautify(examples, null, 2, 100));
  84. }
  85. function readConfigJson(exampleSlug) {
  86. console.log(exampleSlug);
  87. return require('./exemples/jquery/' + exampleSlug + '/config.json');
  88. }
  89. function readFileAsync(file) {
  90. return fs.readFileAsync(file)
  91. .then(buf => (buf.toString()));
  92. }
  93. // function readFilesAsync(path, files) {
  94. // // console.log('reading files', files, 'from path', path);
  95. // return Promise.map(files,
  96. // f => readFileAsync(path + '/' + f)
  97. // );
  98. // }
  99. // function readExampleFiles(slug, config) {
  100. // const exampleDir = __dirname + '/exemples/' + slug;
  101. // const libsCssDir = __dirname + '/css/vendor';
  102. // const libsJsDir = __dirname + '/js/vendor';
  103. // const { html, js, css, libsCss, libsJs } = config;
  104. // return Promise.all([
  105. // readFilesAsync(exampleDir, html),
  106. // readFilesAsync(exampleDir, js),
  107. // readFilesAsync(exampleDir, css),
  108. // readFilesAsync(libsJsDir, libsJs),
  109. // readFilesAsync(libsCssDir, libsCss),
  110. // ]);
  111. // }
  112. app.post('/examples', function(req, res) {
  113. var title = req.body.title;
  114. if(! req.body.title) {
  115. res.status(400).send('Le titre ne peut pas être vide !');
  116. }
  117. var existingTitle = _.find(examples, { title: title });
  118. if(existingTitle) {
  119. res.status(400).send("L'exemple '" + title + "' existe déjà !");
  120. }
  121. var exampleSlug = slug(req.body.title.toLowerCase());
  122. var targetDir = __dirname + '/exemples/' + exampleSlug;
  123. fs.mkdirAsync(targetDir)
  124. .then(() => Promise.map(
  125. ['contenu.html', 'script.js'], f => fs.writeFileAsync(targetDir + '/' + f, '')
  126. ))
  127. .then(files => addExample(exampleSlug, title))
  128. .then(() => res.json({ slug: exampleSlug, title: title }));
  129. });
  130. app.get('/examples/:slug', function(req, res) {
  131. const { slug } = req.params;
  132. const config = readConfigJson(slug);
  133. const { title, html, js, css, libsCss, libsJs } = config;
  134. readFileAsync(__dirname + '/exemples/' + slug + '/example.html')
  135. .then(body =>
  136. Mustache.render(sandboxTpml, { body, slug, title, js, css, libsCss, libsJs })
  137. )
  138. .then(html => res.send(html));
  139. });
  140. app.get('/menu', (rea, res) => {
  141. res.send(es.getMenu());
  142. });
  143. app.get('/list/:repoPath', function(req, res) {
  144. const { repoPath } = req.params;
  145. const repo = es.getList(repoPath);
  146. if(! repo) {
  147. return res.status(404).send('Repo ' + repoPath + ' not found');
  148. }
  149. console.log('found repo', repo);
  150. const data = repo.examples.map(e => (
  151. { slug: e.slug, title: e.title }
  152. ));
  153. res.json(data);
  154. });
  155. app.put('/examples/:slug', function(req, res) {
  156. var slug = req.params.slug;
  157. var existing = _.find(examples, { slug: slug });
  158. if(! existing) {
  159. res.status(404).send("L'exemple avec l'identifiant '" + slug + "' est introuvable !");
  160. }
  161. var targetDir = __dirname + '/exemples/' + slug;
  162. if(req.body.html) {
  163. fs.writeFileSync(targetDir + '/contenu.html', req.body.html);
  164. }
  165. if(req.body.javascript) {
  166. fs.writeFileSync(targetDir + '/script.js', req.body.javascript);
  167. }
  168. var theDate = new Date();
  169. console.log(theDate.getHours() + ':' + theDate.getMinutes() + " - Sauvegarde de l'exemple '" + existing.title + " effectuée'");
  170. res.json({ success: true });
  171. });
  172. module.exports = app;