This repository has been archived by the owner on Feb 9, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from hellyeahllc/master
Refactor & support inline source maps
- Loading branch information
Showing
4 changed files
with
111 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,59 @@ | ||
'use strict'; | ||
|
||
const coffeescript = require('coffee-script'); | ||
const coffee = require('coffee-script'); | ||
const normalizeChecker = checker => { | ||
if (typeof checker === 'function') return checker; | ||
if (checker instanceof RegExp) return path => checker.test(path); | ||
|
||
const isLiterate = path => /\.(litcoffee|coffee\.md)$/.test(path); | ||
|
||
const normalizeChecker = item => { | ||
switch (toString.call(item)) { | ||
case '[object RegExp]': | ||
return string => item.test(string); | ||
case '[object Function]': | ||
return item; | ||
default: | ||
return () => false; | ||
} | ||
return () => false; | ||
}; | ||
|
||
class CoffeeScriptCompiler { | ||
constructor(config) { | ||
if (config == null) config = {}; | ||
const plugin = config.plugins && config.plugins.coffeescript || {}; | ||
const conv = config.conventions && config.conventions.vendor; | ||
const plugin = config.plugins.coffeescript || {}; | ||
this.bare = plugin.bare; | ||
this.sourceMaps = !!config.sourceMaps; | ||
this.isVendor = normalizeChecker(conv); | ||
this.sourceMaps = config.sourceMaps; | ||
this.isVendor = normalizeChecker(config.conventions.vendor); | ||
} | ||
|
||
compile(file) { | ||
const data = file.data; | ||
const path = file.path; | ||
|
||
const options = { | ||
bare: this.bare == null ? !this.isVendor(path) : this.bare, | ||
sourceMap: this.sourceMaps, | ||
filename: path, | ||
sourceFiles: [path], | ||
literate: isLiterate(path) | ||
bare: this.bare == null ? !this.isVendor(path) : this.bare, | ||
literate: coffee.helpers.isLiterate(path), | ||
}; | ||
|
||
let compiled; | ||
if (this.sourceMaps === 'inline') { | ||
options.inlineMap = true; | ||
} else if (this.sourceMaps) { | ||
options.sourceMap = true; | ||
} | ||
|
||
try { | ||
compiled = coffeescript.compile(file.data, options); | ||
var compiled = coffee.compile(data, options); | ||
} catch (err) { | ||
const loc = err.location; | ||
let error; | ||
if (loc) { | ||
error = loc.first_line + ':' + loc.first_column + ' ' + (err.toString()); | ||
} else { | ||
error = err.toString(); | ||
} | ||
console.log('rejecting for', error); | ||
return Promise.reject(error); | ||
const message = loc ? | ||
`${loc.first_line}:${loc.first_column} ${err}` : | ||
`${err}`; | ||
|
||
return Promise.reject(message); | ||
} | ||
const result = (options.sourceMap && typeof compiled === 'object') ? { | ||
data: compiled.js, | ||
map: compiled.v3SourceMap | ||
} : { | ||
data: compiled | ||
}; | ||
|
||
const result = typeof compiled === 'string' ? | ||
{data: compiled} : | ||
{data: compiled.js, map: compiled.v3SourceMap}; | ||
|
||
return Promise.resolve(result); | ||
} | ||
} | ||
|
||
CoffeeScriptCompiler.prototype.brunchPlugin = true; | ||
CoffeeScriptCompiler.prototype.type = 'javascript'; | ||
CoffeeScriptCompiler.prototype.extension = 'coffee'; | ||
CoffeeScriptCompiler.prototype.pattern = /\.(coffee(\.md)?|litcoffee)$/; | ||
|
||
module.exports = CoffeeScriptCompiler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,102 @@ | ||
var expect = require('chai').expect; | ||
var Plugin = require('./'); | ||
'use strict'; | ||
|
||
describe('Plugin', function() { | ||
var plugin; | ||
const expect = require('chai').expect; | ||
const CoffeeCompiler = require('./'); | ||
|
||
beforeEach(function() { | ||
plugin = new Plugin({}); | ||
describe('coffee-script-brunch', () => { | ||
const path = 'file.coffee'; | ||
let plugin; | ||
|
||
beforeEach(() => { | ||
plugin = new CoffeeCompiler({ | ||
conventions: {}, | ||
plugins: {}, | ||
}); | ||
}); | ||
|
||
it('should be an object', function() { | ||
expect(plugin).to.be.ok; | ||
it('should be an object', () => { | ||
expect(plugin).to.be.an.instanceof(CoffeeCompiler); | ||
}); | ||
|
||
it('should has #compile method', function() { | ||
expect(plugin.compile).to.be.an.instanceof(Function); | ||
it('should have #compile method', () => { | ||
expect(plugin).to.respondTo('compile'); | ||
}); | ||
|
||
it('should compile and produce valid result', function(done) { | ||
var content = 'a = 1'; | ||
var expected = 'var a;\n\na = 1;\n'; | ||
it('should compile and produce valid result', () => { | ||
const data = 'a = 1'; | ||
const expected = 'var a;\n\na = 1;\n'; | ||
|
||
plugin.compile({data: content, path: 'file.coffee'}).then(data => { | ||
expect(data.data).to.equal(expected); | ||
done(); | ||
}, error => expect(error).not.to.be.ok); | ||
return plugin.compile({data, path}).then(file => { | ||
expect(file.data).to.equal(expected); | ||
}); | ||
}); | ||
|
||
it('should compile literal source and produce valid result', function(done) | ||
{ | ||
var content = 'I am a literal string\n\n a = 1'; | ||
var expected = 'var a;\n\na = 1;\n'; | ||
it('should compile literal source and produce valid result', () => { | ||
const data = 'I am a literal string\n\n a = 1'; | ||
const path = 'file.litcoffee'; | ||
const expected = 'var a;\n\na = 1;\n'; | ||
|
||
plugin.compile({data: content, path: 'file.litcoffee'}).then(data => { | ||
expect(data.data).to.equal(expected); | ||
done(); | ||
}, error => expect(error).not.to.be.ok); | ||
return plugin.compile({data, path}).then(file => { | ||
expect(file.data).to.equal(expected); | ||
}); | ||
}); | ||
|
||
it('should produce source maps', function(done) { | ||
plugin = new Plugin({sourceMaps: true}); | ||
it('should produce source maps', () => { | ||
plugin = new CoffeeCompiler({ | ||
conventions: {}, | ||
plugins: {}, | ||
sourceMaps: true, | ||
}); | ||
|
||
const data = 'a = 1'; | ||
const expected = 'var a;\n\na = 1;\n'; | ||
|
||
var content = 'a = 1'; | ||
var expected = 'var a;\n\na = 1;\n'; | ||
return plugin.compile({data, path}).then(file => { | ||
expect(file.data).to.equal(expected); | ||
expect(file.map).to.be.a('string'); | ||
}); | ||
}); | ||
|
||
plugin.compile({data: content, path: 'file.coffee'}).then(data => { | ||
expect(data.data).to.equal(expected); | ||
expect(data.map).to.be.a('string'); | ||
done(); | ||
}, error => expect(error).not.to.be.ok); | ||
it('should produce inline source maps', () => { | ||
plugin = new CoffeeCompiler({ | ||
conventions: {}, | ||
plugins: {}, | ||
sourceMaps: 'inline', | ||
}); | ||
|
||
const data = 'a = 1'; | ||
|
||
return plugin.compile({data, path}).then(file => { | ||
expect(file.data).to | ||
.include(data) | ||
.include('//# sourceMappingURL=data:application/json;base64,') | ||
.include(`//# sourceURL=${path}`); | ||
}); | ||
}); | ||
|
||
it('should support explicit bare setting', function(done) { | ||
plugin = new Plugin({plugins:{coffeescript:{bare:false}}}); | ||
it('should support explicit bare setting', () => { | ||
plugin = new CoffeeCompiler({ | ||
conventions: {}, | ||
plugins: {coffeescript: {bare: false}}, | ||
}); | ||
|
||
let data = 'a = 1'; | ||
let expected = '(function() {\n var a;\n\n a = 1;\n\n}).call(this);\n'; | ||
|
||
var content = 'a = 1'; | ||
var expected = '(function() {\n var a;\n\n a = 1;\n\n}).call(this);\n'; | ||
return plugin.compile({data, path}).then(file => { | ||
expect(file.data).to.equal(expected); | ||
|
||
plugin.compile({data: content, path: 'file.coffee'}).then(data => { | ||
expect(data.data).to.equal(expected); | ||
plugin = new CoffeeCompiler({ | ||
conventions: {}, | ||
plugins: {coffeescript: {bare: true}}, | ||
}); | ||
|
||
plugin = new Plugin({plugins:{coffeescript:{bare:true}}}); | ||
content = 'a = 1'; | ||
data = 'a = 1'; | ||
expected = 'var a;\n\na = 1;\n'; | ||
|
||
plugin.compile({data: content, path: 'file.coffee'}).then(data => { | ||
expect(data.data).to.equal(expected); | ||
done(); | ||
}, error => expect(error).not.to.be.ok); | ||
}, error => expect(error).not.to.be.ok); | ||
return plugin.compile({data, path}).then(file => { | ||
expect(file.data).to.equal(expected); | ||
}); | ||
}); | ||
}); | ||
}); |