Bläddra i källkod

server-side rendering

Benoît Hubert 8 år sedan
förälder
incheckning
c20d54f690
7 ändrade filer med 167 tillägg och 60 borttagningar
  1. 44 9
      css/styles.css
  2. 7 0
      css/vendor/pure-grids-min.css
  3. 7 0
      css/vendor/pure-grids-responsive-min.css
  4. 32 26
      html/index.mustache.html
  5. 5 0
      js/editor.js
  6. 14 4
      lib/ExampleStore.js
  7. 58 21
      sandboxApp.js

+ 44 - 9
css/styles.css

@@ -3,11 +3,11 @@
  */
 @font-face {
   font-family: 'icomoon';
-  src:  url('fonts/icomoon.eot?xjk54g');
-  src:  url('fonts/icomoon.eot?xjk54g#iefix') format('embedded-opentype'),
-    url('fonts/icomoon.ttf?xjk54g') format('truetype'),
-    url('fonts/icomoon.woff?xjk54g') format('woff'),
-    url('fonts/icomoon.svg?xjk54g#icomoon') format('svg');
+  src:  url('fonts/icomoon.eot?q7b5dg');
+  src:  url('fonts/icomoon.eot?q7b5dg#iefix') format('embedded-opentype'),
+    url('fonts/icomoon.ttf?q7b5dg') format('truetype'),
+    url('fonts/icomoon.woff?q7b5dg') format('woff'),
+    url('fonts/icomoon.svg?q7b5dg#icomoon') format('svg');
   font-weight: normal;
   font-style: normal;
 }
@@ -27,6 +27,9 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-menu:before {
+  content: "\e9bd";
+}
 .icon-cloud-upload:before {
   content: "\e9c3";
 }
@@ -202,14 +205,46 @@ button:hover {
   border-bottom: 1px solid #aaa;
 }
 
+#nav-menus {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 0;
+  overflow: hidden;
+  transition: width 0.7s;
+  /*font-size: 16px;*/
+}
+
+#nav-menus.in {
+  width: 800px;
+}
+
+#nav-menus ul {
+  padding-left: 0;
+}
+
 /* Menus de nav */
-.nav-menu {
-  background: #eee;
+#nav-menus {
+  color: #000;
+  background: #f8f8f8;
   padding: 10px;
 }
+#nav-menus li {
+ list-style-type: none;
+}
+#menu-example {
+  overflow: 
+}
+#menu-example > li {
+  display: block;
+  float:left;
+  vertical-align: top;
+  width: 50%;
+}
 .nav-menu a {
-  color: #000;
+  color: #58c;
 }
 .nav-menu a:hover {
-  color: #555;
+  color: #7af;
 }

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 7 - 0
css/vendor/pure-grids-min.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 7 - 0
css/vendor/pure-grids-responsive-min.css


+ 32 - 26
html/index.mustache.html

@@ -2,11 +2,13 @@
 <html lang="en">
 <head>
 <title>{{title}} - Web sandbox</title>
-    <link rel="stylesheet" href="css/normalize.css">
-    <link rel="stylesheet" href="css/main.css">
+    <link rel="stylesheet" href="/css/normalize.css">
+    <link rel="stylesheet" href="/css/main.css">
 <!--     <link rel="stylesheet" href="css/qunit-2.4.1.css"> -->
-    <link rel="stylesheet" href="css/vendor/styles.css">
-    <link rel="stylesheet" href="css/styles.css">
+    <link rel="stylesheet" href="/css/vendor/pure-grids-min.css">
+    <link rel="stylesheet" href="/css/vendor/pure-grids-responsive-min.css">
+    <link rel="stylesheet" href="/css/vendor/styles.css">
+    <link rel="stylesheet" href="/css/styles.css">
 <style type="text/css" media="screen">
 
 </style>
@@ -16,18 +18,22 @@
 <div class="panel-container">
 
     <div class="panel-left">
+        <div id="nav-menus">
+            <ul id="menu-repo" class="nav-menu">{{#menuRepo}}
+              <li><a href="/{{slug}}">{{title}}</a></li>{{/menuRepo}}
+            </ul>
+
+            <div id="menu-example" class="pure-g nav-menu">{{#menuExample}}
+              <div class="pure-u-1 pure-u-md-1-2">{{category.title}}
+              <ul>{{#examples}}
+              <li><a href="/{{{slug}}}">{{title}}</a></li>{{/examples}}</ul>
+            </div>{{/menuExample}}</div>
+        </div>
+
         <div id="notification"></div>
         <div class="panel-inner">
 
-            <div id="nav-menus">
-                <ul id="menu-repo" class="nav-menu">{{#menuRepo}}
-                  <li><a href="{{slug}}">{{title}}</a></li>{{/menuRepo}}
-                </ul>
-
-                <ul id="menu-repo" class="nav-menu">{{#menuExample}}
-                  <li><a href="{{slug}}">{{title}}</a></li>{{/menuExample}}
-                </ul>
-            </div>
+            <button id="menu-btn" class="icon-menu"></button>
 
             <button id="add-example-btn" class="icon-plus rounded blue"></button>
             <form id="add-example-form" style="display: none;">
@@ -62,20 +68,20 @@
     <div class="splitter">
     </div>
 
-    <iframe class="panel-right" src="html/start-iframe.html"></iframe>
+    <iframe class="panel-right" src="/html/start-iframe.html"></iframe>
 </div>
 
-<script src="js/vendor/modernizr-3.5.0.min.js"></script>
-<script src="js/vendor/jquery-3.2.1.min.js" ></script>
-<script src="js/vendor/jquery-resizable.min.js" ></script>
-<!-- <script src="js/vendor/qunit-2.4.1.js" ></script> -->
-<script src="js/vendor/lodash.min.js" ></script>
-<script src="js/vendor/loadJS.js" ></script>
-<script src="js/plugins.js"></script>
-<script src="js/main.js"></script>
-<script src="js/vendor/ace/ace.js" type="text/javascript" charset="utf-8"></script>
-<script src="js/req-promise.js"></script>
-<script src="js/editor-local-storage.js"></script>
-<script src="js/editor.js"></script>
+<script src="/js/vendor/modernizr-3.5.0.min.js"></script>
+<script src="/js/vendor/jquery-3.2.1.min.js" ></script>
+<script src="/js/vendor/jquery-resizable.min.js" ></script>
+<!-- <script src="/js/vendor/qunit-2.4.1.js" ></script> -->
+<script src="/js/vendor/lodash.min.js" ></script>
+<script src="/js/vendor/loadJS.js" ></script>
+<script src="/js/plugins.js"></script>
+<script src="/js/main.js"></script>
+<script src="/js/vendor/ace/ace.js" type="text/javascript" charset="utf-8"></script>
+<script src="/js/req-promise.js"></script>
+<script src="/js/editor-local-storage.js"></script>
+<script src="/js/editor.js"></script>
 </body>
 </html>

+ 5 - 0
js/editor.js

@@ -28,6 +28,11 @@ $(document).ready(function() {
   var exampleList;
 
 
+  $('#menu-btn').click(() => {
+    $('#nav-menus').toggleClass('in');
+  });
+
+
   /**
    * Make the left panel resizable
    */

+ 14 - 4
lib/ExampleStore.js

@@ -18,12 +18,11 @@ ExampleStore.prototype.loadRepository = function(repoPath) {
   const loadExample    = this.loadExample.bind(this);
   const fullPath       = this.rootPath + '/' + repoPath;
   const repoConfig     = require(fullPath + '/repo-config.json');
-  const repoDescriptor = {
-    title: repoConfig.title,
+  const repoDescriptor = Object.assign(repoConfig, {
     path: repoPath,
     fullPath,
     examples: []
-  };
+  });
   this.repos.push(repoDescriptor);
   return scandir(fullPath, ['.gitkeep', 'repo-config.json'])
   .then(examples => Promise.map(
@@ -50,9 +49,20 @@ ExampleStore.prototype.getRepoMenu = function(path) {
 
 ExampleStore.prototype.getExampleMenu = function(path) {
   const repo = _.find(this.repos, { path });
-  return repo.examples.map(
+  console.log('repo examples', repo.examples)
+  const menu = repo.categories.map(category => {
+    const examplesInCat = repo.examples.filter(ex => (ex.category === category.slug));
+    console.log('examples in cat', category, examplesInCat);
+    const examples = examplesInCat.map(
     ({ title, slug }) => ({ title, slug: repo.path + '/' + slug }) 
   );
+    return { category, examples };
+  });
+  console.log(menu);
+  return menu;
+  // return repo.examples.map(
+  //   ({ title, slug }) => ({ title, slug: repo.path + '/' + slug }) 
+  // );
 };
 
 ExampleStore.prototype.getMenu = function(path) {

+ 58 - 21
sandboxApp.js

@@ -39,27 +39,31 @@ function readFileAsync(file) {
   .then(buf => (buf.toString()));
 }
 
-// function readFilesAsync(path, files) {
-//   // console.log('reading files', files, 'from path', path);
-//   return Promise.map(files,
-//     f => readFileAsync(path + '/' + f)
-//   );
-// }
-
-// function readExampleFiles(slug, config) {
-//   const exampleDir = __dirname + '/exemples/' + slug;
-//   const libsCssDir = __dirname + '/css/vendor';
-//   const libsJsDir  = __dirname + '/js/vendor';
-//   const { html, js, css, libsCss, libsJs } = config;
-//   return Promise.all([
-//     readFilesAsync(exampleDir, html),
-//     readFilesAsync(exampleDir, js),
-//     readFilesAsync(exampleDir, css),
-//     readFilesAsync(libsJsDir, libsJs),
-//     readFilesAsync(libsCssDir, libsCss),
-//   ]);
-// }
+function readFilesAsync(path, files) {
+  // console.log('reading files', files, 'from path', path);
+  return Promise.map(files,
+    f => readFileAsync(path + '/' + f)
+  );
+}
+
+function readExampleFiles(repoSlug, exampleSlug, config) {
+  const exampleDir = __dirname + '/exemples/' + repoSlug + '/' + exampleSlug;
+  const libsCssDir = __dirname + '/css/vendor';
+  const libsJsDir  = __dirname + '/js/vendor';
+  const { html, js, css } = config; // libsCss, libsJs 
+  return Promise.all([
+    readFilesAsync(exampleDir, html),
+    readFilesAsync(exampleDir, js),
+    readFilesAsync(exampleDir, css),
+    // readFilesAsync(libsJsDir, libsJs),
+    // readFilesAsync(libsCssDir, libsCss),
+  ]);
+}
+
 
+/**
+ * Index page: render with only repo list in menu
+ */
 app.get('/', function(req, res) {
   const menuRepo = exStore.getRepoMenu();
   // const title    = 'Home';
@@ -70,6 +74,9 @@ app.get('/', function(req, res) {
   }));
 });
 
+/**
+ * Repo page: render with repo list and selected repo's example list in menu
+ */
 app.get('/:repoSlug',
   function(req, res) {
     const repo = exStore.getRepo(req.params.repoSlug);
@@ -79,7 +86,7 @@ app.get('/:repoSlug',
     const menuRepo = exStore.getRepoMenu();
     const menuExample = exStore.getExampleMenu(repo.path);
     // const title    = 'Home';
-    console.log(menuRepo);
+    console.log(menuExample);
     res.send(Mustache.render(indexTpml, {
       // title,
       menuRepo,
@@ -87,6 +94,36 @@ app.get('/:repoSlug',
     }));
 });
 
+/**
+ * Example page: render with repo list and selected repo's example list in menu,
+ * and the editor with the selected example
+ */
+app.get('/:repoSlug/:exampleSlug',
+  function(req, res) {
+    const repo = exStore.getRepo(req.params.repoSlug);
+    if(! repo) {
+      return res.status(404).send('Repo ' + req.params.repoSlug + ' not found');
+    }
+    const menuRepo = exStore.getRepoMenu();
+    const menuExample = exStore.getExampleMenu(repo.path);
+    const example = _.find(repo.examples, { slug: req.params.exampleSlug });
+    if(! example) {
+      return res.status(404).send('Example ' + req.params.repoSlug + '/' + req.params.exampleSlug + ' not found');
+    }
+    // const title    = 'Home';
+    console.log(menuExample);
+    const { repoSlug, exampleSlug } = req.params;
+    readExampleFiles(repoSlug, exampleSlug, example)
+    .then(([ html, js, css ]) => {
+      console.log('example files', html, js, css);
+      res.send(Mustache.render(indexTpml, {
+        // title,
+        menuRepo,
+        menuExample
+      }));
+    });
+});
+
 app.post('/examples', function(req, res) {
   var title = req.body.title;
   if(! req.body.title) {