├── .editorconfig ├── .gitignore ├── .jscs.json ├── .jshintrc ├── .travis.yml ├── HISTORY.md ├── LICENSE.md ├── README.md ├── bundle.js ├── gulpfile.js ├── lib └── mithrilify.js ├── package.json └── test ├── mithrilify.spec.js └── mock ├── example.js ├── view.js └── view_invalid.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | .DS_Store 4 | .idea 5 | *.iml -------------------------------------------------------------------------------- /.jscs.json: -------------------------------------------------------------------------------- 1 | { 2 | "requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"], 3 | "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], 4 | "disallowSpaceBeforeBinaryOperators": [",", ":"], 5 | "disallowSpaceAfterBinaryOperators": ["!"], 6 | "requireSpaceBeforeBinaryOperators": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="], 7 | "requireSpaceAfterBinaryOperators": ["?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="], 8 | "disallowImplicitTypeConversion": ["string"], 9 | "disallowKeywords": ["with"], 10 | "disallowMultipleLineBreaks": true, 11 | "disallowKeywordsOnNewLine": ["else"], 12 | "disallowTrailingWhitespace": true, 13 | "requireLineFeedAtFileEnd": true, 14 | "validateJSDoc": { 15 | "checkParamNames": true, 16 | "requireParamTypes": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "eqeqeq": true, 4 | "immed": true, 5 | "latedef": true, 6 | "newcap": true, 7 | "noarg": true, 8 | "sub": true, 9 | "undef": true, 10 | "unused": true, 11 | "boss": true, 12 | "eqnull": true, 13 | "node": true, 14 | "validthis": true, 15 | "globals": { 16 | /* MOCHA */ 17 | "describe" : false, 18 | "it" : false, 19 | "before" : false, 20 | "beforeEach" : false, 21 | "after" : false, 22 | "afterEach" : false, 23 | /* browserify */ 24 | "stream": false 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - '0.10' 5 | 6 | before_install: 7 | - npm install -g gulp 8 | 9 | script: 10 | - npm run test 11 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | ## mithrilify - HISTORY 2 | 3 | 4 | ### 0.0.6 - 2015/12/09 5 | - [#6 'Allow user to specify hasMithrilExtension'](https://github.com/sectore/mithrilify/pull/6) 6 | - Update node packages 7 | 8 | ### 0.0.5 - 2015/09/09 9 | - [#5 'Improving README consistency'](https://github.com/sectore/mithrilify/pull/5) 10 | - Remove deprecated `/* @jsx m */` pragma from mock files 11 | - Update node packages 12 | 13 | ### 0.0.4 - 2015/06/04 14 | - [#3 'Minor updates'](https://github.com/sectore/mithrilify/pull/3) 15 | 16 | ### 0.0.3 - 2015/03/02 17 | - [#2 'Minor updates'](https://github.com/sectore/mithrilify/pull/2) 18 | 19 | ### 0.0.2 - 2014/08/30 20 | - Test for error handling added 21 | - [#1 'Fixed undefined variable'](https://github.com/sectore/mithrilify/pull/1) 22 | 23 | ### 0.0.1 - 2014/07/07 24 | Release 25 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jens Krause ("sectore") // [WEBSECTOR.DE](http://www.websector.de) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mithrilify 2 | 3 | [Browserify](http://browserify.org/) [transform](https://github.com/substack/node-browserify#btransformopts-tr) 4 | for converting [Mithril](http://lhorie.github.io/mithril/) view templates 5 | using [MSX](https://github.com/insin/msx) 6 | 7 | [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-url]][daviddm-image] 8 | 9 | 10 | ## Install 11 | 12 | ```bash 13 | $ npm install --save-dev mithrilify 14 | ``` 15 | 16 | 17 | ## Usage 18 | 19 | ### Example of a Mithril view template. 20 | 21 | It can be defined within a `*.js` or `*.msx` file and 22 | should include `/** @jsx m */` at the top. 23 | 24 | 25 | ```javascript 26 | 'use strict'; 27 | 28 | var View = function (ctrl) { 29 | return
30 | hello 31 |
; 32 | }; 33 | 34 | module.exports = View; 35 | ``` 36 | 37 | ### Command line: 38 | 39 | ```bash 40 | $ browserify -t mithrilify ./view.js > ./bundle.js 41 | ``` 42 | 43 | ### [Gulp](http://gulpjs.com/) and [gulp-browserify](https://github.com/deepak1556/gulp-browserify) 44 | 45 | ```javascript 46 | var gulp = require('gulp'); 47 | browserify = require('gulp-browserify'), 48 | rename = require('gulp-rename'); 49 | 50 | gulp.task('bundle', function() { 51 | gulp.src('app/scripts/view.js') 52 | .pipe(browserify({ 53 | transform: ['mithrilify'] 54 | })) 55 | .pipe(rename('bundle.js')) 56 | .pipe(gulp.dest('build/')) 57 | }); 58 | ``` 59 | 60 | 61 | ### [Grunt](http://gruntjs.com/) and [grunt-browserify](https://github.com/jmreidy/grunt-browserify) 62 | 63 | ```javascript 64 | 65 | browserify: { 66 | dist: { 67 | files: { 68 | 'build/bundle.js': 'app/scripts/view.js', 69 | }, 70 | options: { 71 | transform: ['mithrilify'] 72 | } 73 | } 74 | } 75 | ``` 76 | 77 | 78 | ### Output: 79 | 80 | 81 | ```javascript 82 | 'use strict'; 83 | 84 | var View = function (ctrl) { 85 | return {tag: "div", attrs: {}, children: [ 86 | "hello" 87 | ]}; 88 | }; 89 | module.exports = View; 90 | ``` 91 | 92 | ## Test 93 | 94 | Clone project: 95 | 96 | ```bash 97 | $ git clone https://github.com/sectore/mithrilify.git && cd $_ 98 | ``` 99 | 100 | Install dependencies (only once): 101 | 102 | ```bash 103 | $ npm install 104 | ``` 105 | 106 | Run tests: 107 | 108 | ```bash 109 | $ gulp test 110 | ``` 111 | 112 | ## Credits: 113 | 114 | * [MSX](https://github.com/insin/msx) for supporting JSX to Mithril 115 | * [generator-node-gulp](https://github.com/youngmountain/generator-node-gulp) to create a Node.js module with yo, including gulp and Mocha unit tests. 116 | 117 | 118 | ## Contributors 119 | 120 | * [magnetised](https://github.com/magnetised) 121 | * [mkautzmann ](https://github.com/mkautzmann) 122 | * [Naddiseo](https://github.com/Naddiseo) 123 | * [shigi](https://github.com/shigi) 124 | * [sibsibsib](https://github.com/sibsibsib) 125 | 126 | 127 | ## Release History 128 | 129 | [History](./HISTORY.md) 130 | 131 | 132 | ## License 133 | 134 | Copyright (c) 2015 Jens Krause. Licensed under the [MIT license](./LICENSE.md). 135 | 136 | 137 | 138 | [npm-url]: https://npmjs.org/package/mithrilify 139 | [npm-image]: https://badge.fury.io/js/mithrilify.svg 140 | [travis-url]: https://travis-ci.org/sectore/mithrilify 141 | [travis-image]: https://travis-ci.org/sectore/mithrilify.svg?branch=master 142 | [daviddm-url]: https://david-dm.org/sectore/mithrilify.svg?theme=shields.io 143 | [daviddm-image]: https://david-dm.org/sectore/mithrilify 144 | -------------------------------------------------------------------------------- /bundle.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sectore/mithrilify/67a7099861ab7efd91410615081d663fa38983fd/bundle.js -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var plugins = require('gulp-load-plugins')(); 5 | 6 | var paths = { 7 | lint: ['./gulpfile.js', './lib/**/*.js'], 8 | watch: ['./gulpfile.js', './lib/**', './test/**/*.spec.js', '!test/{temp,temp/**}'], 9 | tests: ['./test/**/*.spec.js', '!test/{temp,temp/**}'] 10 | }; 11 | 12 | gulp.task('lint', function () { 13 | return gulp.src(paths.lint) 14 | .pipe(plugins.jshint('.jshintrc')) 15 | .pipe(plugins.plumber()) 16 | .pipe(plugins.jscs({})) 17 | .pipe(plugins.jshint.reporter('jshint-stylish')); 18 | }); 19 | 20 | gulp.task('mocha', function () { 21 | gulp.src(paths.tests, {cwd: __dirname}) 22 | .pipe(plugins.plumber()) 23 | .pipe(plugins.mocha({ reporter: 'list' })); 24 | }); 25 | 26 | gulp.task('bump', ['test'], function () { 27 | var bumpType = plugins.util.env.type || 'patch'; // major.minor.patch 28 | 29 | return gulp.src(['./package.json']) 30 | .pipe(plugins.bump({ type: bumpType })) 31 | .pipe(gulp.dest('./')); 32 | }); 33 | 34 | gulp.task('watch', ['test'], function () { 35 | gulp.watch(paths.watch, ['test']); 36 | }); 37 | 38 | gulp.task('test', ['lint', 'mocha']); 39 | 40 | gulp.task('release', ['bump']); 41 | 42 | gulp.task('default', ['test']); 43 | -------------------------------------------------------------------------------- /lib/mithrilify.js: -------------------------------------------------------------------------------- 1 | /* 2 | * mithrilify 3 | * https://github.com/sectore/mithrilify 4 | * 5 | * Copyright (c) 2014 Jens Krause 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | var msx = require('msx'), 12 | through = require('through'); 13 | 14 | function hasMithrilExtension(file) { 15 | return /\.(js|msx)$/.test(file); 16 | } 17 | 18 | function mithrilify(file, opts) { 19 | opts = opts || {}; 20 | if (!mithrilify.hasMithrilExtension(file)) { 21 | return through(); 22 | } 23 | 24 | var data = ''; 25 | 26 | function write(buf) { 27 | data += buf; 28 | } 29 | 30 | function end() { 31 | try { 32 | var src = msx.transform(data, opts.msx_opts); 33 | this.queue(src); 34 | } catch (error) { 35 | this.emit('error', error); 36 | } 37 | 38 | this.queue(null); 39 | } 40 | 41 | return through(write, end); 42 | } 43 | 44 | mithrilify.hasMithrilExtension = hasMithrilExtension; 45 | 46 | module.exports = mithrilify; 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mithrilify", 3 | "description": "Browserify transform for precompiling Mithril views", 4 | "version": "0.0.6", 5 | "homepage": "https://github.com/sectore/mithrilify", 6 | "bugs": "https://github.com/sectore/mithrilify/issues", 7 | "license": "MIT", 8 | "main": "lib/mithrilify.js", 9 | "author": { 10 | "name": "Jens Krause", 11 | "email": "info@websector.de", 12 | "url": "http://websector.de" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/sectore/mithrilify" 17 | }, 18 | "keywords": [], 19 | "dependencies": { 20 | "msx": "^0.4.1", 21 | "through": "^2.3.8" 22 | }, 23 | "devDependencies": { 24 | "browserify": "^12.0.1", 25 | "browserify-transform-tools": "^1.5.0", 26 | "debug": "^2.2.0", 27 | "gulp": "^3.9.0", 28 | "gulp-bump": "^1.0.0", 29 | "gulp-jscs": "^3.0.2", 30 | "gulp-jshint": "^2.0.0", 31 | "gulp-load-plugins": "^1.1.0", 32 | "gulp-mocha": "^2.2.0", 33 | "gulp-plumber": "^1.0.1", 34 | "gulp-util": "^3.0.7", 35 | "jshint-stylish": "^2.1.0", 36 | "should": "^8.0.0", 37 | "sinon": "^1.17.2" 38 | }, 39 | "scripts": { 40 | "test": "gulp test" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/mithrilify.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var mithrilify = require('../lib/mithrilify.js'), 4 | should = require('should'), 5 | assert = require('assert'), 6 | browserify = require('browserify'), 7 | sinon = require('sinon'), 8 | vm = require('vm'), 9 | fs = require("fs"), 10 | through = require('through'), 11 | path = require('path'), 12 | transformTools = require('browserify-transform-tools'); 13 | 14 | describe('mithrilify', function() { 15 | 16 | /** 17 | * Helper method to bundle code using browserify 18 | * @param file {string} 19 | * @param cb {function} Callback 20 | * @returns {*} Content of bundled file 21 | */ 22 | function bundle(file, cb) { 23 | return browserify(file, { 24 | basedir: __dirname 25 | }) 26 | .transform(mithrilify, { 27 | msx_opts: { 28 | precompile: false 29 | } 30 | }) 31 | .bundle(cb); 32 | }; 33 | 34 | /** 35 | * Helper method to remove linebreaks from string 36 | * to compare code loaded from files 37 | * @param value {string} 38 | * @returns {string} Cleaned string 39 | */ 40 | function cleanUpString(value) { 41 | // remove linebreaks 42 | value = value.replace(/\r?\n|\r/g, ''); 43 | return value; 44 | } 45 | 46 | it('should compile Mithril view', function(done) { 47 | 48 | var expectedView = 'function (ctrl) {' + 49 | ' return m("div", ["Hello ", ctrl.name()])' + '}'; 50 | 51 | bundle('./mock/example.js', function(err, src) { 52 | if (err) { 53 | done(err); 54 | } else { 55 | var sandbox = { 56 | console: { 57 | log: function(value) { 58 | value = 59 | cleanUpString( 60 | String( 61 | value)); 62 | value.should.equal( 63 | expectedView 64 | ); 65 | } 66 | } 67 | }; 68 | 69 | vm.runInNewContext(src, sandbox); 70 | done(); 71 | } 72 | }); 73 | }); 74 | 75 | it('should detect Mithril view files using .js file extension', 76 | function(done) { 77 | var f = "folder/any-view.js", 78 | result = mithrilify.hasMithrilExtension(f); 79 | result.should.be.ok; 80 | done(); 81 | }); 82 | 83 | 84 | it('should detect Mithril view files using .msx file extension', 85 | function(done) { 86 | var file = "folder/another-view.msx", 87 | result = mithrilify.hasMithrilExtension(file); 88 | result.should.be.ok; 89 | done(); 90 | }); 91 | 92 | it('should throw an error trying to parse an invalid view', 93 | function(done) { 94 | 95 | var invalid_file = path.resolve(__dirname, 96 | "./mock/view_invalid.js"); 97 | 98 | transformTools.runTransform( 99 | mithrilify, 100 | invalid_file, {}, 101 | function(error, result) { 102 | // test messge of error object to check parse error 103 | (error !== null).should.be.true; 104 | var hasParseErrorMessage = error.message.indexOf( 105 | 'Parse Error:') > -1; 106 | hasParseErrorMessage.should.be.true; 107 | done(); 108 | }) 109 | 110 | }); 111 | 112 | }); 113 | -------------------------------------------------------------------------------- /test/mock/example.js: -------------------------------------------------------------------------------- 1 | var view = require('./view.js'); 2 | console.log(view); -------------------------------------------------------------------------------- /test/mock/view.js: -------------------------------------------------------------------------------- 1 | module.exports = function (ctrl) { 2 | return
Hello {ctrl.name()}
3 | }; 4 | -------------------------------------------------------------------------------- /test/mock/view_invalid.js: -------------------------------------------------------------------------------- 1 | module.exports = function (ctrl) { 2 | return

3 | }; 4 | --------------------------------------------------------------------------------