can-compile
Advanced tools
Comparing version 0.6.0 to 0.7.0
module.exports = function (grunt) { | ||
// Project configuration. | ||
grunt.initConfig({ | ||
cancompile: { | ||
dist: { | ||
src: ['**/*.ejs', '**/*.mustache'], | ||
// Change into the example folder | ||
out: 'production/views.production.js' | ||
} | ||
}, | ||
concat: { | ||
dist: { | ||
src: [ | ||
'js/base.js', | ||
'../resources/js/can.jquery.1.1.2.js', | ||
'../resources/js/can.view.mustache.1.1.2.js', | ||
'js/can.localstorage.js', | ||
'js/app.js', | ||
'<%= cancompile.dist.out %>' // The compiled views | ||
], | ||
dest: 'production/production.js' | ||
} | ||
}, | ||
uglify: { | ||
dist: { | ||
files: { | ||
'production/production.min.js': ['<%= concat.dist.dest %>'] | ||
} | ||
} | ||
} | ||
}); | ||
// Project configuration. | ||
grunt.initConfig({ | ||
cancompile: { | ||
options: { | ||
version: '2.1.1' | ||
}, | ||
dist: { | ||
src: ['**/*.ejs', '**/*.mustache', '**/*.stache'], | ||
dest: 'dist/views.production.js' | ||
} | ||
}, | ||
concat: { | ||
dist: { | ||
src: [ | ||
'bower_components/todomvc-common/base.js', | ||
'bower_components/jquery/jquery.js', | ||
'bower_components/canjs/can.jquery.js', | ||
'bower_components/canjs-localstorage/can.localstorage.js', | ||
'js/models/todo.js', | ||
'js/components/todo-app.js', | ||
'js/app.js', | ||
'<%= cancompile.dist.dest %>' // The compiled views | ||
], | ||
dest: 'dist/production.js' | ||
} | ||
}, | ||
uglify: { | ||
dist: { | ||
files: { | ||
'dist/production.min.js': ['<%= concat.dist.dest %>'] | ||
} | ||
} | ||
} | ||
}); | ||
// Default task. | ||
grunt.registerTask('default', ['cancompile', 'concat', 'uglify']); | ||
// Default task. | ||
grunt.registerTask('default', ['cancompile', 'concat', 'uglify']); | ||
grunt.loadTasks('../tasks'); | ||
grunt.loadNpmTasks('grunt-contrib-uglify'); | ||
grunt.loadNpmTasks('grunt-contrib-concat'); | ||
}; | ||
grunt.loadTasks('../tasks'); | ||
grunt.loadNpmTasks('grunt-contrib-uglify'); | ||
grunt.loadNpmTasks('grunt-contrib-concat'); | ||
}; |
@@ -1,181 +0,15 @@ | ||
/*global can */ | ||
(function (namespace, undefined) { | ||
/* global $, can */ | ||
(function () { | ||
'use strict'; | ||
// Basic Todo entry model | ||
// { text: 'todo', complete: false } | ||
var Todo = can.Model.LocalStorage({ | ||
storageName: 'todos-canjs' | ||
}, { | ||
// Returns if this instance matches a given filter | ||
// (currently `active` and `complete`) | ||
matches : function() { | ||
var filter = can.route.attr('filter'); | ||
return !filter || (filter === 'active' && !this.attr('complete')) | ||
|| (filter === 'completed' && this.attr('complete')); | ||
} | ||
}); | ||
// List for Todos | ||
Todo.List = can.Model.List({ | ||
completed: function() { | ||
var completed = 0; | ||
this.each(function(todo) { | ||
completed += todo.attr('complete') ? 1 : 0; | ||
}); | ||
return completed; | ||
}, | ||
remaining: function() { | ||
return this.attr('length') - this.completed(); | ||
}, | ||
allComplete: function() { | ||
return this.attr('length') === this.completed(); | ||
} | ||
}); | ||
namespace.Models = namespace.Models || {}; | ||
namespace.Models.Todo = Todo; | ||
})(this); | ||
/*global can, Models, $ */ | ||
(function (namespace, undefined) { | ||
'use strict'; | ||
var ENTER_KEY = 13; | ||
var Todos = can.Control({ | ||
// Default options | ||
defaults : { | ||
view : 'views/todos.ejs' | ||
} | ||
}, { | ||
// Initialize the Todos list | ||
init: function() { | ||
// Render the Todos | ||
this.element.append(can.view(this.options.view, this.options)); | ||
}, | ||
// Listen for when a new Todo has been entered | ||
'#new-todo keyup': function(el, e) { | ||
var value = can.trim(el.val()); | ||
if (e.keyCode === ENTER_KEY && value !== '') { | ||
new Models.Todo({ | ||
text : value, | ||
complete : false | ||
}).save(function () { | ||
el.val(''); | ||
}); | ||
} | ||
}, | ||
// Handle a newly created Todo | ||
'{Models.Todo} created': function(list, e, item) { | ||
this.options.todos.push(item); | ||
// Reset the filter so that you always see your new todo | ||
this.options.state.attr('filter', ''); | ||
}, | ||
// Listener for when the route changes | ||
'{state} change' : function() { | ||
// Remove the `selected` class from the old link and add it to the link for the current location hash | ||
this.element.find('#filters').find('a').removeClass('selected') | ||
.end().find('[href="' + window.location.hash + '"]').addClass('selected'); | ||
}, | ||
// Listen for editing a Todo | ||
'.todo dblclick': function(el) { | ||
el.data('todo').attr('editing', true).save(function() { | ||
el.children('.edit').focus(); | ||
}); | ||
}, | ||
// Update a todo | ||
updateTodo: function(el) { | ||
var value = can.trim(el.val()), | ||
todo = el.closest('.todo').data('todo'); | ||
// If we don't have a todo we don't need to do anything | ||
if(!todo) return; | ||
if (value === '') { | ||
todo.destroy(); | ||
} else { | ||
todo.attr({ | ||
editing : false, | ||
text : value | ||
}).save(); | ||
} | ||
}, | ||
// Listen for an edited Todo | ||
'.todo .edit keyup': function(el, e) { | ||
if (e.keyCode === ENTER_KEY) { | ||
this.updateTodo(el); | ||
} | ||
}, | ||
'.todo .edit focusout' : "updateTodo", | ||
// Listen for the toggled completion of a Todo | ||
'.todo .toggle click': function(el) { | ||
el.closest('.todo').data('todo') | ||
.attr('complete', el.is(':checked')) | ||
.save(); | ||
}, | ||
// Listen for a removed Todo | ||
'.todo .destroy click': function(el) { | ||
el.closest('.todo').data('todo').destroy(); | ||
}, | ||
// Listen for toggle all completed Todos | ||
'#toggle-all click': function (el) { | ||
var toggle = el.prop('checked'); | ||
can.each(this.options.todos, function(todo) { | ||
todo.attr('complete', toggle).save(); | ||
}); | ||
}, | ||
// Listen for removing all completed Todos | ||
'#clear-completed click': function() { | ||
for (var i = this.options.todos.length - 1, todo; i > -1 && (todo = this.options.todos[i]); i--) { | ||
if (todo.attr('complete')) { | ||
todo.destroy(); | ||
} | ||
} | ||
} | ||
}); | ||
namespace.Todos = Todos; | ||
})(this); | ||
(function() { | ||
$(function() { | ||
$('body').append(can.view('views/app.ejs', {})); | ||
$(function () { | ||
// Set up a route that maps to the `filter` attribute | ||
can.route( ':filter' ); | ||
// Delay routing until we initialized everything | ||
can.route.ready(false); | ||
can.route(':filter'); | ||
// View helper for pluralizing strings | ||
Mustache.registerHelper('plural', function(str, count) { | ||
return str + (count !== 1 ? 's' : ''); | ||
}); | ||
// Render #app-template | ||
$('#todoapp').html(can.view('views/todos.mustache', {})); | ||
// Initialize the app | ||
Models.Todo.findAll({}, function(todos) { | ||
new Todos('#todoapp', { | ||
todos: todos, | ||
state : can.route, | ||
view : 'views/todos.mustache' | ||
}); | ||
}); | ||
// Now we can start routing | ||
can.route.ready(true); | ||
// Start the router | ||
can.route.ready(); | ||
}); | ||
})(); | ||
})(); |
{ | ||
"name" : "can-compile-example", | ||
"description" : "An example for can-compile", | ||
"version" : "0.1.0", | ||
"homepage" : "http://daffl.github.com/can-compile", | ||
"author" : { | ||
"name" : "David Luecke", | ||
"email" : "daff@neyeon.com", | ||
"web" : "http://daffl.github.com" | ||
"name": "can-compile-example", | ||
"version": "0.6.0", | ||
"description": "CanJS TodoMVC example using can-comile", | ||
"main": "Gruntfile.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"engines" : { | ||
"node" : "~0.8" | ||
}, | ||
"devDependencies" : { | ||
"grunt": "~ 0.4.0", | ||
"grunt-contrib-uglify": "*", | ||
"grunt-contrib-concat": "*" | ||
"author": "David Luecke <daff@neyeon.com", | ||
"license": "MIT", | ||
"dependencies": { | ||
"grunt": "^0.4.5", | ||
"grunt-contrib-concat": "^0.4.0", | ||
"grunt-contrib-uglify": "^0.4.0" | ||
} | ||
} | ||
} |
@@ -1,3 +0,7 @@ | ||
# Can-Compile TodoMVC example | ||
# CanJS TodoMVC Example | ||
> CanJS is a MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy. | ||
> _[CanJS - canjs.com](http://canjs.com)_ | ||
This folder mainly contains the [TodoMVC](http://todomvc.com) example for | ||
@@ -10,2 +14,45 @@ [CanJS](http://todomvc.com/labs/architecture-examples/canjs/) and a Mustache and EJS CanJS view | ||
You will notice that the production version won't make any requests to external view files and performs about | ||
20% faster. | ||
20% faster. | ||
## Learning CanJS | ||
The [CanJS website](http://canjs.com) is a great resource for getting started. | ||
Here are some links you may find helpful: | ||
* [CanJS guides documentation](http://canjs.com/guides/index.html) | ||
* [API documentation](http://canjs.com/docs/index.html) | ||
* [Blog](http://bitovi.com/blog/tag/canjs) | ||
* [Getting started video](http://www.youtube.com/watch?v=GdT4Oq6ZQ68) | ||
Get help from other CanJS users: | ||
* [CanJS on StackOverflow](http://stackoverflow.com/questions/tagged/canjs) | ||
* [CanJS Forums](http://forum.javascriptmvc.com/#Forum/canjs) | ||
* [CanJS on Twitter](http://twitter.com/canjs) | ||
* [#canjs](http://webchat.freenode.net/?channels=canjs) IRC channel on Freenode | ||
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ | ||
## Implementation | ||
The CanJS TodoMVC example uses [can.Component](http://canjs.com/guides/Components.html) introduced in CanJS 2.0. | ||
can.Component supports declarative view bindings using Mustache/Handlebars as the template syntax. | ||
Version 2 is mostly backwards compatible with previous 1.1.x version. For alternative architecture examples have a look at | ||
the [TodoMVC 1.2.0 CanJS example](https://github.com/tastejs/todomvc/tree/1.2.0/architecture-examples/canjs). | ||
### CanJS and JavaScriptMVC | ||
CanJS is the extracted, more modern and more library-like MVC parts of [JavaScriptMVC](http://javascriptmvc.com), formerly known as jQueryMX. | ||
JavaScriptMVC 3.3 uses CanJS for the MVC structure so this TodoMVC example applies to JavaScriptMVC as well. | ||
Additionally, JavaScriptMVC contains: | ||
- [CanJS](http://canjs.com) - For the MVC parts | ||
- [jQuery++](http://jquerypp.com) - jQuery's missing utils and special events | ||
- [StealJS](http://javascriptmvc.com/docs.html#!stealjs) - A JavaScript package manager | ||
- [DocumentJS](http://javascriptmvc.com/docs.html#!DocumentJS) - A documentation engine | ||
- [FuncUnit](http://funcunit.com) - jQuery style functional unit testing |
@@ -35,3 +35,7 @@ 'use strict'; | ||
visit(options.version || 'latest', function(error, win) { | ||
if(!options.version) { | ||
return callback(new Error('A specific CanJS version number must be passed to compile views.')); | ||
} | ||
visit(options.version, function(error, win) { | ||
if (typeof options.log === 'function') { | ||
@@ -58,6 +62,10 @@ options.log('Compiling ' + filename); | ||
// TODO throw error if type is not registered | ||
var script = can.view.types["." + type].script(id, text); | ||
var script = can.view.types["." + type] ? can.view.types["." + type].script(id, text) : null; | ||
callback(null, script, id); | ||
callback(null, script, { | ||
id: id, | ||
text: text, | ||
type: type | ||
}); | ||
}); | ||
}; |
@@ -38,5 +38,16 @@ 'use strict'; | ||
var list = results.map(function(compiled) { | ||
return "can.view.preload('" + compiled[1] + "'," + compiled[0] + ");"; | ||
var options = compiled[1]; | ||
var method = configuration.version.indexOf('2.1') === 0 ? 'preloadStringRenderer' : 'preload'; | ||
var output = compiled[0]; | ||
if(output === null) { | ||
return "can." + options.type + "('" + options.id + "', " + JSON.stringify(options.text) + ");"; | ||
} | ||
return "can.view." + method + "('" + options.id + "'," + output + ");"; | ||
}); | ||
var output = renderer({ content: list.join('\n'), list: list }); | ||
var output = renderer({ | ||
content: list.join('\n'), | ||
list: list | ||
}); | ||
@@ -53,2 +64,2 @@ if (configuration.out) { | ||
module.exports.compile = compiler; | ||
module.exports.compile = compiler; |
{ | ||
"name": "can-compile", | ||
"description": "Compile CanJS Mustache and EJS views for lightning fast production apps", | ||
"version": "0.6.0", | ||
"version": "0.7.0", | ||
"homepage": "http://daffl.github.com/can-compile", | ||
@@ -6,0 +6,0 @@ "author": { |
@@ -20,5 +20,5 @@ # can-compile | ||
Compile all EJS and Mustache files in the current folder and write them to `views.combined.js`: | ||
Compile all EJS and Mustache files in the current folder and write them to `views.combined.js` using version 2.1.0: | ||
> can-compile --out views.combined.js | ||
> can-compile --out views.combined.js --can 2.1.0 | ||
@@ -32,3 +32,3 @@ Compile `todo.ejs` using CanJS version 1.1.2, write it to `views.production.js`: | ||
> can-compile **/*.ejs mustache/test.mustache --out views.combined.js | ||
> can-compile **/*.ejs mustache/test.mustache --out views.combined.js --can 2.0.0 | ||
@@ -48,7 +48,12 @@ ## Grunt task | ||
cancompile: { | ||
options: { | ||
version: '2.1.1' | ||
}, | ||
dist: { | ||
options: { | ||
wrapper: '!function() { {{{content}}} }();', | ||
tags: ['editor', 'my-component'] | ||
}, | ||
src: ['**/*.ejs', '**/*.mustache'], | ||
out: 'production/views.production.js', | ||
wrapper: '!function() { {{{content}}} }();', | ||
tags: ['editor', 'my-component'] | ||
dest: 'production/views.production.js' | ||
}, | ||
@@ -58,3 +63,5 @@ legacy: { | ||
out: 'production/views.production.js', | ||
version: '1.1.2' | ||
options: { | ||
version: '1.1.2' | ||
} | ||
} | ||
@@ -68,3 +75,3 @@ }, | ||
'js/app.js', // You app | ||
'<%= cancompile.dist.out %>' // The compiled views | ||
'<%= cancompile.dist.dest %>' // The compiled views | ||
], | ||
@@ -102,2 +109,3 @@ dest: 'production/production.js' | ||
var options = { | ||
version: '2.0.0', | ||
src: ['client/app/**/*.mustache'], | ||
@@ -138,3 +146,3 @@ out: 'public/assets/views.production.js', | ||
compiler.compile('file.ejs', function(error, output) { | ||
compiler.compile({ filename: 'file.ejs', version: '2.0.1' }, function(error, output) { | ||
output // -> compiled `file.ejs` | ||
@@ -147,3 +155,3 @@ }); | ||
- `filename` {String}: The name of the file to be compiled | ||
- `version` {String} (default: `latest`): The CanJS version to be used | ||
- `version` {String}: The CanJS version to be used | ||
- `log` {Function}: A logger function (e..g `console.log.bind(console)`) | ||
@@ -160,3 +168,3 @@ - `normalizer` {Function}: A Function that returns the normalized path name | ||
}, | ||
version: '1.1.6' | ||
version: '2.0.7' | ||
}, function(error, output) { | ||
@@ -177,7 +185,9 @@ output // -> compiled `file.ejs` | ||
grunt.initConfig({ | ||
options: { | ||
wrapper: 'define(["can/view/mustache"], function(can) { {{{content}}} });' | ||
}, | ||
cancompile: { | ||
dist: { | ||
src: ['**/*.mustache'], | ||
out: 'production/views.production.js', | ||
wrapper: 'define(["can/view/mustache"], function(can) { {{{content}}} });' | ||
files: ['**/*.mustache'], | ||
dest: 'production/views.production.js', | ||
} | ||
@@ -212,6 +222,12 @@ } | ||
> can-compile --out app/views.production.js | ||
> can-compile --out app/views.production.js --can 2.0.0 | ||
## Changelog | ||
__0.7.0:__ | ||
- Made `version` flag mandatory (caused unexpected behaviour after CanJS updates) | ||
- Added CanJS 2.1 compatibility ([#20](https://github.com/daffl/can-compile/issues/20), [#21](https://github.com/daffl/can-compile/issues/21), [#22](https://github.com/daffl/can-compile/issues/22)) | ||
- Fixed Grunt options ([#8](https://github.com/daffl/can-compile/pull/8)) | ||
__0.6.0:__ | ||
@@ -218,0 +234,0 @@ |
@@ -8,6 +8,7 @@ 'use strict'; | ||
var done = this.async(); | ||
var options = this.data; | ||
var files = grunt.file.expand(this.data.src); | ||
var options = this.options(); | ||
var file = this.files[0]; | ||
var files = file.src; | ||
options.out = options.out || 'views.production.js'; | ||
options.out = file.dest || 'views.production.js'; | ||
@@ -14,0 +15,0 @@ compiler(files, options, function(err, output, outfile) { |
@@ -39,7 +39,11 @@ /*global describe, it */ | ||
mustache: "can.Mustache(function(scope,options) { var ___v1ew = [];___v1ew.push(\n\"<h2>\");___v1ew.push(\ncan.view.txt(\n1,\n'h2',\n0,\nthis,\nfunction(){ return can.Mustache.txt(\n{scope:scope,options:options},\nnull,{get:\"message\"})}));\n___v1ew.push(\n\"</h2>\");; return ___v1ew.join('') })" | ||
}, | ||
'2.1.0': { | ||
ejs: "can.EJS(function(_CONTEXT,_VIEW) { with(_VIEW) { with (_CONTEXT) {var ___v1ew = [];___v1ew.push(\n\"<h2>\");___v1ew.push(\ncan.view.txt(\n1,\n'h2',\n0,\nthis,\nfunction(){ return message }));\n___v1ew.push(\n\"</h2>\");; return ___v1ew.join('')}} })", | ||
mustache: "can.Mustache(function(scope,options) { var ___v1ew = [];___v1ew.push(\n\"<h2>\");___v1ew.push(\ncan.view.txt(\n1,\n'h2',\n0,\nthis,\ncan.Mustache.txt(\n{scope:scope,options:options},\nnull,{get:\"message\"})));___v1ew.push(\n\"</h2>\");; return ___v1ew.join('') })" | ||
} | ||
}; | ||
expected.latest = expected['2.0.0']; | ||
var normalizer = function (filename) { | ||
@@ -51,2 +55,5 @@ return path.relative(__dirname, filename); | ||
(function(version, expectedEJS, expectedMustache) { | ||
var is21 = version.indexOf('2.1') === 0; | ||
var preloadMethod = is21 ? 'preloadStringRenderer' : 'preload'; | ||
describe('CanJS view compiler tests, version ' + version, function () { | ||
@@ -58,5 +65,5 @@ it('compiles EJS, normalizes view ids', function (done) { | ||
version: version | ||
}, function (error, output, id) { | ||
}, function (error, output, options) { | ||
expect(output).to.be(expectedEJS); | ||
expect(id).to.be('fixtures_view_ejs'); | ||
expect(options.id).to.be('fixtures_view_ejs'); | ||
done(); | ||
@@ -71,5 +78,5 @@ }); | ||
version: version | ||
}, function (error, output, id) { | ||
}, function (error, output, options) { | ||
expect(output).to.be(expectedMustache); | ||
expect(id).to.be('fixtures_view_mustache'); | ||
expect(options.id).to.be('fixtures_view_mustache'); | ||
done(); | ||
@@ -85,4 +92,4 @@ }); | ||
var expected = '!function() { ' + | ||
"can.view.preload('test_fixtures_view_ejs'," + expectedEJS + ");\n" + | ||
"can.view.preload('test_fixtures_view_mustache'," + expectedMustache + "); " + | ||
"can.view." + preloadMethod + "('test_fixtures_view_ejs'," + expectedEJS + ");\n" + | ||
"can.view." + preloadMethod + "('test_fixtures_view_mustache'," + expectedMustache + "); " + | ||
'}();'; | ||
@@ -94,2 +101,14 @@ | ||
}); | ||
if(is21) { | ||
it('Adds plain text for unkown templating engines', function(done) { | ||
compiler([__dirname + '/fixtures/view.stache'], { | ||
version: version, | ||
wrapper: '!function() { {{{content}}} }();' | ||
}, function(err, result) { | ||
expect(result).to.be("!function() { can.stache('test_fixtures_view_stache', \"<h2 class=\\\"something\\\">{{message}}</h2>\"); }();"); | ||
done(); | ||
}); | ||
}); | ||
} | ||
}); | ||
@@ -96,0 +115,0 @@ })(version, expected[version].ejs, expected[version].mustache); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
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
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
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
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
9613116
444
204427
264
8
35
27