Skip to content

Commit

Permalink
Migrate to individual lodash dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
dvonlehman committed Apr 15, 2016
1 parent 27188ae commit 0e8a0d1
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 35 deletions.
4 changes: 2 additions & 2 deletions index.js
@@ -1,11 +1,11 @@
var through2 = require('through2');
var _ = require('lodash');
var defaults = require('lodash.defaults');
var StringDecoder = require('string_decoder').StringDecoder;
var debug = require('debug')('htmlprep');
var Parser = require('./lib/parser');

exports = module.exports = function(options) {
options = _.defaults(options, {
options = defaults(options, {
attrPrefix: null,
buildType: 'debug',
liveReload: false, // Should livereload script be injected
Expand Down
40 changes: 26 additions & 14 deletions lib/attribute-modifier.js
@@ -1,4 +1,11 @@
var _ = require('lodash');
var defaults = require('lodash.defaults');
var trimStart = require('lodash.trimstart');
var trimEnd = require('lodash.trimend');
var includes = require('lodash.includes');
var isEmpty = require('lodash.isempty');
var isString = require('lodash.isstring');
var toArray = require('lodash.toarray');
var has = require('lodash.has');
var minimatch = require('minimatch');

var absoluteUrlRe = /^http[s]?:\/\//i;
Expand All @@ -7,7 +14,12 @@ var linkRelAttributeUrlValues = ['alternate', 'help', 'license', 'next', 'prev',
var inlineCssUrlRe = /url\(["']?(.*?)["']?\)/;

module.exports = function(options) {
_.defaults(options, {noPathPrefixPatterns: []});
defaults(options, {noPathPrefixPatterns: []});

// Strip leading slashes from prefix patterns
options.noPathPrefixPatterns = options.noPathPrefixPatterns.map(function(pattern) {
return trimStart(pattern, '/');
});

var customAttribute = require('./custom-attribute')(options.attrPrefix);

Expand Down Expand Up @@ -40,26 +52,26 @@ module.exports = function(options) {

// If the tagName is not a standard src attribute tag, leave it alone.
// For example angular2 does this: <ng-include src="\'header.html\'"></ng-include>
if (srcAttr === 'src' && !_.includes(validSrcAttributeTags, tagName)) {
if (srcAttr === 'src' && !includes(validSrcAttributeTags, tagName)) {
return;
}

var attrValue = attribs[srcAttr];

// If the attribute is empty, nothing to do.
if (_.isEmpty(attrValue)) return;
if (isEmpty(attrValue)) return;

// If the assetPathPrefix option is specified and there is not a data-src-keep
// attribute, then prepend the assetPathPrefix. This is generally to repoint
// static assets to an absolute CDN url.
if (options.assetPathPrefix && !_.has(attribs, customAttribute('src-keep'))) {
if (options.assetPathPrefix && !has(attribs, customAttribute('src-keep'))) {
attrValue = prependAssetPath(attrValue);
}

// If the fingerprint option is specified and the data-fingerprint custom attribute
// is declared on the tag, then append the fingerprint to the assetPath
var fingerprintAttr = customAttribute('fingerprint');
if (options.fingerprint && _.has(attribs, fingerprintAttr)) {
if (options.fingerprint && has(attribs, fingerprintAttr)) {
attrValue += (attrValue.indexOf('?') === -1 ? '?' : '&');
attrValue += options.fingerprintQuery + '=' + options.fingerprint;
attribs[fingerprintAttr] = null;
Expand All @@ -72,7 +84,7 @@ module.exports = function(options) {
// Don't prepend the asset path to any path that matches
// one of the noAssetPathPrefixes patterns.
for (var i = 0; i < options.noPathPrefixPatterns.length; i++) {
if (minimatch(assetPath, options.noPathPrefixPatterns[i])) {
if (minimatch(trimStart(assetPath, '/'), options.noPathPrefixPatterns[i])) {
return assetPath;
}
}
Expand All @@ -98,7 +110,7 @@ module.exports = function(options) {
assetPath = stripExtraLeadingSlash(assetPath);
if (assetPath.substr(0, 2) === '//') return assetPath;

if (assetPath[0] !== '/' && !_.isEmpty(options.pathFromRoot)) {
if (assetPath[0] !== '/' && !isEmpty(options.pathFromRoot)) {
return slashJoin(options.assetPathPrefix, options.pathFromRoot, assetPath);
}
return slashJoin(options.assetPathPrefix, assetPath);
Expand Down Expand Up @@ -141,7 +153,7 @@ module.exports = function(options) {
}

function replaceBaseUrlPlaceholder(attr) {
if (!_.isString(attr) || !options.baseUrlPlaceholder || !options.baseUrl) return attr;
if (!isString(attr) || !options.baseUrlPlaceholder || !options.baseUrl) return attr;
return attr.replace(options.baseUrlPlaceholder, options.baseUrl);
}

Expand All @@ -151,16 +163,16 @@ module.exports = function(options) {
}

function slashJoin() {
var items = _.toArray(arguments);
var items = toArray(arguments);
for (var i = 0; i < items.length; i++) {
// Trim off any leading slashes
if (i > 0) {
items[i] = _.trimStart(items[i], '/');
items[i] = trimStart(items[i], '/');
}

// If not the last item and the rightmost character is a slash
if (i < items.length - 1) {
items[i] = _.trimEnd(items[i], '/');
items[i] = trimEnd(items[i], '/');
}
}

Expand All @@ -169,14 +181,14 @@ module.exports = function(options) {

function isResourceLink(tagName, attribs) {
if (tagName !== 'link' || !attribs.href) return false;
if (!_.includes(linkRelAttributeUrlValues, attribs.rel)) return true;
if (!includes(linkRelAttributeUrlValues, attribs.rel)) return true;
return false;
}

// Determine if this tag has an href attribute that is a hyperlink to another URL.
function isHrefHyperlink(tagName, attribs) {
if (tagName === 'a' && attribs.href) return true;
if (tagName === 'link' && _.includes(linkRelAttributeUrlValues, attribs.rel)) return true;
if (tagName === 'link' && includes(linkRelAttributeUrlValues, attribs.rel)) return true;
return false;
}

Expand Down
35 changes: 20 additions & 15 deletions lib/parser.js
Expand Up @@ -2,7 +2,12 @@ var EventEmitter = require('events').EventEmitter;
var HtmlParser = require('../htmlparser2').Parser;
var debug = require('debug')('htmlprep');
var util = require('util');
var _ = require('lodash');
var includes = require('lodash.includes');
var isEmpty = require('lodash.isempty');
var isString = require('lodash.isstring');
var isNull = require('lodash.isnull');
var forEach = require('lodash.foreach');
var has = require('lodash.has');
var glob = require('glob');

var singletonTags = ['link', 'meta', 'param', 'source', 'area', 'base', 'br', 'col',
Expand Down Expand Up @@ -92,14 +97,14 @@ Parser.prototype.onOpenTag = function(tagName, attribs) {
debug('open %s', tagName);

// Trim all the attribs
_.each(attribs, function(value, key) {
forEach(attribs, function(value, key) {
attribs[key] = value.trim();
});

// Content variation block
if (this._removing !== true) {
// var contentVariation = attribs[customAttrs.contentVariation];
// if (_.isEmpty(contentVariation) === false) {
// if (isEmpty(contentVariation) === false) {
// if (context.tagMatch) throw new Error("Invalid nesting of content-variation element");

// context.variations[variation] = new VariationBuffer();
Expand All @@ -108,14 +113,14 @@ Parser.prototype.onOpenTag = function(tagName, attribs) {
// }

// var variationName = attribs[customAttrs.variation];
// if (_.isEmpty(variationName) === false) {
// if (isEmpty(variationName) === false) {
// if (this._tagMatch)
// throw new Error("Invalid nesting of variation element");

// if (options.variation && variationName !== options.variation) {
// // Check if we have content for this variation name.
// var substituteContent = context.contentVariations[variationName];
// if (_.isEmpty(substituteContent) === false) {
// if (isEmpty(substituteContent) === false) {
// // Write the substitute content.
// context.writeOutput(substituteContent);
// context.startTagMatch(name, true);
Expand All @@ -129,12 +134,12 @@ Parser.prototype.onOpenTag = function(tagName, attribs) {
// If there is a data-placeholder attribute, replace the tag
// with the new contents.
var placeholder = attribs[this._customAttribute('placeholder')];
if (_.isEmpty(placeholder) === false) {
if (isEmpty(placeholder) === false) {
attribs[this._customAttribute('placeholder')] = null;

this._output.push(buildTag(tagName, attribs));

if (_.isEmpty(this._options.inject[placeholder]) === false) {
if (isEmpty(this._options.inject[placeholder]) === false) {
debug('injecting block %s', placeholder);
this._output.push(this._options.inject[placeholder]);
}
Expand All @@ -153,13 +158,13 @@ Parser.prototype.onOpenTag = function(tagName, attribs) {
if (this._removing === true) return;

// If the data-strip attribute is present, remove this tag and everything within it.
if (_.has(attribs, this._customAttribute('strip'))) {
if (has(attribs, this._customAttribute('strip'))) {
this.startTagMatch(tagName, true);
return;
}

var buildType = attribs[this._customAttribute('build')];
if (_.isEmpty(buildType) === false) {
if (isEmpty(buildType) === false) {
this.startTagMatch(tagName, buildType !== this._options.buildType);

if (this._removing === true) return;
Expand Down Expand Up @@ -202,7 +207,7 @@ Parser.prototype.onOpenTag = function(tagName, attribs) {

this._attributeModifier(tagName, attribs);

this._output.push(buildTag(tagName, attribs, _.includes(singletonTags, tagName)));
this._output.push(buildTag(tagName, attribs, includes(singletonTags, tagName)));
};

Parser.prototype.onCloseTag = function(tagName) {
Expand All @@ -218,7 +223,7 @@ Parser.prototype.onCloseTag = function(tagName) {
if (removing === true) return;

// Don't close singleton tags
if (_.includes(singletonTags, tagName)) return;
if (includes(singletonTags, tagName)) return;

// Special blocks appended to the head
if (tagName === 'head') {
Expand Down Expand Up @@ -267,7 +272,7 @@ Parser.prototype.popTag = function(tagName) {

Parser.prototype.appendFingerprintQuery = function(attribs) {
var assetPath = attribs.src;
if (_.isEmpty(assetPath)) return;
if (isEmpty(assetPath)) return;

// If this is an embedded url, leave it be.
if (assetPath.slice(0, 5) === 'data:') return;
Expand Down Expand Up @@ -301,10 +306,10 @@ Parser.prototype.expandGlobPattern = function(tagName, pattern, attribs) {

function buildTag(name, attribs, selfClosing) {
var tag = '<' + name;
_.each(attribs, function(attrValue, key) {
if (_.isString(attrValue) && attrValue.length === 0) {
forEach(attribs, function(attrValue, key) {
if (isString(attrValue) && attrValue.length === 0) {
tag += ' ' + key;
} else if (_.isNull(attrValue) === false) {
} else if (isNull(attrValue) === false) {
tag += ' ' + key + '="' + attrValue + '"';
}
});
Expand Down
14 changes: 12 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "htmlprep",
"version": "1.5.2",
"version": "1.5.3",
"description": "High-performance streaming HTML pre-processor designed to run in middleware.",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -33,7 +33,17 @@
"domutils": "^1.5.1",
"entities": "^1.1.1",
"glob": "^7.0.3",
"lodash": "^4.6.1",
"lodash.defaults": "^4.0.1",
"lodash.foreach": "^4.2.0",
"lodash.has": "^4.3.1",
"lodash.includes": "^4.1.2",
"lodash.isempty": "^4.2.1",
"lodash.isfunction": "^3.0.8",
"lodash.isnull": "^3.0.0",
"lodash.isstring": "^4.0.1",
"lodash.toarray": "^4.2.4",
"lodash.trimend": "^4.3.0",
"lodash.trimstart": "^4.3.0",
"minimatch": "^3.0.0",
"readable-stream": "^2.0.5",
"through2": "^2.0.1"
Expand Down
16 changes: 16 additions & 0 deletions test/attributes.js
Expand Up @@ -306,6 +306,22 @@ describe('htmlprep attributes', function() {
});
});

it('noAssetPathPrefixes handles non-leading slash', function(done) {
var html = '<html><img src="img/bg.jpg"/></html>';

var opts = {
noPathPrefixPatterns: ['/img/*.jpg'],
assetPathPrefix: '//cdn.net/'
};

run(html, opts, function(err, output) {
if (err) return done(err);

assert.equal(output, html);
done();
});
});

it('trims leading whitespace from attributes', function(done) {
var html = '<a href=" https://__baseurl__" class="btn btn-default"><i class="fa fa-home"></i> Home</a>';

Expand Down
4 changes: 2 additions & 2 deletions test/run.js
@@ -1,9 +1,9 @@
var _ = require('lodash');
var isFunction = require('lodash.isfunction');
var htmlprep = require('../');
var stream = require('stream');

module.exports = function(html, options, callback) {
if (_.isFunction(options)) {
if (isFunction(options)) {
callback = options;
options = {};
}
Expand Down

0 comments on commit 0e8a0d1

Please sign in to comment.