drizzle-builder
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -7,27 +7,16 @@ 'use strict'; | ||
var _handlebars = require('handlebars'); | ||
var _deepmerge = require('deepmerge'); | ||
var Handlebars = _interopRequireDefault(_handlebars).default; | ||
var merge = _interopRequireDefault(_deepmerge).default; | ||
var _utils = require('./utils'); | ||
var _defaults = require('./defaults'); | ||
var merge = _utils.merge; | ||
var defaults = _interopRequireDefault(_defaults).default; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var defaults = { | ||
templates: { | ||
handlebars: Handlebars, | ||
helpers: {}, | ||
layouts: ['src/layouts/*'], | ||
pages: ['src/pages/**/*'], | ||
partials: ['src/partials/**/*'] | ||
} | ||
}; | ||
/** | ||
* Merge defaults into options. | ||
* @return {object} merged options | ||
* Merge defaults into passed options | ||
*/ | ||
function mergeDefaults() { | ||
function parseOptions() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
@@ -38,49 +27,3 @@ | ||
/** | ||
* Map old options object shape onto new shape | ||
* so that we can provide backwards-compatibility with fabricator | ||
* The returned options {object} is of the correct shape to have | ||
* defaults merged into it. | ||
* | ||
* @TODO Eventually, support for fabricator/deprecated things should be | ||
* moved into their own module | ||
* @return {object} User options | ||
*/ | ||
function translateOptions() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
/* eslint-disable prefer-const */ | ||
var handlebars = options.handlebars; | ||
var helpers = options.helpers; | ||
var layouts = options.layouts; | ||
var pages = options.views; | ||
var partials = options.layoutIncludes; | ||
var result = { | ||
templates: { | ||
handlebars: handlebars, | ||
helpers: helpers, | ||
layouts: layouts, | ||
pages: pages, | ||
partials: partials | ||
} | ||
}; | ||
return result; | ||
/* eslint-enable prefer-const */ | ||
} | ||
var parseOptions = function parseOptions(options) { | ||
return mergeDefaults(translateOptions(options)); | ||
}; | ||
/** | ||
* Sigh... | ||
* > Single exports and multiple exports are mutually exclusive. You have to use | ||
* > either one the two styles. Some modules combine both styles as follows: | ||
* http://www.2ality.com/2015/12/babel-commonjs.html | ||
*/ | ||
parseOptions.translator = translateOptions; | ||
exports.default = parseOptions; | ||
module.exports = exports['default']; |
@@ -7,14 +7,10 @@ 'use strict'; | ||
var _parse = require('../utils/parse'); | ||
var _utils = require('../utils'); | ||
var readFileTree = _parse.readFileTree; | ||
var utils = _interopRequireWildcard(_utils); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
/** | ||
* Parse layout files. | ||
* @param {Object} options | ||
* @return {Promise} resolving to layout data | ||
*/ | ||
function parseLayouts(options) { | ||
return readFileTree(options.src.layouts, options); | ||
return utils.readFilesKeyed(options.src.layouts, options); | ||
} | ||
@@ -21,0 +17,0 @@ |
@@ -37,3 +37,3 @@ 'use strict'; | ||
var alreadyWrapped = new RegExp('{{\\s*#extend\\s*[\'"]' + layout + '[\'"].*}}').test(page.contents); | ||
var wrapped = alreadyWrapped ? page.contents : ' {{#extend \'' + layout + '\' }}\n {{#content \'body\'}}' + page.contents + '{{/content}}\n {{/extend}}'; | ||
var wrapped = alreadyWrapped ? page.contents : ' {{#extend \'' + layout + '\' }}\n {{#content \'main\'}}' + page.contents + '{{/content}}\n {{/extend}}'; | ||
return wrapped; | ||
@@ -40,0 +40,0 @@ } |
@@ -89,5 +89,4 @@ 'use strict'; | ||
function prepareTemplates(opts) { | ||
var templateOpts = opts.templates; | ||
return Promise.all([prepareHelpers(templateOpts.handlebars, templateOpts.helpers), preparePartials(templateOpts.handlebars, templateOpts.partials)]).then(function (handlebarsInfo) { | ||
return templateOpts.handlebars; | ||
return Promise.all([prepareHelpers(opts.handlebars, opts.helpers), preparePartials(opts.handlebars, opts.partials)]).then(function (handlebarsInfo) { | ||
return opts.handlebars; | ||
}); | ||
@@ -94,0 +93,0 @@ } |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.titleCase = exports.readFilesKeyed = exports.readFiles = exports.parentDirname = exports.merge = exports.keyname = exports.isGlob = exports.getFiles = exports.dirname = undefined; | ||
exports.titleCase = exports.resourceKey = exports.resourceId = exports.relativePathArray = exports.readFilesKeyed = exports.readFiles = exports.parentDirname = exports.matchParser = exports.localDirname = exports.keyname = exports.isGlob = exports.getFiles = exports.getDirs = exports.dirname = exports.deepObj = exports.commonRoot = undefined; | ||
@@ -30,19 +30,129 @@ var _globby = require('globby'); | ||
/* Helper functions */ | ||
var basename = function basename(filepath) { | ||
/** | ||
* Return extension-less basename of filepath | ||
* @param {String} filepath | ||
* @example basename('foo/bar/baz.txt'); // -> 'baz' | ||
*/ | ||
function basename(filepath) { | ||
return path.basename(filepath, path.extname(filepath)); | ||
}; | ||
var dirname = function dirname(filepath) { | ||
} | ||
/** | ||
* Return normalized (no '..', '.') full dirname of filepath | ||
* @param {String} filepath | ||
* @example dirname('../ding/foo.txt'); // -> '/Users/shiela/ding/' | ||
*/ | ||
function dirname(filepath) { | ||
return path.normalize(path.dirname(filepath)); | ||
}; | ||
var parentDirname = function parentDirname(filepath) { | ||
} | ||
/** | ||
* Return the name of this file's directory's immediate parent directory | ||
* @param {String} filepath | ||
* @example basename('foo/bar/baz.txt'); // -> 'bar' | ||
*/ | ||
function localDirname(filepath) { | ||
return dirname(filepath).split(path.sep).pop(); | ||
}; | ||
var removeNumbers = function removeNumbers(str) { | ||
} | ||
/** | ||
* Return the name of this file's directory's immediate parent directory | ||
* @param {String} filepath | ||
* @example basename('foo/bar/baz.txt'); // -> 'foo' | ||
*/ | ||
function parentDirname(filepath) { | ||
return dirname(filepath).split(path.sep).slice(-2, -1)[0]; | ||
} | ||
/** | ||
* TODO: see https://github.com/cloudfour/drizzle-builder/issues/8 | ||
*/ | ||
function removeLeadingNumbers(str) { | ||
return str.replace(/^[0-9|\.\-]+/, ''); | ||
}; | ||
var getFiles = function getFiles(glob) { | ||
return globby(glob, { nodir: true }); | ||
}; | ||
} | ||
/** | ||
* Given an array of file objects, take all of their paths and find | ||
* what the common root directory is for all of them. | ||
* @example commonRoot([ | ||
* 'foo/bar/baz/ding/dong.html', | ||
* 'foo/bar/baz/huff/dumb.txt', | ||
* 'foo/bar/baz/oleo.html', | ||
* 'foo/bar/baz/one/two.html']); // -> 'foo/bar/baz/' | ||
* | ||
* @param {Array} files File objects. Each should have a `path` property | ||
* @return {String} Common root path | ||
*/ | ||
function commonRoot(files) { | ||
var paths = files.map(function (file) { | ||
return file.path; | ||
}); | ||
var relativePath = paths.reduce(function (prev, curr) { | ||
prev = prev.split(path.sep); | ||
curr = curr.split(path.sep); | ||
prev = prev.filter(function (prevBit) { | ||
return curr.some(function (currBit) { | ||
return prevBit === currBit; | ||
}); | ||
}); | ||
return prev.join(path.sep); | ||
}); | ||
return relativePath; | ||
} | ||
/** | ||
* Return (creating if necessary) a deep reference to a nested object | ||
* based on path elements. This will mutate `obj` by adding needed properties | ||
* to it. Think of it like mkdir with a multi-directory path that will create | ||
* directory entries if they don't exist. | ||
* | ||
* @param {Array} pathKeys Elements making up the "path" to the reference | ||
* @param {Object} Object to add needed references to | ||
* | ||
* @example deepRef(['foo', 'bar', 'baz'], { foo: {} }); // => foo.bar.baz | ||
*/ | ||
function deepObj(pathKeys, obj) { | ||
return pathKeys.reduce(function (prev, curr) { | ||
prev[curr] = prev[curr] || {}; | ||
return prev[curr]; | ||
}, obj); | ||
} | ||
/** | ||
* Take a given glob and convert it to a glob that will match directories | ||
* (instead of files). Return Promise that resolves to matching dirs. | ||
* | ||
* @example getDirs('foo/bar/baz') | ||
* | ||
* @param {glob} glob to convert to directory glob | ||
* @param {Object} options to pass on to getFiles/globby | ||
* @return {Promise} resolving to glob matches | ||
*/ | ||
function getDirs(glob) { | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var opts = Object.assign({ | ||
nodir: false | ||
}, options); | ||
var dirGlob = typeof glob === 'string' ? Array.of(glob) : glob; | ||
return getFiles(dirGlob.map(function (dirEntry) { | ||
return path.dirname(dirEntry) + '/*/'; | ||
}), opts); | ||
} | ||
/** | ||
* @param {glob} glob | ||
* @return {Promise} resolving to {Array} of files matching glob | ||
*/ | ||
function getFiles(glob) { | ||
var globOpts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var opts = Object.assign({ | ||
nodir: true | ||
}, globOpts); | ||
return globby(glob, opts); | ||
} | ||
/** | ||
* Utility function to test if a value COULD be a glob. A single string or | ||
@@ -68,15 +178,85 @@ * an Array of strings counts. Just because this returns true, however, | ||
/** | ||
* Take a glob; read the files. Return a Promise that ultimately resolves | ||
* to an Array of objects: | ||
* [{ path: original filepath, | ||
* contents: utf-8 file contents}...] | ||
* Utility function to provide a consistent "key" for elements, materials, | ||
* partials, etc, based on a filepath: | ||
* - replace whitespace characters with `-` | ||
* - use only the basename, no extension | ||
* - unless stripNumbers option false, remove numbers from the string as well | ||
* | ||
* @param {String} str filepath | ||
* @param {Object} options | ||
* @return {String} | ||
*/ | ||
function keyname(str) { | ||
var _ref = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var _ref$stripNumbers = _ref.stripNumbers; | ||
var stripNumbers = _ref$stripNumbers === undefined ? true : _ref$stripNumbers; | ||
var name = basename(str).replace(/\s/g, '-'); | ||
return stripNumbers ? removeLeadingNumbers(name) : name; | ||
} | ||
/** | ||
* Retrieve the correct parsing function for a file based on its | ||
* path. Each parser with a `pattern` property will compile that pattern | ||
* to a RegExp and test it against the filepath. If no match is found | ||
* against any of the parsers by path pattern, a default parser will be | ||
* returned: either a parser keyed by `default` in the `parsers` object | ||
* or, lacking that, a default function that leaves the contents of the | ||
* file untouched. | ||
* | ||
* @param {String} filepath | ||
* @param {Object} parsers | ||
* @see options module | ||
* @return {Function} applicable parsing function for file contents | ||
*/ | ||
function matchParser(filepath) { | ||
var parsers = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
for (var parserKey in parsers) { | ||
if (parsers[parserKey].pattern) { | ||
if (new RegExp(parsers[parserKey].pattern).test(filepath)) { | ||
return parsers[parserKey].parseFn; | ||
} | ||
} | ||
} | ||
return parsers.default && parsers.default.parseFn || function (contents, filepath) { | ||
return { contents: contents }; | ||
}; | ||
} | ||
/** | ||
* Take a glob; read the files, optionally running a `contentFn` over | ||
* the contents of the file. | ||
* | ||
* @param {glob} glob of files to read | ||
* @param {Object} Options: | ||
* - {Object} available parsers | ||
* - {String} encoding | ||
* - {Object} globOpts gets passed to getFiles | ||
* @return {Promise} resolving to Array of Objects: | ||
* - {String} path | ||
* - {String || Mixed} contents: contents of file after contentFn | ||
*/ | ||
function readFiles(glob) { | ||
return getFiles(glob).then(function (paths) { | ||
var fileReadPromises = paths.map(function (path) { | ||
return readFile(path, 'utf-8').then(function (contents) { | ||
return { path: path, contents: contents }; | ||
var _ref2 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var _ref2$parsers = _ref2.parsers; | ||
var parsers = _ref2$parsers === undefined ? {} : _ref2$parsers; | ||
var _ref2$encoding = _ref2.encoding; | ||
var encoding = _ref2$encoding === undefined ? 'utf-8' : _ref2$encoding; | ||
var _ref2$globOpts = _ref2.globOpts; | ||
var globOpts = _ref2$globOpts === undefined ? {} : _ref2$globOpts; | ||
return getFiles(glob, globOpts).then(function (paths) { | ||
return Promise.all(paths.map(function (filepath) { | ||
return readFile(filepath, encoding).then(function (fileData) { | ||
var parser = matchParser(filepath, parsers); | ||
fileData = parser(fileData, filepath); | ||
if (typeof fileData === 'string') { | ||
fileData = { contents: fileData }; | ||
} | ||
return Object.assign(fileData, { path: filepath }); | ||
}); | ||
}); | ||
return Promise.all(fileReadPromises); | ||
})); | ||
}); | ||
@@ -89,9 +269,20 @@ } | ||
* single object; each file's contents is keyed by its filename run | ||
* through keyname(). | ||
* through optional `keyFn(filePath, options)`` (default: keyname). | ||
* Will pass other options on to readFiles and keyFn | ||
* | ||
* @param {glob} | ||
* @param {Object} options (all optional): | ||
* - keyFn | ||
* - contentFn | ||
* - stripNumbers | ||
* @return {Promise} resolving to {Object} of keyed file contents | ||
*/ | ||
function readFilesKeyed(glob) { | ||
var preserveNumbers = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var _options$keyFn = options.keyFn; | ||
var keyFn = _options$keyFn === undefined ? function (path, options) { | ||
return keyname(path, options); | ||
} : _options$keyFn; | ||
return readFiles(glob).then(function (allFileData) { | ||
return readFiles(glob, options).then(function (allFileData) { | ||
var keyedFileData = new Object(); | ||
@@ -106,3 +297,3 @@ var _iteratorNormalCompletion = true; | ||
keyedFileData[keyname(aFile.path, preserveNumbers)] = aFile.contents; | ||
keyedFileData[keyFn(aFile.path, options)] = aFile; | ||
} | ||
@@ -129,20 +320,50 @@ } catch (err) { | ||
/** | ||
* Utility function to provide a consistent "key" for elements, materials, | ||
* partials, etc, based on a filepath: | ||
* - replace whitespace characters with `-` | ||
* - use only the basename, no extension | ||
* - unless preserveNumbers, remove numbers from the string as well | ||
* Given a file's path and a string representing a directory name, | ||
* return an Array that only contains directories at or beneath that | ||
* directory. | ||
* | ||
* @param {String} str filepath | ||
* @param {Boolean} preserveNumbers | ||
* @return {String} | ||
* @example relativePathArray('/foo/bar/baz/ding/dong/tink.txt', 'baz') | ||
* // -> ['baz', 'ding', 'dong'] | ||
* @param {String} filePath | ||
* @param {String} fromPath | ||
* @return {Array} | ||
*/ | ||
function keyname(str) { | ||
var preserveNumbers = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; | ||
function relativePathArray(filePath, fromPath) { | ||
var keys = path.relative(fromPath, path.dirname(filePath)); | ||
if (keys && keys.length) { | ||
return keys.split(path.sep); | ||
} | ||
return []; | ||
} | ||
var name = basename(str).replace(/\s/g, '-'); | ||
return preserveNumbers ? name : removeNumbers(name); | ||
/** | ||
* Generate a resourceId for a file. Use file.path and base the | ||
* ID elements on the path elements between relativeRoot and file. Path | ||
* elements will have special characters removed. | ||
* @example resourceId( | ||
* '/foo/bar/baz/ole/01-fun-times.hbs', '/foo/bar/baz/', 'patterns' | ||
* ); // -> patterns.ole.fun-times | ||
* @param {Object} Object representing file. Needs to have a `path` property | ||
* @param {String} || {Array} relativeRoot path to relative root or path | ||
* elements to same in Array | ||
* @param {String} resourceCollection Will be prepended as first element in ID | ||
* @return {String} ID for this resource | ||
*/ | ||
function resourceId(resourceFile, relativeRoot, resourceCollection) { | ||
var pathKeys = relativePathArray(resourceFile.path, relativeRoot).map(keyname); | ||
return [resourceCollection].concat(pathKeys).concat([keyname(resourceFile.path)]).join('.'); | ||
} | ||
/** | ||
* Convenience function to create proper variant of file's basename for | ||
* use as a key in a data object. | ||
* @example resourceKey({ path: '/foo/bar/baz/04-fun' }); // -> '04-fun' | ||
* @param {Object} resourceFile Object representing a file. Needs `path` prop | ||
* @return {String} | ||
*/ | ||
function resourceKey(resourceFile) { | ||
return keyname(resourceFile.path, { stripNumbers: false }); | ||
} | ||
/** | ||
* Convert str to title case (every word will be capitalized) | ||
@@ -158,30 +379,17 @@ * @param {String} str | ||
/** | ||
* Perform a deep merge of two objects. | ||
* @param {Object} target | ||
* @param {Object} source | ||
* @return {Object} | ||
* @example merge(defaults, options); | ||
*/ | ||
function merge(target, source) { | ||
Object.keys(source).forEach(function (key) { | ||
if (Object.isExtensible(source[key])) { | ||
merge(target[key], source[key]); | ||
} else { | ||
if (typeof source[key] !== 'undefined') { | ||
target[key] = source[key]; | ||
} | ||
} | ||
}); | ||
return target; | ||
} | ||
exports.commonRoot = commonRoot; | ||
exports.deepObj = deepObj; | ||
exports.dirname = dirname; | ||
exports.getDirs = getDirs; | ||
exports.getFiles = getFiles; | ||
exports.isGlob = isGlob; | ||
exports.keyname = keyname; | ||
exports.merge = merge; | ||
exports.localDirname = localDirname; | ||
exports.matchParser = matchParser; | ||
exports.parentDirname = parentDirname; | ||
exports.readFiles = readFiles; | ||
exports.readFilesKeyed = readFilesKeyed; | ||
exports.relativePathArray = relativePathArray; | ||
exports.resourceId = resourceId; | ||
exports.resourceKey = resourceKey; | ||
exports.titleCase = titleCase; |
{ | ||
"name": "drizzle-builder", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "The builder for Drizzle", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
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
109668
45
2655
7