gulp-resource-hints
Advanced tools
Comparing version 0.1.2 to 0.2.0
@@ -6,2 +6,3 @@ 'use strict' | ||
getCSSAssets: true, | ||
silent: false, | ||
paths: { | ||
@@ -8,0 +9,0 @@ 'dns-prefetch': '//*', |
@@ -6,10 +6,13 @@ 'use strict' | ||
const Soup = require('soup') | ||
const gutil = require('gulp-util') | ||
const parse = require('url').parse | ||
const defaults = require('./defaults') | ||
var appOptions = {} | ||
var appLoaded = false | ||
const PLUGIN_NAME = 'gulp-resource-hints' | ||
var parsedAssets = [] | ||
var parsedAssets = [] // helps check for duplicates | ||
var insertionPoint = '' // dictates where to insert resource hints | ||
// const PLUGIN_NAME = 'gulp-resource-hints' | ||
var fonts = [ | ||
@@ -59,7 +62,2 @@ '**/*.woff', | ||
function clearParsedAssets () { | ||
parsedAssets = [] | ||
} | ||
module.exports.clearParsedAssets = clearParsedAssets | ||
/** | ||
@@ -71,2 +69,8 @@ * Checking duplicates is necessary for dns-prefetch and prefetch | ||
*/ | ||
/** | ||
* Check for duplicates in parsedAssets helper array | ||
* @param {string} assetToCheck | ||
* @param {boolean} isHost | ||
*/ | ||
function isDuplicate (assetToCheck, isHost) { | ||
@@ -85,4 +89,88 @@ if (parsedAssets.length <= 0) { | ||
// Checks if asset matches user glob pattern | ||
// Writes resource hint if it does | ||
/** | ||
* Unset helper variables | ||
*/ | ||
function reset () { | ||
parsedAssets = [] | ||
insertionPoint = '' | ||
} | ||
module.exports.reset = reset | ||
/** | ||
* Log to the console unless user opts out | ||
* @param {string} message | ||
* @param {boolean} warn | ||
*/ | ||
function logger (message, warn) { | ||
if (appOptions.silent) { | ||
return | ||
} | ||
if (warn) { | ||
console.warn(message) | ||
return | ||
} | ||
console.log(message) | ||
} | ||
module.exports.logger = logger | ||
/** | ||
* Determine if file has a valid area to inject resource hints | ||
* @param {stream} file | ||
*/ | ||
function hasInsertionPoint (file) { | ||
var token = appOptions.pageToken | ||
if (token !== '' && String(file.contents).indexOf(token) > -1) { | ||
insertionPoint = 'token' | ||
} else if (token !== '' && token !== defaults.pageToken) { | ||
logger('Token not found in ' + file.relative) | ||
} | ||
var soup = new Soup(String(file.contents)) | ||
// Append after metas | ||
soup.setInnerHTML('head > meta:last-of-type', function (oldHTML) { | ||
if (oldHTML !== null) { | ||
insertionPoint = 'meta' | ||
return oldHTML | ||
} | ||
}) | ||
if (insertionPoint) { | ||
return true | ||
} | ||
// Else, prepend before links | ||
soup.setInnerHTML('head > link:first-of-type', function (oldHTML) { | ||
if (oldHTML !== null) { | ||
insertionPoint = 'link' | ||
return oldHTML | ||
} | ||
}) | ||
if (insertionPoint) { | ||
return true | ||
} | ||
// Else, append to head | ||
soup.setInnerHTML('head', function (oldHTML) { | ||
if (oldHTML !== null) { | ||
insertionPoint = 'head' | ||
return oldHTML | ||
} | ||
}) | ||
return insertionPoint | ||
} | ||
module.exports.hasInsertionPoint = hasInsertionPoint | ||
/** | ||
* Validate asset is desireable by user | ||
* Build resource hint if so | ||
* @param {string} hint | ||
* @param {string} asset | ||
* @param {string} glob | ||
* @return {string} | ||
*/ | ||
function buildResourceHint (hint, asset, glob) { | ||
@@ -116,75 +204,65 @@ var as = '' | ||
function mergeOptions (userOpts) { | ||
// iterate over existing keys | ||
/** | ||
* Merge user options with defaults | ||
* @param {object} userOpts | ||
* @return {object} | ||
*/ | ||
function options (userOpts) { | ||
if (appLoaded && typeof userOpts === 'undefined') { | ||
return appOptions | ||
} | ||
userOpts = typeof userOpts === 'object' ? userOpts : {} | ||
appOptions = Object.assign({}, defaults, userOpts) | ||
appOptions.paths = Object.assign({}, defaults.paths, userOpts.paths) | ||
appLoaded = true | ||
var options = {} | ||
return appOptions | ||
} | ||
module.exports.options = options | ||
if (!userOpts) { | ||
return defaults | ||
} else { | ||
var iterate = function (obj) { | ||
for (var key in defaults) { | ||
if (typeof obj[key] === 'object' && typeof defaults[key] !== 'object') { | ||
// Deep compare if object found | ||
iterate(obj[key]) | ||
} else if (!obj[key] && defaults[key] !== '') { | ||
// Use non-blank default since there is no user option | ||
options[key] = defaults[key] | ||
} else if (typeof defaults[key] === typeof obj[key]) { | ||
// Use user-defined value only if the type matches | ||
options[key] = obj[key] | ||
} | ||
} | ||
} | ||
/** | ||
* Write resource hints to file | ||
* @param {stream} file | ||
* @param {string} data | ||
* @param {string} token | ||
* @return {string} | ||
*/ | ||
function writeDataToFile (file, data, token) { | ||
// insertionPoint was set in hasInsertionPoint(), so we can assume it is safe to write to file | ||
var selectors = [ | ||
'head > meta:last-of-type', | ||
'head > link:first-of-type', | ||
'head' | ||
] | ||
var selectorIndex = 0 | ||
iterate(userOpts) | ||
return options | ||
switch (insertionPoint) { | ||
case 'meta': | ||
selectorIndex = 0 | ||
break | ||
case 'link': | ||
selectorIndex = 1 | ||
break | ||
case 'head': | ||
selectorIndex = 2 | ||
break | ||
case 'token': | ||
let html = String(file.contents).replace(token, data) | ||
return new Buffer(html) | ||
default: | ||
return '' | ||
} | ||
} | ||
module.exports.mergeOptions = mergeOptions | ||
function writeData (file, data, token) { | ||
if (token !== '' && String(file.contents).indexOf(token) > -1) { | ||
let html = String(file.contents).replace(token, data) | ||
return new Buffer(html) | ||
} | ||
if (token !== '' && token !== defaults.pageToken) { | ||
gutil.log(PLUGIN_NAME, 'Provided token was not found in: ' + file.relative + '\nWill attempt to append to <head>') | ||
} | ||
var soup = new Soup(String(file.contents)) | ||
var hasMeta = false | ||
var hasLink = false | ||
var hasHead = false | ||
// Append after metas | ||
soup.setInnerHTML('head > meta:last-of-type', function (oldHTML) { | ||
hasMeta = true | ||
// Inject Resource Hints | ||
soup.setInnerHTML(selectors[selectorIndex], function (oldHTML) { | ||
if (insertionPoint === 'link') { | ||
return data + oldHTML | ||
} | ||
return oldHTML + data | ||
}) | ||
// Else, prepend before links | ||
if (!hasMeta) { | ||
soup.setInnerHTML('head > link:first-of-type', function (oldHTML) { | ||
hasLink = true | ||
return data + oldHTML | ||
}) | ||
} | ||
// Else, append to head | ||
if (!hasMeta && !hasLink) { | ||
soup.setInnerHTML('head', function (oldHTML) { | ||
hasHead = true | ||
return oldHTML + data | ||
}) | ||
} | ||
// No head? Oh noes! | ||
if (!hasHead) { | ||
gutil.log(PLUGIN_NAME, 'No document <head> found, cannot write resource hints. Skipping file:', file.relative) | ||
return false | ||
} | ||
return soup.toString() | ||
} | ||
module.exports.writeData = writeData | ||
module.exports.writeDataToFile = writeDataToFile |
'use strict' | ||
const listAssets = require('list-assets') | ||
const gutil = require('gulp-util') | ||
const Transform = require('stream').Transform | ||
@@ -10,10 +9,16 @@ | ||
/** | ||
* Main Function | ||
* Read file streams, parse assets, build resource hints | ||
* @param {object} opt | ||
*/ | ||
function gulpResourceHints (opt) { | ||
var options = helpers.mergeOptions(opt) | ||
var options = helpers.options(opt) | ||
helpers.reset() | ||
var stream = new Transform({ | ||
return new Transform({ | ||
objectMode: true, | ||
transform: function (file, enc, cb) { | ||
if (file.isNull()) { | ||
gutil.log(PLUGIN_NAME, 'no file') | ||
helpers.logger(PLUGIN_NAME, 'no file', true) | ||
@@ -26,4 +31,5 @@ cb(null, file) | ||
// Gather assets | ||
var assets = listAssets.html( | ||
// Gather assets, keep unique values | ||
// Using https://www.npmjs.com/package/list-assets | ||
var assets = new Set(listAssets.html( | ||
fileContents, | ||
@@ -34,7 +40,6 @@ { | ||
} | ||
).map((ob) => { | ||
return ob.url | ||
}) | ||
).map(ob => ob.url)) | ||
if (assets.length < 0) { | ||
if (assets.size < 0) { | ||
// Skip file: no static assets | ||
cb(null, file) | ||
@@ -44,3 +49,7 @@ return | ||
helpers.clearParsedAssets() | ||
if (!helpers.hasInsertionPoint(file)) { | ||
helpers.logger(PLUGIN_NAME, 'Skipping file: no <head> or token found', true) | ||
cb(null, file) | ||
return | ||
} | ||
@@ -59,5 +68,5 @@ // Future feature! Gotta do more stream madness | ||
// Build resource hints based on user-selected assets | ||
var data = '' | ||
var data = [''] | ||
for (var i = 0, len = assets.length; i < len; i++) { | ||
assets.forEach((aVal, aKey, set) => { | ||
Object.keys(options.paths).forEach((key) => { | ||
@@ -67,9 +76,11 @@ if (options.paths[key] === '') { | ||
} | ||
data += helpers.buildResourceHint(key, assets[i], options.paths[key]) | ||
data.push(helpers.buildResourceHint(key, aVal, options.paths[key])) | ||
}) | ||
} | ||
}) | ||
var newFile = helpers.writeData(file, data, options.pageToken) | ||
data = data.reduce((a, b) => a + b) | ||
var newFile = helpers.writeDataToFile(file, data, options.pageToken) | ||
if (!newFile) { | ||
helpers.logger(PLUGIN_NAME + ': Could not write data to file. ' + file.relative) | ||
cb(null, file) | ||
@@ -84,6 +95,4 @@ return | ||
}) | ||
return stream | ||
} | ||
module.exports = gulpResourceHints |
{ | ||
"name": "gulp-resource-hints", | ||
"version": "0.1.2", | ||
"version": "0.2.0", | ||
"description": "Add resource hints to your html files", | ||
@@ -43,3 +43,2 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"gulp-util": "^3.0.8", | ||
"is-css": "^2.0.0", | ||
@@ -49,3 +48,8 @@ "list-assets": "0.0.2", | ||
"soup": "^0.1.5" | ||
}, | ||
"standard": { | ||
"ignore": [ | ||
"**/node_modules/**" | ||
] | ||
} | ||
} |
@@ -75,2 +75,3 @@ # gulp-resource-hints | ||
- `pageToken <String>` : add your own custom string replace token (default is **##gulp-resource-hints##**) | ||
- `silent <Boolean>` : disable logs and warnings (default is `false`) | ||
- `paths <Object>` : custom string patterns for their respective resource hint. | ||
@@ -113,2 +114,6 @@ - `dns-prefetch <String>` : custom [URL pattern](#url-patterns). Default is `//*` (all non-relative URLs) | ||
## Changelog | ||
See [latest release](https://github.com/theetrain/gulp-resource-hints/releases/latest). | ||
--- | ||
@@ -115,0 +120,0 @@ |
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
14478
4
316
122
- Removedgulp-util@^3.0.8
- Removedansi-gray@0.1.1(transitive)
- Removedansi-regex@2.1.1(transitive)
- Removedansi-styles@2.2.1(transitive)
- Removedansi-wrap@0.1.0(transitive)
- Removedarray-differ@1.0.0(transitive)
- Removedarray-uniq@1.0.3(transitive)
- Removedbeeper@1.1.1(transitive)
- Removedchalk@1.1.3(transitive)
- Removedclone@1.0.4(transitive)
- Removedclone-stats@0.0.1(transitive)
- Removedcolor-support@1.1.3(transitive)
- Removeddateformat@2.2.0(transitive)
- Removedduplexer2@0.0.2(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedfancy-log@1.3.3(transitive)
- Removedglogg@1.0.2(transitive)
- Removedgulp-util@3.0.8(transitive)
- Removedgulplog@1.0.0(transitive)
- Removedhas-ansi@2.0.0(transitive)
- Removedhas-gulplog@0.1.0(transitive)
- Removedisarray@1.0.0(transitive)
- Removedlodash._basecopy@3.0.1(transitive)
- Removedlodash._basetostring@3.0.1(transitive)
- Removedlodash._basevalues@3.0.0(transitive)
- Removedlodash._getnative@3.9.1(transitive)
- Removedlodash._isiterateecall@3.0.9(transitive)
- Removedlodash._reescape@3.0.0(transitive)
- Removedlodash._reevaluate@3.0.0(transitive)
- Removedlodash._reinterpolate@3.0.0(transitive)
- Removedlodash._root@3.0.1(transitive)
- Removedlodash.escape@3.2.0(transitive)
- Removedlodash.isarguments@3.1.0(transitive)
- Removedlodash.isarray@3.0.4(transitive)
- Removedlodash.keys@3.1.2(transitive)
- Removedlodash.restparam@3.6.1(transitive)
- Removedlodash.template@3.6.2(transitive)
- Removedlodash.templatesettings@3.1.1(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmultipipe@0.1.2(transitive)
- Removedobject-assign@3.0.0(transitive)
- Removedparse-node-version@1.0.1(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedreplace-ext@0.0.1(transitive)
- Removedsafe-buffer@5.1.2(transitive)
- Removedsparkles@1.0.1(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedstrip-ansi@3.0.1(transitive)
- Removedsupports-color@2.0.0(transitive)
- Removedthrough2@2.0.5(transitive)
- Removedtime-stamp@1.1.0(transitive)
- Removedvinyl@0.5.3(transitive)
- Removedxtend@4.0.2(transitive)