initial commit
This commit is contained in:
		
							parent
							
								
									3f3b892240
								
							
						
					
					
						commit
						f31f6ea1a4
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +1,6 @@ | ||||
| node_modules | ||||
| bower_components | ||||
| 
 | ||||
| # Logs | ||||
| logs | ||||
| *.log | ||||
|  | ||||
							
								
								
									
										40
									
								
								bower.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								bower.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| { | ||||
|   "name": "deardesi", | ||||
|   "version": "1.0.0", | ||||
|   "authors": [ | ||||
|     "AJ ONeal <awesome@coolaj86.com>" | ||||
|   ], | ||||
|   "description": "A blogging platform in the browser. Wow!", | ||||
|   "main": "deardesi.js", | ||||
|   "moduleType": [ | ||||
|     "globals", | ||||
|     "node" | ||||
|   ], | ||||
|   "keywords": [ | ||||
|     "dear", | ||||
|     "desi", | ||||
|     "deardesi", | ||||
|     "blog", | ||||
|     "blogging", | ||||
|     "platform", | ||||
|     "browser" | ||||
|   ], | ||||
|   "license": "Apache2", | ||||
|   "homepage": "http://github.com/coolaj86/deardesi", | ||||
|   "ignore": [ | ||||
|     "**/.*", | ||||
|     "node_modules", | ||||
|     "bower_components", | ||||
|     "test", | ||||
|     "tests" | ||||
|   ], | ||||
|   "dependencies": { | ||||
|     "mustache": "~0.8.2", | ||||
|     "bluebird": "~2.5.2", | ||||
|     "rsvp": "~3.0.16", | ||||
|     "escape-string-regexp": "~1.0.2", | ||||
|     "marked": "~0.3.2", | ||||
|     "js-yaml": "~3.2.5", | ||||
|     "path": "~3.46.1" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										216
									
								
								deardesi.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								deardesi.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,216 @@ | ||||
| ;(function (exports) { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   //require('require-yaml');
 | ||||
| 
 | ||||
|   var PromiseA      = exports.Promise       || require('bluebird').Promise | ||||
|     , path          = exports.path          || require('path') | ||||
|     , Mustache      = exports.Mustache      || require('mustache') | ||||
|     , marked        = exports.marked        || require('marked') | ||||
|     , forEachAsync  = exports.forEachAsync  || require('foreachasync').forEachAsync | ||||
|     , sha1sum       = exports.sha1sum       || require('./lib/deardesi-node').sha1sum | ||||
|     , frontmatter   = exports.frontmatter   || require('./lib/frontmatter').Frontmatter | ||||
|     , safeResolve   = exports.safeResolve   || require('./lib/deardesi-utils').safeResolve | ||||
|     , getStats      = exports.getStats      || require('./lib/deardesi-node').getStats | ||||
|     , getContents   = exports.getContents   || require('./lib/deardesi-node').getContents | ||||
|     ; | ||||
| 
 | ||||
|   function getCollections(blogbase, ignorable, collectionnames) { | ||||
|     var collectiondir | ||||
|       , collectiondirs = [] | ||||
|       , lost = [] | ||||
|       , found = [] | ||||
|       , errors = [] | ||||
|       ; | ||||
| 
 | ||||
| 
 | ||||
|     collectionnames.forEach(function (collectionname) { | ||||
|       collectiondir = safeResolve(_dirname, collectionname); | ||||
| 
 | ||||
|       if (!collectiondir) { | ||||
|         return PromiseA.reject(new Error("Please update your config.yml: " + collectionname + " is outside of '" + _dirname + "'")); | ||||
|       } | ||||
| 
 | ||||
|       collectiondirs.push({ name: collectionname, path: collectiondir }); | ||||
|     }); | ||||
| 
 | ||||
| 
 | ||||
|     return getFolders(collectiondirs, { recursive: true, limit: 5, stats: true }).then(function (stats) { | ||||
|       collectiondirs.forEach(function (collection) { | ||||
|         if (!stats[collection.path]) { | ||||
|           errors.push({ | ||||
|             collection: collection | ||||
|           , message: "server did not return success or error for " + collection.path + ':\n' + JSON.stringify(stats) | ||||
|           }); | ||||
|         } | ||||
|         else if (!stats[collection.path].type) { | ||||
|           lost.push(collection); | ||||
|         } | ||||
|         else if ('directory' !== stats[collection.path].type) { | ||||
|           errors.push({ | ||||
|             collection: collection | ||||
|           , message: collection.path + " is not a directory (might be a symbolic link)" | ||||
|           }); | ||||
|         } else { | ||||
|           found.push(collection); | ||||
|         } | ||||
|       }); | ||||
| 
 | ||||
|       return { | ||||
|         lost: lost | ||||
|       , found: found | ||||
|       , errors: errors | ||||
|       }; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function showCollectionNotes(notes) { | ||||
|     if (notes.lost.length) { | ||||
|       console.warn("WARNING: these collections you specified couldn't be found"); | ||||
|       notes.lost.forEach(function (node) { | ||||
|         console.warn('? ' + node.name); | ||||
|       }); | ||||
|       console.log(''); | ||||
|     } | ||||
| 
 | ||||
|     if (notes.found.length) { | ||||
|       console.log("Will compile these collections"); | ||||
|       notes.found.forEach(function (node) { | ||||
|         console.log('+ ' + node.name); | ||||
|       }); | ||||
|       console.log(''); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   function getLayouts() { | ||||
|     // TODO
 | ||||
|   } | ||||
| 
 | ||||
|   function updatePage(pagedir, node, lstat, data) { | ||||
|     var parts = frontmatter.parse(data) | ||||
|       , meta | ||||
|       , html | ||||
|       , view | ||||
|       ; | ||||
| 
 | ||||
|     if (!parts.yml) { | ||||
|       console.error("Could not parse frontmatter for " + node); | ||||
|       console.error(parts.frontmatter); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     if (/\.(html|htm)$/.test(node)) { | ||||
|       html = parts.body.trim(); | ||||
|     } else if (/\.(md|markdown|mdown|mkdn|mkd|mdwn|mdtxt|mdtext)$/.test(node)) { | ||||
|       console.log('parsing markdown...'); | ||||
|       html = marked(parts.body.trim()); | ||||
|     } else { | ||||
|       console.error('unknown parser for ' + node); | ||||
|     } | ||||
| 
 | ||||
|     meta = { | ||||
|       mtime: lstat.mtime | ||||
|     , ymlsum: sha1sum(parts.frontmatter.trim()) | ||||
|     , textsum: sha1sum(parts.body.trim()) | ||||
|     , htmlsum: sha1sum(html) | ||||
|     , filesum: sha1sum(data) | ||||
|     , filename: node | ||||
|     , filepath: pagedir | ||||
|     }; | ||||
| 
 | ||||
|     /* | ||||
|     // TODO
 | ||||
|     db.getCached(meta).error(function () { | ||||
|       // TODO rebuild and save
 | ||||
|     }); | ||||
|     */ | ||||
| 
 | ||||
|     // TODO meta.layout
 | ||||
|     view = { | ||||
|       page: parts.yml | ||||
|     , content: html | ||||
|     }; | ||||
| 
 | ||||
|     console.log(node); | ||||
|     console.log(parts.frontmatter); | ||||
|     console.log(parts.yml); //Mustache.render(pagetpl, view));
 | ||||
|     //console.log(meta.mtime.valueOf(), meta.ymlsum, meta.textsum, node);
 | ||||
| 
 | ||||
|     return meta; | ||||
|   } | ||||
| 
 | ||||
|   function templatePosts() { | ||||
|     var pagetpl | ||||
|       , defaulttpl | ||||
|       ; | ||||
| 
 | ||||
|     // TODO declare path to theme
 | ||||
|     pagetpl = frontmatter.parse(fs.readFileSync(path.join(config.theme, 'layouts', 'page.html'), 'utf8')); | ||||
|     defaulttpl = frontmatter.parse(fs.readFileSync(path.join(config.theme, 'layouts', 'default.html'), 'utf8')); | ||||
| 
 | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   function getCollection() { | ||||
|   } | ||||
| 
 | ||||
|   console.log(''); | ||||
|   console.log(''); | ||||
|   console.log('loading caches...'); | ||||
| 
 | ||||
|   getMetaCache().then(function (db) { | ||||
|     console.log('last update: ' + (db.lastUpdate && new Date(db.lastUpdate) || 'never')); | ||||
| 
 | ||||
|     console.log('checking for local updates...'); | ||||
| 
 | ||||
| 
 | ||||
|     // TODO get layouts here
 | ||||
|     return getCollections('.', Object.keys(config.collections)).then(function (notes) { | ||||
|       showCollectionNotes(notes); | ||||
| 
 | ||||
|       return notes.found; | ||||
|     }).then(function (found) { | ||||
|       var metas = [] | ||||
|         ; | ||||
| 
 | ||||
|       return forEachAsync(found, function (collection) { | ||||
|         begintime = Date.now(); | ||||
|         console.log('begin', ((begintime - starttime) / 1000).toFixed(4)); | ||||
| 
 | ||||
|         return fs.readdirAsync(collection.path).then(function (nodes) { | ||||
| 
 | ||||
|           // TODO look for companion yml file aside html|md|jade
 | ||||
|           nodes = nodes.filter(function (node) { | ||||
|             // TODO have handlers accept or reject extensions in the order they are registered
 | ||||
|             if (!/\.(htm|html|md|markdown|mdown|mkdn|mkd|jade)$/.test(node)) { | ||||
|               console.warn("ignoring " + collection.name + '/' + node + " (unknown filetype processor)"); | ||||
|               return false; | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|           }); | ||||
| 
 | ||||
|           return forEachAsync(nodes, function (pagename) { | ||||
|             var pagepath = path.join(collection.path, pagename) | ||||
|               ; | ||||
| 
 | ||||
|             // TODO: support walking deep
 | ||||
|             // TODO: test .html, .md, etc
 | ||||
|             return fs.lstatAsync(pagepath).then(function (lstat) { | ||||
|               // no funny business allowed
 | ||||
|               if (!lstat.isFile()) { | ||||
|                 return; | ||||
|               } | ||||
| 
 | ||||
|               return fs.readFileAsync(nodepath, 'utf8').then(function (data) { | ||||
|                 updatePage(pagedir, node, lstat, data); | ||||
|               }); | ||||
|             }); | ||||
|           }); | ||||
|         }).then(function () { | ||||
|           console.log('doneish', ((Date.now() - begintime) / 1000).toFixed(4)); | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| }('undefined' !== typeof exports && exports || window)); | ||||
							
								
								
									
										19
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| 
 | ||||
| <html> | ||||
|   <head> | ||||
|     <title>Dear Desi</title> | ||||
|     <script src="./bower_components/bluebird/js/browser/bluebird.js"></script> | ||||
|     <script src="./bower_components/mustache/mustache.js"></script> | ||||
|     <script src="./bower_components/marked/lib/marked.js"></script> | ||||
|     <script src="./bower_components/js-yaml/dist/js-yaml.js"></script> | ||||
|     <script src="./bower_components/path/path.js"></script> | ||||
|     <script src="./lib/deardesi-utils.js"></script> | ||||
|     <script src="./lib/verify-config.js"></script> | ||||
|     <script src="./lib/deardesi-browser.js"></script> | ||||
|     <script src="./lib/frontmatter.js"></script> | ||||
|     <script src="./deardesi.js"></script> | ||||
|   </head> | ||||
|   <body> | ||||
|     <p>Open up the console, fool!</p> | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										7
									
								
								lib/convert-ruhoh-config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								lib/convert-ruhoh-config.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| module.exports.convert = function () { | ||||
|   console.error("I haven't implemented a ruhoh -> nuhoh converter yet, but it's not very hard to do."); | ||||
|   console.error("see https://github.com/coolaj86/nuhoh/tree/master/MIGRATE.md"); | ||||
|   throw new Error('Not Implemented.'); | ||||
| }; | ||||
							
								
								
									
										128
									
								
								lib/deardesi-browser.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								lib/deardesi-browser.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | ||||
| /*jshint -W054 */ | ||||
| var tmpglobal | ||||
|   ; | ||||
| 
 | ||||
| try { | ||||
|   tmpglobal = new Function('return this')(); | ||||
| }  catch(e) { | ||||
|   tmpglobal = window; | ||||
| } | ||||
| 
 | ||||
| ;(function (exports) { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   // Chrome, Firefox, and even MSIE11+ all support crypto
 | ||||
|   var crypto = window.crypto || window.msCrypto | ||||
|     , algos | ||||
|     ; | ||||
| 
 | ||||
|   // convenience mappings for common digest algorithms
 | ||||
|   algos = { | ||||
|     'sha1': 'SHA-1' | ||||
|   , 'sha256': 'SHA-256' | ||||
|   , 'sha512': 'SHA-512' | ||||
|   }; | ||||
| 
 | ||||
|   // The function to generate a sha1sum is the same as generating any digest
 | ||||
|   // but here's a shortcut function anyway
 | ||||
|   function sha1sum(str) { | ||||
|     return hashsum('sha1', str); | ||||
|   } | ||||
| 
 | ||||
|   // a more general convenience function
 | ||||
|   function hashsum(hash, str) { | ||||
|       // you have to convert from string to array buffer
 | ||||
|     var ab | ||||
|       // you have to represent the algorithm as an object 
 | ||||
|       , algo = { name: algos[hash] } | ||||
|       ; | ||||
| 
 | ||||
|     if ('string' === typeof str) { | ||||
|       ab = str2ab(str); | ||||
|     } else { | ||||
|       ab = str; | ||||
|     } | ||||
| 
 | ||||
|     // All crypto digest methods return a promise
 | ||||
|     return crypto.subtle.digest(algo, ab).then(function (digest) { | ||||
|       // you have to convert the ArrayBuffer to a DataView and then to a hex String
 | ||||
|       return ab2hex(digest); | ||||
|     }).catch(function (e) { | ||||
|       // if you specify an unsupported digest algorithm or non-ArrayBuffer, you'll get an error
 | ||||
|       console.error('sha1sum ERROR'); | ||||
|       console.error(e); | ||||
|       throw e; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   // convert from arraybuffer to hex
 | ||||
|   function ab2hex(ab) { | ||||
|     var dv = new DataView(ab) | ||||
|       , i | ||||
|       , len | ||||
|       , hex = '' | ||||
|       , c | ||||
|       ; | ||||
| 
 | ||||
|     for (i = 0, len = dv.byteLength; i < len; i += 1) { | ||||
|       c = dv.getUint8(i).toString(16); | ||||
| 
 | ||||
|       if (c.length < 2) { | ||||
|         c = '0' + c; | ||||
|       } | ||||
| 
 | ||||
|       hex += c; | ||||
|     } | ||||
| 
 | ||||
|     return hex; | ||||
|   } | ||||
| 
 | ||||
|   // convert from string to arraybuffer
 | ||||
|   function str2ab(stringToEncode, insertBom) { | ||||
|     stringToEncode = stringToEncode.replace(/\r\n/g,"\n"); | ||||
| 
 | ||||
|     var utftext = [] | ||||
|       , n | ||||
|       , c | ||||
|       ; | ||||
| 
 | ||||
|     if (true === insertBom)  { | ||||
|       utftext[0] =  0xef; | ||||
|       utftext[1] =  0xbb; | ||||
|       utftext[2] =  0xbf; | ||||
|     } | ||||
| 
 | ||||
|     for (n = 0; n < stringToEncode.length; n += 1) { | ||||
| 
 | ||||
|       c = stringToEncode.charCodeAt(n); | ||||
| 
 | ||||
|       if (c < 128) { | ||||
|           utftext[utftext.length]= c; | ||||
|       } | ||||
|       else if((c > 127) && (c < 2048)) { | ||||
|           utftext[utftext.length] = (c >> 6) | 192; | ||||
|           utftext[utftext.length] = (c & 63) | 128; | ||||
|       } | ||||
|       else { | ||||
|           utftext[utftext.length] = (c >> 12) | 224; | ||||
|           utftext[utftext.length] = ((c >> 6) & 63) | 128; | ||||
|           utftext[utftext.length] = (c & 63) | 128; | ||||
|       } | ||||
| 
 | ||||
|     } | ||||
|     return new Uint8Array(utftext).buffer; | ||||
|   } | ||||
| 
 | ||||
|   exports.hashsum = hashsum; | ||||
|   exports.sha1sum = sha1sum; | ||||
| }('undefined' !== typeof exports && exports || tmpglobal)); | ||||
| 
 | ||||
| ;(function () { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   exports.getStats | ||||
|   exports.getContents | ||||
|   exports.getMetaCache | ||||
|   exports.getContentCache | ||||
|   //require('./db').create(path.join(_dirname, 'db.json'))
 | ||||
| }()); | ||||
							
								
								
									
										9
									
								
								lib/deardesi-node.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								lib/deardesi-node.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| var PromiseA = require('bluebird').Promise | ||||
|   , secretutils = require('secret-utils') | ||||
|   ; | ||||
| 
 | ||||
| module.exports.sha1sum = function (str) { | ||||
|   return PromiseA.resolve( secretutils.hashsum('sha1', str) ); | ||||
| }; | ||||
							
								
								
									
										23
									
								
								lib/deardesi-utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/deardesi-utils.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| ;(function (exports) { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   var path  = exports.path  || require('path') | ||||
|     ; | ||||
| 
 | ||||
|   function escapeRegExp(str) { | ||||
|     return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); | ||||
|   } | ||||
| 
 | ||||
|   function safeResolve(basename, target) { | ||||
|     basename = path.resolve(basename); | ||||
| 
 | ||||
|     var targetname = path.resolve(basename, target) | ||||
|       , re = new RegExp('^' + escapeRegExp(basename) + '(/|$)') | ||||
|       ; | ||||
| 
 | ||||
|     return re.test(targetname) && targetname; | ||||
|   } | ||||
| 
 | ||||
|   exports.safeResolve = safeResolve; | ||||
|   exports.escapeRegExp = escapeRegExp; | ||||
| }('undefined' !== typeof exports && exports || window)); | ||||
							
								
								
									
										103
									
								
								lib/frontmatter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								lib/frontmatter.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| /*jshint -W054 */ | ||||
| ;(function (exports) { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   var YAML = {} | ||||
|     ; | ||||
| 
 | ||||
|   YAML.parse = exports.jsyaml.load || require('jsyaml').load; | ||||
|   //YAML.parse = require('yaml').eval;
 | ||||
|   //YAML.parse2 = require('yamljs').parse;
 | ||||
| 
 | ||||
|   function readFrontMatter(text) { | ||||
|     var lines | ||||
|       , line | ||||
|       , padIndent = '' | ||||
|       , ymllines = [] | ||||
|       ; | ||||
| 
 | ||||
|     lines = text.split(/\n/); | ||||
|     line = lines.shift(); | ||||
| 
 | ||||
|     if (!line.match(/^---\s*$/)) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     // our yaml parser can't handle objects
 | ||||
|     // that start without indentation, so
 | ||||
|     // we can add it if this is the case
 | ||||
|     if (lines[0] && lines[0].match(/^\S/)) { | ||||
|       padIndent = ''; | ||||
|     } | ||||
| 
 | ||||
|     while (true) { | ||||
|       line = lines.shift(); | ||||
| 
 | ||||
|       // premature end-of-file (unsupported yaml)
 | ||||
|       if (!line && '' !== line) { | ||||
|         ymllines = []; | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       // end-of-yaml front-matter
 | ||||
|       if (line.match(/^---\s*$/)) { | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       if (line) { | ||||
|         // supported yaml
 | ||||
|         ymllines.push(padIndent + line);  | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     // XXX can't be sorted because arrays get messed up
 | ||||
|     //ymllines.sort();
 | ||||
|     if (ymllines) { | ||||
|       return '---\n' + ymllines.join('\n'); | ||||
|     } | ||||
| 
 | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   function separateText(text, fm) { | ||||
|     var len | ||||
|       , yml | ||||
|       ; | ||||
| 
 | ||||
|     yml = readFrontMatter(fm); | ||||
|     // strip frontmatter from text, if any
 | ||||
|     // including trailing '---' (which is accounted for by the added '\n')
 | ||||
|     if (yml) { | ||||
|       len = fm.split(/\n/).length; | ||||
|     } else { | ||||
|       len = 0; | ||||
|     } | ||||
| 
 | ||||
|     return text.split(/\n/).slice(len).join('\n'); | ||||
|   } | ||||
| 
 | ||||
|   function parseText(text) { | ||||
|     var fm = readFrontMatter(text) | ||||
|       , body = separateText(text, fm) | ||||
|       , yml | ||||
|       ; | ||||
| 
 | ||||
|     try { | ||||
|       yml = YAML.parse(fm); | ||||
|     } catch(e) { | ||||
|       //
 | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       yml: yml | ||||
|     , frontmatter: fm | ||||
|     , body: body | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   exports.Frontmatter.Frontmatter = exports.Frontmatter = {}; | ||||
|   exports.Frontmatter.readText = readFrontMatter; | ||||
|   exports.Frontmatter.separateText = separateText; | ||||
|   exports.Frontmatter.parse = parseText; | ||||
| }('undefined' !== typeof exports && exports || window)); | ||||
							
								
								
									
										56
									
								
								lib/verify-config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								lib/verify-config.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| module.export.verify = function (conf) { | ||||
|   if (!conf.NuhohSpec) { | ||||
|     throw new Error("missing key NuhohSpec"); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.production) { | ||||
|     throw new Error("missing key production"); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.production.canonical_url) { | ||||
|     throw new Error("missing key production.canonical_url"); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.production.base_path) { | ||||
|     throw new Error("missing key production.base_path"); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.development) { | ||||
|     throw new Error("missing key development"); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.development.compiled_path) { | ||||
|     throw new Error("missing key development.compiled_path"); | ||||
|   } | ||||
| 
 | ||||
|   if (!Array.isArray(conf.collections)) { | ||||
|     if (conf.posts) { | ||||
|       console.error("Please indent and nest 'posts' under the key 'collection' to continue"); | ||||
|     } | ||||
|     throw new Error("missing key 'collections'."); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.themes) { | ||||
|     if (conf.twitter) { | ||||
|       console.error("Please indent and nest 'twitter' under the key 'themes' to continue"); | ||||
|     } | ||||
|     throw new Error("missing key 'themes'"); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.themes.default) { | ||||
|     if (conf.twitter) { | ||||
|       console.error("Please set themes.default to 'twitter'"); | ||||
|     } | ||||
|     throw new Error("missing key 'themes.default'"); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.root) { | ||||
|     throw new Error("missing key root"); | ||||
|   } | ||||
| 
 | ||||
|   if (!conf.widgets) { | ||||
|     throw new Error("missing key root"); | ||||
|   } | ||||
| }; | ||||
							
								
								
									
										28
									
								
								lib/walk.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								lib/walk.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| var PromiseA = require('bluebird').Promise | ||||
|   , path = require('path') | ||||
|   , walk = require('walk') | ||||
|   , walker | ||||
|   ; | ||||
| 
 | ||||
| function getFs(parent, sub) { | ||||
|   // TODO safe
 | ||||
|   var trueRoot = path.resolve(parent, sub) | ||||
|     ; | ||||
| 
 | ||||
|   return new PromiseA(function (resolve) { | ||||
|     walker = walk.walk('posts'); | ||||
|     walker.on('directories', function (root, stat, next) { | ||||
|       console.log(root, stat); | ||||
|       next(); | ||||
|     }); | ||||
|     walker.on('files', function (root, stat, next) { | ||||
|       //console.log(root, stat);
 | ||||
|       next(); | ||||
|     }); | ||||
|     walker.on('end', function () { | ||||
|       console.log('done'); | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
							
								
								
									
										47
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| { | ||||
|   "name": "deardesi", | ||||
|   "version": "0.1.0", | ||||
|   "description": "An in-browser knockoff of the Ruhoh static blog generator. (similar to Jekyll, Octopress, Nanoc, etc)", | ||||
|   "main": "server.js", | ||||
|   "scripts": { | ||||
|     "test": "echo \"Error: no test specified\" && exit 1" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|     "url": "git@github.com:coolaj86/deardesi.git" | ||||
|   }, | ||||
|   "keywords": [ | ||||
|     "dear", | ||||
|     "deardesi", | ||||
|     "desi", | ||||
|     "ruhoh", | ||||
|     "ruhoh", | ||||
|     "blog", | ||||
|     "static", | ||||
|     "jekyll", | ||||
|     "octopress", | ||||
|     "nanoc" | ||||
|   ], | ||||
|   "author": "AJ ONeal", | ||||
|   "license": "Apache2", | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/coolaj86/deardesi/issues" | ||||
|   }, | ||||
|   "homepage": "https://github.com/coolaj86/deardesi", | ||||
|   "dependencies": { | ||||
|     "bluebird": "^2.5.3", | ||||
|     "circular-json": "^0.1.6", | ||||
|     "escape-string-regexp": "^1.0.2", | ||||
|     "foreachasync": "^5.0.2", | ||||
|     "json2yaml": "^1.0.3", | ||||
|     "markdown": "^0.5.0", | ||||
|     "marked": "^0.3.2", | ||||
|     "mustache": "^1.0.0", | ||||
|     "require-yaml": "0.0.1", | ||||
|     "require-yamljs": "^1.0.1", | ||||
|     "secret-utils": "^1.0.2", | ||||
|     "walk": "^2.3.5", | ||||
|     "yaml": "^0.2.3", | ||||
|     "yamljs": "^0.2.1" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										41
									
								
								server.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								server.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| var connect = require('connect') | ||||
|   , query = require('connect-query') | ||||
|   , bodyParser = require('body-parser') | ||||
|   , serveStatic = require('serve-static') | ||||
|   , app = connect() | ||||
|   ; | ||||
| 
 | ||||
| app | ||||
|   .use('/api/fs', query()) | ||||
|   .use('/api/fs', bodyParser.json()) | ||||
|   .use('/api/fs', function (req, res, next) { | ||||
|       if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) { | ||||
|         next(); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       /* | ||||
|       return forEachAsync(collectiondirs, function (collection) { | ||||
|         return fs.lstatAsync(collection.path).then(function (stat) { | ||||
|           if (!stat.isDirectory()) { | ||||
|             //return;
 | ||||
|           } | ||||
| 
 | ||||
|         }).error(function () { | ||||
|         }); | ||||
|       }).then(function () { | ||||
|       }); | ||||
|       */ | ||||
| 
 | ||||
|       res.end('not implemented'); | ||||
|     }) | ||||
|   .use('/api/fs', function (req, res, next) { | ||||
|       next(); | ||||
|       return; | ||||
|     }) | ||||
|   .use(serveStatic('.')) | ||||
|   ; | ||||
| 
 | ||||
| module.exports = app; | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user