Browse Source

kinda broken, kinda working

month_name
AJ ONeal 9 years ago
parent
commit
b81ed8af1c
  1. 56
      ENTITY.md
  2. 851
      desirae.js
  3. 121
      lib/aggregate-core.js
  4. 11
      lib/datamap-core.js
  5. 44
      lib/render-core.js
  6. 178
      lib/transform-core.js
  7. 95
      tests/permalink.js

56
ENTITY.md

@ -0,0 +1,56 @@
This is what an entity looks like:
```yml
# inherited from File Entity
path : My Posts/My-Old-Name.html
lastModifiedDate : 2015-07-04T13:56:01Z
createdDate : 2015-07-04T13:56:01Z
contents : '...' # whatever the file is
# inherited from Collection Entity
name : My-Old-Name.html
relativePath : My Posts
ext : .html
collection : posts
# inherited from Content Entity
frontmatter : '---\n...\n---' # frontmatter as a string
yml : {} # frontmatter, parsed
body : 'I think ...' # body, after frontmatter
# inherited from Normalized Entity
title : My Title # yml.title | titlize(entity.name)
slug : my-title # slugify(title)
slug_path : my-posts # slugifyPath(relativePath)
year : 2014
month : 07
day : 04
hour : 13
twelve_hour : 1
meridian : pm
minute : 22
categories : ['tech']
tags : ['http','url','website']
# includes index.html
relative_file : /posts/foo/index.html
# excludes index.html
relative_link : /posts/foo/
# actual url of this file, even if redirect
# excludes index.html
url : http://dev.example.com/posts/foo/
# the appropriate url, even in a redirect or duplicate
# excludes index.html
canonical_url : http://dev.example.com/posts/foo/
# production url, even in development (for disqus, etc)
# excludes index.html
production_url : http://example.com/posts/foo/
```
Note: The option `env.explicitIndexes` turns on `/index.html`. This option is automatically turned on when Dropbox is the host.

851
desirae.js

File diff suppressed because it is too large

121
lib/aggregate-core.js

@ -0,0 +1,121 @@
/*jshint -W054 */
;(function (exports) {
'use strict';
var path = exports.path || require('path')
, months
, cores = {}
;
months = {
1: 'January'
, 2: 'February'
, 3: 'March'
, 4: 'April'
, 5: 'May'
, 6: 'June'
, 7: 'July'
, 8: 'August'
, 9: 'September'
, 10: 'October'
, 11: 'November'
, 12: 'December'
};
function byDate(a, b) {
a.year = parseInt(a.year, 10) || 0;
b.year = parseInt(b.year, 10) || 0;
if (a.year > b.year) {
return -1;
} else if (a.year < b.year) {
return 1;
}
a.month = parseInt(a.month, 10) || 0;
b.month = parseInt(b.month, 10) || 0;
if (a.month > b.month) {
return -1;
} else if (a.month < b.month) {
return 1;
}
a.day = parseInt(a.day, 10) || 0;
b.day = parseInt(b.day, 10) || 0;
if (a.day > b.day) {
return -1;
} else if (a.day < b.day) {
return 1;
}
if (a.hour > b.hour) {
return -1;
} else if (a.hour < b.hour) {
return 1;
}
if (a.minute > b.minute) {
return -1;
} else if (a.minute < b.minute) {
return 1;
}
if (a.title.toLowerCase() <= b.title.toLowerCase()) {
return -1;
}
return 1;
}
function collate(entities, env) {
var yearsArr = []
;
entities.forEach(function (f) {
var set
, yindex = 3000 - f.year
, mindex = 12 - f.month
;
f.url = path.join(env.base_path, f.permalink);
if (!yearsArr[yindex]) {
yearsArr[yindex] = { year: f.year, months: [] };
}
set = yearsArr[yindex];
if (!set.months[mindex]) {
set.months[mindex] = { month: months[parseInt(f.month, 10)], pages: [] };
}
set = set.months[mindex];
set.pages.push(f);
});
yearsArr = yearsArr.filter(function (y) {
if (!y) {
return false;
}
y.months = y.months.filter(function (m) {
return m && m.pages.length;
});
if (!y.months.length) {
return false;
}
return true;
});
return { years: yearsArr };
}
cores.collate = function (desi, env) {
// TODO categories
// TODO tags
desi.content.collections.sort(byDate);
desi.collated = collate(desi.content.collections, env);
};
exports.DesiraeAggregateCore = cores.DesiraeAggregateCore = cores;
}('undefined' !== typeof exports && exports || window));

11
lib/datamap-core.js

@ -0,0 +1,11 @@
/*jshint -W054 */
;(function (exports) {
'use strict';
function desiMap(obj) {
obj.desi = obj;
return obj;
}
exports.DesiraeDatamapCore = desiMap.DesiraeDatamapCore = desiMap;
}('undefined' !== typeof exports && exports || window));

44
lib/render-core.js

@ -0,0 +1,44 @@
/*jshint -W054 */
;(function (exports) {
'use strict';
var PromiseA = exports.Promise || require('bluebird').Promise
;
function renderMd(contentstr/*, desi*/) {
var markitdown = (exports.markdownit || require('markdown-it'))({ html: true, linkify: true })
;
return PromiseA.resolve(
markitdown.render(contentstr)
//.replace('&quot;', '"')
//.replace('&#39;', "'")
//.replace('&#x2F;', '/')
);
}
function renderNoop(contentstr/*, desi*/) {
// hmmm... that was easy
return PromiseA.resolve(contentstr);
}
function renderJade(contentstr, desi, options) {
options = options || {};
if (!('pretty' in options)) {
options.pretty = true;
}
var jade = (exports.jade || require('jade'))
, fn = jade.compile(contentstr, options)
, html = fn(desi)
;
return PromiseA.resolve(html);
}
exports.DesiraeRenderMarkdown = renderMd.DesiraeRenderMarkdown = renderMd;
exports.DesiraeRenderHtml = renderNoop.DesiraeRenderHtml = renderNoop;
exports.DesiraeRenderCss = renderNoop.DesiraeRenderCss = renderNoop;
exports.DesiraeRenderJs = renderNoop.DesiraeRenderJs = renderNoop;
exports.DesiraeRenderJade = renderJade.DesiraeRenderJade = renderJade;
}('undefined' !== typeof exports && exports || window));

178
lib/transform-core.js

@ -0,0 +1,178 @@
/*jshint -W054 */
;(function (exports) {
'use strict';
var cores = {}
, Desi = exports.Desirae || require('desirae').Desirae
, path = exports.path || require('path')
;
cores.lint = function (desi, env, collection, entity) {
// TODO splice
//desi.content.collections = desi.content.collections.filter(function (entity) {
// TODO throw for any files that don't have a registered renderer
if (!entity.yml) {
if (!desi.config.empty_frontmatter) {
throw new Error("no frontmatter for " + (entity.path || entity.name) + "."
+ "Set `config.yml.empty_frontmatter: include|skip` to ignore this error."
);
}
if ('include' === desi.config.empty_frontmatter) {
entity.yml = {};
}
else if ('skip' === desi.config.empty_frontmatter) {
return false;
}
else {
throw new Error('unrecognize option ' + desi.config.empty_frontmatter +
' for `config.yml.empty_frontmatter: include|skip`.');
}
}
if (!entity.body || !entity.body.trim()) {
if (!desi.config.empty_body) {
throw new Error('empty content file ' + (entity.path || entity.name)
+ '. Set `config.yml.empty_body: include|skip` to ignore this error.'
);
}
if ('include' === desi.config.empty_body) {
entity.body = '';
}
else if ('skip' === desi.config.empty_body) {
return false;
}
else {
throw new Error('unrecognize option ' + desi.config.empty_frontmatter +
' for `config.yml.empty_body: include|skip`.');
}
}
return true;
//});
};
cores.root = function (desi, env, collection, entity) {
entity.yml = entity.yml || {};
entity.layout = entity.yml.layout || '__page__';
// _root is not subject to the same permalink rules as collections,
// so we just go ahead and define that here
entity.permalink = entity.yml.permalink || entity.path.replace(/\.\w+$/, '');
};
cores.normalize = function (desi, env, collection, entity) {
entity.title = entity.yml.title || Desi.firstCap(entity.name.replace(/\.\w+$/, ''));
entity.date = entity.yml.date;
if (!entity.date) {
// TODO tell YAML parser to keep the date a string
entity.date = new Date(entity.yml.created_at
|| entity.yml.time
|| entity.yml.updated_at
|| entity.createdDate
|| entity.lastModifiedDate
).toISOString();
}
if ('object' === typeof entity.date) {
entity.date = entity.date.toISOString();
}
entity.updated_at = entity.yml.updated_at || entity.lastModifiedDate;
entity.published_at = Desi.fromLocaleDate(entity.date || entity.lastModifiedDate);
entity.year = entity.published_at.year;
entity.month = entity.published_at.month;
entity.day = entity.published_at.day;
entity.hour = entity.published_at.hour;
entity.twelve_hour = entity.published_at.twelve_hour;
entity.meridian = entity.published_at.meridian;
entity.minute = entity.published_at.minute;
// let's just agree that that's too far
//entity.second = entity.published_at.second;
entity.slug = Desi.slugify(entity.title);
entity.slug_path = Desi.slugifyPath(entity.relativePath);
entity.slugPath = Desi.slugifyPath(entity.relativePath);
// categories
if (Array.isArray(entity.yml.categories)) {
entity.categories = entity.yml.categories;
}
else if ('string' === typeof entity.yml.categories) {
entity.categories = [entity.yml.categories];
}
else if ('string' === typeof entity.yml.category) {
entity.categories = [entity.yml.category];
}
else {
entity.categories = [];
}
// tags
if (Array.isArray(entity.yml.tags)) {
entity.tags = entity.yml.tags;
}
else if ('string' === typeof entity.yml.tags) {
entity.tags = [entity.yml.tags];
}
else {
entity.tags = [];
}
entity.permalink = entity.permalink || entity.yml.permalink;
if (!entity.permalink) {
// try the fallback_permalink first (because we're looking at files that don't have yml)
// then try the normal permalink (because :filename -> :title and whatnot, so it'll work)
Desi.permalinkify(desi, collection.fallback_permalink || collection.permalink, entity);
}
/*
if (!/\.x?html?$/.test(entity.permalink)) {
entity.htmllink = path.join(entity.permalink, 'index.html');
}
*/
// The root index is the one exception
if (/^(index)?\/?index(\.x?html?)?$/.test(entity.permalink)) {
entity.permalink = '';
}
// relative to the site
entity.relative_file = path.join(env.base_path, entity.permalink)
.replace(/\/$/, '/index.html');
entity.relative_href = path.join(env.base_path, entity.permalink)
.replace(/\/index\.html$/, '/');
entity.url = env.base_url + path.join(env.base_path, entity.permalink)
.replace(/\/index\.html$/, '/');
entity.canonical_url = env.base_url + path.join(env.base_path, entity.permalink)
.replace(/\/index\.html$/, '/');
entity.production_url = desi.site.base_url + path.join(desi.site.base_path, entity.permalink)
.replace(/\/index\.html$/, '/');
entity.relative_url = path.join(env.base_path, entity.permalink)
.replace(/\/index\.html$/, '/');
if (env.explicitIndexes || env.explicitIndices || env.explicit_indexes || env.explicit_indices) {
// NOTE: file_url is NOT replaced
['url', 'canonical_url', 'production_url', 'relative_url'].forEach(function (url) {
entity[url] = entity[url].replace(/\/$/, '/index.html');
});
}
};
cores.disqus = function (desi, env, collection, entity) {
var yml = entity.yml
;
if (yml.uuid) {
entity.disqus_identifier = yml.uuid;
}
entity.disqus_url = entity.production_url;
};
exports.DesiraeTransformCore = cores.DesiraeTransformCore = cores;
}('undefined' !== typeof exports && exports || window));

95
tests/permalink.js

@ -37,101 +37,6 @@ function pad(str, n) {
return str;
}
permalinkTransforms = {
year: function (entity) {
return entity.year;
}
, month: function (entity) {
return pad(entity.month, 2);
}
, day: function (entity) {
return pad(entity.day, 2);
}
, path: function (entity) {
return entity.relativePath
.toLowerCase()
.replace(/^\//, '')
;
}
, relative_path: function (entity) {
// TODO slug the path in desirae proper?
// TODO remove collection from start of path instead
// of blindly assuming one directory at start of path
// entity.collection.name
return entity.relativePath
.toLowerCase()
.replace(/^\/?[^\/]+\//, '')
;
}
, filename: function (entity) {
// don't put .html
return entity.name
.toLowerCase()
.replace(/\.\w+$/, '')
;
}
, slug: function (entity) {
// alias of title
return entity.slug;
}
, title: function (entity) {
return entity.slug;
}
, name: function (entity) {
// alias of title
return entity.slug;
}
, collection: function (entity) {
// TODO implement in desirae
return entity.collection && entity.collection.name
|| entity.collectionname
|| entity.collection
|| ''
;
}
, categories: function (entity) {
return (entity.yml.categories||[])[0]||'';
}
, i_month: function (entity) {
return parseInt(entity.month, 10) || 0;
}
, i_day: function (entity) {
return parseInt(entity.day, 10) || 0;
}
};
function permalinker(purl, entity) {
var parts = purl.split('/')
;
parts.forEach(function (part, i) {
var re = /:(\w+)/g
, m
// needs to be a copy, not a reference
, opart = part.toString()
;
/* jshint -W084 */
while (null !== (m = re.exec(opart))) {
if (permalinkTransforms[m[1]]) {
part = part.replace(':' + m[1], permalinkTransforms[m[1]](entity));
}
}
/* jshint +W084 */
parts[i] = part || '';
});
parts.unshift('/');
purl = path.join.apply(null, parts);
if (!/(\/|\.html?)$/.test(purl)) {
// we just default to a slash if you were ambiguous
purl += '/';
}
return purl;
}
// https://www.youtube.com/watch?v=1NryFD9_hR0&list=RDOeLUK4a6Ojc&index=2
cases = {
"/:title.html" : "/my-title.html"

Loading…
Cancel
Save