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

bolivar

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bolivar - npm Package Compare versions

Comparing version 0.1.0 to 1.0.0

.travis.yml

67

bin/bolivar.js

@@ -5,4 +5,8 @@ #!/usr/bin/env node

var path = require('path');
var findit = require('findit');
var color = require('cli-color');
var cErr = color.red;
var cOk = color.green;
var cInfo = color.blue;
var Bolivar = require('../index.js');

@@ -12,8 +16,5 @@

.script('bolivar')
.help('Get independant from external css, js and images');
parser.command('start')
.help('Get independant from external css, js and images')
.option('root', {
abbr: 'r',
default: process.cwd(),
position: 0,
help: 'The root directory to work on'

@@ -53,37 +54,39 @@ })

})
.help('Start the replacing')
.callback(function(options) {
start(options);
})
;
parser.parse();
var options = parser.nom();
function start(options) {
options.paths = {
css: path.join(options.parent, options.css, options.child),
js: path.join(options.parent, options.js, options.child),
img: path.join(options.parent, options.img, options.child)
};
if(!options.root) {
parser.print(parser.getUsage());
process.exit();
}
var bolivar = new Bolivar(options);
options.paths = {
css: path.join(options.parent, options.css, options.child),
js: path.join(options.parent, options.js, options.child),
img: path.join(options.parent, options.img, options.child)
};
if(!options.silent) {
console.log('Root ' + options.root);
bolivar.on('file', function(data) {
console.log('File: ' + data.name);
});
options.root = path.resolve(options.root);
var bolivar = new Bolivar(options);
bolivar.on('url', function(data) {
console.log('* ' + data.url);
});
}
if(!options.silent) {
console.log(cInfo('Root: ' + options.root));
if(!options.force && !fs.existsSync(path.join(options.root, '.git'))) {
console.error('No .git found in root. Use -f if you are sure what you are doing.');
process.exit();
}
bolivar.on('file', function(data) {
console.log('File: ' + data.name);
});
bolivar.start();
bolivar.on('url', function(data) {
console.log('\uD83C\uDF0E ' + data.url);
console.log(' \u21B3 ' + cOk(data.path));
});
}
if(!options.force && !fs.existsSync(path.join(options.root, '.git'))) {
console.error(cErr('Warning: No .git found in root. Use -f if you are sure what you are doing.'));
process.exit();
}
bolivar.start();
var fs = require('fs');
var http = require('http');
var path = require('path');
var urlParse = require('url').parse;
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var cheerio = require('cheerio');
var findit = require('findit');
var sar = require('search-act-replace');
var getAccepted = require('get-accepted');
var mkdir = require('mkdirp');
// Helper
var isExternal = function(path) {
return path && path.indexOf('//') > -1;
};
var completeUrl = function(url) {

@@ -31,67 +28,128 @@ // Assuming it is an URL not a local path

if(!options.paths.img) options.paths.img = 'img';
if(!options.paths.fonts) options.paths.fonts = 'fonts';
options.filetypes = {
css: {
exts: ['.css'],
mimes: ['text/css']
},
js: {
exts: ['.js'],
mimes: ['application/javascript', 'application/x-javascript', 'application/ecmascript']
},
img: {
exts: ['.jpg', '.jpeg', '.png', '.gif'],
mimes: ['image/gif', 'image/jpeg', 'image/png']
},
fonts: {
exts: ['.ttf', '.eot', '.woff', '.svg'],
mimes: ['application/x-font-ttf']
}
}
// This Url RegEx probably needs improvement...
options.regex = /(https?:)?\/\/([\w\-]\.?)+(\/[\w\.\-]+)+\/?(\?(\w+(=\w+)?(\&\w+(=\w+)?)*)?)?/g;
this.options = options;
}
Bolivar.prototype.start = function() {
Bolivar.prototype.start = function () {
var self = this;
self.finder = findit(self.options.root);
sar(self.options.root, self.options.regex, matchedUrl)
.on('end',function () {
self.emit('end');
})
;
self.finder.on('directory', function (dir, stat, stop) {
var base = path.basename(dir);
if (base === '.git' || base === 'node_modules') stop();
});
self.finder.on('file', function (file, stat) {
var relFile = path.relative(self.options.root, file);
if(path.extname(file) === '.html') {
self.emit('file', {name: relFile});
self.freeFile(self.options.root, relFile);
function matchedUrl(match, file, replace) {
var url = completeUrl(match[0]);
var filetypes = self.options.filetypes;
var fileExt = path.extname(urlParse(url).pathname);
if (fileExt) {
// by file extension
for(filetype in filetypes) {
var exts = filetypes[filetype].exts;
if (exts.indexOf(fileExt) > -1) {
self.extDownload(url, filetype, replace);
return;
}
}
});
replace(false);
} else {
// by mime type
self.mimeDownload(url, replace);
}
}
}
self.finder.on('end', self.emit.bind(self, 'end'));
};
Bolivar.prototype.stop = function() {
this.finder.stop();
};
Bolivar.prototype.mimeDownload = function (url, replace) {
var self = this;
var filetypes = self.options.filetypes;
var mimetypes = [];
for(filetype in filetypes) {
mimetypes = mimetypes.concat(filetypes[filetype].mimes);
}
getAccepted(url, mimetypes, function (res) {
if(res) {
var type;
var mime = res.headers['content-type'];
for(filetype in filetypes) {
var mimes = filetypes[filetype].mimes;
if (mimes.indexOf(mime) > -1) {
type = filetype;
}
}
self.saveLocally(url, res, type, replace);
} else {
replace(false);
}
})
}
Bolivar.prototype.freeFile = function(root, relFile) {
Bolivar.prototype.saveLocally = function (url, res, type, replace) {
// Takes the FileStream and saves it
this.emit('download', {url: url});
var self = this;
var filepath = path.join(root, relFile);
var file = fs.readFileSync(filepath);
var $ = cheerio.load(file.toString());
var filename = url.split('/').pop();
var savePathRel = this.options.paths[type];
var savePathFull = path.join(this.options.root, savePathRel);
mkdir(savePathFull);
var intFile = fs.createWriteStream(path.join(savePathFull, filename));
if (savePathRel) {
res
.pipe(intFile)
.on('finish', function () {
var replacePath = path.join('/', savePathRel, filename);
replace(replacePath);
self.emit('url', {url: url, path: replacePath});
})
;
} else {
replace(false);
}
}
var saveLocally = function(selector, attrName, type) {
$(selector).each(function(i, elem) {
var url = $(this).attr(attrName);
localPath = self.downloadLocally(type, url);
$(this).attr(attrName, localPath);
});
};
Bolivar.prototype.extDownload = function(url, type, replace) {
// checks before if it should download
var self = this;
saveLocally('link[rel=stylesheet]', 'href', 'css');
saveLocally('script', 'src', 'js');
saveLocally('img', 'src', 'img');
fs.writeFileSync(filepath, $.html());
};
if (!type) {
replace(false);
return;
}
url = completeUrl(url);
Bolivar.prototype.downloadLocally = function(type, url) {
if(isExternal(url)) {
url = completeUrl(url);
var filename = url.split('/').pop();
this.emit('url', {url: url});
var savePath = this.options.paths[type];
var intFile = fs.createWriteStream(path.join(this.options.root, savePath, filename));
http.get(url, function(extFile) {
extFile.pipe(intFile);
});
return path.join('/', savePath, filename);
} else {
return url;
}
http.get(url, function(res) {
self.saveLocally(url, res, type, replace);
});
};
module.exports = Bolivar;
{
"name": "bolivar",
"version": "0.1.0",
"version": "1.0.0",
"description": "Get independant from external css, js and images",

@@ -10,3 +10,3 @@ "main": "index.js",

"scripts": {
"test": "mocha test/test.js"
"test": "mocha -R spec test/test.js"
},

@@ -21,10 +21,13 @@ "repository": {

"dependencies": {
"cheerio": "~0.15.0",
"findit": "~1.1.1",
"nomnom": "~1.6.2"
"cli-color": "~0.3.2",
"get-accepted": "0.0.1",
"mkdirp": "^0.5.0",
"nomnom": "~1.6.2",
"search-act-replace": "0.1.0"
},
"devDependencies": {
"mocha": "~1.18.2",
"mkdirp": "~0.5.0"
"tmp": "0.0.23",
"nock": "~0.31.1"
}
}
# Bolivar
[![Build Status](https://travis-ci.org/finnp/node-bolivar.svg?branch=master)](https://travis-ci.org/finnp/node-bolivar)
> Get independant from external css, js and images

@@ -36,3 +36,3 @@

You can also use bolivar via require. It will not `console.log` messages but emit
`file` and `url` events as well as an `end` event.
`file`, `url` and `download` events as well as an `end` event.
```javascript

@@ -39,0 +39,0 @@ var bolivar = require('bolivar');

@@ -8,5 +8,7 @@ http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js

http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css
http://fonts.googleapis.com/css?family=Roboto
http://weloveiconfonts.com/api/?family=brandico
http://cdn.jsdelivr.net/16pixels/0.1/16pixels.css
http://farm8.staticflickr.com/7456/14154949784_3399df86ff_n.jpg
http://weloveiconfonts.com/api/fonts/brandico/brandico.eot
http://weloveiconfonts.com/api/fonts/brandico/brandico.eot?
http://weloveiconfonts.com/api/fonts/brandico/brandico.woff
http://weloveiconfonts.com/api/fonts/brandico/brandico.ttf
var os = require('os');
var fs = require('fs');
var path = require('path');
var mocha = require('mocha');
var mkdir = require('mkdirp').sync;
var tmpdir = require('tmp').dir;
var nock = require('nock');
var bolivar = require('../index.js');
var urlParse = require('url').parse;
describe('bolivar', function () {
var tmp;
function mockUrls(id) {
var urls = fs.readFileSync(path.join(__dirname, id + '-urls.txt'), 'utf-8').trim().split('\n');
before(function () {
tmp = os.tmpdir();
mkdir(tmp + 'css');
mkdir(tmp + 'js');
mkdir(tmp + 'img');
// mocking urls
var mocks = [];
urls.forEach(function (urlRaw) {
url = urlParse(urlRaw);
baseUrl = url.protocol + '//' + url.host;
mocks.push(nock(baseUrl).get(url.path).reply(200, 'OK'));
});
it('should detect the correct urls', function (done) {
var urls = fs.readFileSync(__dirname + '/detect-urls.txt', 'utf-8').trim().split('\n');
return mocks;
}
fs.createReadStream(__dirname + '/detect.html')
.pipe(fs.createWriteStream(tmp + 'detect.html'))
describe('bolivar', function () {
var tmp;
before(function (done) {
// Tempdir
tmpdir({unsafeCleanup: true}, function (err, tmpPath) {
if(err) throw err;
mkdir(path.join(tmpPath, 'css')); // one already exists
tmp = tmpPath;
done();
});
// no real http calls here
nock.disableNetConnect();
});
// files: detect.html detect-urls.txt
it('should detect the correct urls', function (done) {
// mocking urls
var mocks = mockUrls('detect');
fs.createReadStream(path.join(__dirname, 'detect.html'))
.pipe(fs.createWriteStream(path.join(tmp, 'detect.html')))
;
bolivar({root: tmp})
.on('end', function () {
var missed = mocks.filter(function (url) {
return !url.isDone();
})
if (missed.length === 0) {
done();
} else {
done('Missed ' + missed.length + ' urls. One is ' + missed[0].pendingMocks());
}
})
.start()
;
});
// files: replace-ref.html replace.html replace-urls.txt
it('should replace the urls properly', function (done) {
mockUrls('replace');
fs.createReadStream(path.join(__dirname, 'replace.html'))
.pipe(fs.createWriteStream(path.join(tmp, 'replace.html')))
;
bolivar({root: tmp})
.on('url', function (data) {
var index = urls.indexOf(data.url);
if(index > -1) {
urls.splice(index, 1);
} else {
done('Matched ' + data.url + ' as URL.');
}
})
.on('end', function () {
if (urls.length === 0) {
var file = fs.readFileSync(path.join(tmp, 'replace.html'), 'utf-8');
var fRef = fs.readFileSync(path.join(__dirname, 'replace-ref.html'), 'utf-8');
if (file === fRef) {
done();
} else {
done('Missed ' + urls.length + ' urls.');
done(new Error('Wrong content'));
}

@@ -42,23 +87,54 @@ })

;
});
});
it('should replace the urls properly', function (done) {
fs.createReadStream(__dirname + '/replace.html')
.pipe(fs.createWriteStream(tmp + 'replace.html'))
;
// file: header.html
it('should detect headers properly of files without ending', function (done) {
var mocks = [
nock('http://fonts.googleapis.com')
.get('/css?family=Roboto')
.reply(200, 'OK', { 'Content-Type': 'text/css'}),
nock('http://test.de')
.get('/dadimg')
.reply(200, 'OK', { 'Content-Type': 'image/jpeg'}),
nock('http://www.google.de')
.get('/test')
.reply(200, 'OK', { 'Content-Type': 'text/html'})
];
bolivar({root: tmp})
.on('end', function () {
var file = fs.readFileSync(tmp + 'replace.html', 'utf-8');
var fRef = fs.readFileSync(__dirname + '/replace-ref.html', 'utf-8');
if (file === fRef) {
done();
} else {
done('Wrong content');
}
})
.start()
;
fs.createReadStream(path.join(__dirname, 'header.html'))
.pipe(fs.createWriteStream(path.join(tmp, 'header.html')))
;
})
var urls = [
'http://fonts.googleapis.com/css?family=Roboto',
'http://test.de/dadimg'
]
bolivar({root: tmp})
.on('url', function (data) {
var pos;
if (pos = urls.indexOf(data.url) > -1) {
urls = urls.splice(pos, 1);
} else {
done(new Error('False hit'));
}
})
.on('end', function () {
var missed = mocks.filter(function (url) {
return !url.isDone();
})
if (missed.length === 0) {
if (urls.length === 0) {
done();
} else {
done(new Error('Miss'));
}
} else {
done(new Error('Missed ' + missed.length + ' urls. One is ' + missed[0].pendingMocks()));
}
})
.start()
;
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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