gulp-processhtml
Advanced tools
| <!doctype html> | ||
| <html> | ||
| <head></head> | ||
| <body> | ||
| <script src="app.js"></script> | ||
| </body> | ||
| </html> |
| <!doctype html> | ||
| <html> | ||
| <head> | ||
| <link rel="stylesheet" href="style.min.css"> | ||
| </head> | ||
| <body> | ||
| <script src="app.min.js"></script> | ||
| </body> | ||
| </html> |
| <!doctype html> | ||
| <html> | ||
| <head> | ||
| <style> | ||
| body { background: teal; } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <h1 class="title">This is a title</h1> | ||
| <section><p>This is a section</p></section> | ||
| </body> | ||
| </html> |
| <!doctype html> | ||
| <html> | ||
| <head></head> | ||
| <body> | ||
| </body> | ||
| </html> |
| <!doctype html> | ||
| <html> | ||
| <head></head> | ||
| <body> | ||
| <!-- build:[src] app.js --> | ||
| <script src="livereload.js"></script> | ||
| <!-- /build --> | ||
| </body> | ||
| </html> |
| <!doctype html> | ||
| <html> | ||
| <head> | ||
| <!-- build:css style.min.css --> | ||
| <link rel="stylesheet" href="style.css"> | ||
| <!-- /build --> | ||
| </head> | ||
| <body> | ||
| <!-- build:js app.min.js --> | ||
| <script src="app.js"></script> | ||
| <!-- /build --> | ||
| </body> | ||
| </html> |
| <!doctype html> | ||
| <html> | ||
| <head> | ||
| <style> | ||
| <!-- build:include includes/styles.css --> | ||
| <!-- Me thinks it should replace whatever is in between the build tags --> | ||
| <div>FOO</div> | ||
| <!-- /build --> | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <!-- build:include includes/title.html --><!-- /build --> | ||
| <!-- build:include includes/section.html --><!-- /build --> | ||
| </body> | ||
| </html> |
| <section><p>This is a section</p></section> |
| body { background: teal; } |
| <h1 class="title">This is a title</h1> |
| <!doctype html> | ||
| <html> | ||
| <head></head> | ||
| <body> | ||
| <!-- build:remove --> | ||
| <script src="livereload.js"></script> | ||
| <!-- /build --> | ||
| </body> | ||
| </html> |
+48
| 'use strict'; | ||
| var assert = require('assert') | ||
| , os = require('os') | ||
| , fs = require('fs') | ||
| , path = require('path') | ||
| , through = require('through2') | ||
| , gulp = require('gulp') | ||
| , htmlprocessor = require('../'); | ||
| require('mocha'); | ||
| function process(input, options, output, done) { | ||
| options = options || {}; | ||
| gulp | ||
| .src(input) | ||
| .pipe(htmlprocessor(options)) | ||
| .pipe(through.obj(function (file, enc) { | ||
| var actual = file.contents.toString(enc); | ||
| fs.readFile(output, function (err, data) { | ||
| assert.deepEqual(actual, data.toString(enc)); | ||
| done(); | ||
| }); | ||
| })); | ||
| } | ||
| describe('gulp-processhtml', function () { | ||
| it('should process html comments', function (done) { | ||
| process('test/fixtures/basic.html', null, 'test/expected/basic.html', done); | ||
| }); | ||
| it('should remove content', function (done) { | ||
| process('test/fixtures/remove.html', null, 'test/expected/remove.html', done); | ||
| }); | ||
| it('should transform attributes', function (done) { | ||
| process('test/fixtures/attributes.html', null, 'test/expected/attributes.html', done); | ||
| }); | ||
| it('should include files', function (done) { | ||
| process('test/fixtures/include.html', null, 'test/expected/include.html', done); | ||
| }); | ||
| }); |
+19
-167
@@ -1,181 +0,33 @@ | ||
| var through = require('through') | ||
| , os = require('os') | ||
| , path = require('path') | ||
| var through = require('through2') | ||
| , gutil = require('gulp-util') | ||
| , PluginError = gutil.PluginError | ||
| , File = gutil.File | ||
| , fs = require('fs') | ||
| , transformer; | ||
| , HTMLProcessor = require('htmlprocessor') | ||
| , PluginError = gutil.PluginError; | ||
| module.exports = function(fileName, options) { | ||
| transformer = { | ||
| replace: function (content, section, line, asset) { | ||
| return content.replace(line, section.indent + asset); | ||
| }, | ||
| var processor = new HTMLProcessor(options); | ||
| attr: function (content, section, line, lineContent) { | ||
| var reg, replaced; | ||
| // only run attr replacer for the block content | ||
| reg = new RegExp('(\\s*(?:' + section.attr + ')=[\'"])(.*?)(".*)', 'gi'); | ||
| replaced = lineContent.replace(reg, function (wholeMatch, start, asset, end) { | ||
| // check if only the path was provided to leave the original asset name intact | ||
| asset = (!path.extname(section.asset) && /\//.test(section.asset))? section.asset + path.basename(asset) : section.asset; | ||
| return start + asset + end; | ||
| }); | ||
| return content.replace(line, replaced); | ||
| }, | ||
| function processContent(file, enc, cb) { | ||
| var content; | ||
| css: function (content, section, line) { | ||
| return transformer.replace(content, section, line, '<link rel="stylesheet" href="' + section.asset + '">'); | ||
| }, | ||
| js: function (content, section, line) { | ||
| return transformer.replace(content, section, line, '<script src="' + section.asset + '"></script>'); | ||
| }, | ||
| remove: function (content, section, line) { | ||
| var escaped = line.replace(/([.?*+\^=!:$\[\]\\(){}|\-])/g, '\\$1') | ||
| , regReplace = new RegExp(escaped.replace(/^\s*|[\r\n]+\s*/g, '\\s*').replace(/\n{1}$/g, '\\n')); | ||
| return content.replace(regReplace, ''); | ||
| }, | ||
| include: function (content, section, line, asset) { | ||
| var file = fs.readFileSync(path.join(process.cwd(), section.asset), 'utf8') | ||
| , i | ||
| , l; | ||
| l = line.length; | ||
| while ((i = content.indexOf(line)) !== -1) { | ||
| content = content.substring(0, i) + | ||
| section.indent + file.toString().trim() + content.substring(i + l); | ||
| } | ||
| return content; | ||
| } | ||
| }; | ||
| function findSections(content, marker) { | ||
| var lines | ||
| , line | ||
| , i | ||
| , l | ||
| , sections = [] | ||
| , section | ||
| , regStart | ||
| , regEnd | ||
| , inside | ||
| , buildStart | ||
| , buildEnd | ||
| , attr; | ||
| regStart = new RegExp('<!--\\s*' + marker + ':(\\[?[\\w-]+\\]?)(?::(\\w+))?(?:\\s*([^\\s]+)\\s*-->)*'); | ||
| regEnd = new RegExp('(?:<!--\\s*)*\\/' + marker + '\\s*-->'); | ||
| lines = content.split(/\n/); | ||
| l = lines.length; | ||
| for (i = 0; i < l; i += 1) { | ||
| line = lines[i]; | ||
| buildStart = line.match(regStart); | ||
| buildEnd = regEnd.test(line); | ||
| if (buildStart) { | ||
| inside = true; | ||
| attr = buildStart[1].match(/(?:\[([\w-]+)\])*/)[1]; | ||
| section = { | ||
| type: attr ? 'attr' : buildStart[1], | ||
| attr: attr, | ||
| target: buildStart[2], | ||
| asset: buildStart[3], | ||
| indent: /^\s*/.exec(line)[0], | ||
| raw: [] | ||
| }; | ||
| } | ||
| if (inside && section) { | ||
| section.raw.push(line); | ||
| } | ||
| if (inside && buildEnd) { | ||
| inside = false; | ||
| sections.push(section); | ||
| } | ||
| } | ||
| return sections; | ||
| } | ||
| module.exports = function(fileName, opt){ | ||
| var buffer = [] | ||
| , firstFile; | ||
| if (!fileName) { | ||
| throw new PluginError('gulp-processhtml', 'Missing fileName option for gulp-processhtml'); | ||
| } | ||
| opt = opt || {}; | ||
| opt.newLine = opt.newLine || gutil.linefeed; | ||
| opt.marker = opt.marker || 'build'; | ||
| function processContents(file) { | ||
| var contents | ||
| , sections | ||
| , section | ||
| , line | ||
| , content | ||
| , i | ||
| , l; | ||
| if (file.isNull()) { | ||
| return; | ||
| } | ||
| if (file.isStream()) { | ||
| return this.emit('error', new PluginError('gulp-processhtml', 'Streaming not supported')); | ||
| this.emit('error', new PluginError('gulp-processhtml', 'Streams aren\'t supported')); | ||
| return cb(); | ||
| } | ||
| if (!firstFile) { | ||
| firstFile = file; | ||
| } | ||
| if (file.isBuffer()) { | ||
| content = processor.processContent(file.contents.toString(enc), file.path); | ||
| contents = file.contents.toString('utf8').replace(/\r\n/g, '\n'); | ||
| sections = findSections(contents, opt.marker); | ||
| if (options && options.process) { | ||
| content = processor.template(content, processor.data, options.templateSettings); | ||
| } | ||
| l = sections.length; | ||
| for (i = 0; i < l; i += 1) { | ||
| section = sections[i]; | ||
| line = section.raw.join(opt.newLine); | ||
| content = section.raw.slice(1, -1).join(opt.newLine); | ||
| contents = transformer[section.type](contents, section, line, content); | ||
| file.contents = new Buffer(content, enc); | ||
| } | ||
| buffer.push(contents); | ||
| } | ||
| function endStream(){ | ||
| var joinedContents | ||
| , joinedPath | ||
| , joinedFile; | ||
| this.push(file); | ||
| cb(); | ||
| }; | ||
| if (buffer.length === 0) { | ||
| return this.emit('end'); | ||
| } | ||
| joinedContents = buffer.join(opt.newLine); | ||
| joinedPath = path.join(firstFile.base, fileName); | ||
| joinedFile = new File({ | ||
| cwd: firstFile.cwd, | ||
| base: firstFile.base, | ||
| path: joinedPath, | ||
| contents: new Buffer(joinedContents) | ||
| }); | ||
| this.emit('data', joinedFile); | ||
| this.emit('end'); | ||
| } | ||
| return through(processContents, endStream); | ||
| return through.obj(processContent); | ||
| }; | ||
+10
-6
| { | ||
| "name": "gulp-processhtml", | ||
| "version": "0.0.6", | ||
| "version": "1.0.0", | ||
| "description": "Process html files at build time to modify them as you wish", | ||
@@ -15,11 +15,15 @@ "repository": { | ||
| "keywords": [ | ||
| "gulpplugin" | ||
| "gulpplugin", | ||
| "htmlprocessor", | ||
| "process", | ||
| "html" | ||
| ], | ||
| "dependencies": { | ||
| "through": "*", | ||
| "gulp-util": "*" | ||
| "gulp-util": "latest", | ||
| "htmlprocessor": "latest", | ||
| "through2": "latest" | ||
| }, | ||
| "devDependencies": { | ||
| "mocha": "*", | ||
| "should": "*" | ||
| "gulp": "latest", | ||
| "mocha": "latest" | ||
| }, | ||
@@ -26,0 +30,0 @@ "author": "Julien Castelain <jcastelain@gmail.com> (http://www.punkscum.org)", |
+20
-14
| #gulp-processhtml | ||
| This is a port of Denis Ciccale's [grunt-processhtml](https://github.com/dciccale/grunt-processhtml) | ||
| [Grunt](http://www.gruntjs.com) plugin for [gulp.js](http://www.gulpjs.com). | ||
| This gulp-plugin uses Denis Ciccale's [node-htmlprocessor](https://github.com/dciccale/node-htmlprocessor), | ||
| to process/transform html files. | ||
| Some things are still missing (includes and templates) | ||
| #Usage | ||
| ###Install the dependencies: | ||
@@ -20,15 +16,16 @@ | ||
| var gulp = require('gulp') | ||
| , processhtml = require('gulp-processhtml'); | ||
| , processhtml = require('gulp-processhtml') | ||
| , opts = { /* plugin options */ }; | ||
| gulp.task('default', function () { | ||
| gulp.src('index.html') | ||
| .pipe(processhtml('test.html')) | ||
| .pipe(gulp.dest('./')); | ||
| gulp.src('./*.html') | ||
| .pipe(processhtml(opts)) | ||
| .pipe(gulp.dest('dist')); | ||
| }); | ||
| ``` | ||
| ###Example usage | ||
| ###Example usage | ||
| You might need to change some attributes in your html, when you're releasing | ||
| for a different environment. | ||
| for a different environment. | ||
@@ -46,7 +43,7 @@ Using this plugin, you can transform this: | ||
| <body> | ||
| <!--build:js app.min.js--> | ||
| <script src="app.js"></script> | ||
| <!--/build --> | ||
| <!--build:remove--> | ||
@@ -73,2 +70,11 @@ <script src="http://192.168.0.1:35729/livereload.js?snipver=1"></script> | ||
| ###Credits | ||
| [Denis Ciccale](https://twitter.com/tdecs) | ||
| ###Note | ||
| Since I don't usually use [Gulp](http://gulpjs.com) and prefer [G.N.U. Make](http://www.gnu.org/software/make), | ||
| feel free to ask me to transfer this repo to your GitHub account if you want to maintain it. | ||
| <section> | ||
| <p>This is a section</p> | ||
| </section> |
| body { background: teal; } |
| <h1 class="title">This is a title</h1> |
-282
| var processhtml = require('../') | ||
| , should = require('should') | ||
| , os = require('os') | ||
| , path = require('path') | ||
| , File = require('gulp-util').File | ||
| , Buffer = require('buffer').Buffer; | ||
| require('mocha'); | ||
| describe('gulp-processhtml', function() { | ||
| describe('processhtml()', function() { | ||
| it('should processhtml comments', function(done) { | ||
| var stream = processhtml('processed.html') | ||
| , fakeFile = new File({ | ||
| cwd: './', | ||
| base: './', | ||
| path: './file.html', | ||
| contents: new Buffer([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head>', | ||
| ' <!-- build:css style.min.css -->', | ||
| ' <link rel="stylesheet" href="style.css">', | ||
| ' <!-- /build -->', | ||
| '</head>', | ||
| '<body>', | ||
| ' <!-- build:js app.min.js -->', | ||
| ' <script src="app.js"></script>', | ||
| ' <!-- /build -->', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')) | ||
| }); | ||
| stream.on('data', function (newFile) { | ||
| var newFilePath | ||
| , expectedFilePath; | ||
| should.exist(newFile); | ||
| should.exist(newFile.path); | ||
| should.exist(newFile.relative); | ||
| should.exist(newFile.contents); | ||
| newFilePath = path.resolve(newFile.path); | ||
| expectedFilePath = path.resolve('./processed.html'); | ||
| newFilePath.should.equal(expectedFilePath); | ||
| newFile.relative.should.equal('processed.html'); | ||
| Buffer.isBuffer(newFile.contents).should.equal(true); | ||
| String(newFile.contents).should.equal([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head>', | ||
| ' <link rel="stylesheet" href="style.min.css">', | ||
| '</head>', | ||
| '<body>', | ||
| ' <script src="app.min.js"></script>', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')); | ||
| done(); | ||
| }); | ||
| stream.write(fakeFile); | ||
| stream.end(); | ||
| }); | ||
| it('should handle carriage returns', function(done) { | ||
| var stream = processhtml('processed.html') | ||
| , fakeFile = new File({ | ||
| cwd: './', | ||
| base: './', | ||
| path: './file.html', | ||
| contents: new Buffer([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head>', | ||
| ' <!-- build:css style.min.css -->', | ||
| ' <link rel="stylesheet" href="style.css">', | ||
| ' <!-- /build -->', | ||
| '</head>', | ||
| '<body>', | ||
| ' <!-- build:js app.min.js -->', | ||
| ' <script src="app.js"></script>', | ||
| ' <!-- /build -->', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\r\n')) | ||
| }); | ||
| stream.on('data', function (newFile) { | ||
| var newFilePath | ||
| , expectedFilePath; | ||
| should.exist(newFile); | ||
| should.exist(newFile.path); | ||
| should.exist(newFile.relative); | ||
| should.exist(newFile.contents); | ||
| newFilePath = path.resolve(newFile.path); | ||
| expectedFilePath = path.resolve('./processed.html'); | ||
| newFilePath.should.equal(expectedFilePath); | ||
| newFile.relative.should.equal('processed.html'); | ||
| Buffer.isBuffer(newFile.contents).should.equal(true); | ||
| String(newFile.contents).should.equal([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head>', | ||
| ' <link rel="stylesheet" href="style.min.css">', | ||
| '</head>', | ||
| '<body>', | ||
| ' <script src="app.min.js"></script>', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')); | ||
| done(); | ||
| }); | ||
| stream.write(fakeFile); | ||
| stream.end(); | ||
| }); | ||
| it('should remove content', function(done) { | ||
| var stream = processhtml('processed.html') | ||
| , fakeFile = new File({ | ||
| cwd: './', | ||
| base: './', | ||
| path: './file.html', | ||
| contents: new Buffer([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head></head>', | ||
| '<body>', | ||
| ' <!-- build:remove -->', | ||
| ' <script src="livereload.js"></script>', | ||
| ' <!-- /build -->', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')) | ||
| }); | ||
| stream.on('data', function (newFile) { | ||
| var newFilePath | ||
| , expectedFilePath; | ||
| should.exist(newFile); | ||
| should.exist(newFile.path); | ||
| should.exist(newFile.relative); | ||
| should.exist(newFile.contents); | ||
| Buffer.isBuffer(newFile.contents).should.equal(true); | ||
| String(newFile.contents).should.equal([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head></head>', | ||
| '<body>', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')); | ||
| done(); | ||
| }); | ||
| stream.write(fakeFile); | ||
| stream.end(); | ||
| }); | ||
| it('should transform attributes', function(done) { | ||
| var stream = processhtml('processed.html') | ||
| , fakeFile = new File({ | ||
| cwd: './', | ||
| base: './', | ||
| path: './file.html', | ||
| contents: new Buffer([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head></head>', | ||
| '<body>', | ||
| ' <!-- build:[src] app.js -->', | ||
| ' <script src="livereload.js"></script>', | ||
| ' <!-- /build -->', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')) | ||
| }); | ||
| stream.on('data', function (newFile) { | ||
| var newFilePath | ||
| , expectedFilePath; | ||
| should.exist(newFile); | ||
| should.exist(newFile.path); | ||
| should.exist(newFile.relative); | ||
| should.exist(newFile.contents); | ||
| Buffer.isBuffer(newFile.contents).should.equal(true); | ||
| String(newFile.contents).should.equal([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head></head>', | ||
| '<body>', | ||
| ' <script src="app.js"></script>', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')); | ||
| done(); | ||
| }); | ||
| stream.write(fakeFile); | ||
| stream.end(); | ||
| }); | ||
| it('should include files', function(done) { | ||
| var stream = processhtml('processed.html') | ||
| , fakeFile = new File({ | ||
| cwd: './', | ||
| base: './', | ||
| path: './file.html', | ||
| contents: new Buffer([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head>', | ||
| ' <style>', | ||
| ' <!-- build:include test/fixtures/styles.css -->', | ||
| ' <!-- Me thinks it should replace whatever is in between the build tags -->', | ||
| ' <div>FOO</div>', | ||
| ' <!-- /build -->', | ||
| ' </style>', | ||
| '</head>', | ||
| '<body>', | ||
| '<!-- build:include test/fixtures/title.html --><!-- /build -->', | ||
| '<!-- build:include test/fixtures/section.html --><!-- /build -->', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')) | ||
| }); | ||
| stream.on('data', function (newFile) { | ||
| var newFilePath | ||
| , expectedFilePath; | ||
| should.exist(newFile); | ||
| should.exist(newFile.path); | ||
| should.exist(newFile.relative); | ||
| should.exist(newFile.contents); | ||
| Buffer.isBuffer(newFile.contents).should.equal(true); | ||
| String(newFile.contents).should.equal([ | ||
| '<!doctype html>', | ||
| '<html>', | ||
| '<head>', | ||
| ' <style>', | ||
| ' body { background: teal; }', | ||
| ' </style>', | ||
| '</head>', | ||
| '<body>', | ||
| '<h1 class="title">This is a title</h1>', | ||
| '<section>', | ||
| ' <p>This is a section</p>', | ||
| '</section>', | ||
| '</body>', | ||
| '</html>' | ||
| ].join('\n')); | ||
| done(); | ||
| }); | ||
| stream.write(fakeFile); | ||
| stream.end(); | ||
| }); | ||
| }); | ||
| }); | ||
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
17
88.89%1
-50%0
-100%78
8.33%6864
-57.58%3
50%61
-84.36%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
Updated