Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

gulp-manifest

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gulp-manifest - npm Package Compare versions

Comparing version 0.0.10 to 0.1.0

test/fixtures/subdir/other/file.txt

50

index.js

@@ -8,11 +8,17 @@ "use strict";

minimatch = require('minimatch'),
slash = require('slash'),
lineBreak = '\n';
function manifest(options) {
var filename, exclude, hasher, cwd, contents;
var filename, exclude, include, hasher, cwd, contents;
options = options || {};
if(options.basePath) {
gutil.log('basePath option is deprecated. Consider using gulp.src base instead: https://github.com/gulpjs/gulp/blob/master/docs/API.md#optionsbase');
}
filename = options.filename || 'app.manifest';
exclude = Array.prototype.concat(options.exclude || []);
include = Array.prototype.concat(options.include || []);
exclude = Array.prototype.concat(options.exclude || []).concat(include);
hasher = crypto.createHash('sha256');

@@ -32,5 +38,7 @@ cwd = process.cwd();

contents.push(lineBreak);
contents.push('');
contents.push('CACHE:');
contents = contents.concat(include);
if (options.cache) {

@@ -42,4 +50,8 @@ options.cache.forEach(function (file) {

function shouldExcludeFile(filePath) {
return exclude.some(minimatch.bind(null, filePath));
}
function writeToManifest(file) {
var prefix, filepath;
var prefix, suffix, filepath;

@@ -49,11 +61,17 @@ if (file.isNull()) return;

for (var i = 0; i < exclude.length; i++) {
if(minimatch(file.relative, exclude[i])){
return;
}
prefix = slash(options.prefix || '');
suffix = slash(options.suffix || '');
filepath = slash(file.relative);
if (shouldExcludeFile(filepath)) {
return;
}
prefix = options.prefix || '';
filepath = prefix + file.relative;
if(options.basePath) { // deprecated
var relative = path.relative(file.base, __dirname);
filepath = filepath.replace(new RegExp('^' + path.join(relative, options.basePath)), '');
}
filepath = [prefix, filepath, suffix].join('');
contents.push(encodeURI(filepath));

@@ -69,3 +87,3 @@

options.network = options.network || ['*'];
contents.push(lineBreak);
contents.push('');
contents.push('NETWORK:');

@@ -78,4 +96,7 @@ options.network.forEach(function (file) {

if (options.fallback) {
contents.push(lineBreak);
contents.push('');
contents.push('FALLBACK:');
if (typeof options.fallback === 'string') {
options.fallback = [options.fallback];
}
options.fallback.forEach(function (file) {

@@ -98,3 +119,3 @@ var firstSpace = file.indexOf(' ');

if (options.preferOnline) {
contents.push(lineBreak);
contents.push('');
contents.push('SETTINGS:');

@@ -106,3 +127,4 @@ contents.push('prefer-online');

if (options.hash) {
contents.push('\n# hash: ' + hasher.digest("hex"));
contents.push('');
contents.push('# hash: ' + hasher.digest("hex"));
}

@@ -109,0 +131,0 @@

{
"name": "gulp-manifest",
"version": "0.0.10",
"version": "0.1.0",
"description": "Generate HTML5 Cache Manifest files",

@@ -28,8 +28,10 @@ "main": "index.js",

"mocha": "~1.16.2",
"should": "~2.1.1"
"should": "~2.1.1",
"gulp": "^3.9.0"
},
"dependencies": {
"through": "~2.3.4",
"gulp-util": "~2.2.6",
"minimatch": "~2.0.1"
"minimatch": "~2.0.1",
"slash": "^1.0.0",
"through": "~2.3.4"
},

@@ -36,0 +38,0 @@ "bugs": {

@@ -1,5 +0,5 @@

# gulp-manifest
# gulp-manifest
> Generate HTML5 Cache Manifest files. Submitted by [Scott Hillman](https://github.com/hillmanov/).
Big thanks to [Gunther Brunner](https://github.com/gunta/) for writing the [grunt-manifest](https://github.com/gunta/grunt-manifest) plugin. This plugin was heavily influenced by his great work.
Big thanks to [Gunther Brunner](https://github.com/gunta/) for writing the [grunt-manifest](https://github.com/gunta/grunt-manifest) plugin. This plugin was heavily influenced by his great work.

@@ -25,16 +25,16 @@ Visit the [HTML 5 Guide to AppCache](http://www.html5rocks.com/en/tutorials/appcache/beginner/) for more information on Cache Manifest files.

#### options.prefix
Type: `String`
Default: `undefined`
Type: `String`
Default: `undefined`
Add a prefix to the file paths. Useful when your files are in a different URL than the page.
#### options.basePath
#### options.suffix
Type: `String`
Default: `undefined`
Set a basepath for the files. Useful when the files are not served from the toplevel directory.
Add a suffix to the file paths. Useful when your files have query string.
#### options.filename
Type: `String`
Default: `"app.manifest"`
Type: `String`
Default: `'app.manifest'`

@@ -44,4 +44,4 @@ Set name of the Cache Manifest file.

#### options.cache
Type: `String`
Default: `undefined`
Type: `String`
Default: `undefined`

@@ -51,4 +51,4 @@ Adds manually a string to the **CACHE** section. Needed when you have cache buster for example.

#### options.exclude
Type: `String` `Array`
Default: `undefined`
Type: `String` `Array`
Default: `undefined`

@@ -58,4 +58,4 @@ Exclude specific files from the Cache Manifest file.

#### options.network
Type: `String` `Array`
Default: `"*"` (By default, an online whitelist wildcard flag is added)
Type: `String` `Array`
Default: `'*'` (By default, an online whitelist wildcard flag is added)

@@ -67,4 +67,4 @@ Adds a string to the **NETWORK** section.

#### options.fallback
Type: `String` `Array`
Default: `undefined`
Type: `String` `Array`
Default: `undefined`

@@ -76,4 +76,4 @@ Adds a string to the **FALLBACK** section.

#### options.preferOnline
Type: `Boolean`
Default: `undefined`
Type: `Boolean`
Default: `undefined`

@@ -85,4 +85,4 @@ Adds a string to the **SETTINGS** section, specifically the cache mode flag of the ```prefer-online``` state.

#### options.timestamp
Type: `Boolean`
Default: `true`
Type: `Boolean`
Default: `true`

@@ -94,4 +94,4 @@ Adds a timestamp as a comment for easy versioning.

#### options.hash
Type: `Boolean`
Default: `false`
Type: `Boolean`
Default: `false`

@@ -106,3 +106,3 @@ Adds a sha256 hash of all `src` files (actual contents) as a comment.

gulp.task('manifest', function(){
gulp.src(['build/*'])
gulp.src(['build/*'], { base: './' })
.pipe(manifest({

@@ -121,19 +121,20 @@ hash: true,

CACHE MANIFEST
```
CACHE MANIFEST
CACHE:
js/app.js
css/style
css/style.css
js/zepto.min.js
js/script.js
some_files/index.html
some_files/about.html
CACHE:
js/app.js
css/style
css/style.css
js/zepto.min.js
js/script.js
some_files/index.html
some_files/about.html
NETWORK:
*
NETWORK:
*
# hash: 76f0ef591f999871e1dbdf6d5064d1276d80846feeef6b556f74ad87b44ca16a
# hash: 76f0ef591f999871e1dbdf6d5064d1276d80846feeef6b556f74ad87b44ca16a
```
You do need to be fully aware of standard browser caching.

@@ -143,1 +144,80 @@ If the files in **CACHE** are in the network cache, they won't actually update,

Therefore, it's recommended to add a hash to the filenames's, akin to rails or yeoman. See [here](http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/) why query strings are not recommended.
### Composition of paths
Sometimes your assets are served from different source directories. To route these correctly the `gulp.src.base` option can be used to [define a glob's base path](https://github.com/gulpjs/gulp/blob/master/docs/API.md#optionsbase). Later multiple streams can be composed with [merge-stream](https://github.com/grncdr/merge-stream), so that one single manifest file is created from them
```javascript
var path = require('path');
var mergeStream = require('merge-stream');
var config = {
app: './app',
tmp: './tmp'
};
mergeStream(
gulp.src([
path.join(config.app + '*.html'),
path.join(config.app + 'assets/*.{png,svg,jpg}'),
path.join(config.app + 'js/*.js')
], {
base: config.app
}),
gulp.src([
path.join(config.tmp + 'css/*.css')
], {
base: config.tmp
})
);
.pipe(plugins.manifest({
hash: true,
preferOnline: false,
network: ['*'],
filename: 'appcache.manifest'
}))
.pipe(gulp.dest(config.tmp));
```
for the given file tree
```
├── app
│   ├── assets
│   │   ├── cover.png
│   │   └── logo.svg
│   ├── index.html
│   ├── js
│   │   └── script.js
│   └── scss
│   └── style.scss
└── tmp
└── css
└── style.css
```
will result in
```
index.html
assets/cover.png
assets/logo.svg
js/script.js
css/style.css
```
Sometimes you might want to alter the way paths are passed to the plugin. The correct way will be to provide options to `gulp.src` so that it generates correct paths.
Say, you have a single folder named `public`, which is the top-level directory that's served to the browser. In the same directory, you have the `css`, `js` and `asset` files under different directories, along with the `html` files.
```
public/
├── assets
│   ├── cover.png
│   └── logo.png
├── css
│   └── style.css
├── js
│   └── app.js
└── index.html
```

@@ -7,2 +7,3 @@ var fs = require('fs'),

gutil = require('gulp-util'),
gulp = require('gulp'),
mocha = require('mocha'),

@@ -62,7 +63,10 @@ manifestPlugin = require('../');

var contents = '';
stream.on('data', function(data) {
var contents = data.contents.toString();
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.contain('fixture/hello.js');
done();
});
stream.once('end', done);

@@ -84,4 +88,7 @@ stream.write(new gutil.File({

var contents = '';
stream.on('data', function(data) {
var contents = data.contents.toString();
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.contain('file1.js');

@@ -91,4 +98,4 @@ contents.should.not.contain('file2.js');

contents.should.not.contain('file4.js');
done();
});
stream.once('end', done);

@@ -99,17 +106,44 @@ fakeFiles.forEach(stream.write.bind(stream));

it('Should allow options.exclude to be a string', function(done) {
var stream = manifestPlugin({
exclude: 'file2.js'
});
var contents = '';
stream.on('data', function(data) {
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.contain('file1.js');
contents.should.not.contain('file2.js');
contents.should.contain('file3.js');
done();
});
fakeFiles.forEach(stream.write.bind(stream));
stream.end();
});
it('Should work with hash multiple times', function (done) {
var pending = 2;
function generateWithHash() {
var stream = manifestPlugin({ hash: true });
stream.on('data', function (data) {
data.contents.toString().should.contain('# hash: ');
return new Promise(function(resolve, reject) {
var stream = manifestPlugin({ hash: true });
var contents = '';
stream.on('data', function (data) {
contents += data.contents.toString();
});
stream.once('end', function () {
contents.should.contain('# hash: ');
resolve();
});
fakeFiles.forEach(stream.write.bind(stream));
stream.end();
});
stream.once('end', function () {
if (--pending <= 0) done();
});
fakeFiles.forEach(stream.write.bind(stream));
stream.end();
}
generateWithHash();
generateWithHash();
Promise.all([
generateWithHash(),
generateWithHash()
]).then(function() {
done();
});
});

@@ -124,10 +158,14 @@

var contents = '',
relatives = [];
stream.on('data', function(data) {
data.should.be.an.instanceOf(gutil.File);
data.relative.should.eql('cache.manifest');
var contents = data.contents.toString();
relatives.push(data.relative);
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.contain('FALLBACK:\n/ /offline.html');
relatives.indexOf('cache.manifest').should.not.be.equal(-1);
done();
});
stream.once('end', done);
stream.end();

@@ -142,6 +180,31 @@ });

var contents = '';
stream.on('data', function(data) {
var contents = data.contents.toString();
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.contain(prefix);
done();
});
stream.write(new gutil.File({
path: path.resolve('test\\fixture\\hello.js'),
cwd: path.resolve('test/'),
base: path.resolve('test/'),
contents: new Buffer('notimportant')
}));
stream.end();
});
it('Should add a suffix', function(done) {
var suffix = '?query',
stream = manifestPlugin({
suffix: suffix
});
stream.on('data', function(data) {
var contents = data.contents.toString();
contents.should.contain(suffix);
});
stream.once('end', done);

@@ -159,2 +222,61 @@

it('Should lookup fileglobs in directories', function(done) {
var stream = manifestPlugin();
var contents = '';
stream.on('data', function(data) {
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.match(/^subdir\/somefile.txt$/gm);
contents.should.match(/^subdir\/other\/file.txt$/gm);
done();
});
gulp.src(path.join(__dirname, 'fixtures/**'))
.pipe(stream);
});
it('Should lookup fileglobs relative to working directory when gulp.src.base is ./', function(done) {
var stream = manifestPlugin();
var contents = '';
stream.on('data', function(data) {
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.match(/^test\/fixtures\/subdir\/somefile.txt$/gm);
contents.should.match(/^test\/fixtures\/subdir\/other\/file.txt$/gm);
done();
});
gulp.src(path.join(__dirname, 'fixtures/**'), {
base: './'
})
.pipe(stream);
});
it('Should lookup fileglobs relative to gulp.src.base', function(done) {
var stream = manifestPlugin();
var contents = '';
stream.on('data', function(data) {
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.match(/^fixtures\/subdir\/somefile.txt$/gm);
contents.should.match(/^fixtures\/subdir\/other\/file.txt$/gm);
done();
});
gulp.src(path.join(__dirname, 'fixtures/**'), {
base: 'test'
})
.pipe(stream);
});
it('Should add correct path', function(done) {

@@ -164,13 +286,16 @@ var filepath = 'test\\fixture\\hello.js',

var contents = '';
stream.on('data', function(data) {
var contents = data.contents.toString();
contents.should.contain(slash(filepath));
contents += data.contents.toString();
});
stream.once('end', done);
stream.once('end', function() {
contents.should.match(new RegExp('^' + slash(filepath) + '$', 'gm'));
done();
});
stream.write(new gutil.File({
path: path.resolve(filepath),
path: slash(filepath),
cwd: path.resolve('test/'),
base: path.resolve('test/'),
base: './',
contents: new Buffer('notimportant')

@@ -188,13 +313,16 @@ }));

var contents = '';
stream.on('data', function(data) {
var contents = data.contents.toString();
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.not.contain(basePath);
done();
});
stream.once('end', done);
stream.write(new gutil.File({
path: path.resolve(basePath + '\\test\\fixture\\hello.js'),
path: slash(basePath + '\\test\\fixture\\hello.js'),
cwd: path.resolve('test/'),
base: path.resolve('test/'),
base: path.resolve('./'),
contents: new Buffer('notimportant')

@@ -209,3 +337,3 @@ }));

filename: 'cache.manifest',
exclude: ['file2.js','exclude/**',"children2/**/exclude*.js"],
exclude: ['file2.js','exclude/**','children2/**/exclude*.js'],
hash: true,

@@ -216,7 +344,11 @@ network: ['http://*', 'https://*', '*'],

var contents = '', relatives = [];
stream.on('data', function(data) {
data.should.be.an.instanceOf(gutil.File);
data.relative.should.eql('cache.manifest');
var contents = data.contents.toString();
relatives.push(data.relative);
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.startWith('CACHE MANIFEST');

@@ -233,6 +365,7 @@ contents.should.contain('CACHE:');

contents.should.contain('include2.js');
relatives.indexOf('cache.manifest').should.not.be.equal(-1);
done();
});
stream.once('end', done);
fakeFiles.forEach(stream.write.bind(stream));

@@ -242,2 +375,113 @@

});
it('Should exclude backslash excaped exclusions', function(done) {
var stream = manifestPlugin({
filename: 'cache.manifest',
exclude: ['some\\file.txt']
});
var contents = '', relatives = [];
stream.on('data', function(data) {
data.should.be.an.instanceOf(gutil.File);
relatives.push(data.relative);
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.startWith('CACHE MANIFEST');
contents.should.contain('CACHE:');
contents.should.contain('somefile.txt');
contents.should.not.contain('some/file.js');
relatives.indexOf('cache.manifest').should.not.be.equal(-1);
done();
});
gulp.src(path.join(__dirname, 'fixtures/**'), {
base: 'test'
})
.pipe(stream);
});
it('Should add includes provided by option.include', function(done) {
var basePath = 'basedir',
stream = manifestPlugin({
include: [
'foo/bar'
]
});
var contents = '';
stream.on('data', function(data) {
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.contain('baz');
contents.should.contain('foo/bar');
done();
});
stream.write(new gutil.File({
path: 'baz',
base: path.resolve('./'),
contents: new Buffer('notimportant')
}));
stream.end();
});
it('Should allow option.include to be a string', function(done) {
var basePath = 'basedir',
stream = manifestPlugin({
include: 'foo/bar'
});
var contents = '';
stream.on('data', function(data) {
contents += data.contents.toString();
});
stream.once('end', function() {
contents.should.contain('baz');
contents.should.contain('foo/bar');
done();
});
stream.write(new gutil.File({
path: 'baz',
base: path.resolve('./'),
contents: new Buffer('notimportant')
}));
stream.end();
});
it('Should not duplicate includes', function(done) {
var basePath = 'basedir',
stream = manifestPlugin({
include: [
'foobar'
]
});
var contents = '', count = 0;
stream.on('data', function(data) {
data.should.be.an.instanceOf(gutil.File);
contents += data.contents.toString();
});
stream.once('end', function() {
contents.match(/foobar/gm).length.should.equal(1);
done();
});
stream.write(new gutil.File({
path: 'foobar',
base: path.resolve('./'),
contents: new Buffer('notimportant')
}));
stream.end();
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc