├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── example
├── bar.js
├── bat.js
├── baz.coffee
├── baz.litcoffee
├── error.coffee
├── foo.coffee
├── foo.litcoffee
├── multiline_error.coffee
├── neat-ui.coffee
└── rad-component.cjsx
├── index.js
├── package.json
├── test
├── bundle.js
├── cjsx.js
├── error.js
└── transform.js
└── update.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | src/
2 | test/
3 | examples/
4 | Cakefile
5 | *.sh
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 0.8
4 | - 0.10
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 James Friend
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all 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,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # coffee-reactify
2 |
3 | # STATUS: DEPRECATED
4 |
5 | This tool is no longer maintained. If you need to transition your codebase from
6 | it, a codemod is available to do so: [cjsx-codemod](https://github.com/jsdf/cjsx-codemod)
7 |
8 | This project started as a way for me to explore how JSX could fit into
9 | Coffeescript syntax, as a quickly hacked together prototype. While I never
10 | really promoted it, it quickly took on a life of its own, and before long people
11 | were asking for it to support all kinds of different use cases. On top of that I
12 | had no experience writing parsers, so the result is something with
13 | [insurmountable limitations](https://github.com/jsdf/coffee-react/issues/32).
14 |
15 | As I eventually stopped using Coffeescript I ended up neglecting this project,
16 | but as people were using it I didn't want to kill it. I really should have,
17 | however, because it meant that people were using a crappy, ill-conceived,
18 | unmaintained tool. Now, long overdue, I'm putting it out to pasture.
19 |
20 | Original readme follows:
21 |
22 | browserify v2 plugin for compiling [coffee-react-transform](https://github.com/jsdf/coffee-react-transform) CJSX markup in Coffeescript.
23 |
24 | # example
25 |
26 | given some files written in a mix of `coffee` and `cjsx`:
27 |
28 | neat-ui.coffee:
29 | ``` coffee
30 | require './rad-component.cjsx'
31 |
32 | React.renderComponent RadComponent({rad:"mos def"}),
33 | document.getElementById('container')
34 | ```
35 |
36 | rad-component.cjsx:
37 | ``` coffee
38 | # @cjsx React.DOM
39 |
40 | React = require('react')
41 |
42 | RadComponent = React.createClass
43 | render: ->
44 |
45 |
is this component rad? {@props.rad}
46 |
47 | ```
48 |
49 | install coffee-reactify:
50 |
51 | ```bash
52 | $ npm install -g coffee-reactify
53 | ```
54 |
55 | version compatibility:
56 |
57 | - 2.1.x - React 0.12.1
58 | - 2.x - React 0.12
59 | - 1.x - React 0.11.2
60 | - 0.x - React 0.11 and below
61 |
62 | when you compile your app, pass `-t coffee-reactify` to browserify:
63 |
64 | ```bash
65 | $ browserify -t coffee-reactify neat-ui.coffee > bundle.js
66 | ```
67 |
68 | you can omit the `.coffee` or `.cjsx` extension from your requires if you add the extension to browserify's module extensions:
69 |
70 | ``` coffee
71 | require './component'
72 | ...
73 | ```
74 |
75 | ```bash
76 | $ browserify -t coffee-reactify --extension=".cjsx" --extension=".coffee" neat-ui.coffee > bundle.js
77 | ```
78 |
79 | providing the transform option `coffeeout: true` will passthrough the transformed
80 | output of `.coffee` files with the `@cjsx` pragma without compiling them to javascript.
81 | this means you can use a different coffee compiler transform such as [icsify](https://github.com/maxtaco/icsify) or [coffeeify](https://github.com/jnordberg/coffeeify) in conjunction with this transform.
82 |
83 | **note:** at this stage, `.cjsx` files will still be compiled even with `--coffeeout`.
84 | this is a workaround for the fact that other transform modules like `coffeeify` will
85 | ignore `.cjsx` files due to the different file extension.
86 |
87 | ```bash
88 | $ browserify -t [ coffee-reactify --coffeeout ] -t coffeeify neat-ui.coffee > bundle.js
89 | ```
90 |
91 | # install
92 |
93 | With [npm](https://npmjs.org) do:
94 |
95 | ```bash
96 | npm install coffee-reactify
97 | ```
98 |
99 | # license
100 |
101 | MIT
102 |
--------------------------------------------------------------------------------
/example/bar.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./baz.coffee')(5)
2 |
--------------------------------------------------------------------------------
/example/bat.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./baz.litcoffee')(5)
2 |
--------------------------------------------------------------------------------
/example/baz.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (n) -> n * 111
2 |
--------------------------------------------------------------------------------
/example/baz.litcoffee:
--------------------------------------------------------------------------------
1 | Multiply all the things with 111
2 |
3 | module.exports = (n) -> n * 111
4 |
--------------------------------------------------------------------------------
/example/error.coffee:
--------------------------------------------------------------------------------
1 | #----------------------------------#
2 | # hello, my name is: SµNTtaX E®Rör #
3 | #----------------------------------#
4 |
5 | thisIsWrong = , 'waaa'
6 |
--------------------------------------------------------------------------------
/example/foo.coffee:
--------------------------------------------------------------------------------
1 | console.log(require './bar.js')
2 |
--------------------------------------------------------------------------------
/example/foo.litcoffee:
--------------------------------------------------------------------------------
1 | Here is a bat
2 |
3 | console.log(require './bat.js')
4 |
--------------------------------------------------------------------------------
/example/multiline_error.coffee:
--------------------------------------------------------------------------------
1 | #----------------------------------#
2 | # hello, my name is: SµNTtaX E®Rör #
3 | #----------------------------------#
4 |
5 |
6 | 'this is very wrong. notice that the first line is''
7 | longer'
--------------------------------------------------------------------------------
/example/neat-ui.coffee:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 |
3 | RadComponent = require './rad-component'
4 |
5 | console.log React.renderToStaticMarkup React.createElement(RadComponent, rad: 'mos def')
6 |
--------------------------------------------------------------------------------
/example/rad-component.cjsx:
--------------------------------------------------------------------------------
1 | # @cjsx React.DOM
2 |
3 | React = require 'react'
4 |
5 | RadComponent = React.createClass
6 | render: ->
7 |
8 |
is this component rad? {@props.rad}
9 |
10 |
11 | module.exports = RadComponent
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var util = require('util');
2 | var through = require('through');
3 | var convert = require('convert-source-map');
4 | var coffeereact = require('coffee-react');
5 |
6 | function hasCoffeeExtension (file) {
7 | return (/\.((lit)?coffee|coffee\.md)$/).test(file);
8 | }
9 |
10 | function hasLiterateExtension (file) {
11 | return (/\.(litcoffee|coffee\.md)$/).test(file);
12 | }
13 |
14 | function ParseError(error, src, file) {
15 | /* Creates a ParseError from a CoffeeScript SyntaxError
16 | modeled after substack's syntax-error module */
17 | SyntaxError.call(this);
18 |
19 | this.message = error.message;
20 |
21 | this.line = error.location.first_line + 1; // cs linenums are 0-indexed
22 | this.column = error.location.first_column + 1; // same with columns
23 |
24 | var markerLen = 2;
25 | if(error.location.first_line === error.location.last_line) {
26 | markerLen += error.location.last_column - error.location.first_column;
27 | }
28 | this.annotated = [
29 | file + ':' + this.line,
30 | src.split('\n')[this.line - 1],
31 | Array(this.column).join(' ') + Array(markerLen).join('^'),
32 | 'ParseError: ' + this.message
33 | ].join('\n');
34 | }
35 |
36 | ParseError.prototype = Object.create(SyntaxError.prototype);
37 |
38 | ParseError.prototype.toString = function () {
39 | return this.annotated;
40 | };
41 |
42 | ParseError.prototype.inspect = function () {
43 | return this.annotated;
44 | };
45 |
46 | function compile(file, data, callback) {
47 | var compiled;
48 | try {
49 | compiled = coffeereact.compile(data, {
50 | sourceMap: true,
51 | generatedFile: file,
52 | inline: true,
53 | bare: true,
54 | literate: hasLiterateExtension(file)
55 | });
56 | } catch (e) {
57 | var error = e;
58 | if (e.location) {
59 | error = new ParseError(e, data, file);
60 | }
61 | callback(error);
62 | return;
63 | }
64 |
65 | var map = convert.fromJSON(compiled.v3SourceMap);
66 | map.setProperty('sources', [file]);
67 |
68 | callback(null, compiled.js + '\n' + map.toComment() + '\n');
69 | }
70 |
71 | function coffeereactify(file, opts) {
72 | opts = opts || {};
73 | var passthroughCoffee = opts['coffeeout'] || false;
74 | var hasCoffeeExt = hasCoffeeExtension(file);
75 | var hasCJSXExt = coffeereact.hasCJSXExtension(file);
76 |
77 | if (!(hasCoffeeExt || hasCJSXExt)) {
78 | return through();
79 | }
80 |
81 | var data = '', stream = through(write, end);
82 |
83 | return stream;
84 |
85 | function write(buf) {
86 | data += buf;
87 | }
88 |
89 | function end() {
90 | if (hasCoffeeExt && passthroughCoffee) {
91 | // passthrough un-compiled coffeescript
92 | var transformed;
93 | try {
94 | transformed = coffeereact.transform(data);
95 | } catch (error) {
96 | return stream.emit('error', error);
97 | }
98 | stream.queue(transformed || data);
99 | stream.queue(null);
100 | } else {
101 | // otherwise compile either cjsx or pure coffee
102 | compile(file, data, function(error, result) {
103 | if (error) stream.emit('error', error);
104 | stream.queue(result);
105 | stream.queue(null);
106 | });
107 | }
108 | }
109 | }
110 |
111 | coffeereactify.compile = compile;
112 | coffeereactify.isCoffee = hasCoffeeExtension;
113 | coffeereactify.isLiterate = hasLiterateExtension;
114 | coffeereactify.hasCJSXExtension = coffeereact.hasCJSXExtension;
115 | coffeereactify.hasCJSXPragma = coffeereact.hasCJSXPragma;
116 |
117 | module.exports = coffeereactify;
118 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "coffee-reactify",
3 | "version": "5.1.0",
4 | "description": "browserify v2 plugin for coffee-react cjsx",
5 | "main": "index.js",
6 | "dependencies": {
7 | "coffee-react": "^5.0.0",
8 | "convert-source-map": "~0.3.3",
9 | "through": "~2.3.4"
10 | },
11 | "devDependencies": {
12 | "tap": "~0.4.0",
13 | "browserify": "^3.38.0",
14 | "react": "^0.12.0"
15 | },
16 | "scripts": {
17 | "test": "tap test/*.js"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git://github.com/jsdf/coffee-reactify.git"
22 | },
23 | "homepage": "https://github.com/jsdf/coffee-reactify",
24 | "keywords": [
25 | "coffee-script",
26 | "react",
27 | "browserify",
28 | "transform"
29 | ],
30 | "contributors": [
31 | {
32 | "name": "James Halliday",
33 | "email": "mail@substack.net",
34 | "url": "http://substack.net"
35 | },
36 | {
37 | "name": "Johan Nordberg",
38 | "email": "code@johan-nordberg.com",
39 | "url": "http://johan-nordberg.com"
40 | },
41 | {
42 | "name": "James Friend",
43 | "email": "james@jsdf.co",
44 | "url": "http://jsdf.co"
45 | }
46 | ],
47 | "license": "MIT"
48 | }
49 |
--------------------------------------------------------------------------------
/test/bundle.js:
--------------------------------------------------------------------------------
1 | var test = require('tap').test;
2 | var browserify = require('browserify');
3 | var vm = require('vm');
4 |
5 | function bundle (file) {
6 | test('bundle transform', function (t) {
7 | t.plan(1);
8 |
9 | var b = browserify();
10 | b.add(__dirname + file);
11 | b.transform(__dirname + '/..');
12 | b.bundle(function (err, src) {
13 | if (err) t.fail(err);
14 | vm.runInNewContext(src, {
15 | console: { log: log }
16 | });
17 | });
18 |
19 | function log (msg) {
20 | t.equal(msg, 555);
21 | }
22 | });
23 | }
24 |
25 | bundle('/../example/foo.coffee');
26 | bundle('/../example/foo.litcoffee');
27 |
--------------------------------------------------------------------------------
/test/cjsx.js:
--------------------------------------------------------------------------------
1 | var test = require('tap').test;
2 | var browserify = require('browserify');
3 | var vm = require('vm');
4 | var fs = require('fs');
5 |
6 | function bundle (file, opts) {
7 | test('bundle transform', function (t) {
8 | t.plan(1);
9 |
10 | var b = browserify({extensions: ['.coffee', '.cjsx']});
11 | b.add(__dirname + file);
12 | b.transform((opts||{}),__dirname + '/..');
13 | b.bundle(function (err, src) {
14 | if (err) t.fail(err);
15 | vm.runInNewContext(src, {
16 | console: { log: log }
17 | });
18 | });
19 |
20 | function log (msg) {
21 | var expected = "is this component rad? mos def
";
22 |
23 | t.equal(JSON.stringify(msg), JSON.stringify(expected));
24 | }
25 | });
26 | }
27 |
28 | bundle('/../example/neat-ui.coffee');
29 |
--------------------------------------------------------------------------------
/test/error.js:
--------------------------------------------------------------------------------
1 | var test = require('tap').test;
2 | var browserify = require('browserify');
3 | var path = require('path');
4 | var fs = require('fs');
5 |
6 | var file = path.resolve(__dirname, '../example/error.coffee');
7 | var multilineFile = path.resolve(__dirname, '../example/multiline_error.coffee');
8 | var transform = path.join(__dirname, '..');
9 |
10 | test('transform error', function (t) {
11 | t.plan(5);
12 |
13 | var b = browserify([file]);
14 | b.transform(transform);
15 |
16 | b.bundle(function (error) {
17 | t.ok(error !== undefined, "bundle should callback with an error");
18 | t.ok(error.line !== undefined, "error.line should be defined");
19 | t.ok(error.column !== undefined, "error.column should be defined");
20 | t.equal(error.line, 5, "error should be on line 5");
21 | t.equal(error.column, 15, "error should be on column 15");
22 | });
23 | });
24 |
25 | test('multiline transform error', function (t) {
26 | t.plan(1);
27 |
28 | var b = browserify([multilineFile]);
29 | b.transform(transform);
30 | b.bundle(function (error) {
31 | t.ok(error !== undefined, "bundle should callback with an error");
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/test/transform.js:
--------------------------------------------------------------------------------
1 | var test = require('tap').test;
2 | var fs = require('fs');
3 | var path = require('path');
4 | var through = require('through');
5 | var convert = require('convert-source-map');
6 | var transform = require('..');
7 |
8 | test('transform adds sourcemap comment', function (t) {
9 | t.plan(1);
10 | var data = '';
11 |
12 | var file = path.join(__dirname, '../example/foo.coffee')
13 | fs.createReadStream(file)
14 | .pipe(transform(file))
15 | .pipe(through(write, end));
16 |
17 | function write (buf) { data += buf }
18 | function end () {
19 | var sourceMap = convert.fromSource(data).toObject();
20 |
21 | t.deepEqual(
22 | sourceMap,
23 | { version: 3,
24 | file: file,
25 | sourceRoot: '',
26 | sources: [ file ],
27 | names: [],
28 | mappings: 'AAAA,OAAO,CAAC,GAAR,CAAY,OAAA,CAAQ,UAAR,CAAZ',
29 | sourcesContent: [ 'console.log(require \'./bar.js\')\n' ] },
30 | 'adds sourcemap comment including original source'
31 | );
32 | }
33 | });
34 |
--------------------------------------------------------------------------------
/update.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | git pull origin master
4 | DEPENDENCY="coffee-react"
5 | VERSION=`npm view ${DEPENDENCY} version`
6 | echo "updating to $VERSION"
7 | npm install --save "${DEPENDENCY}@${VERSION}"
8 | npm test
9 | git add ./package.json
10 | git commit -m "updated ${DEPENDENCY} to v${VERSION}"
11 | npm version $VERSION
12 | read -p "will publish $VERSION. are you sure? " -n 1 -r
13 | echo
14 | if [[ $REPLY =~ ^[Yy]$ ]]
15 | then
16 | git push origin master
17 | npm publish .
18 | fi
--------------------------------------------------------------------------------