Skip to content

Commit

Permalink
minify based on white list
Browse files Browse the repository at this point in the history
  • Loading branch information
siva-sundar committed Oct 27, 2017
1 parent 7d2a563 commit 80c7479
Show file tree
Hide file tree
Showing 9 changed files with 842 additions and 30 deletions.
527 changes: 527 additions & 0 deletions __snapshots__/hbs-minifier-plugin.test.js.snap

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions ember-cli-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
module.exports = function(defaults) {
let app = new EmberAddon(defaults, {
// Add options here
'ember-hbs-minifier': {
whiteList: {
elementNodes: ['pre', 'address'],
elementClassNames: ['description'],
components: ['foo-bar'],
partials: []
}
}
});

/*
Expand Down
52 changes: 35 additions & 17 deletions hbs-minifier-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@ const stripWhiteSpace = Util.stripWhiteSpace;
const isWhitespaceTextNode = Util.isWhitespaceTextNode;
const hasLeadingOrTrailingWhiteSpace = Util.hasLeadingOrTrailingWhiteSpace;
const stripNoMinifyBlocks = Util.stripNoMinifyBlocks;
const canTrimBlockStatementContent = Util.canTrimBlockStatementContent;
const canTrimElementNodeContent = Util.canTrimElementNodeContent;
const canTrimModule = Util.canTrimModule;
const assignDefaultValues = Util.assignDefaultValues;

class BasePlugin {
constructor(env) {
env = env || {};
this.moduleName = env.moduleName;
}

class HBSMinifierPlugin {

static createASTPlugin() {
static createASTPlugin(config) {
config = config || {};
let preStack = [];
let visitor = {
TextNode(node) {
Expand All @@ -21,13 +30,14 @@ class HBSMinifierPlugin {

BlockStatement: {
enter(node) {
if (node.path.original === 'no-minify') {
preStack.push(true);
let canTrim = canTrimBlockStatementContent(node, config);
if (!canTrim) {
preStack.push(node);
}
},

exit(node) {
if (node.path.original === 'no-minify') {
if (preStack[preStack.length - 1] === node) {
preStack.pop();
}
},
Expand Down Expand Up @@ -57,8 +67,10 @@ class HBSMinifierPlugin {

ElementNode: {
enter(node) {
if (node.tag === 'pre') {
preStack.push(true);
let canTrim = canTrimElementNodeContent(node, config);

if (!canTrim) {
preStack.push(node);
}

if (preStack.length !== 0) {
Expand All @@ -79,7 +91,7 @@ class HBSMinifierPlugin {
exit(node) {
node.children = stripNoMinifyBlocks(node.children);

if (node.tag === 'pre') {
if (preStack[preStack.length - 1] === node) {
preStack.pop();
}
}
Expand All @@ -88,15 +100,21 @@ class HBSMinifierPlugin {

return { name: 'hbs-minifier-plugin', visitor };
}
}

transform(ast) {
let plugin = HBSMinifierPlugin.createASTPlugin();

this.syntax.traverse(ast, plugin.visitor);
module.exports = function(config) {
config = config || {};
config = assignDefaultValues(config);

return ast;
}
return class HBSMinifierPlugin extends BasePlugin {

}
transform(ast) {

module.exports = HBSMinifierPlugin;
if (canTrimModule(this.moduleName, config)) {
let plugin = HBSMinifierPlugin.createASTPlugin(config);
this.syntax.traverse(ast, plugin.visitor);
}
return ast;
}
};
};
44 changes: 41 additions & 3 deletions hbs-minifier-plugin.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
'use strict';

/* eslint-env jest */

const defaultConfig = {
whiteList: {
elementNodes: ['pre', 'address'],
elementClassNames: ['description'],
components: ['foo-bar'],
partials: []
}
};
const glimmer = require('@glimmer/syntax');
const HbsMinifierPlugin = require('./hbs-minifier-plugin');
const HbsMinifierPlugin = require('./hbs-minifier-plugin')(defaultConfig);

it('collapses whitespace into single space character', () => {
assert(`{{foo}} \n\n \n{{bar}}`);
Expand Down Expand Up @@ -56,6 +63,34 @@ it('12. does not collapse   surrounding a text content into a single whites
</div>`);
});

it('13. does not minify `tagNames` specified in .hbs-minifyrc.js', function() {
assert(`<address>
Box 564,
<b>
Disneyland
</b>
<br>
<u> USA </u>
</address>`);
});

it('14. does not minify `classNames` specified in .hbs-minifyrc.js', function() {
assert(`<div class="description">
1
<span>
2
</span>
</div>`);
});

it('15. does not minify `components` specified in .hbs-minifyrc.js', function() {
assert(`{{#foo-bar}}
<span>
yield content
</span>
{{/foo-bar}}`);
});

function assert(template) {
let ast = process(template);
expect(ast).toMatchSnapshot();
Expand All @@ -65,9 +100,12 @@ function assert(template) {
}

function process(template) {
let plugin = () => {
return HbsMinifierPlugin.createASTPlugin(defaultConfig.whiteList);
};
return glimmer.preprocess(template, {
plugins: {
ast: [HbsMinifierPlugin.createASTPlugin]
ast: [plugin]
}
});
}
31 changes: 22 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,28 @@
module.exports = {
name: 'ember-hbs-minifier',

setupPreprocessorRegistry(type, registry) {
if (type === 'parent') {
let HbsMinifierPlugin = require('./hbs-minifier-plugin');
_getMinifierOptions() {
return (this.parent && this.parent.options) || (this.app && this.app.options) || {};
},

_setupPreprocessorRegistry(app) {
let registry = app.registry;
let options = this._getMinifierOptions(app);
let config = options['ember-hbs-minifier'] || {};

registry.add('htmlbars-ast-plugin', {
name: 'hbs-minifier-plugin',
plugin: HbsMinifierPlugin,
baseDir() { return __dirname; }
});
}
let HbsMinifierPlugin = require('./hbs-minifier-plugin')(config.whiteList || {});
registry.add('htmlbars-ast-plugin', {
name: 'hbs-minifier-plugin',
plugin: HbsMinifierPlugin,
baseDir() { return __dirname; }
});
},
included(app) {
this._super.included.apply(this, arguments);
/*
Calling setupPreprocessorRegistry in included hook since app.options is not accessible
Refer PR: https://github.com/ember-cli/ember-cli/pull/7059
*/
this._setupPreprocessorRegistry(app);
}
};
6 changes: 6 additions & 0 deletions tests/dummy/app/components/foo-bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Ember from 'ember';
import layout from '../templates/components/foo-bar';

export default Ember.Component.extend({
layout
});
8 changes: 8 additions & 0 deletions tests/dummy/app/templates/components/foo-bar.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
1
<span>
2
</span>
<span>
3
</span>
{{yield}}
55 changes: 55 additions & 0 deletions tests/integration/components/dummy-component-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,59 @@ describe('HBS Minifier plugin', function() {
expect(childNode.textContent.trim()).to.equal('1');
});

it('does not minify `tagNames` specified in .hbs-minifyrc.js', function() {
this.render(hbs `
<address>
Box 564,
<b>
Disneyland
</b>
<br>
<u> USA </u>
</address>`);

let childNodes = this.$('address')[0].childNodes;
expect(childNodes[0].textContent).to.equal('\n Box 564,\n ');
// ensuring the textContent is surrounded by whitespaces
expect(childNodes[1].textContent).to.equal('\n Disneyland\n ');
expect(childNodes[2].textContent).to.equal('\n ');
expect(childNodes[4].textContent).to.equal('\n ');
expect(childNodes[5].textContent).to.equal(' USA ');
});


it('does not minify `classNames` specified in .hbs-minifyrc.js', function() {
this.render(hbs `
<div class="description">
1
<span>
2
</span>
</div>`);

let childNodes = this.$('div')[0].childNodes;
expect(childNodes[0].textContent).to.equal('\n 1\n ');
expect(childNodes[1].textContent).to.equal('\n 2\n ');
expect(childNodes[2].textContent).to.equal('\n');
});

it('does not minify `components` specified in .hbs-minifyrc.js', function() {
this.render(hbs `
{{#foo-bar}}
<span>
yield content
</span>
{{/foo-bar}}`);

let childNodes = this.$('div')[0].childNodes;
expect(childNodes[0].textContent).to.equal('1\n');
expect(childNodes[1].textContent).to.equal('\n 2\n');
expect(childNodes[3].textContent).to.equal('\n 3\n');
expect(childNodes[4].textContent).to.equal('\n');
expect(childNodes[5].textContent).to.equal(' ');
expect(childNodes[6].textContent).to.equal('\n yield content\n ');
expect(childNodes[7].textContent).to.equal('\n');
});


});
Loading

0 comments on commit 80c7479

Please sign in to comment.