cleanup while documenting
This commit is contained in:
parent
842cabed78
commit
6378a02f51
82
desirae.js
82
desirae.js
|
@ -5,15 +5,23 @@
|
|||
, path = exports.path || require('path')
|
||||
, Mustache = exports.Mustache || require('mustache')
|
||||
, 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
|
||||
, fsapi = exports.fsapi || require('./lib/deardesi-node').fsapi
|
||||
//, UUID = exports.uuid || require('node-uuid')
|
||||
, months
|
||||
, THEME_PREFIX = 'themes'
|
||||
//, sha1sum = exports.sha1sum || require('./lib/deardesi-node').sha1sum
|
||||
//, safeResolve = exports.safeResolve || require('./lib/deardesi-utils').safeResolve
|
||||
//, UUID = exports.uuid || require('node-uuid')
|
||||
;
|
||||
|
||||
function Desi() {
|
||||
}
|
||||
|
||||
if (!exports.window) {
|
||||
// adds Desi.Frontmatter
|
||||
require('./lib/frontmatter').create(Desi);
|
||||
// adds Desi.fsapi
|
||||
require('./lib/deardesi-node').create(Desi);
|
||||
}
|
||||
|
||||
months = {
|
||||
1: 'January'
|
||||
, 2: 'February'
|
||||
|
@ -95,7 +103,7 @@
|
|||
|
||||
function readFrontmatter(things) {
|
||||
return forEachAsync(things, function (file) {
|
||||
var parts = frontmatter.parse(file.contents)
|
||||
var parts = Desi.Frontmatter.parse(file.contents)
|
||||
;
|
||||
|
||||
if (!file.sha1) {
|
||||
|
@ -219,8 +227,12 @@
|
|||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
function Desi() {
|
||||
}
|
||||
Desi.YAML = {
|
||||
parse: exports.jsyaml.load || require('jsyaml').load
|
||||
, stringify: exports.jsyaml.dump || require('jsyaml').dump
|
||||
};
|
||||
|
||||
|
||||
|
||||
Desi.toLocaleDate = function (d) {
|
||||
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate())
|
||||
|
@ -232,7 +244,7 @@
|
|||
// read config and such
|
||||
Desi.init = function (desi) {
|
||||
// config.yml, data.yml, site.yml, authors
|
||||
return PromiseA.all([fsapi.getAllConfigFiles()/*, fsapi.getBlogdir()*/]).then(function (plop) {
|
||||
return PromiseA.all([Desi.fsapi.getAllConfigFiles()/*, fsapi.getBlogdir()*/]).then(function (plop) {
|
||||
var arr = plop[0]
|
||||
//, blogdir = plop[1]
|
||||
;
|
||||
|
@ -279,31 +291,31 @@
|
|||
|
||||
// TODO make document configurability
|
||||
return PromiseA.all([
|
||||
fsapi.getMeta(
|
||||
Desi.fsapi.getMeta(
|
||||
themenames.map(function (n) { return path.join(THEME_PREFIX, n); })
|
||||
, { dotfiles: false
|
||||
, extensions: ['md', 'markdown', 'htm', 'html', 'jade', 'css', 'js', 'yml']
|
||||
}
|
||||
)
|
||||
, fsapi.getMeta(
|
||||
, Desi.fsapi.getMeta(
|
||||
[desi.config.rootdir]
|
||||
, { dotfiles: false
|
||||
, extensions: ['md', 'markdown', 'htm', 'html', 'jade']
|
||||
}
|
||||
)
|
||||
, fsapi.getMeta(
|
||||
, Desi.fsapi.getMeta(
|
||||
collectionnames
|
||||
, { dotfiles: false
|
||||
, extensions: ['md', 'markdown', 'htm', 'html', 'jade']
|
||||
}
|
||||
)
|
||||
, fsapi.getMeta(
|
||||
, Desi.fsapi.getMeta(
|
||||
assetnames
|
||||
, { dotfiles: false
|
||||
//, extensions: ['md', 'markdown', 'htm', 'html', 'jade', 'css', 'js', 'yml']
|
||||
}
|
||||
)
|
||||
, fsapi.getCache()
|
||||
, Desi.fsapi.getCache()
|
||||
]);
|
||||
}).then(function (things) {
|
||||
console.info('loaded theme meta, root meta, collection meta');
|
||||
|
@ -407,9 +419,9 @@
|
|||
*/
|
||||
|
||||
return PromiseA.all([
|
||||
Object.keys(droot).length ? fsapi.getContents(Object.keys(droot)) : PromiseA.resolve([])
|
||||
, Object.keys(dfiles).length ? fsapi.getContents(Object.keys(dfiles)) : PromiseA.resolve([])
|
||||
, Object.keys(dthemes).length ? fsapi.getContents(Object.keys(dthemes)) : PromiseA.resolve([])
|
||||
Object.keys(droot).length ? Desi.fsapi.getContents(Object.keys(droot)) : PromiseA.resolve([])
|
||||
, Object.keys(dfiles).length ? Desi.fsapi.getContents(Object.keys(dfiles)) : PromiseA.resolve([])
|
||||
, Object.keys(dthemes).length ? Desi.fsapi.getContents(Object.keys(dthemes)) : PromiseA.resolve([])
|
||||
]).then(function (arr) {
|
||||
// TODO XXX display errors in html
|
||||
function noErrors(o) {
|
||||
|
@ -448,7 +460,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
return (Object.keys(files).length && fsapi.copy(files).then(function (copied) {
|
||||
return (Object.keys(files).length && Desi.fsapi.copy(files).then(function (copied) {
|
||||
if (copied.error) {
|
||||
console.error(copied.error);
|
||||
throw new Error(copied.error);
|
||||
|
@ -707,12 +719,20 @@
|
|||
return PromiseA.resolve(desi);
|
||||
};
|
||||
|
||||
Desi.datamaps = {};
|
||||
Desi.datamaps['desirae@1.0'] = function (obj) {
|
||||
Desi._datamaps = {};
|
||||
Desi.registerDataMapper = function (name, fn) {
|
||||
if (!Desi._datamaps[name]) {
|
||||
Desi._datamaps[name] = fn;
|
||||
} else {
|
||||
console.warn("ignoring additional data mapper for '"
|
||||
+ name + "' (there's already one assigned)");
|
||||
}
|
||||
};
|
||||
Desi.registerDataMapper('desirae@1.0', function (obj) {
|
||||
obj.desi = obj;
|
||||
return obj;
|
||||
};
|
||||
Desi.datamaps['ruhoh@2.6'] = function (view) {
|
||||
});
|
||||
Desi.registerDataMapper('ruhoh@2.6', function (view) {
|
||||
var newview
|
||||
;
|
||||
|
||||
|
@ -781,10 +801,11 @@
|
|||
newview.page.content = view.contents;
|
||||
|
||||
return newview;
|
||||
};
|
||||
});
|
||||
|
||||
Desi.renderers = {};
|
||||
Desi.registerRenderer = function(ext, fn, opts) {
|
||||
ext = ext.replace(/^\./, '');
|
||||
// TODO allow a test method for ext and content (new RegExp("\\." + escapeRegExp(ext) + "$", i).test(current.ext))
|
||||
opts = opts || {};
|
||||
// TODO opts.priority
|
||||
|
@ -851,7 +872,6 @@
|
|||
;
|
||||
|
||||
layers = getLayout(desi, entity.yml.theme, entity.yml.layout, [entity]);
|
||||
// TODO inherit datamap from theme layout
|
||||
|
||||
return forEachAsync(layers, function (current) {
|
||||
var body = (current.body || current.contents || '').trim()
|
||||
|
@ -862,7 +882,8 @@
|
|||
|
||||
|
||||
return Desi.render(current.ext, body, view).then(function (html) {
|
||||
var datamap = Desi.datamaps[env.datamap] || Desi.datamaps[entity.datamap] || Desi.datamaps['ruhoh@2.6']
|
||||
// TODO inherit datamap from theme layout
|
||||
var datamap = Desi._datamaps[env.datamap] || Desi._datamaps[entity.datamap] || Desi._datamaps['ruhoh@2.6']
|
||||
, newview
|
||||
;
|
||||
|
||||
|
@ -992,8 +1013,6 @@
|
|||
});
|
||||
});
|
||||
}).catch(function (e) {
|
||||
console.error('failing at build step here here here');
|
||||
throw e;
|
||||
if (env.onError) {
|
||||
return env.onError(e);
|
||||
} else {
|
||||
|
@ -1023,7 +1042,7 @@
|
|||
}
|
||||
|
||||
if (!desi.partials) {
|
||||
return fsapi.getAllPartials().then(function (partials) {
|
||||
return Desi.fsapi.getAllPartials().then(function (partials) {
|
||||
if (partials.error) {
|
||||
throw partials.error;
|
||||
}
|
||||
|
@ -1042,7 +1061,7 @@
|
|||
.then(Desi.getNav)
|
||||
.then(Desi.normalizeYml)
|
||||
.then(function () {
|
||||
Desi.collate(desi, env)
|
||||
Desi.collate(desi, env);
|
||||
})
|
||||
.then(function () {
|
||||
return Desi.build(desi, env);
|
||||
|
@ -1086,7 +1105,7 @@
|
|||
now = Date.now();
|
||||
console.info('compiled files');
|
||||
return forEachAsync(batches, function (files) {
|
||||
return fsapi.putFiles(files).then(function (saved) {
|
||||
return Desi.fsapi.putFiles(files).then(function (saved) {
|
||||
size += saved.size;
|
||||
|
||||
if (saved.error) {
|
||||
|
@ -1116,5 +1135,6 @@
|
|||
if (!exports.window && !exports.window.Mustache) {
|
||||
Desi.fsapi = require('./lib/fsapi');
|
||||
}
|
||||
exports.Desi = Desi.Desi = Desi;
|
||||
|
||||
exports.Desirae = exports.Desi = Desi.Desirae = Desi.Desi = Desi;
|
||||
}('undefined' !== typeof exports && exports || window));
|
||||
|
|
|
@ -0,0 +1,288 @@
|
|||
/*jshint -W054 */
|
||||
;(function (exports) {
|
||||
'use strict';
|
||||
|
||||
function create(Desi) {
|
||||
// Chrome, Firefox, and even MSIE11+ all support crypto
|
||||
var crypto = window.crypto || window.msCrypto
|
||||
, PromiseA = window.Promise
|
||||
, 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;
|
||||
|
||||
//
|
||||
// FSAPI
|
||||
//
|
||||
var fsapi
|
||||
;
|
||||
|
||||
function request() {
|
||||
}
|
||||
request.get = function (url/*, query*/) {
|
||||
// Return a new promise.
|
||||
return new PromiseA(function(resolve, reject) {
|
||||
// Do the usual XHR stuff
|
||||
var req = new XMLHttpRequest()
|
||||
;
|
||||
|
||||
req.onload = function() {
|
||||
// This is called even on 404 etc
|
||||
// so check the status
|
||||
if (200 === req.status) {
|
||||
// Resolve the promise with the response text
|
||||
resolve(req.response);
|
||||
}
|
||||
else {
|
||||
// Otherwise reject with the status text
|
||||
// which will hopefully be a meaningful error
|
||||
reject(Error(req.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
// Handle network errors
|
||||
req.onerror = function() {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
// Make the request
|
||||
req.open('GET', url);
|
||||
req.send();
|
||||
});
|
||||
};
|
||||
request.post = function (url/*, query*/, body) {
|
||||
// Return a new promise.
|
||||
return new PromiseA(function(resolve, reject) {
|
||||
// Do the usual XHR stuff
|
||||
var req = new XMLHttpRequest()
|
||||
;
|
||||
|
||||
req.onload = function() {
|
||||
// This is called even on 404 etc
|
||||
// so check the status
|
||||
if (200 === req.status) {
|
||||
// Resolve the promise with the response text
|
||||
resolve(req.response);
|
||||
}
|
||||
else {
|
||||
// Otherwise reject with the status text
|
||||
// which will hopefully be a meaningful error
|
||||
reject(Error(req.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
// Handle network errors
|
||||
req.onerror = function() {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
req.open('POST', url);
|
||||
req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
// Make the request
|
||||
if ('string' !== typeof body) {
|
||||
body = JSON.stringify(body);
|
||||
}
|
||||
req.send(body);
|
||||
});
|
||||
};
|
||||
|
||||
Desi.fsapi = fsapi = {};
|
||||
fsapi.getMeta = function (collections, opts) {
|
||||
console.log('dm sub 0');
|
||||
opts = opts || {};
|
||||
|
||||
var extensions = ''
|
||||
, dotfiles = ''
|
||||
, contents = ''
|
||||
, sha1sum = ''
|
||||
;
|
||||
|
||||
if (Array.isArray(opts.extensions)) {
|
||||
extensions = '&extensions=' + opts.extensions.join(','); // md,markdown,jade,htm,html
|
||||
}
|
||||
if (opts.dotfiles) {
|
||||
dotfiles = '&dotfiles=true';
|
||||
}
|
||||
if (opts.contents) {
|
||||
contents = '&contents=true';
|
||||
}
|
||||
if (false === opts.sha1sum) {
|
||||
sha1sum = '&sha1sum=false';
|
||||
}
|
||||
|
||||
console.log('dm sub 1');
|
||||
return request.post('/api/fs/walk?_method=GET' + dotfiles + extensions + contents + sha1sum, {
|
||||
dirs: collections
|
||||
}).then(function (resp) {
|
||||
console.log('dm sub 2');
|
||||
return JSON.parse(resp);
|
||||
}).catch(function (e) {
|
||||
console.log('dm sub 2e');
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.getContents = function (filepaths) {
|
||||
return request.post('/api/fs/files?_method=GET', {
|
||||
paths: filepaths
|
||||
}).then(function (resp) {
|
||||
return JSON.parse(resp);
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.getCache = function () {
|
||||
return request.get('/api/fs/static/cache.json').then(function (resp) {
|
||||
return JSON.parse(resp);
|
||||
}).catch(function (/*e*/) {
|
||||
return {};
|
||||
}).then(function (obj) {
|
||||
return obj;
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.copy = function (files) {
|
||||
var body = { files: files };
|
||||
body = JSON.stringify(body); // this is more or less instant for a few MiB of posts
|
||||
return request.post('/api/fs/copy', body).then(function (resp) {
|
||||
var response = JSON.parse(resp)
|
||||
;
|
||||
|
||||
// not accurate for utf8/unicode, but close enough
|
||||
response.size = body.length;
|
||||
return response;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
fsapi.putFiles = function (files) {
|
||||
var body = { files: files }
|
||||
;
|
||||
|
||||
files.forEach(function (file) {
|
||||
if (!file.contents || 'string' === typeof file.contents) {
|
||||
return;
|
||||
}
|
||||
if (/\.json$/i.test(file.path)) {
|
||||
file.contents = JSON.stringify(file.contents);
|
||||
}
|
||||
else if (/\.ya?ml$/i.test(file.path)) {
|
||||
file.contents = exports.jsyaml.dump(file.contents);
|
||||
}
|
||||
});
|
||||
|
||||
body = JSON.stringify(body); // this is more or less instant for a few MiB of posts
|
||||
return request.post('/api/fs/files', body).then(function (resp) {
|
||||
var response = JSON.parse(resp)
|
||||
;
|
||||
|
||||
// not accurate for utf8/unicode, but close enough
|
||||
response.size = body.length;
|
||||
return response;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (exports.Desirae) {
|
||||
create(exports.Desirae);
|
||||
} else {
|
||||
exports.create = create;
|
||||
}
|
||||
}('undefined' !== typeof exports && exports || window));
|
|
@ -1,379 +0,0 @@
|
|||
/*jshint -W054 */
|
||||
;(function (exports) {
|
||||
'use strict';
|
||||
|
||||
window.YAML = window.YAML || {};
|
||||
window.YAML.parse = exports.jsyaml.load || require('jsyaml').load;
|
||||
|
||||
// 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 || window));
|
||||
|
||||
;(function (exports) {
|
||||
'use strict';
|
||||
|
||||
var fsapi
|
||||
;
|
||||
|
||||
function request() {
|
||||
}
|
||||
request.get = function (url/*, query*/) {
|
||||
// Return a new promise.
|
||||
return new Promise(function(resolve, reject) {
|
||||
// Do the usual XHR stuff
|
||||
var req = new XMLHttpRequest()
|
||||
;
|
||||
|
||||
req.onload = function() {
|
||||
// This is called even on 404 etc
|
||||
// so check the status
|
||||
if (200 === req.status) {
|
||||
// Resolve the promise with the response text
|
||||
resolve(req.response);
|
||||
}
|
||||
else {
|
||||
// Otherwise reject with the status text
|
||||
// which will hopefully be a meaningful error
|
||||
reject(Error(req.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
// Handle network errors
|
||||
req.onerror = function() {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
// Make the request
|
||||
req.open('GET', url);
|
||||
req.send();
|
||||
});
|
||||
};
|
||||
request.post = function (url/*, query*/, body) {
|
||||
// Return a new promise.
|
||||
return new Promise(function(resolve, reject) {
|
||||
// Do the usual XHR stuff
|
||||
var req = new XMLHttpRequest()
|
||||
;
|
||||
|
||||
req.onload = function() {
|
||||
// This is called even on 404 etc
|
||||
// so check the status
|
||||
if (200 === req.status) {
|
||||
// Resolve the promise with the response text
|
||||
resolve(req.response);
|
||||
}
|
||||
else {
|
||||
// Otherwise reject with the status text
|
||||
// which will hopefully be a meaningful error
|
||||
reject(Error(req.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
// Handle network errors
|
||||
req.onerror = function() {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
req.open('POST', url);
|
||||
req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
// Make the request
|
||||
if ('string' !== typeof body) {
|
||||
body = JSON.stringify(body);
|
||||
}
|
||||
req.send(body);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
exports.fsapi = fsapi = {};
|
||||
fsapi.getMeta = function (collections, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
var extensions = ''
|
||||
, dotfiles = ''
|
||||
, contents = ''
|
||||
, sha1sum = ''
|
||||
;
|
||||
|
||||
if (Array.isArray(opts.extensions)) {
|
||||
extensions = '&extensions=' + opts.extensions.join(','); // md,markdown,jade,htm,html
|
||||
}
|
||||
if (opts.dotfiles) {
|
||||
dotfiles = '&dotfiles=true';
|
||||
}
|
||||
if (opts.contents) {
|
||||
contents = '&contents=true';
|
||||
}
|
||||
if (false === opts.sha1sum) {
|
||||
sha1sum = '&sha1sum=false';
|
||||
}
|
||||
|
||||
return request.post('/api/fs/walk?_method=GET' + dotfiles + extensions + contents + sha1sum, {
|
||||
dirs: collections
|
||||
}).then(function (resp) {
|
||||
return JSON.parse(resp);
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.getContents = function (filepaths) {
|
||||
return request.post('/api/fs/files?_method=GET', {
|
||||
paths: filepaths
|
||||
}).then(function (resp) {
|
||||
return JSON.parse(resp);
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.getConfigs = function (confs) {
|
||||
var opts = { extensions: ['yml', 'yaml', 'json'], dotfiles: false, contents: true, sha1sum: true }
|
||||
;
|
||||
|
||||
return fsapi.getMeta(confs, opts).then(function (collections) {
|
||||
var obj = {}
|
||||
;
|
||||
|
||||
Object.keys(collections).forEach(function (key) {
|
||||
var files = collections[key]
|
||||
, keyname = key.replace(/\.(json|ya?ml|\/)$/i, '')
|
||||
;
|
||||
|
||||
obj[keyname] = obj[keyname] || {};
|
||||
|
||||
files.forEach(function (file) {
|
||||
var filename = file.name.replace(/\.(json|ya?ml)$/i, '')
|
||||
, data = {}
|
||||
;
|
||||
|
||||
if (file.error) {
|
||||
console.error(file);
|
||||
console.error(file.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (/\.(ya?ml)$/i.test(file.name)) {
|
||||
try {
|
||||
data = exports.YAML.parse(file.contents) || {};
|
||||
if ("undefined" === data) {
|
||||
data = {};
|
||||
}
|
||||
} catch(e) {
|
||||
data = { error: e };
|
||||
console.error("Could not parse yaml for " + filename);
|
||||
console.error(file);
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
else if (/\.(json)$/i.test(file.name)) {
|
||||
try {
|
||||
data = JSON.parse(file.contents) || {};
|
||||
} catch(e) {
|
||||
data = { error: e };
|
||||
console.error("Could not parse json for " + filename);
|
||||
console.error(file);
|
||||
console.error(e);
|
||||
}
|
||||
} else {
|
||||
console.error("Not sure what to do with this one...");
|
||||
console.error(file);
|
||||
}
|
||||
|
||||
obj[keyname][filename] = data || obj[keyname][filename];
|
||||
/*
|
||||
if (!obj[keyname][filename]) {
|
||||
obj[keyname][filename] = {};
|
||||
}
|
||||
|
||||
Object.keys(data).forEach(function (key) {
|
||||
obj[keyname][filename][key] = data[key];
|
||||
});
|
||||
*/
|
||||
});
|
||||
});
|
||||
|
||||
return obj;
|
||||
});
|
||||
};
|
||||
fsapi.getAllPartials = function () {
|
||||
return fsapi.getConfigs(['partials', 'partials.yml']).then(function (results) {
|
||||
var partials = {}
|
||||
;
|
||||
|
||||
Object.keys(results.partials).forEach(function (key) {
|
||||
var partial = results.partials[key]
|
||||
;
|
||||
|
||||
Object.keys(partial).forEach(function (prop) {
|
||||
if (partials[prop]) {
|
||||
console.warn('partial \'' + prop + '\' overwritten by ' + key);
|
||||
}
|
||||
|
||||
partials[prop] = partial[prop];
|
||||
});
|
||||
});
|
||||
|
||||
return partials;
|
||||
});
|
||||
};
|
||||
fsapi.getAllConfigFiles = function () {
|
||||
return fsapi.getConfigs(['config.yml', 'site.yml', 'authors']).then(function (results) {
|
||||
var authors = results.authors
|
||||
, config = results.config.config
|
||||
, site = results.site.site
|
||||
;
|
||||
|
||||
return { config: config, authors: authors, site: site };
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.getCache = function () {
|
||||
return request.get('/api/fs/static/cache.json').then(function (resp) {
|
||||
return JSON.parse(resp);
|
||||
}).catch(function (/*e*/) {
|
||||
return {};
|
||||
}).then(function (obj) {
|
||||
return obj;
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.copy = function (files) {
|
||||
var body = { files: files };
|
||||
body = JSON.stringify(body); // this is more or less instant for a few MiB of posts
|
||||
return request.post('/api/fs/copy', body).then(function (resp) {
|
||||
var response = JSON.parse(resp)
|
||||
;
|
||||
|
||||
// not accurate for utf8/unicode, but close enough
|
||||
response.size = body.length;
|
||||
return response;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
fsapi.putFiles = function (files) {
|
||||
var body = { files: files }
|
||||
;
|
||||
|
||||
files.forEach(function (file) {
|
||||
if (!file.contents || 'string' === typeof file.contents) {
|
||||
return;
|
||||
}
|
||||
if (/\.json$/i.test(file.path)) {
|
||||
file.contents = JSON.stringify(file.contents);
|
||||
}
|
||||
else if (/\.ya?ml$/i.test(file.path)) {
|
||||
file.contents = exports.jsyaml.dump(file.contents);
|
||||
}
|
||||
});
|
||||
|
||||
body = JSON.stringify(body); // this is more or less instant for a few MiB of posts
|
||||
return request.post('/api/fs/files', body).then(function (resp) {
|
||||
var response = JSON.parse(resp)
|
||||
;
|
||||
|
||||
// not accurate for utf8/unicode, but close enough
|
||||
response.size = body.length;
|
||||
return response;
|
||||
});
|
||||
};
|
||||
}('undefined' !== typeof exports && exports || window));
|
|
@ -5,6 +5,7 @@
|
|||
;
|
||||
|
||||
function escapeRegExp(str) {
|
||||
console.log('hello', str);
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||
}
|
||||
|
||||
|
@ -20,4 +21,121 @@
|
|||
|
||||
exports.safeResolve = safeResolve;
|
||||
exports.escapeRegExp = escapeRegExp;
|
||||
|
||||
function create(Desi) {
|
||||
var fsapi = Desi.fsapi || require('./node-adapters').fsapi
|
||||
;
|
||||
|
||||
fsapi.getConfigs = function (confs) {
|
||||
var opts = { extensions: ['yml', 'yaml', 'json'], dotfiles: false, contents: true, sha1sum: true }
|
||||
;
|
||||
|
||||
return fsapi.getMeta(confs, opts).then(function (collections) {
|
||||
var obj = {}
|
||||
;
|
||||
|
||||
Object.keys(collections).forEach(function (key) {
|
||||
var files = collections[key]
|
||||
, keyname = key.replace(/\.(json|ya?ml|\/)$/i, '')
|
||||
;
|
||||
|
||||
obj[keyname] = obj[keyname] || {};
|
||||
|
||||
files.forEach(function (file) {
|
||||
var filename = file.name.replace(/\.(json|ya?ml)$/i, '')
|
||||
, data = {}
|
||||
;
|
||||
|
||||
if (file.error) {
|
||||
console.error(file);
|
||||
console.error(file.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (/\.(ya?ml)$/i.test(file.name)) {
|
||||
try {
|
||||
data = Desi.YAML.parse(file.contents) || {};
|
||||
if ("undefined" === data) {
|
||||
data = {};
|
||||
}
|
||||
} catch(e) {
|
||||
data = { error: e };
|
||||
console.error("Could not parse yaml for " + filename);
|
||||
console.error(file);
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
else if (/\.(json)$/i.test(file.name)) {
|
||||
try {
|
||||
data = JSON.parse(file.contents) || {};
|
||||
} catch(e) {
|
||||
data = { error: e };
|
||||
console.error("Could not parse json for " + filename);
|
||||
console.error(file);
|
||||
console.error(e);
|
||||
}
|
||||
} else {
|
||||
console.error("Not sure what to do with this one...");
|
||||
console.error(file);
|
||||
}
|
||||
|
||||
obj[keyname][filename] = data || obj[keyname][filename];
|
||||
/*
|
||||
if (!obj[keyname][filename]) {
|
||||
obj[keyname][filename] = {};
|
||||
}
|
||||
|
||||
Object.keys(data).forEach(function (key) {
|
||||
obj[keyname][filename][key] = data[key];
|
||||
});
|
||||
*/
|
||||
});
|
||||
});
|
||||
|
||||
return obj;
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.getAllPartials = function () {
|
||||
return fsapi.getConfigs(['partials', 'partials.yml']).then(function (results) {
|
||||
var partials = {}
|
||||
;
|
||||
|
||||
Object.keys(results.partials).forEach(function (key) {
|
||||
var partial = results.partials[key]
|
||||
;
|
||||
|
||||
Object.keys(partial).forEach(function (prop) {
|
||||
if (partials[prop]) {
|
||||
console.warn('partial \'' + prop + '\' overwritten by ' + key);
|
||||
}
|
||||
|
||||
partials[prop] = partial[prop];
|
||||
});
|
||||
});
|
||||
|
||||
return partials;
|
||||
});
|
||||
};
|
||||
|
||||
fsapi.getAllConfigFiles = function () {
|
||||
return fsapi.getConfigs(['config.yml', 'site.yml', 'authors']).then(function (results) {
|
||||
var authors = results.authors
|
||||
, config = results.config.config
|
||||
, site = results.site.site
|
||||
;
|
||||
|
||||
return { config: config, authors: authors, site: site };
|
||||
});
|
||||
};
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
if (exports.Desirae) {
|
||||
create(exports.Desirae);
|
||||
}
|
||||
else {
|
||||
exports.create = create;
|
||||
}
|
||||
}('undefined' !== typeof exports && exports || window));
|
||||
|
|
|
@ -2,106 +2,115 @@
|
|||
;(function (exports) {
|
||||
'use strict';
|
||||
|
||||
var Desi = {}
|
||||
;
|
||||
function create(Desi) {
|
||||
console.info('FRONTMATTER');
|
||||
Desi.YAML = {};
|
||||
Desi.YAML.parse = (exports.jsyaml || require('js-yaml')).load;
|
||||
Desi.YAML.stringify = (exports.jsyaml || require('js-yaml')).dump;
|
||||
|
||||
Desi.YAML = {};
|
||||
Desi.YAML.parse = (exports.jsyaml || require('js-yaml')).load;
|
||||
Desi.YAML.stringify = (exports.jsyaml || require('js-yaml')).dump;
|
||||
function readFrontMatter(text) {
|
||||
var lines
|
||||
, line
|
||||
, padIndent = ''
|
||||
, ymllines = []
|
||||
;
|
||||
|
||||
function readFrontMatter(text) {
|
||||
var lines
|
||||
, line
|
||||
, padIndent = ''
|
||||
, ymllines = []
|
||||
;
|
||||
lines = text.split(/\n/);
|
||||
line = lines.shift();
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
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 = '';
|
||||
}
|
||||
function separateText(text, fm) {
|
||||
var len
|
||||
, yml
|
||||
;
|
||||
|
||||
while (true) {
|
||||
line = lines.shift();
|
||||
|
||||
// premature end-of-file (unsupported yaml)
|
||||
if (!line && '' !== line) {
|
||||
ymllines = [];
|
||||
break;
|
||||
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 + 1;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
// end-of-yaml front-matter
|
||||
if (line.match(/^---\s*$/)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (line) {
|
||||
// supported yaml
|
||||
ymllines.push(padIndent + line);
|
||||
}
|
||||
return text.split(/\n/).slice(len).join('\n');
|
||||
}
|
||||
|
||||
function parseText(text) {
|
||||
var fm = readFrontMatter(text)
|
||||
, body = fm && separateText(text, fm)
|
||||
, yml
|
||||
;
|
||||
|
||||
// XXX can't be sorted because arrays get messed up
|
||||
//ymllines.sort();
|
||||
if (ymllines) {
|
||||
return '---\n' + ymllines.join('\n');
|
||||
if (fm) {
|
||||
try {
|
||||
yml = Desi.YAML.parse(fm);
|
||||
} catch(e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
yml: yml
|
||||
, frontmatter: fm
|
||||
, body: body
|
||||
};
|
||||
}
|
||||
|
||||
return;
|
||||
exports.Frontmatter = {};
|
||||
exports.Frontmatter.Frontmatter = exports.Frontmatter;
|
||||
exports.Frontmatter.readText = readFrontMatter;
|
||||
exports.Frontmatter.separateText = separateText;
|
||||
exports.Frontmatter.parse = parseText;
|
||||
exports.Frontmatter.YAML = Desi.YAML;
|
||||
Desi.Frontmatter = exports.Frontmatter;
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
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 + 1;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
return text.split(/\n/).slice(len).join('\n');
|
||||
if (exports.Desirae) {
|
||||
create(exports.Desirae);
|
||||
} else {
|
||||
exports.create = create;
|
||||
}
|
||||
|
||||
function parseText(text) {
|
||||
var fm = readFrontMatter(text)
|
||||
, body = fm && separateText(text, fm)
|
||||
, yml
|
||||
;
|
||||
|
||||
if (fm) {
|
||||
try {
|
||||
yml = Desi.YAML.parse(fm);
|
||||
} catch(e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
yml: yml
|
||||
, frontmatter: fm
|
||||
, body: body
|
||||
};
|
||||
}
|
||||
|
||||
exports.Frontmatter = {};
|
||||
exports.Frontmatter.Frontmatter = exports.Frontmatter;
|
||||
exports.Frontmatter.readText = readFrontMatter;
|
||||
exports.Frontmatter.separateText = separateText;
|
||||
exports.Frontmatter.parse = parseText;
|
||||
exports.Frontmatter.YAML = Desi.YAML;
|
||||
}('undefined' !== typeof exports && exports || window));
|
||||
|
|
|
@ -5,7 +5,7 @@ var PromiseA = require('bluebird').Promise
|
|||
, forEachAsync = require('foreachasync').forEachAsync
|
||||
, path = require('path')
|
||||
, walk = require('walk')
|
||||
, escapeRegExp = require('./deardesi-utils').escapeRegExp
|
||||
, escapeRegExp = require('escape-string-regexp')
|
||||
, safeResolve = require('./deardesi-utils').safeResolve
|
||||
, sha1sum = function (str) { return require('secret-utils').hashsum('sha1', str); }
|
||||
, mkdirp = PromiseA.promisify(require('mkdirp'))
|
||||
|
@ -80,9 +80,8 @@ function walkDir(parent, sub, opts) {
|
|||
var file
|
||||
;
|
||||
|
||||
|
||||
if (!filter(stat.name)) {
|
||||
return;
|
||||
return PromiseA.resolve();
|
||||
}
|
||||
|
||||
file = {
|
||||
|
@ -99,7 +98,7 @@ function walkDir(parent, sub, opts) {
|
|||
files.push(file);
|
||||
|
||||
if (!(opts.sha1sum || opts.content)) {
|
||||
return;
|
||||
return PromiseA.resolve();
|
||||
}
|
||||
|
||||
// TODO stream sha1 (for assets)
|
||||
|
@ -120,7 +119,9 @@ function walkDir(parent, sub, opts) {
|
|||
stats.forEach(eachFile);
|
||||
next();
|
||||
} else {
|
||||
forEachAsync(stats, eachFile).then(next);
|
||||
forEachAsync(stats, eachFile).then(function () {
|
||||
next();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
exports.fsapi = require('./fsapi');
|
Loading…
Reference in New Issue