Comparing version 0.8.2 to 0.9.0
#!/usr/bin/env node | ||
var blake = require('../index.js') | ||
var blake = require('../index') | ||
, cop = require('cop') | ||
, getReader = require('../lib/getReader.js') | ||
, copy = require('../lib/copy.js') | ||
, files = require('../lib/read').fstream | ||
, copy = require('../lib/copy') | ||
, join = require('path').join | ||
@@ -20,10 +20,2 @@ | ||
function bake () { | ||
getReader(source, arg) | ||
.pipe(cop('path')) | ||
.pipe(blake(source, target)) | ||
.pipe(cop(function (filename) { return filename + '\n' })) | ||
.pipe(process.stdout) | ||
} | ||
if (!arg.length) { | ||
@@ -37,3 +29,15 @@ copy(join(source, 'resources'), target) | ||
} | ||
function bake () { | ||
files(source, arg) | ||
.pipe(cop('path')) | ||
.pipe(blake(source, target)) | ||
.pipe(cop(format)) | ||
.pipe(process.stdout) | ||
} | ||
})() | ||
function format (str) { | ||
return str += '\n' | ||
} | ||
42
index.js
@@ -6,23 +6,24 @@ | ||
, fs = require('fs') | ||
, write = require('./lib/write.js') | ||
, reader = require('./lib/read.js') | ||
, getProps = require('./lib/getProps.js') | ||
, mkdirp = require('mkdirp') | ||
, dirname = require('path').dirname | ||
, writeFile = require('fs').writeFile | ||
, StringDecoder = require('string_decoder').StringDecoder | ||
, read = require('./lib/read.js').readItems | ||
, getConf = require('./lib/read.js').conf | ||
module.exports = function (s, target) { | ||
var props = s && target ? getProps(s, target) : s | ||
var conf = s && target ? getConf(s, target) : s | ||
, decoder = new StringDecoder('utf8') | ||
, stream = new Transform({ objectMode:true }) | ||
var stream = new Transform({ objectMode:true }) | ||
, read = reader(props).read | ||
stream._transform = function (chunk, encoding, cb) { | ||
var filename = chunk.toString() | ||
read(filename, function (err, item) { | ||
process(item, function (err) { | ||
var filename = decoder.write(chunk) | ||
read(conf)(filename, function (er, item) { | ||
bake(item, function (er) { | ||
stream.push(item.path) | ||
cb(err) | ||
cb(er) | ||
}) | ||
}) | ||
} | ||
function process (item, cb) { | ||
function bake (item, cb) { | ||
if (!item.bake) { | ||
@@ -32,6 +33,6 @@ cb(new Error('Undefined bake function for ' + item.name)) | ||
} | ||
item.read = read | ||
item.bake(item, function (err, result) { | ||
if (err) { | ||
stream.emit('error', err) | ||
item.read = read(conf) | ||
item.bake(item, function (er, result) { | ||
if (er) { | ||
stream.emit('error', er) | ||
return | ||
@@ -42,4 +43,9 @@ } | ||
} | ||
return stream | ||
} | ||
function write (path, data, callback) { | ||
mkdirp(dirname(path), function (err, made) { | ||
writeFile(path, data, callback) | ||
}) | ||
} |
176
lib/read.js
// read - transform read files to blake items | ||
// read - read all the things | ||
var getItem = require('./getItem.js') | ||
module.exports.readItems = readItems | ||
module.exports.fstream = fstream | ||
module.exports.conf = conf | ||
var item = require('./item').item | ||
, util = require('util') | ||
, fs = require('fs') | ||
, fstream = require('fstream') | ||
, join = require('path').join | ||
, Writable = require('stream').Writable | ||
, StringDecoder = require('string_decoder').StringDecoder | ||
, createHash = require('crypto').createHash | ||
, Reader = require('fstream').Reader | ||
, resolve = require('path').resolve | ||
, readArray = require('event-stream').readArray | ||
, LRU = require("lru-cache") | ||
, cache = LRU({ max: 50, maxAge: 1000 * 60 * 3 }) | ||
, StringDecoder = require('string_decoder').StringDecoder | ||
, decoder = new StringDecoder('utf8') | ||
var me = null | ||
function fstream (source, filenames) { | ||
var reader | ||
if (filenames.length) { | ||
var items = [] | ||
filenames.forEach(function (filename) { | ||
items.push({ path:filename }) | ||
}) | ||
reader = readArray(items) | ||
} else { | ||
reader = new Reader({ path:resolve(source, 'data') }) | ||
} | ||
return reader | ||
} | ||
module.exports = function (props) { | ||
if (me) return me | ||
function Paths (resources, data, templates, posts, target) { | ||
this.resources = resources | ||
this.data = data | ||
this.templates = templates | ||
this.posts = posts | ||
this.target = target | ||
} | ||
me = Object.create(null) | ||
me.read = function (path, cb) { | ||
if (!path) { | ||
cb(new Error('No Path')) | ||
return | ||
} | ||
fs.stat(path, function (er, stats) { | ||
if (stats.isDirectory()) { | ||
readDirectory(path, cb) | ||
} else { | ||
readFile(path, cb) | ||
} | ||
}) | ||
var pathz = null | ||
function paths (source, target, config) { | ||
if (pathz) return pathz | ||
source = source || '/' | ||
target = target || '/' | ||
var p = config.paths | ||
, resources = p.resources ? join(source, p.resources) : null | ||
, data = p.data ? join(source, p.data) : null | ||
, templates = p.templates ? join(source, p.templates) : null | ||
, posts = p.posts ? join(source, p.posts) : null | ||
pathz = new Paths(resources, data, templates, posts, target) | ||
return pathz | ||
} | ||
function conf (source, target) { | ||
var uc = require(join(source, 'config.js')) | ||
var res = Object.create(null) | ||
res.paths = paths(source, target, uc) | ||
res.templates = templates(res.paths.templates) | ||
res.views = uc.views | ||
return res | ||
} | ||
var templatez = null | ||
function templates (path) { | ||
if (templatez) return templatez | ||
templatez = Object.create(null) | ||
fs.readdirSync(path).forEach(function (name) { | ||
templatez[name] = fs.readFileSync(resolve(path, name)) | ||
}) | ||
return templatez | ||
} | ||
function readItems (props) { | ||
var reader = new ItemReader(props) | ||
return function (path, cb) { | ||
reader.read(path, cb) | ||
} | ||
} | ||
var cache = LRU({ max: 50, maxAge: 1000 * 60 * 3 }) | ||
var decoder = new StringDecoder('utf8') | ||
function readFile (filename, cb) { | ||
var key = createHash('md5').update(filename).digest('hex') | ||
if ((cached = cache.get(key))) { | ||
cb(null, cached) | ||
return | ||
function ItemReader (props) { | ||
if (!(this instanceof ItemReader)) return new ItemReader(props) | ||
this.props = props | ||
} | ||
ItemReader.prototype.read = function (path, cb) { | ||
if (!path) { | ||
cb(new Error('No Path')) | ||
return | ||
} | ||
var me = this | ||
fs.stat(path, function (er, stats) { | ||
if (stats.isDirectory()) { | ||
me.readDirectory(path, cb) | ||
} else { | ||
me.readFile(path, cb) | ||
} | ||
fs.readFile(filename, function (er, data) { | ||
var item = getItem(props, filename, decoder.write(data)) | ||
cache.set(key, item) | ||
return cb(er, item) | ||
}) | ||
}) | ||
} | ||
ItemReader.prototype.readFile = function (filename, cb) { | ||
var key = createHash('md5').update(filename).digest('hex') | ||
if ((cached = cache.get(key))) { | ||
cb(null, cached) | ||
return | ||
} | ||
me = this | ||
fs.readFile(filename, function (er, data) { | ||
var it = item(me.props, filename, decode(data)) | ||
cache.set(key, it) | ||
return cb(er, it) | ||
}) | ||
} | ||
function readDirectory(path, cb) { | ||
var reader = fstream.Reader({ path: path }) | ||
stream = new Writable() // pseudo | ||
, items = [] | ||
ItemReader.prototype.readDirectory = function (path, cb) { | ||
var reader = Reader({ path: path }) | ||
, stream = new Writable() // pseudo | ||
, items = [] | ||
, me = this | ||
stream.add = function (entry) { | ||
if (entry.type === 'Directory') { | ||
entry.on('entry', stream.add) | ||
return true | ||
} | ||
readFile(entry.path, function (er, item) { | ||
items.push(item) | ||
reader.resume() | ||
}) | ||
return false | ||
stream.add = function (entry) { | ||
if (entry.type === 'Directory') { | ||
entry.on('entry', stream.add) | ||
return true | ||
} | ||
stream.end = function () { | ||
cb(null, items) | ||
} | ||
reader.pipe(stream) | ||
me.readFile(entry.path, function (er, item) { | ||
items.push(item) | ||
entry.depth === 1 ? stream.end() : reader.resume() | ||
}) | ||
return false | ||
} | ||
stream.end = function () { | ||
cb(null, items) | ||
} | ||
reader.pipe(stream) | ||
} | ||
return me | ||
function decode (data) { | ||
return decoder.write(data) | ||
} |
{ | ||
"name": "blake", | ||
"version": "0.8.2", | ||
"version": "0.9.0", | ||
"description": "Simple, blog aware infrastructure to generate static sites", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -14,3 +14,3 @@ # blake - generate site | ||
``` | ||
In the first synopsis form, `blake` writes all files generated from input data in the `source_directory` to the `target_directory`. In the second synopsis form, output is generated from the specified source files only. | ||
In the first form, `blake` writes all files generated from input data in the `source_directory` to the `target_directory`. In the second synopsis form, output is generated from the specified source files only. | ||
@@ -133,3 +133,3 @@ ## Library Usage | ||
At the top of each input file blake expects a JSON string that is interpreted as header providing transformation parameters. Besides it can contain additional user defined data—the `item` parameter, passed to the view functions, provides a reference to the raw header. Input data for a blog entry could look like so: | ||
```js | ||
``` | ||
{ | ||
@@ -142,3 +142,5 @@ "title": "Example", | ||
Your highness, when I said that you are like a stream of bat's piss, I only mean that you shine out like a shaft of gold when all around it is dark. | ||
Your highness, when I said that you are like a stream of bat's piss, | ||
I only mean that you shine out like a shaft of gold when all around | ||
it is dark. | ||
``` | ||
@@ -145,0 +147,0 @@ The end of the header is marked by an empty line. Everything that follows is interpreted as content and is passed to the views untouched. |
@@ -5,7 +5,7 @@ | ||
var path = require('path') | ||
, getProps = require('../lib/getProps.js') | ||
, conf = require('../lib/read').conf | ||
exports.source = path.resolve('../example/blake-site') | ||
exports.target = '/tmp/blake-' + Math.floor(Math.random() * (1<<24)) | ||
exports.props = getProps(exports.source, exports.target) | ||
exports.props = conf(exports.source, exports.target) | ||
var test = require('tap').test | ||
, path = require('path') | ||
, reader = require('../lib/read.js') | ||
, config = require('./config.js') | ||
, props = config.props | ||
, read = reader(props).read | ||
, read = require('../lib/read').readItems | ||
, config = require('./config') | ||
, props = config.props | ||
test('read file', function (t) { | ||
read(path.join(props.paths.data, 'index.md'), function (err, item) { | ||
var file = path.join(props.paths.data, 'index.md') | ||
read(props)(file, function (err, item) { | ||
t.ok(item.header, 'should have header') | ||
@@ -17,5 +17,3 @@ t.ok(item.body, 'should have body') | ||
test('read directory', function (t) { | ||
t.end() | ||
read(props.paths.data, function (err, items) { | ||
read(props)(props.paths.data, function (err, items) { | ||
items.forEach(function (item) { | ||
@@ -22,0 +20,0 @@ t.ok(item.header, 'should have header') |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30576
560
254
11
25