diff --git a/bower.json b/bower.json index 4949cc4..613762d 100644 --- a/bower.json +++ b/bower.json @@ -36,6 +36,7 @@ "marked": "~0.3.2", "js-yaml": "~3.2.5", "path": "~3.46.1", - "forEachAsync": "~5.0.2" + "forEachAsync": "~5.0.5", + "node-uuid": "~1.4.2" } } diff --git a/deardesi.js b/deardesi.js index 316a9f8..dd4cbd9 100644 --- a/deardesi.js +++ b/deardesi.js @@ -8,21 +8,85 @@ , Mustache = exports.Mustache || require('mustache') , marked = exports.marked || require('marked') , forEachAsync = exports.forEachAsync || require('foreachasync').forEachAsync - , sha1sum = exports.sha1sum || require('./lib/deardesi-node').sha1sum + //, sha1sum = exports.sha1sum || require('./lib/deardesi-node').sha1sum , frontmatter = exports.Frontmatter || require('./lib/frontmatter').Frontmatter - , safeResolve = exports.safeResolve || require('./lib/deardesi-utils').safeResolve + //, safeResolve = exports.safeResolve || require('./lib/deardesi-utils').safeResolve , fsapi = exports.fsapi || require('./lib/deardesi-node').fsapi + //, UUID = exports.uuid || require('node-uuid') ; - function runDesi(desi) { - var config = desi.config - , cache = desi.cache + // See https://github.com/janl/mustache.js/issues/415 + function num2str(obj) { + return JSON.parse(JSON.stringify(obj, function (key, val) { + if ('number' === typeof val) { + val = val.toString(); + } + return val; + })); + } + + function getLayout(desi, themename, layout, arr) { + arr = arr || []; + + var layoutdir = 'layouts' + , themepath + , file + ; + + if (!themename) { + themename = desi.config.themes.default; + } + if (!layout) { + layout = 'post.html'; + } + + + themepath = themename + '/' + layoutdir + '/' + layout; + + desi.content.themes.some(function (theme) { + // TODO what if it isn't html? + if (theme.path === themepath || theme.path.match(themepath + '\\.html')) { + file = theme; + arr.push(theme); + return true; + } + }); + + if (!file) { + console.error("could not find " + themepath); + return; + } + + // TODO handle possible circular dep condition page -> post -> page + console.info(file); + if (file.yml && file.yml.layout) { + return getLayout(desi, themename, file.yml.layout, arr); + } else { + // return the chain page -> posts -> default -> twitter + return arr; + } + } + + function runDesi(desi, development) { + var cache = desi.cache + //, config = desi.config , cacheByPath = {} , cacheBySha1 = {} , dfiles , dthemes ; + desi.urls = desi.config.urls = {}; + if (development) { + desi.urls.base_path = desi.config.development.base_path; + desi.urls.url = desi.config.development.url; + desi.urls.development_url = desi.config.development.url; + } else { + desi.config.base_path = desi.urls.base_path = desi.config.production.base_path; + desi.urls.url = desi.config.production.url; + desi.urls.production_url = desi.config.production.url; + } + cache.sources = cache.sources || []; cache.sources.forEach(function (source) { cacheByPath[source.path] = source; @@ -103,37 +167,40 @@ console.log(''); console.log(''); - console.log('getting config...'); - return fsapi.getConfig().then(function (config) { - console.log('loading caches...'); - return fsapi.getCache().then(function (cache) { - console.log('cache'); - console.log(cache); - console.log('last update: ' + (cache.lastUpdate && new Date(cache.lastUpdate) || 'never')); - var collectionnames = Object.keys(config.collections) + console.log('getting config, data, caches...'); + return PromiseA.all([fsapi.getConfig(), fsapi.getData(), fsapi.getCache(), fsapi.getPartials()]).then(function (things) { + var config = things[0] + , data = things[1] + , cache = things[2] + , partials = things[3] + ; + + console.log('loaded config, data, caches.'); + console.log(things); + console.log('last update: ' + (cache.lastUpdate && new Date(cache.lastUpdate) || 'never')); + var collectionnames = Object.keys(config.collections) + ; + + return fsapi.getMeta( + collectionnames + , { dotfiles: false + , extensions: ['md', 'markdown', 'htm', 'html', 'jade'] + } + ).then(function (collections) { + var themenames = Object.keys(config.themes).filter(function (k) { return 'default' !== k; }) ; + console.log('collections'); + console.log(collections); return fsapi.getMeta( - collectionnames - , { dotfiles: false - , extensions: ['md', 'markdown', 'htm', 'html', 'jade'] + themenames + , { dotfiles: false + , extensions: ['md', 'markdown', 'htm', 'html', 'jade', 'css', 'js', 'yml'] } - ).then(function (collections) { - var themenames = Object.keys(config.themes).filter(function (k) { return 'default' !== k; }) - ; - - console.log('collections'); - console.log(collections); - return fsapi.getMeta( - themenames - , { dotfiles: false - , extensions: ['md', 'markdown', 'htm', 'html', 'jade', 'css', 'js', 'yml'] - } - ).then(function (themes) { - console.log('themes'); - console.log(themes); - return { config: config, cache: cache, meta: { collections: collections, themes: themes } }; - }); + ).then(function (themes) { + console.log('themes'); + console.log(themes); + return { config: config, data: data, cache: cache, meta: { collections: collections, themes: themes }, partials: partials }; }); }); }).then(runDesi).then(function (desi) { @@ -168,48 +235,33 @@ return desi; }); }); + }).then(function (desi) { - function getLayout(themename, layout, arr) { - arr = arr || []; - - var layoutdir = 'layouts' - , themepath - , file - ; - - if (!themename) { - themename = desi.config.themes.default; - } - if (!layout) { - layout = 'post.html'; + // TODO add missing metadata and resave file + desi.content.collections.forEach(function (article) { + if (!article.yml.permalink) { + // TODO read the config for this collection + article.yml.permalink = path.join(desi.urls.base_path, article.title); } - - themepath = themename + '/' + layoutdir + '/' + layout; - - desi.content.themes.some(function (theme) { - // TODO what if it isn't html? - if (theme.path === themepath || theme.path.match(themepath + '\\.html')) { - file = theme; - arr.push(theme); - return true; - } - }); - - if (!file) { - console.error("could not find " + themepath); - return; + if (!article.yml.uuid) { + // TODO only do this if it's going to be saved + // article.yml.uuid = UUID.v4(); } - // TODO handle possible circular dep condition page -> post -> page - console.info(file); - if (file.yml && file.yml.layout) { - return getLayout(themename, file.yml.layout, arr); - } else { - // return the chain page -> posts -> default -> twitter - return arr; + if (!article.yml.date) { + article.yml.date = article.createdDate || article.lastModifiedDate; } - } + + if (!article.yml.updated_at) { + article.yml.updated_at = article.lastModifiedDate; + } + }); + + return desi; + }).then(function (desi) { + var compiled = [] + ; desi.content.collections.forEach(function (article) { // TODO process tags and categories and such @@ -221,19 +273,43 @@ var child = '' , layers + , view ; console.log(article.path || (article.relativePath + '/' + article.name)); //console.log(article.frontmatter); console.log(article.yml); - layers = getLayout(article.yml.theme, article.yml.layout, [article]); + layers = getLayout(desi, article.yml.theme, article.yml.layout, [article]); console.log('LAYERS'); console.log(layers); + + view = { + page: article.yml // data for just *this* page + , content: child // processed content for just *this* page + //, data: desi.data // data.yml + // https://github.com/janl/mustache.js/issues/415 + , data: num2str(desi.data) + , collection: {} // data for just *this* collection + , categories: [] // *all* categories in all collections + , tags: [] // *all* tags in all collections + , site: num2str(desi.site || {}) + , url: path.join(desi.urls.url, desi.urls.base_path, article.yml.permalink) + , canonical_url: path.join(desi.urls.url, desi.urls.base_path, article.yml.permalink) + , relative_url: path.join(desi.urls.base_path, article.yml.permalink) + , urls: desi.urls + }; + view.site.author = desi.data.author; + view.site['navigation?to_pages'] = desi.data.navigation.map(function (nav) { + var title = nav.replace(/^./, function ($1) { return $1.toUpperCase(); }) + ; + + return { path: '/' + nav, active: false, title: /*TODO*/ title }; + }); + layers.forEach(function (parent) { // TODO meta.layout - var view - , body = (parent.body || parent.contents || '').trim() + var body = (parent.body || parent.contents || '').trim() , html ; @@ -249,24 +325,52 @@ console.error('unknown parser for ' + (article.path)); } - view = { - page: article.yml // data for just *this* page - , content: child // processed content for just *this* page - , data: {} // data.yml - , collection: {} // data for just *this* collection - , categories: [] // *all* categories in all collections - , tags: [] // *all* tags in all collections - }; + view.content = child; + + child = Mustache.render(html, view, desi.partials); - child = Mustache.render(html, view); }); - console.log('child'); - console.log(child); - //console.log(meta.mtime.valueOf(), meta.ymlsum, meta.textsum, node); + console.warn('view data.author contains objects?'); + console.warn(JSON.stringify(view.data.author, null, ' ')); + console.warn(typeof view.data.author.twitter_id); + console.warn(view.data.author); + // TODO add html meta-refresh redirects + compiled.push({ contents: child, path: path.join(desi.config.compiled_path, article.yml.permalink) }); + if (Array.isArray(article.yml.redirects)) { + child = + '' + + '
' + + 'This page has moved to a ' + article.yml.title + '.
' + + '' + + '' + ; + + compiled.push({ contents: child, url: view.url, path: path.join(desi.config.compiled, article.yml.permalink) }); + } + + + }); + + desi.compiled = compiled; + return desi; + }).then(function (desi) { + var compiled = desi.compiled + ; + + console.info('das compiled files'); + console.info(compiled); + return fsapi.putFiles(compiled).then(function (saved) { + console.info('files saved'); + console.info(saved); }); }).catch(function (e) { - console.error('The Badness is upon us...'); + console.error('A great and uncatchable error has befallen the land. Read ye here for das detalles..'); + console.error(e.message); throw e; }); }('undefined' !== typeof exports && exports || window)); diff --git a/index.html b/index.html index a948046..a5533f2 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,7 @@ + diff --git a/lib/deardesi-browser.js b/lib/deardesi-browser.js index 7d42fa7..00437e9 100644 --- a/lib/deardesi-browser.js +++ b/lib/deardesi-browser.js @@ -216,8 +216,12 @@ fsapi.getConfig = function () { return request.get('/config.yml').then(function (resp) { - console.log('config'); - console.log(exports.YAML.parse(resp)); + return exports.YAML.parse(resp); + }); + }; + + fsapi.getData = function () { + return request.get('/data.yml').then(function (resp) { return exports.YAML.parse(resp); }); }; @@ -230,8 +234,19 @@ }); }; + fsapi.getPartials = function () { + return request.get('/partials.yml').then(function (resp) { + var partials = exports.YAML.parse(resp) + ; + + console.info('partials'); + console.info(partials); + return partials; + }); + }; + fsapi.putFiles = function (files) { - return request.put('/api/fs/files', { + return request.post('/api/fs/files', { files: files }).then(function (resp) { return JSON.parse(resp); diff --git a/package.json b/package.json index 6fab3a5..046cb9d 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "marked": "^0.3.2", "mkdirp": "^0.5.0", "mustache": "^1.0.0", + "node-uuid": "^1.4.2", "require-yaml": "0.0.1", "require-yamljs": "^1.0.1", "secret-utils": "^1.0.2",