snowball 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .idea
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ node_modules
20
+ npm-shrinkwrap.json
21
+ Makefile
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in snowball.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Bjørge Næss
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,142 @@
1
+ ```
2
+ ______ ___________
3
+ _______________________ ____ /_______ ___ /__ /
4
+ __ ___/_ __ \ __ \_ | /| / /_ __ \ __ `/_ /__ /
5
+ _(__ )_ / / / /_/ /_ |/ |/ /_ /_/ / /_/ /_ / _ /
6
+ /____/ /_/ /_/\____/____/|__/ /_.___/\__,_/ /_/ /_/
7
+
8
+ Makes your front-end code roll
9
+ ```
10
+
11
+ # What?
12
+ Snowball enables you to:
13
+
14
+ - Use npm for dependency management
15
+ - Run your front-end javascript on a server with ease (i.e. running tests on a CI server)
16
+ - Serve pre-defined bundles through Sinatra
17
+ - Compile and minifiy all your JavaScript in a pre-deploy step
18
+ - Write your front-end code in CoffeeScript
19
+ - Serve pre-compiled Jade templates for your front-end
20
+
21
+ # Why?
22
+ Because:
23
+
24
+ - [Sprockets](https://github.com/sstephenson/sprockets) is kinda cumbersome when you have a large number of dependencies.
25
+ - [npm](http://npmjs.org) is really really good at managing dependencies for you.
26
+
27
+ # How?
28
+ - It uses [browserify](https://github.com/substack/node-browserify) magic to search your code for require() statements and figure
29
+ out which dependencies to include in the bundle.
30
+
31
+ ## FAQ
32
+
33
+ ### Oh, but I depend on a javascript library that is not in the npm repository!
34
+
35
+ No problem, really! You can still require reqular files in your bundle files like this:
36
+
37
+ ```js
38
+ require("./path/to/my-esoteric-lib.js")
39
+ ```
40
+
41
+ ### Oh, but I have a lot of javascript code that is not written as Node modules!
42
+
43
+ Really? Then you should start converting right away.
44
+
45
+ The only thing you need to make sure is that your esoteric library follows the [CommonJS / Modules spec](http://wiki.commonjs.org/wiki/Modules/1.1)
46
+ and adds itself to the `exports` object. This is how [underscore.js](http://underscorejs.org/docs/underscore.html#section-10) does that:
47
+ ```js
48
+ if (typeof exports !== 'undefined') {
49
+ if (typeof module !== 'undefined' && module.exports) {
50
+ exports = module.exports = _;
51
+ }
52
+ exports._ = _;
53
+ } else {
54
+ root['_'] = _;
55
+ }
56
+ ```
57
+
58
+ ## Installation
59
+
60
+ Add this line to your application's Gemfile:
61
+
62
+ gem 'snowball'
63
+
64
+ And then execute:
65
+
66
+ $ bundle
67
+
68
+ ## Usage
69
+
70
+ # Define a bundle
71
+
72
+ Defining a bundle is as easy as creating a javascript file and require() your dependencies. Then you just
73
+ add the containing folder to the Snowball search path, configure the endpoint you'd like to
74
+ serve bundles from, and you are good to go.
75
+
76
+ I.e. given the follwing project layout:
77
+
78
+ ```
79
+ myapp
80
+ |- js
81
+ |- all.js
82
+ ```
83
+ ```js
84
+ var $ = require("jquery");
85
+ var Backbone = require("backbone");
86
+ var myJsApp = require("myjsapp").App;
87
+ myJsApp.init()
88
+ ```
89
+ ```
90
+ |- minimal.js
91
+ ```
92
+ ```js
93
+ var $ = require("jquery");
94
+ var myTinyVersion = require("tinyapp").TinyApp;
95
+ myTinyVersion.init();
96
+ ```
97
+ ```
98
+ |- my_app.rb
99
+ ```
100
+ ```ruby
101
+ class MyApp extends Sinatra::Base
102
+ register Sinatra::Snowball
103
+ snowball do
104
+ set_serve_path "/bundles"
105
+ add_load_path "js"
106
+ end
107
+ # (...)
108
+ end
109
+ ```
110
+
111
+ Now your bundles are available from /bundles/all.js and /bundles/minimal.js and all dependencies are automatically
112
+ resolved and concatenated into that file
113
+
114
+ # Precompiling bundles pre-deploy
115
+
116
+ Example rake task that takes a an entry file, concatenates and compresses it to a target file.
117
+
118
+ ```ruby
119
+ namespace :snowball do
120
+ target = './public/all.js'
121
+ entryfile = './js/all.coffee'
122
+
123
+ desc "Roll a new javascript bundle"
124
+ task :roll do
125
+ require "uglifier"
126
+ require "snowball/roller"
127
+ puts "Rolling..."
128
+ File.open(target, 'w') do |f|
129
+ f.write(Uglifier.compile(Snowball::Roller.roll(entryfile, Snowball::Config.new)))
130
+ end
131
+ puts "Done!"
132
+ end
133
+ end
134
+ ```
135
+
136
+ ## Contributing
137
+
138
+ 1. Fork it
139
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
140
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
141
+ 4. Push to the branch (`git push origin my-new-feature`)
142
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,132 @@
1
+ var browserify = require("browserify"),
2
+ jade = require("jade"),
3
+ fs = require("fs"),
4
+ path = require("path"),
5
+ optimist = require('optimist'),
6
+ bundle;
7
+
8
+ var argv = optimist
9
+ .usage('Usage: browserify [entry files] {OPTIONS}')
10
+ .wrap(80)
11
+ .option('help', {
12
+ desc : 'Show this help'
13
+ })
14
+ .option('require', {
15
+ alias : 'r',
16
+ desc : 'A module name or file to bundle.require()\n'
17
+ + 'Optionally use a colon separator to set the target.'
18
+ })
19
+ .option('entry', {
20
+ alias : 'e',
21
+ desc : 'An entry point of your app'
22
+ })
23
+ .option('ignore', {
24
+ alias : 'i',
25
+ desc : 'Ignore a file'
26
+ })
27
+ .option('prelude', {
28
+ default : true,
29
+ type : 'boolean',
30
+ desc : 'Include the code that defines require() in this bundle.'
31
+ })
32
+ .option('env', {
33
+ type : 'string',
34
+ desc : 'Pass one or more environment variables to the "process" object in browserified code\n'+
35
+ 'Example: --env NODE_ENV=development --env FOO=bar'
36
+ }).argv;
37
+
38
+ if (argv.help) {
39
+ return optimist.showHelp()
40
+ }
41
+
42
+ // Parse argv.env properly
43
+ // turns argv.env strings like ['FOO=bar', 'BAZ=qux', ...] into an object of { FOO: 'bar', BAZ:'qux' }
44
+ if (argv.env) {
45
+ var util = require("util");
46
+ argv.env = (util.isArray(argv.env) ? argv.env : [argv.env]).reduce(function(env, str) {
47
+ var parts = str.split("=");
48
+ env[parts[0]] = parts[1];
49
+ return env;
50
+ }, {});
51
+ }
52
+
53
+ bundle = browserify();
54
+
55
+ // Todo: make jade-support optional (consider snowball plugins?)
56
+ bundle.register('.jade', function () {
57
+ var compileDebug = !!(argv.env && argv.env.hasOwnProperty('NODE_ENV') && argv.env.NODE_ENV == 'development');
58
+ return function (b, filename) {
59
+ var body = fs.readFileSync(filename);
60
+ var compiled;
61
+ try {
62
+ compiled = jade.compile(body, {
63
+ filename: filename,
64
+ client: true,
65
+ compileDebug: compileDebug
66
+ }).toString();
67
+ }
68
+ catch (e) {
69
+ // There's a syntax error in the template. Wrap it into a function that will throw an error when templates is used
70
+ compiled = "function() {throw new Error(unescape('"+escape(e.toString()+"\nIn "+filename)+"'))}"
71
+ }
72
+ // Wrap the compiled template function in a function that merges in previously registered globals (i.e. helpers, etc)
73
+ return ''+
74
+ 'var jade = require("jade-runtime").runtime;' +
75
+ 'module.exports = function(locals, attrs, escape, rethrow, merge) {' +
76
+ ' var locals = require("jade-runtime").globals.merge(locals);' +
77
+ ' return ('+compiled+")(locals, attrs, escape, rethrow, merge);" +
78
+ '}';
79
+ }
80
+ });
81
+
82
+ if (argv.prelude === false) {
83
+ bundle.files = [];
84
+ bundle.prepends = [];
85
+ }
86
+
87
+ if (argv.env) {
88
+ // Using the browserify internal bundle.entries array - (yup, asking for trouble).
89
+ // Todo: file a feature request for setting env variables in __browserify_process
90
+ bundle.entries['/__browserify_process__setenv'] = {
91
+ body: ''+
92
+ 'var __browserify_process = require("__browserify_process"),' +
93
+ ' env = '+JSON.stringify(argv.env)+';' +
94
+ 'Object.keys(env).forEach(function(varname) {'+
95
+ ' if (!(varname in __browserify_process.env)) {'+
96
+ ' __browserify_process.env[varname] = env[varname];'+
97
+ ' }' +
98
+ ' else {' +
99
+ ' console.log("Environment variable already set in browserify environment: %s", varname);' +
100
+ ' }'+
101
+ '})'};
102
+ }
103
+
104
+ ([].concat(argv.require || [])).forEach(function (req) {
105
+ bundle.require(req);
106
+ });
107
+
108
+ if (argv.ignore) {
109
+ bundle.ignore(argv.ignore);
110
+ }
111
+
112
+ bundle.on("loadError", function(e) {
113
+ bundle.prepend('\nthrow new Error('+JSON.stringify(e.message)+');');
114
+ });
115
+
116
+ bundle.on("syntaxError", function(e) {
117
+ bundle.prepend('throw new Error('+JSON.stringify(e.message)+');');
118
+ });
119
+
120
+ (argv._.concat(argv.entry || [])).forEach(function (entry) {
121
+ try {
122
+ bundle.addEntry(entry);
123
+ }
124
+ catch (e) {
125
+ bundle.emit("loadError", e);
126
+ }
127
+ });
128
+
129
+ // Write bundle on nextTick since browserify events are emitted on process.nextTick
130
+ process.nextTick(function() {
131
+ process.stdout.write(bundle.bundle());
132
+ });
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+ require 'open3'
3
+
4
+ create_makefile("Dummy")
5
+
6
+ ['npm install', 'npm shrinkwrap'].each do |cmd|
7
+ puts "* Running #{cmd}"
8
+ Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
9
+ fail "Error running '#{cmd}': #{stderr.read}" unless wait_thr.value.success?
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ require "bundler"
2
+ Bundler.require
3
+
4
+ require "snowball/version"
5
+ require "snowball/config"
6
+ require "snowball/sinatra"
7
+ require "snowball/roller"
8
+
9
+ module Snowball
10
+ end
@@ -0,0 +1,51 @@
1
+ # Todo: rewrite
2
+ module Snowball
3
+ class Config
4
+ class Builder
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+ def http_path(path)
9
+ @config.http_path = path
10
+ end
11
+ alias_method :set_serve_path, :http_path # todo: deprecate
12
+ def source_path(path)
13
+ @config.source_paths << File.expand_path(path)
14
+ end
15
+
16
+ alias_method :add_load_path, :source_path # todo: deprecate
17
+ def raw(glob_string)
18
+ @config.raw << glob_string
19
+ end
20
+
21
+ def ignore(node_module)
22
+ @config.ignores << node_module
23
+ end
24
+
25
+ def setenv(*args)
26
+ @config.env.merge!(args.first) and return if args.size == 1
27
+ @config.env[args.first] = args[1]
28
+ end
29
+
30
+ def include(node_module)
31
+ @config.includes << node_module
32
+ end
33
+
34
+ def prelude(bool)
35
+ @config.prelude = bool
36
+ end
37
+ end
38
+
39
+ attr_accessor :http_path, :source_paths, :raw, :extensions, :includes, :ignores, :prelude, :env
40
+
41
+ def initialize
42
+ @extensions = [:js, :coffee]
43
+ @source_paths = []
44
+ @raw = []
45
+ @includes = []
46
+ @ignores = []
47
+ @env = {}
48
+ @prelude = true
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,35 @@
1
+ require "open3"
2
+
3
+ module Snowball
4
+ EXECUTABLE = Pathname.new(__FILE__).join("../../../", "bin/roll.js").realpath
5
+ class RollError < Exception; end
6
+
7
+ class Roller
8
+ def self.roll(entry, opts)
9
+ args = []
10
+
11
+ ignores = opts.ignores.dup
12
+ ignores.unshift *%w(jsdom xmlhttprequest location navigator)
13
+ ignores.uniq!
14
+
15
+ args << ignores.map { |node_module| "--ignore #{node_module}" }.join(" ")
16
+ args << opts.includes.map { |node_module| "--require #{node_module}" }.join(" ")
17
+ args << "--prelude #{!!opts.prelude}"
18
+ args << "--entry #{entry}"
19
+
20
+ args += (opts.env || {}).map do |k,v|
21
+ "--env #{k}=#{v}"
22
+ end
23
+
24
+ cmd = "node #{EXECUTABLE} #{args.join(" ")}"
25
+
26
+ Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
27
+ source = stdout.read
28
+ unless wait_thr.value.success?
29
+ raise RollError.new "Got error while executing \"#{cmd}\" command: #{stderr.read}"
30
+ end
31
+ return source
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,60 @@
1
+ require "snowball/roller"
2
+
3
+ module Sinatra
4
+ module Snowball
5
+ # Resolves a file relative to the source path
6
+ def self.resolve_file(config, file)
7
+ source_paths = config.source_paths
8
+ extensions = config.extensions
9
+
10
+ source_paths.each do |source_path|
11
+ try_file = File.expand_path(File.join(source_path, file))
12
+
13
+ # Skip if file is not descendant of the current source path
14
+ next unless try_file =~ /^#{source_path}/
15
+
16
+ return try_file if File.exists?(try_file)
17
+ extensions.each do |ext|
18
+ try_file = File.join(source_path, File.dirname(file), "#{File.basename(file, File.extname(file))}.#{ext}")
19
+ return try_file if File.exists?(try_file)
20
+ end
21
+ end
22
+ raise Errno::ENOENT.new(file)
23
+ end
24
+
25
+ def self.registered(app)
26
+ app.helpers(Sinatra::Snowball::Helpers)
27
+ end
28
+
29
+ def snowball(&block)
30
+ config = ::Snowball::Config.new
31
+ builder = ::Snowball::Config::Builder.new(config)
32
+ builder.send(:instance_eval, &block)
33
+ self.set :snowball, config
34
+ self.get "#{config.http_path}/*" do |bundle|
35
+ begin
36
+ entryfile = Snowball.resolve_file(config, bundle)
37
+ rescue Errno::ENOENT => e
38
+ halt 404, "File #{bundle} not found"
39
+ end
40
+
41
+ if File.extname(bundle) != '.js' or config.raw.any? { |glob_str| File.fnmatch(glob_str, entryfile) }
42
+ send_file entryfile
43
+ else
44
+ content_type :js
45
+ [200, ::Snowball::Roller.roll(*[entryfile, config].compact)]
46
+ end
47
+ end
48
+ end
49
+
50
+ module Helpers
51
+ def javascript_path(file)
52
+ "#{self.settings.snowball.http_path}/#{file}.js"
53
+ end
54
+
55
+ def javascript_tag(file, opts={})
56
+ "<script src=\"#{javascript_path(file)}\"#{' async' if opts[:async]}></script>"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,3 @@
1
+ module Snowball
2
+ VERSION = "0.1.3"
3
+ end
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "snowball",
3
+ "version": "0.0.0",
4
+ "dependencies": {
5
+ "browserify": "latest",
6
+ "jade": "latest",
7
+ "jade-runtime": "git://github.com/bjoerge/jade-runtime",
8
+ "optimist": "latest"
9
+ },
10
+ "engines": {
11
+ "node": "*"
12
+ },
13
+ "devDependencies": {},
14
+ "optionalDependencies": {}
15
+ }
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "snowball/version"
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.authors = ["Bjørge Næss"]
7
+ gem.email = ["bjoerge@bengler.no"]
8
+ gem.description = %q{A better way of managing and serving your front-end dependencies}
9
+ gem.summary = %q{It currently uses browserify to roll a ball of your application npm dependencies}
10
+ gem.homepage = ""
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "snowball"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = Snowball::VERSION
18
+
19
+ gem.extensions << 'extconf.rb'
20
+
21
+ gem.add_development_dependency "sinatra"
22
+ gem.add_development_dependency "haml"
23
+ gem.add_development_dependency "rspec"
24
+ gem.add_development_dependency "rack-test"
25
+ gem.add_development_dependency "simplecov"
26
+ end
@@ -0,0 +1,3 @@
1
+ exports.saySomething = function() {
2
+ console.log("Chunky bacon");
3
+ };
@@ -0,0 +1,3 @@
1
+ console.log("There's only one thing that is better than butter: more butter");
2
+
3
+ require("./bacon").saySomething();
@@ -0,0 +1 @@
1
+ alert("Hello world");
@@ -0,0 +1 @@
1
+ var steak = "raw";
File without changes
@@ -0,0 +1,5 @@
1
+ console.log(
2
+ "A tart is a baked dish consisting of a filling over a pastry base with an open top not covered with pastry.",
3
+ "The pastry is usually shortcrust pastry; the filling may be sweet or savoury, though modern tarts are usually",
4
+ "fruit-based, sometimes with custard."
5
+ );
@@ -0,0 +1 @@
1
+ console.log "Tartlet refers to a miniature tart."
@@ -0,0 +1 @@
1
+ require("./syntax-error")
@@ -0,0 +1,6 @@
1
+ bacon = require("./bacon")
2
+
3
+ test = ->
4
+ require("./butter")
5
+
6
+ hello = require("./hello")
@@ -0,0 +1,2 @@
1
+ func = (arg)->
2
+ alert("Arg is #{arg}")
@@ -0,0 +1,3 @@
1
+ var module = require("this-module-doesnt-exist");
2
+
3
+
@@ -0,0 +1,21 @@
1
+ class SnowballApp < Sinatra::Base
2
+ register Sinatra::Snowball
3
+ snowball do
4
+ http_path "/js"
5
+ source_path "spec/fixtures/js"
6
+ source_path "spec/fixtures/js/food"
7
+ raw "*/food/steak.js"
8
+ end
9
+
10
+ get "/javascript_tag" do
11
+ haml '= javascript_tag("some")'
12
+ end
13
+
14
+ get "/javascript_tag_async" do
15
+ haml '= javascript_tag("pastry/tart", async: true)'
16
+ end
17
+
18
+ get "/javascript_path" do
19
+ haml "%script{:src => javascript_path('food/steak')}"
20
+ end
21
+ end
@@ -0,0 +1 @@
1
+ var secret = "chunky bacon";
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+ require 'sinatra'
4
+ require 'snowball/sinatra'
5
+
6
+ require 'fixtures/snowball_app'
7
+
8
+ describe "SnowballApp" do
9
+ include Rack::Test::Methods
10
+
11
+ def app
12
+ SnowballApp
13
+ end
14
+
15
+ describe "endpoints" do
16
+ it "serves js-files with the correct status code and content-type" do
17
+ get "/js/dummy.js"
18
+ last_response.status.should eq 200
19
+ last_response.content_type.should match /application\/javascript(;.+)?/
20
+ end
21
+
22
+ it "locates a js-file in the load path" do
23
+ get "/js/dummy.js"
24
+ last_response.body.should match Regexp.escape('alert("Hello world")')
25
+ end
26
+
27
+ it "resolves a coffee-script entry file and serves it compiled" do
28
+ get "/js/some.js"
29
+ last_response.status.should eq 200
30
+ compiled = Regexp.escape("var func;\n\n func = function(arg) {\n return alert(\"Arg is \" + arg);\n };\n\n}")
31
+ last_response.body.should match compiled
32
+ end
33
+
34
+ it "serves the coffee-script file raw if requested with .coffee as extension" do
35
+ get "/js/require.coffee"
36
+ last_response.status.should eq 200
37
+ last_response.body.should match Regexp.escape("test = ->")
38
+ end
39
+
40
+ it "includes transitive dependencies" do
41
+ get "/js/require.js"
42
+ last_response.status.should eq 200
43
+ last_response.body.should match Regexp.escape('console.log("Chunky bacon")')
44
+ end
45
+
46
+ it "returns 404 for files not found" do
47
+ get "/js/thisdoesntexists.js"
48
+ last_response.status.should eq 404
49
+ end
50
+
51
+ it "forwards errors to the browser by throwing them in the bundle" do
52
+ get "/js/will-fail.js"
53
+ last_response.status.should eq 200
54
+
55
+ last_response.body.should match /throw new Error\(\"Cannot find module\: \\"this\-module\-doesnt\-exist\\" from directory (.*) while processing file (.*)will\-fail\.js/
56
+ end
57
+
58
+ it "also forwards parse/syntax errors" do
59
+ get "/js/syntax-error.js"
60
+ last_response.status.should eq 200
61
+ last_response.body.should match /throw new Error\(\"In (.*)syntax\-error\.coffee\, Parse error on line 1\: Unexpected \'\.\.\.\'\"/
62
+ end
63
+
64
+ it "forwards parse/syntax errors even if the error occurs in a require()'d file" do
65
+ get "/js/require-error.js"
66
+ last_response.status.should eq 200
67
+ last_response.body.should match /throw new Error\(\"In (.*)syntax\-error\.coffee\, Parse error on line 1\: Unexpected \'\.\.\.\'\"/
68
+ end
69
+
70
+ it "can specify a glob string of files that should be served raw" do
71
+ get "/js/food/steak.js"
72
+ last_response.status.should eq 200
73
+ last_response.body.should match 'var steak = "raw"'
74
+ end
75
+ end
76
+
77
+ describe "sinatra helpers" do
78
+ it "inserts a <script tag into the template" do
79
+ get "/javascript_tag"
80
+ last_response.body.should include '<script src="/js/some.js"></script>'
81
+ end
82
+ it "inserts a <script tag into the template" do
83
+ get "/javascript_tag_async"
84
+ last_response.body.should include '<script src="/js/pastry/tart.js" async></script>'
85
+ end
86
+ it "inserts a <script tag into the template" do
87
+ get "/javascript_path"
88
+ last_response.body.should include "<script src='/js/food/steak.js'></script>"
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ require 'simplecov'
3
+ require 'rack/test'
4
+ SimpleCov.add_filter "spec"
5
+ SimpleCov.start
6
+
7
+ Bundler.require
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: snowball
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bjørge Næss
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sinatra
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: haml
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rack-test
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: simplecov
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: A better way of managing and serving your front-end dependencies
95
+ email:
96
+ - bjoerge@bengler.no
97
+ executables:
98
+ - roll.js
99
+ extensions:
100
+ - extconf.rb
101
+ extra_rdoc_files: []
102
+ files:
103
+ - .gitignore
104
+ - .rspec
105
+ - Gemfile
106
+ - LICENSE
107
+ - README.md
108
+ - Rakefile
109
+ - bin/roll.js
110
+ - extconf.rb
111
+ - lib/snowball.rb
112
+ - lib/snowball/config.rb
113
+ - lib/snowball/roller.rb
114
+ - lib/snowball/sinatra.rb
115
+ - lib/snowball/version.rb
116
+ - package.json
117
+ - snowball.gemspec
118
+ - spec/fixtures/js/bacon.js
119
+ - spec/fixtures/js/butter.js
120
+ - spec/fixtures/js/dummy.js
121
+ - spec/fixtures/js/food/steak.js
122
+ - spec/fixtures/js/hello.jade
123
+ - spec/fixtures/js/pastry/tart.js
124
+ - spec/fixtures/js/pastry/tartlet.coffee
125
+ - spec/fixtures/js/require-error.js
126
+ - spec/fixtures/js/require.coffee
127
+ - spec/fixtures/js/some.coffee
128
+ - spec/fixtures/js/syntax-error.coffee
129
+ - spec/fixtures/js/will-fail.js
130
+ - spec/fixtures/snowball_app.rb
131
+ - spec/fixtures/super-secret.js
132
+ - spec/snowball_spec.rb
133
+ - spec/spec_helper.rb
134
+ homepage: ''
135
+ licenses: []
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ none: false
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 1.8.24
155
+ signing_key:
156
+ specification_version: 3
157
+ summary: It currently uses browserify to roll a ball of your application npm dependencies
158
+ test_files:
159
+ - spec/fixtures/js/bacon.js
160
+ - spec/fixtures/js/butter.js
161
+ - spec/fixtures/js/dummy.js
162
+ - spec/fixtures/js/food/steak.js
163
+ - spec/fixtures/js/hello.jade
164
+ - spec/fixtures/js/pastry/tart.js
165
+ - spec/fixtures/js/pastry/tartlet.coffee
166
+ - spec/fixtures/js/require-error.js
167
+ - spec/fixtures/js/require.coffee
168
+ - spec/fixtures/js/some.coffee
169
+ - spec/fixtures/js/syntax-error.coffee
170
+ - spec/fixtures/js/will-fail.js
171
+ - spec/fixtures/snowball_app.rb
172
+ - spec/fixtures/super-secret.js
173
+ - spec/snowball_spec.rb
174
+ - spec/spec_helper.rb
175
+ has_rdoc: