From 6378a02f5193a66f30878ad6c8a35c1f7c6ec673 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 15 Jan 2015 00:36:59 -0500 Subject: [PATCH] cleanup while documenting --- desirae.js | 82 ++++--- lib/browser-adapters.js | 288 +++++++++++++++++++++++ lib/deardesi-browser.js | 379 ------------------------------- lib/deardesi-utils.js | 118 ++++++++++ lib/frontmatter.js | 177 ++++++++------- lib/{ => node-adapters}/fsapi.js | 11 +- lib/node-adapters/index.js | 3 + 7 files changed, 559 insertions(+), 499 deletions(-) create mode 100644 lib/browser-adapters.js delete mode 100644 lib/deardesi-browser.js rename lib/{ => node-adapters}/fsapi.js (97%) create mode 100644 lib/node-adapters/index.js diff --git a/desirae.js b/desirae.js index 25a3336..d644d9a 100644 --- a/desirae.js +++ b/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)); diff --git a/lib/browser-adapters.js b/lib/browser-adapters.js new file mode 100644 index 0000000..f60214f --- /dev/null +++ b/lib/browser-adapters.js @@ -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)); diff --git a/lib/deardesi-browser.js b/lib/deardesi-browser.js deleted file mode 100644 index e44556f..0000000 --- a/lib/deardesi-browser.js +++ /dev/null @@ -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)); diff --git a/lib/deardesi-utils.js b/lib/deardesi-utils.js index fa8c392..0f0c6e8 100644 --- a/lib/deardesi-utils.js +++ b/lib/deardesi-utils.js @@ -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)); diff --git a/lib/frontmatter.js b/lib/frontmatter.js index a0a3911..17a2c4d 100644 --- a/lib/frontmatter.js +++ b/lib/frontmatter.js @@ -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)); diff --git a/lib/fsapi.js b/lib/node-adapters/fsapi.js similarity index 97% rename from lib/fsapi.js rename to lib/node-adapters/fsapi.js index d96fa19..62eb45b 100644 --- a/lib/fsapi.js +++ b/lib/node-adapters/fsapi.js @@ -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(); + }); } }); diff --git a/lib/node-adapters/index.js b/lib/node-adapters/index.js new file mode 100644 index 0000000..f15d68b --- /dev/null +++ b/lib/node-adapters/index.js @@ -0,0 +1,3 @@ +'use strict'; + +exports.fsapi = require('./fsapi');