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
|
||||||
logs
|
logs
|
||||||
*.log
|
*.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