-
-
Save lyzadanger/e4641adac704431c62c8 to your computer and use it in GitHub Desktop.
| /* global Buffer, console */ | |
| /** | |
| * Strip inline <script> elements and push each | |
| * <script> tag's contents to `file.scripts` | |
| * (Array; each element is the contents of a script element) | |
| */ | |
| 'use strict'; | |
| var through = require('through2'); | |
| var gutil = require('gulp-util'); | |
| var cheerio = require('cheerio'); | |
| module.exports = function gulpStripScripts(opts) { | |
| opts = opts || {}; | |
| opts.property = opts.property || 'scripts'; | |
| return through.obj(function(file, enc, cb) { | |
| var $, content; | |
| if (file.isNull()) { | |
| this.push(file); | |
| return cb(); | |
| } | |
| if (file.isStream()) { | |
| cb(new gutil.PluginError('stripScripts', 'Streaming not supported')); | |
| return; | |
| } | |
| content = file.contents.toString(); | |
| try { | |
| $ = cheerio.load(content); | |
| } catch (e) { | |
| console.warn(e); | |
| return; | |
| } | |
| file[opts.property] = (typeof file[opts.property] !== 'undefined' && | |
| Array.isArray(file[opts.property])) ? file[opts.property] : []; | |
| $('script').not('[src]').each(function(i, elem) { | |
| file[opts.property].push($(elem).text()); | |
| content = content.replace($(elem).toString(), ''); | |
| }); | |
| file.contents = Buffer(content); | |
| this.push(file); | |
| cb(); | |
| }); | |
| }; |
@erikjung The traversal is necessary to a certain extent because I'm operating on file.contents ultimately, not the parsed DOM ($). Because the file's content string to cheerio DOM to string again is by no means idempotent (and a lot of the files we're processing are fragmentary HBS templates), it doesn't make sense to operate directly on $ (i.e. remove the <script> elements using the cheerio API and then toString at the end). I also need to extract the script but not the tags (ergo the .text() invocation).
However, you're right, I can certainly tighten up that selector! Updated to
$('script').not('[src]').each(function(i, elem) {
file[opts.property].push($(elem).text());
content = content.replace($(elem).toString(), '');
});That's a very valid point about file.contents.toString() !== $.html().
To piggy-back on the [src] selector exclusion, it might be nice to allow embedded templates to pass through as well by acknowledging the type attribute in some way...
/**
* All scripts excluding:
* a) those with a "src" attribute, and/or
* b) those with a "type" attribute having a value other than "text/javascript"
*/
$('script').not('[src], [type][type!="text/javascript"]').each(function(i, elem) {
// ...
});To support cases such as this: http://jsbin.com/ciseyicuto/1/edit?html,js
Would it be more reliable to use Cheerio to transform the entire "DOM" of the file by removing all
<script>swithout thesrcattribute instead of iterating over each one and doing a string manipulation each time?Example: