This commit is contained in:
AJ ONeal 2015-01-13 03:08:25 -07:00
parent 38b02c1c3b
commit 98251b3a68
7 changed files with 554 additions and 317 deletions

View File

@ -13,4 +13,12 @@
, "unused": true
, "latedef": true
, "globals": { "angular": true }
, "bitwise": true
, "curly": true
, "forin": true
, "freeze": true
, "immed": true
, "funcscope": false
}

View File

@ -34,7 +34,7 @@ angular.module('myApp.services', []).
return d.promise;
}
Desi.build(desi, env).then(function () {
Desi.buildAll(desi, env).then(function () {
d.resolve(desi);
});

View File

@ -4,7 +4,6 @@
var PromiseA = exports.Promise || require('bluebird').Promise
, path = exports.path || require('path')
, Mustache = exports.Mustache || require('mustache')
, marked = (exports.markdownit || require('markdown-it'))({ html: true, linkify: true })
, forEachAsync = exports.forEachAsync || require('foreachasync').forEachAsync
//, sha1sum = exports.sha1sum || require('./lib/deardesi-node').sha1sum
, frontmatter = exports.Frontmatter || require('./lib/frontmatter').Frontmatter
@ -29,6 +28,19 @@
, 12: 'December'
};
/*
function shallowClone(obj) {
var shallow = {}
;
Object.keys(obj).forEach(function (key) {
shallow[key] = obj[key];
});
return shallow;
}
*/
function firstCap(str) {
return str.replace(/^./, function ($1) { return $1.toUpperCase(); });
}
@ -154,6 +166,7 @@
}
function getLayout(desi, themename, layout, arr) {
// TODO meta.layout for each entity
arr = arr || [];
var layoutdir = 'layouts'
@ -176,6 +189,7 @@
// TODO what if it isn't html?
if (theme.path === themepath || theme.path.match(themepath + '\\.html')) {
file = theme;
theme.ext = path.extname(file.path);
arr.push(theme);
return true;
}
@ -224,8 +238,8 @@
console.info('loaded config, data, caches, partials');
console.log({
config: arr.config
, data: arr.data
, site: arr.site
, authors: arr.authors
});
desi.blogdir = blogdir;
@ -339,22 +353,7 @@
});
};
Desi.setEnv = function (desi, env) {
desi.urls = desi.config.urls = {};
desi.env = {};
if (-1 === ['development', 'staging'].indexOf(env) || !desi.config[env]) {
env = 'production';
}
desi.urls.base_path = desi.config.base_path = desi.config[env].base_path;
desi.urls.url = desi.config[env].url;
desi.config.compiled_path = desi.config[env].compiled_path;
desi.urls[env + '_url'] = desi.config[env].url;
return PromiseA.resolve(desi);
};
Desi.getDirtyFiles = function (desi, env) {
Desi.getDirtyFiles = function (desi) {
var cache = desi.cache
//, config = desi.config
, cacheByPath = {}
@ -364,10 +363,6 @@
, droot
;
if (!desi.env) {
Desi.setEnv(desi, env);
}
cache.sources = cache.sources || [];
cache.sources.forEach(function (source) {
cacheByPath[source.path] = source;
@ -419,7 +414,7 @@
});
};
Desi.copyAssets = function(desi) {
Desi.copyAssets = function(desi, env) {
var files = {}
;
@ -429,10 +424,9 @@
var assets = desi.meta.assets[key]
;
// TODO fix compiled_path + base_path
assets.forEach(function (asset) {
console.log('preparing ' + asset + ' for copy');
files[path.join(asset.relativePath, asset.name)] = path.join(desi.config.compiled_path, 'assets', asset.relativePath, asset.name);
console.log('preparing ' + asset.path + ' for copy');
files[path.join(asset.relativePath, asset.name)] = path.join(env.compiled_path, 'assets', asset.relativePath, asset.name);
});
});
@ -464,25 +458,29 @@
desi.navigation = [];
desi.content.root.forEach(function (page) {
// XXX BUG TODO strip only strip _root so that nested nav will work as expected
var name = path.basename(page.path, path.extname(page.path))
, nindex
;
//if (-1 === desi.data.navigation.indexOf(name) && 'index' !== name)
nindex = desi.data.navigation.indexOf(name);
nindex = (desi.site.navigation).indexOf(name);
if (-1 === nindex) {
return;
}
desi.navigation[nindex] = {
title: page.yml && page.yml.title || firstCap(name)
, href: desi.urls.base_path + '/' + name
, path: desi.urls.base_path + '/' + name
, name: name
, active: false // placeholder
};
});
// transform spare array into compact array
desi.navigation = desi.navigation.filter(function (n) {
return n;
});
return PromiseA.resolve(desi);
};
@ -557,7 +555,7 @@
if (!page.yml.date) {
// TODO tell YAML parser to keep the date a string
page.yml.date = new Date(page.yml.created_at || page.yml.time || page.createdDate || page.lastModifiedDate).toISOString();
page.yml.date = new Date(page.yml.created_at || page.yml.time || page.yml.updated_at || page.createdDate || page.lastModifiedDate).toISOString();
}
if ('object' === typeof page.yml.date) {
page.yml.date = page.yml.date.toISOString();
@ -570,9 +568,6 @@
function normalizeContentEntity(entity) {
entity.ext = path.extname(entity.path);
entity.url = desi.urls.url + path.join(desi.urls.base_path, entity.yml.permalink);
entity.canonical_url = desi.urls.url + path.join(desi.urls.base_path, entity.yml.permalink);
entity.relative_url = path.join(desi.urls.base_path, entity.yml.permalink);
entity.published_at = fromLocaleDate(entity.yml.date);
entity.year = entity.published_at.year;
entity.month = entity.published_at.month;
@ -602,7 +597,7 @@
return PromiseA.resolve(desi);
};
Desi.collate = function (desi/*, collectionname*/) {
Desi.collate = function (desi, env/*, collectionname*/) {
function byDate(a, b) {
if (a.year > b.year) {
return -1;
@ -651,6 +646,8 @@
, mindex = 12 - f.month
;
f.url = path.join(env.base_path, f.yml.permalink);
if (!yearsArr[yindex]) {
yearsArr[yindex] = { year: f.year, months: [] };
}
@ -686,16 +683,218 @@
desi.content.collections.sort(byDate);
desi.collated = collate(desi.content.collections);
console.info('desi.collated');
console.info('7 desi.collated');
console.info(desi.collated);
return PromiseA.resolve(desi);
};
Desi.build = function (desi) {
Desi.datamaps = {};
Desi.datamaps['desirae@1.0'] = function (obj) {
obj.desi = obj;
return obj;
};
Desi.datamaps['ruhoh@2.6'] = function (view) {
var newview
;
newview = {
content: view.contents
, page: {
title: view.entity.yml.title || view.site.title
, tagline: view.entity.yml.tagline
, content: view.contents
, youtube: view.entity.yml.youtube
, disqus_identifier: view.entity.disqus_identifier
, disqus_url: !view.entity.disqus_identifier && view.entity.disqus_url
, tags: view.entity.yml.tags
, categories: view.entity.yml.categories
, player_width: view.entity.yml.player_width
, player_height: view.entity.yml.player_height
, next: view.entities[view.entity_index + 1]
, previous: view.entities[view.entity_index - 1]
, date: view.entity.year + '-' + view.entity.month + '-' + view.entity.day
// TODO , url: view.entities.
}
, posts: { collated: view.desi.collated }
, urls: {
base_url: view.env.base_url
, base_path: view.env.base_path
}
, data: {
author: {
name: view.author.name
, twitter: view.author.twitter
}
, title: view.site.title
}
, assets: view.desi.assets.join('\n')
, widgets: {
comments: view.site.disqus_shortname &&
Mustache.render(view.desi.partials.disqus, { disqus: {
shortname: view.site.disqus_shortname
, identifier: view.entity.disqus_identifier
, url: !view.entity.disqus_identifier && view.entity.disqus_url
}})
, analytics: view.site.google_analytics_tracking_id &&
Mustache.render(view.desi.partials.google_analytics, { google_analytics: {
tracking_id: view.site.google_analytics_tracking_id
}})
, facebook_connect: view.desi.partials.facebook_connect
, twitter: view.desi.partials.twitter
, google_plusone: view.desi.partials.google_plusone
, amazon_link_enhancer: view.site.amazon_affiliate_id &&
Mustache.render(view.desi.partials.amazon_link_enhancer, {
amazon_affiliate_id: view.site.amazon_affiliate_id
})
}
, site: {
navigation: view.navigation
}
};
// backwards compat
newview.site['navigation?to_pages'] = newview.site.navigation;
newview.site['navigation?to__root'] = newview.site.navigation;
newview.data.navigation = view.site.navigation;
newview.data['navigation?to_pages'] = newview.site.navigation;
newview.data['navigation?to__root'] = newview.site.navigation;
newview.page.content = view.contents;
return newview;
};
Desi.renderers = {};
Desi.registerRenderer = function(ext, fn, opts) {
// TODO allow a test method for ext and content (new RegExp("\\." + escapeRegExp(ext) + "$", i).test(current.ext))
opts = opts || {};
// TODO opts.priority
Desi.renderers[ext] = Desi.renderers[ext] || [];
// LIFO
Desi.renderers[ext].unshift(fn);
};
Desi.render = function (ext, content, view) {
ext = (ext||'').toLowerCase().replace(/^\./, '');
if (Desi.renderers[ext] && Desi.renderers[ext].length) {
return Desi.renderers[ext][0](content, view);
}
return PromiseA.reject(new Error("no renderer registered for ." + ext));
};
function registerJade() {
var jade = true || exports.jade || require('jade')
;
function render(contentstr/*, desi*/) {
return PromiseA.resolve(jade(contentstr));
}
if (false) {
Desi.registerRenderer('jade', render);
}
}
registerJade();
function registerMarkdown() {
var markitdown = (exports.markdownit || require('markdown-it'))({ html: true, linkify: true })
;
function render(contentstr/*, desi*/) {
return Promise.resolve(
markitdown.render(contentstr)
//.replace('"', '"')
//.replace(''', "'")
//.replace('/', '/')
);
}
['md', 'markdown', 'mdown', 'mkdn', 'mkd', 'mdwn', 'mdtxt', 'mdtext'].forEach(function (ext) {
Desi.registerRenderer(ext, render);
});
}
registerMarkdown();
function registerHtml() {
function render(contentstr/*, desi*/) {
return PromiseA.resolve(contentstr);
}
Desi.registerRenderer('html', render);
Desi.registerRenderer('htm', render);
Desi.registerRenderer('xhtml', render);
}
registerHtml();
function renderLayers(desi, env, view, entity) {
var mustached = ''
, layers
;
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()
;
// TODO move to normalization
current.path = current.path || (entity.relativePath + '/' + entity.name);
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']
, newview
;
view.contents = mustached;
// shallowClone to prevent perfect object equality (and potential template caching)
if (/Blog$/.test(view.entity.title)) {
console.log('desi.partials');
console.log(desi.partials);
}
newview = datamap(view);
if (/Blog$/.test(view.entity.title)) {
console.info('desi.collated');
console.log(desi);
console.info('newview.posts.collated');
console.log(newview.posts.collated);
}
mustached = Mustache.render(html, newview, desi.partials);
return mustached;
}).catch(function (e) {
console.error(current);
if (env.onError) {
return env.onError(e);
} else {
console.error('no registered renderer for ' + entity.path + ' or rendering failed');
throw e;
}
});
});
}
Desi.build = function (desi, env) {
var compiled = []
;
env.transforms = env.transforms || [];
desi.transforms = (desi.transforms || []).concat(env.transforms);
desi.transforms.push(function (view) {
var yml = view.entity.yml
;
if (yml.uuid) {
view.entity.disqus_identifier = yml.uuid;
} else {
view.entity.disqus_url = view.entity.production_url;
}
return view;
});
/*
function compileScriptEntity(entity, i, arr) {
}
@ -703,160 +902,154 @@
function compileThemeEntity(entity, i, arr) {
console.log("compiling " + (i + 1) + "/" + arr.length + " " + (entity.path || entity.name));
// TODO less / sass / etc
compiled.push({ contents: entity.body || entity.contents, path: path.join(desi.config.compiled_path, 'themes', entity.path) });
compiled.push({ contents: entity.body || entity.contents, path: path.join('themes', entity.path) });
if (/stylesheets.*\.css/.test(entity.path) && (!/google/.test(entity.path) || /obsid/.test(entity.path))) {
// TODO XXX move to a partial
desi.assets.push(
'<link href="' + desi.urls.base_path + '/themes/' + entity.path + '" type="text/css" rel="stylesheet" media="all">'
'<link href="' + env.base_path + '/themes/' + entity.path + '" type="text/css" rel="stylesheet" media="all">'
);
}
}
desi.navigation.filter(function (n) {
return n;
});
//console.log(desi.navigation);
function compileContentEntity(entity, i, arr) {
console.log("compiling " + (i + 1) + "/" + arr.length + " " + (entity.path || entity.name));
var previous = ''
, layers
function compileContentEntity(entity, i, arr) {
console.log("compiling " + (i + 1) + "/" + arr.length + " " + entity.path);
var navigation = JSON.parse(JSON.stringify(desi.navigation))
, author = desi.authors[entity.yml.author] || desi.authors[Object.keys(desi.authors)[0]]
, view
;
layers = getLayout(desi, entity.yml.theme, entity.yml.layout, [entity]);
entity.url = env.base_url + path.join(env.base_path, entity.yml.permalink);
entity.canonical_url = env.base_url + path.join(env.base_path, entity.yml.permalink);
entity.production_url = desi.site.base_url + path.join(desi.site.base_path, entity.yml.permalink);
entity.relative_url = path.join(env.base_path, entity.yml.permalink);
view = {
page: entity.yml // data 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: entity.canonical_url
, canonical_url: entity.canonical_url
, relative_url: entity.relative_url
, urls: desi.urls
, previous: arr[i - 1]
, next: arr[i + 1]
, posts: { collated: desi.collated }
// TODO concat theme, widget, and site assets
, assets: desi.assets.join('\n')
};
// TODO nested names?
navigation.forEach(function (nav) {
nav.href = env.base_path + '/' + nav.name;
nav.path = env.base_path + '/' + nav.name;
//console.log('rel:', view.relative_url);
view.site.author = desi.data.author;
view.site.navigation = JSON.parse(JSON.stringify(desi.navigation));
view.site.navigation.forEach(function (nav) {
if (nav.href === view.relative_url) {
// path.basename(nav.path, path.extname(nav.path))
if (nav.href.replace(/(\/)?(\/index)?(\.html)?$/i, '') === entity.relative_url.replace(/(\/)?(\/index)?(\.html)?$/i, '')) {
nav.active = true;
}
});
// backwards compat
view.site['navigation?to_pages'] = view.site.navigation;
view.site['navigation?to__root'] = view.site.navigation;
view.data.navigation = view.site.navigation;
view.data['navigation?to_pages'] = view.site.navigation;
view.data['navigation?to__root'] = view.site.navigation;
layers.forEach(function (current) {
// TODO meta.layout
var body = (current.body || current.contents || '').trim()
, html
, curview = {}
;
view = {
env: env
, config: desi.config
, site: desi.site
, data: desi.data
, entity: entity
, entity_index: i
, entities: arr
, desi: desi
, navigation: navigation
, author: num2str(author)
};
// TODO move to normalization
current.path = current.path || (entity.relativePath + '/' + entity.name);
if (/\.(html|htm)$/.test(current.path)) {
html = body;
} else if (/\.(md|markdown|mdown|mkdn|mkd|mdwn|mdtxt|mdtext)$/.test(current.ext)) {
html = marked.render(body)
//.replace('&quot;', '"')
//.replace('&#39;', "'")
//.replace('&#x2F;', '/')
;
} else {
console.error('unknown parser for ' + (entity.path));
}
view.content = previous;
view.page.content = previous;
// to prevent perfect object equality (and potential template caching)
Object.keys(view).forEach(function (key) {
curview[key] = view[key];
});
previous = Mustache.render(html, curview, desi.partials);
desi.transforms.forEach(function (fn) {
view = fn(view);
});
// NOTE: by now, all permalinks should be in the format /path/to/page.html or /path/to/page/index.html
if (/^(index)?(\/?index.html)?$/.test(entity.yml.permalink)) {
console.info('found compiled index');
compiled.push({ contents: previous, path: path.join(desi.config.compiled_path, 'index.html') });
} else {
compiled.push({ contents: previous, path: path.join(desi.config.compiled_path, entity.yml.permalink) });
}
return renderLayers(desi, env, view, entity).then(function (html) {
// NOTE: by now, all permalinks should be in the format /path/to/page.html or /path/to/page/index.html
if (/^(index)?(\/?index.html)?$/.test(entity.yml.permalink)) {
console.info('found compiled index');
compiled.push({ contents: html, path: path.join('index.html') });
} else {
compiled.push({ contents: html, path: path.join(entity.yml.permalink) });
}
entity.yml.redirects = entity.yml.redirects || [];
if (/\/index.html$/.test(entity.yml.permalink)) {
entity.yml.redirects.push(entity.yml.permalink.replace(/\/index.html$/, '.html'));
} else if (/\.html$/.test(entity.yml.permalink)) {
entity.yml.redirects.push(entity.yml.permalink.replace(/\.html?$/, '/index.html'));
} else {
console.info('found index, ignoring redirect');
}
entity.yml.redirects.forEach(function (redirect) {
var content
;
entity.yml.redirects = entity.yml.redirects || [];
// TODO move to partial
content =
'<html>'
+ '<head>'
+ '<title>Redirecting to ' + entity.yml.title + '</title>'
+ '<meta http-equiv="refresh" content="0;URL=\''
+ desi.urls.url + path.join(desi.urls.base_path, entity.yml.permalink)
+ '\'" />'
+ '</head>'
+ '<body>'
+ '<p>This page has moved to a <a href="'
+ desi.urls.url + path.join(desi.urls.base_path, entity.yml.permalink)
+'">'
+ entity.yml.title
+ '</a>.</p>'
+ '</body>'
+ '</html>'
;
if (/\/index.html$/.test(entity.yml.permalink)) {
entity.yml.redirects.push(entity.yml.permalink.replace(/\/index.html$/, '.html'));
} else if (/\.html$/.test(entity.yml.permalink)) {
entity.yml.redirects.push(entity.yml.permalink.replace(/\.html?$/, '/index.html'));
} else {
console.info('found index, ignoring redirect');
}
compiled.push({ contents: content, path: path.join(desi.config.compiled_path, redirect) });
entity.yml.redirects.forEach(function (redirect) {
var html = Mustache.render(desi.partials.redirect, view)
;
compiled.push({
contents: html
, path: path.join(redirect)
});
});
}).catch(function (e) {
console.error('failing at build step here here here');
throw e;
if (env.onError) {
return env.onError(e);
} else {
console.error("couldn't render " + entity.path);
console.error(entity);
console.error(e);
throw e;
}
});
}
function doStuff() {
var themes = desi.content.themes.filter(function (f) { return !/\blayouts\b/.test(f.path); })
;
console.info('[first] compiling theme assets');
desi.content.themes.filter(function (f) { return !/\blayouts\b/.test(f.path); }).forEach(compileThemeEntity);
console.info('compiling root pages');
desi.content.root.forEach(compileContentEntity);
console.info('compiling article pages');
desi.content.collections.forEach(compileContentEntity);
desi.compiled = compiled;
return PromiseA.resolve(desi);
return forEachAsync(themes, compileThemeEntity).then(function () {
console.info('compiling root pages');
return forEachAsync(desi.content.root, compileContentEntity).then(function () {
console.info('compiling article pages');
desi.content.collections.forEach(compileContentEntity);
}).then(function () {
desi.compiled = compiled;
return desi;
});
});
}
if (!desi.partials) {
return fsapi.getAllPartials().then(doStuff);
return fsapi.getAllPartials().then(function (partials) {
if (partials.error) {
throw partials.error;
}
desi.partials = partials;
return doStuff();
});
} else {
return doStuff();
}
};
Desi.save = function (desi) {
Desi.buildAll = function (desi, env) {
return Desi.getDirtyFiles(desi, env.since)
.then(Desi.parseFrontmatter)
.then(Desi.getNav)
.then(Desi.normalizeYml)
.then(function () {
Desi.collate(desi, env)
})
.then(function () {
return Desi.build(desi, env);
}).then(function () {
return Desi.copyAssets(desi, env);
}).catch(function (e) {
if (env.onError) {
return env.onError(e);
} else {
console.error('buildAll failed somewhere');
console.error(e);
throw e;
}
})
;
};
Desi.write = function (desi, env) {
var compiled = desi.compiled.slice(0)
, batches = []
, now
@ -868,6 +1061,10 @@
return;
}
compiled.forEach(function (thing) {
thing.path = path.join(env.compiled_path, thing.path);
});
// because some servers / proxies are terrible at handling large uploads (>= 100k)
// (vagrant? or express? one of the two is CRAZY slow)
console.info('saving compiled files', desi.compiled);

137
example/partials.yml Normal file
View File

@ -0,0 +1,137 @@
---
amazon_link_enhancer: |
<!-- amazon -->
<script async="true" type="text/javascript" src="http://wms.assoc-amazon.com/20070822/US/js/link-enhancer-common.js?tag={{ amazon_affiliate_id }}">
</script>
<noscript>
<img src="http://wms.assoc-amazon.com/20070822/US/img/noscript.gif?tag={{ amazon_affiliate_id }}" alt="" />
</noscript>
google_analytics: |
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', '{{ google_analytics.tracking_id }}']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
disqus: |
<div id="disqus_thread"></div>
<script type="text/javascript">
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
var disqus_shortname = '{{ disqus.shortname }}'; // required: replace example with your forum shortname
var disqus_identifier = '{{ disqus.identifier }}' || undefined;
var disqus_url = '{{{ disqus.url }}}' || undefined;
/* * * DON'T EDIT BELOW THIS LINE * * */
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
redirect: >
<html>
<head>
<title>Redirecting to {{ entity.title }}</title>
<meta http-equiv="refresh" content="0;URL='{{{ env.url }}}{{{ entity.permalink }}}'"/>
</head>
<body>
<p>This page has moved to
<a href="{{{ env.url }}}{{{ entity.permalink }}}">{{ entity.title }}</a>.
</p>
</body>
</html>
pages_list: >
<li{{# active }} class="active"{{/ active }}><a{{# active }} class="active"{{/ active }}
href="{{{ path }}}"
>{{ title }}</a></li>
# [{ 'year': year,
# 'months' : [{ 'month' : month,
# 'pages': [{}, {}, ..] }, ..] }, ..]
posts_collate: |
{{# years }}
<h2>{{ year }}</h2>
{{> posts_collate_year }}
{{/ years }}
posts_collate_year: |
{{# months }}
<h3>{{ month }}</h3>
{{> posts_collate_month }}
{{/ months }}
posts_collate_month: |
<ul>
{{# pages }}
{{> posts_collate_pages }}
{{/ pages }}
</ul>
posts_collate_pages: |
<li><span>{{ year }}-{{ month }}-{{ day }}</span> »
<a href="{{{url}}}"
>{{ title }}</a></li>
google_prettify: |
<script src="http://cdnjs.cloudflare.com/ajax/libs/prettify/188.0.0/prettify.js"></script>
<script>
var pres = document.getElementsByTagName("pre");
for (var i=0; i < pres.length; ++i) {
pres[i].className = "prettyprint {{#linenums}}linenums{{/linenums}}";
}
prettyPrint();
</script>
<!-- end Google Prettify -->
google_ads: |
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', {{#id}}'{{.}}'{{/id}}]);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
facebook_connect: |
<!-- facebook -->
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id; js.async=true;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=213439508797174";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
google_plusone: |
<!-- g+ -->
<!-- Place this tag after the last +1 button tag. -->
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
twitter: |
<!-- twitter -->
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.async=true;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

View File

@ -213,7 +213,6 @@
return request.post('/api/fs/walk?_method=GET' + dotfiles + extensions + contents + sha1sum, {
dirs: collections
}).then(function (resp) {
console.log(collections);
return JSON.parse(resp);
});
};
@ -252,14 +251,20 @@
, data = {}
;
if (file.error) {
console.error(file);
console.error(file.error);
return;
}
if (/\.(ya?ml)$/i.test(file.name)) {
console.log();
try {
data = exports.YAML.parse(file.contents) || {};
if ("undefined" === obj[keyname][filename]) {
if ("undefined" === data) {
data = {};
}
} catch(e) {
data = { error: e };
console.error("Could not parse yaml for " + filename);
console.error(file);
console.error(e);
@ -269,6 +274,7 @@
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);
@ -278,7 +284,7 @@
console.error(file);
}
obj[keyname][filename] = data;
obj[keyname][filename] = data || obj[keyname][filename];
/*
if (!obj[keyname][filename]) {
obj[keyname][filename] = {};
@ -300,15 +306,20 @@
;
Object.keys(results.partials).forEach(function (key) {
var partial = partials[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];
});
});
console.info('getAllPartialts', results);
console.info(partials);
return partials;
});
};

View File

@ -1,58 +0,0 @@
---
pages_list: >
<li{{# active }} class="active"{{/ active }}><a{{# active }} class="active"{{/ active }}
href="{{{ path }}}"
>{{ title }}</a></li>
# [{ 'year': year,
# 'months' : [{ 'month' : month,
# 'pages': [{}, {}, ..] }, ..] }, ..]
posts_collate: |
{{# years }}
<h2>{{ year }}</h2>
{{> posts_collate_year }}
{{/ years }}
posts_collate_year: |
{{# months }}
<h3>{{ month }}</h3>
{{> posts_collate_month }}
{{/ months }}
posts_collate_month: |
<ul>
{{# pages }}
{{> posts_collate_pages }}
{{/ pages }}
</ul>
posts_collate_pages: |
<li><span>{{ year }}-{{ month }}-{{ day }}</span> »
<a href="{{{url}}}"
>{{ title }}</a></li>
google_prettify: |
<script src="http://cdnjs.cloudflare.com/ajax/libs/prettify/188.0.0/prettify.js"></script>
<script>
var pres = document.getElementsByTagName("pre");
for (var i=0; i < pres.length; ++i) {
pres[i].className = "prettyprint {{#linenums}}linenums{{/linenums}}";
}
prettyPrint();
</script>
<!-- end Google Prettify -->
google_ads: |
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', {{#id}}'{{.}}'{{/id}}]);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

View File

@ -11,14 +11,14 @@ angular.module('myApp.build', ['ngRoute'])
.controller('BuildCtrl'
, ['$scope', '$location', '$timeout', 'Desirae'
, function ($scope, $location, $timeout, Desirae) {
, function ($scope, $location, $timeout, DesiraeService) {
var scope = this
, path = window.path
;
function init() {
console.log('desi loading');
Desirae.meta().then(function (desi) {
DesiraeService.meta().then(function (desi) {
scope.blogdir = desi.blogdir.path.replace(/^\/(Users|home)\/[^\/]+\//, '~/');
scope.site = desi.site;
@ -40,108 +40,50 @@ angular.module('myApp.build', ['ngRoute'])
scope.extensions = ['md', 'html'];
}
scope.onChange = function () {
var post = scope.selected.post
, selected = scope.selected
;
post.yml.title = post.yml.title || '';
post.yml.description = post.yml.description || '';
if (selected.permalink === post.yml.permalink) {
selected.permalink = '/articles/' + post.yml.title.toLowerCase()
.replace(/["']/g, '')
.replace(/\W/g, '-')
.replace(/^-+/g, '')
.replace(/-+$/g, '')
.replace(/--/g, '-')
+ '.' + selected.format
;
post.yml.permalink = selected.permalink;
}
if (window.path.extname(post.yml.permalink) !== '.' + selected.format) {
post.yml.permalink = post.yml.permalink.replace(/\.\w+$/, '.' + selected.format);
}
post.frontmatter = window.jsyaml.dump(post.yml).trim();
// TODO use some sort of filepath pattern in config.yml
selected.path = window.path.join((selected.collection || 'posts'), window.path.basename(post.yml.permalink));
selected.abspath = window.path.join(scope.blogdir, selected.path);
};
scope.onFrontmatterChange = function () {
var data
;
try {
if (!scope.selected.post.frontmatter || !scope.selected.post.frontmatter.trim()) {
throw new Error('deleted frontmatter');
}
data = window.jsyaml.load(scope.selected.post.frontmatter);
scope.selected.format = data.permalink.replace(/.*\.(\w+$)/, '$1');
if (!data.permalink) {
data = scope.selected.permalink;
}
scope.selected.post.yml = data;
} catch(e) {
console.error(e);
console.error('ignoring update that created parse error');
scope.selected.post.frontmatter = window.jsyaml.dump(scope.selected.post.yml).trim();
scope.onError = function (e) {
console.error(e);
if (window.confirm("Encountered an error. Please inspect the console.\n\nWould you like to ignore the error and continue?")) {
return window.Promise.resolve();
} else {
return window.Promise.reject();
}
};
function updateDate() {
$timeout.cancel(scope.dtlock);
scope.dtlock = $timeout(function () {
if (scope.selected && scope.selected.date === scope.selected.post.yml.date) {
scope.selected.date = scope.selected.post.yml.date = Desirae.toDesiDate(new Date());
}
scope.onChange();
updateDate();
}, 60 * 1000);
}
scope.upsert = function () {
console.log('upserted');
if (-1 === scope.extensions.indexOf(scope.selected.format)) {
window.alert('.' + scope.selected.format + ' is not a supported extension.\n\nPlease choose from: .' + scope.extensions.join(' .'));
return;
}
scope.selected.post.yml.uuid = scope.selected.uuid;
['updated', 'theme', 'layout', 'swatch'].forEach(function (key) {
if (!scope.selected.post.yml[key]) {
delete scope.selected.post.yml[key];
}
});
scope.onChange();
var files = []
scope.buildOne = function (envstr) {
var env
;
files.push({
path: scope.selected.path
, contents:
'---\n'
+ scope.selected.post.frontmatter.trim()
+ '\n'
+ '---\n'
+ '\n'
+ scope.selected.post.body.trim()
});
// TODO is there a legitimate case where in addition to base_path (root of the blog)
// a user would need owner_base? i.e. school.edu/~/rogers/blog school.edu/~/rogers/assets
if ('production' === envstr) {
env = {
url: scope.production_url
, base_url: scope.development_url.replace(/(https?:\/\/[^\/#?]+)/, '$1')
, compiled_path: 'compiled'
, since: 0
, onError: scope.onError
};
} else {
env = {
url: scope.development_url
, base_url: scope.development_url.replace(/(https?:\/\/[^\/#?]+)/, '$1')
, base_path: scope.development_url.replace(/https?:\/\/[^\/#?]+/, '')
, compiled_path: 'compiled_dev'
, since: 0
, onError: scope.onError
};
}
console.log(files);
Desirae.putFiles(files).then(function (results) {
console.log('TODO check for error');
console.log(results);
$location.path('/build');
}).catch(function (e) {
$timeout.cancel(scope.dtlock);
console.error(scope.site);
console.error(e);
window.alert("Error Nation! :/");
throw e;
return DesiraeService.build(env).then(function () {
DesiraeService.write(env);
});
};
scope.build = function (envs) {
window.forEachAsync(envs, function (env) {
return scope.buildOne(env);
}).then(function () {
window.alert('Build(s) Complete');
});
};