cup 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,116 @@
1
+ require 'active_model'
2
+
3
+ module Cup
4
+ class Cupfile
5
+ include ActiveModel::Validations
6
+ class CupfileError < RuntimeError; end
7
+
8
+ attr_accessor :path
9
+ attr_reader :path, :name, :version, :license, :before_build, :after_build, :uglifier_options
10
+
11
+ validates_presence_of :name, :version, :path
12
+ validate :license_file_exists?
13
+
14
+ def initialize path
15
+
16
+ @path = path
17
+ @javascripts = {}
18
+ @uglifier_options = {}
19
+ @before_build = lambda {}
20
+ @after_build = lambda {}
21
+
22
+ %w{vendor spec lib src}.each do |dir|
23
+ set_javascript_patterns_for dir.to_sym, :*
24
+ end
25
+
26
+ cup_define_block = eval(File.read(path), binding, path.to_s)
27
+ DSL.interpret self, &cup_define_block
28
+ end
29
+
30
+ def javascripts
31
+ @javascripts
32
+ end
33
+
34
+ private
35
+
36
+ def set_javascript_patterns_for subdir, *patterns
37
+
38
+ current_directory = File.dirname(File.expand_path(self.path))
39
+
40
+ @javascripts[subdir] = patterns.map do |pattern|
41
+
42
+ default_catch_all = pattern == :*
43
+
44
+ pattern = '**/*.js' if default_catch_all
45
+
46
+ if pattern
47
+ expanded_pattern = current_directory + "/#{subdir}/#{pattern}"
48
+ FileList[expanded_pattern].select do |f|
49
+ if subdir == :spec and f.start_with?(current_directory + "/spec/visual")
50
+ false
51
+ else
52
+ File.extname(f).downcase == '.js'
53
+ end
54
+ end
55
+ end
56
+ end.flatten.compact.uniq
57
+ end
58
+
59
+ def license_file_exists?
60
+ unless license.nil? or path.nil?
61
+ license_path = "#{File.dirname(File.expand_path(path))}/#{license}"
62
+ errors.add :license, "#{license} is not a valid license file" unless File.exist?(license_path) and not File.directory?(license_path)
63
+ end
64
+ end
65
+
66
+ class DSL < BasicObject
67
+ private_class_method :new
68
+
69
+ ## DSL members
70
+ ## setters
71
+ %W{version name license uglifier_options}.each do |m|
72
+ define_method m do |value|
73
+ @cupfile.instance_variable_set "@#{m}", value
74
+ end
75
+ end
76
+
77
+ def self.interpret cupfile, &block
78
+ new(cupfile).instance_eval &block
79
+ cupfile
80
+ end
81
+
82
+ def initialize cupfile
83
+ @cupfile = cupfile
84
+ end
85
+
86
+ def javascripts &block
87
+ JavascriptsDSL.interpret @cupfile, &block
88
+ end
89
+
90
+ ## block cachers
91
+ def before_build &block
92
+ @cupfile.instance_variable_set :@before_build, block
93
+ end
94
+
95
+ def after_build &block
96
+ @cupfile.instance_variable_set :@after_build, block
97
+ end
98
+
99
+ class JavascriptsDSL < BasicObject
100
+
101
+ def initialize cupfile
102
+ @cupfile = cupfile
103
+ end
104
+
105
+ def self.interpret cupfile, &block
106
+ new(cupfile).instance_eval &block
107
+ cupfile
108
+ end
109
+
110
+ def method_missing name, *args, &block
111
+ @cupfile.send :set_javascript_patterns_for, name, *(args.flatten)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,96 @@
1
+ require 'pathname'
2
+ require 'rake'
3
+ require 'cup/cupfile'
4
+
5
+ module Cup
6
+
7
+ # Represents the directory that holds a cup
8
+ class Directory
9
+
10
+ attr_reader :path
11
+
12
+ def initialize path
13
+ @path = Pathname.new File.expand_path(path.to_s)
14
+ end
15
+
16
+ # so that current can be overridden for all tests
17
+ def self.__current__
18
+ new('.')
19
+ end
20
+
21
+ def self.current
22
+ __current__
23
+ end
24
+
25
+ def cupfile
26
+ @cupfile ||= Cup::Cupfile.new(path + 'Cupfile')
27
+
28
+ unless @cupfile.valid?
29
+ raise Cup::Cupfile::CupfileError.new("Cupfile not valid: #{@cupfile.path.to_s}\n#{@cupfile.errors.full_messages}")
30
+ end
31
+
32
+ @cupfile
33
+ end
34
+
35
+ def name
36
+ File.basename path.to_s
37
+ end
38
+
39
+ def concatenated(opts={})
40
+ output = "build/#{name}-#{cupfile.version}.js"
41
+ opts[:relative] ? output : "#{self.path}/#{output}"
42
+ end
43
+
44
+ def minified(opts={})
45
+ output = "build/#{name}-#{cupfile.version}.min.js"
46
+ opts[:relative] ? output : "#{self.path}/#{output}"
47
+ end
48
+
49
+ def license(opts={})
50
+ license = "#{cupfile.license}"
51
+ opts[:relative] ? license : "#{self.path}/#{license}"
52
+ end
53
+
54
+ def javascripts scheme=nil
55
+
56
+ load_paths = case scheme
57
+ when :spec
58
+ ['vendor', 'spec', 'lib', 'src']
59
+ when :build_input
60
+ ['lib', 'src']
61
+ when :spec_concatenated, :spec_minified
62
+ ['vendor', 'spec', 'build']
63
+ when :debug
64
+ ['vendor', 'lib', 'src']
65
+ else
66
+ raise "scheme not known: #{scheme}"
67
+ end
68
+
69
+ javascripts = load_paths.map do |load_path|
70
+ if load_path == 'build'
71
+ build_for scheme
72
+ else
73
+ cupfile.javascripts[load_path.to_sym].map{|filepath| Pathname.new(filepath).to_s}
74
+ end
75
+ end.flatten
76
+
77
+ javascripts
78
+ end
79
+
80
+ def stylesheets
81
+ FileList['**/*.css'].map{|f| Pathname.new(f).expand_path}
82
+ end
83
+
84
+ private
85
+ def build_for scheme
86
+ case scheme
87
+ when :spec_concatenated
88
+ concatenated
89
+ when :spec_minified
90
+ minified
91
+ else
92
+ raise "scheme :#{scheme} not expected to include 'build' load path"
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,12 @@
1
+ module Cup
2
+ module NoopShell
3
+
4
+ module_function
5
+
6
+ def say *params
7
+ end
8
+
9
+ def say_status *params
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,138 @@
1
+ require 'cup/directory'
2
+ require 'cup/server/view_scope'
3
+ require 'cup/server/middleware'
4
+
5
+ require 'sinatra/base'
6
+ require 'yard'
7
+ require 'json'
8
+ require 'slim'
9
+ require 'sass'
10
+ require 'coffee_script'
11
+
12
+ begin
13
+ require 'thin'
14
+ Thin::Logging.debug = :log
15
+ rescue LoadError
16
+ end
17
+
18
+ module Cup
19
+ module Server
20
+ class App < Sinatra::Base
21
+
22
+ use Middleware
23
+
24
+ configure(:development) do
25
+ require 'ruby-debug'
26
+ require 'sinatra/reloader'
27
+ register Sinatra::Reloader
28
+ also_reload "#{File.expand_path('../../..', __FILE__)}/**/*.rb"
29
+ end
30
+
31
+ def self.gem_root_path *params
32
+ # uses a file relative version so that it points to the live files during development
33
+ File.expand_path(File.join('../../../..', *params), __FILE__)
34
+ end
35
+
36
+ set :server, %w{thin mongrel webrick}
37
+ set :views, gem_root_path('views')
38
+ set :public_folder, Cup::Directory.current.path.to_s
39
+
40
+ def view_scope(javascripts_scheme=:debug)
41
+ @view_scope = ViewScope.new self, javascripts_scheme
42
+ end
43
+
44
+ def view (template, options={})
45
+
46
+ options = {
47
+ :scope => view_scope(options.delete(:javascripts_scheme) || :debug),
48
+ :layout => true
49
+ }.merge options
50
+
51
+ slim template, options
52
+ end
53
+
54
+ def visuals
55
+ @visuals ||= VisualSpecs.get
56
+ end
57
+
58
+ def gem_root_path *params
59
+ self.class.gem_root_path *params
60
+ end
61
+
62
+ get '/cup.sass' do
63
+ sass File.read(gem_root_path('views/cup.sass'))
64
+ end
65
+
66
+ get '/cup.coffee' do
67
+ coffee File.read(gem_root_path('views/cup.coffee'))
68
+ end
69
+
70
+ get '/' do
71
+ view :root
72
+ end
73
+
74
+ get '/concatenate' do
75
+
76
+ content_type 'text/javascript'
77
+
78
+ result = Cup.build[:concatenated]
79
+ if result[:status] == :ok
80
+ body result[:output]
81
+ else
82
+ redirect '/'
83
+ end
84
+ end
85
+
86
+ get '/minify' do
87
+
88
+ content_type 'text/javascript'
89
+
90
+ result = Cup.build[:minified]
91
+ if result[:status] == :ok
92
+ body result[:output]
93
+ else
94
+ redirect '/'
95
+ end
96
+ end
97
+
98
+ get '/debug' do
99
+ view ''
100
+ end
101
+
102
+ get '/empty' do
103
+ redirect '/' if view_scope.build_status == :failed
104
+ view '', :layout => :blank
105
+ end
106
+
107
+ get '/spec' do
108
+ view :spec, :javascripts_scheme => :spec
109
+ end
110
+
111
+ get '/spec/concatenated' do
112
+ view :spec, :javascripts_scheme => :spec_concatenated
113
+ end
114
+
115
+ get '/spec/minified' do
116
+ view :spec, :javascripts_scheme => :spec_minified
117
+ end
118
+
119
+ get '/spec/visual' do
120
+ view :visual
121
+ end
122
+
123
+ get '/spec/visual/*' do |visual|
124
+ visual = visuals[visual]
125
+
126
+ pass if visual.nil? or not File.exist?(visual.full_path)
127
+
128
+ redirect '/spec/visual' if view_scope.build_status == :failed
129
+
130
+ view File.read(visual.full_path), :layout => :blank
131
+ end
132
+
133
+ not_found do
134
+ view :not_found
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,27 @@
1
+ require 'rack/directory'
2
+
3
+ module Cup
4
+ module Server
5
+ class Middleware
6
+
7
+ def initialize app
8
+ @app = app
9
+ @directory = Rack::Directory.new(Cup::Directory.current.path)
10
+ end
11
+
12
+ def call(env)
13
+
14
+ status, headers, response = @app.call(env)
15
+
16
+ if status == 404
17
+ directory_status, *result = @directory.call(env)
18
+ if (200...300).include? directory_status
19
+ status, headers, response = directory_status, *result
20
+ end
21
+ end
22
+
23
+ [status, headers, response]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,108 @@
1
+ require 'yard'
2
+ require 'cup'
3
+ require 'cup/directory'
4
+ require 'cup/server/visual_specs'
5
+
6
+ module Cup
7
+ module Server
8
+ class ViewScope
9
+
10
+ def initialize server, javascripts_scheme=nil
11
+ @server = server
12
+ @javascripts_scheme = javascripts_scheme
13
+ end
14
+
15
+ def name
16
+ Cup.cup_name
17
+ end
18
+
19
+ def build_status
20
+ build_result[:status]
21
+ end
22
+
23
+ def build_result
24
+ #return {:status => :failed, :exception => 'you went wrong'}
25
+ @build_result ||= begin
26
+ result = Cup.build
27
+ result[:concatenated][:status] == :ok ? result[:minified] : result[:concatenated]
28
+ end
29
+ end
30
+
31
+ def version
32
+ Cup.version
33
+ end
34
+
35
+ def cup_version
36
+ Cup::VERSION
37
+ end
38
+
39
+ def stylesheets
40
+ @stylesheets ||= Cup::Directory.current.stylesheets.map do |src|
41
+ '/' + File.relative_path(Cup::Directory.current.path, src)
42
+ end
43
+ end
44
+
45
+ def javascripts
46
+ @javascripts ||= if @javascripts_scheme.nil?
47
+ []
48
+ else
49
+ Cup::Directory.current.javascripts(@javascripts_scheme).map do |src|
50
+ '/' + File.relative_path(Cup::Directory.current.path, src)
51
+ end
52
+ end
53
+ end
54
+
55
+ def path
56
+ Cup::Directory.current.path
57
+ end
58
+
59
+ def concatenated
60
+ File.basename Cup.concatenated(:relative => true)
61
+ end
62
+
63
+ def concatenated_size
64
+ "#{File.exist?(Cup.concatenated) ? File.size(Cup.concatenated) : 0} bytes"
65
+ end
66
+
67
+ def minified
68
+ File.basename Cup.minified(:relative => true)
69
+ end
70
+
71
+ def minified_size
72
+ "#{File.exist?(Cup.minified) ? File.size(Cup.minified) : 0} bytes"
73
+ end
74
+
75
+ def minified_percent_available?
76
+ File.exists?(Cup.concatenated) and File.size(Cup.concatenated) > 0
77
+ end
78
+
79
+ def minified_percent
80
+
81
+ concatenated_size = File.size(Cup.concatenated).to_f
82
+ minified_size = File.size(Cup.minified).to_f
83
+
84
+ (100*(minified_size / concatenated_size)).round(2)
85
+ end
86
+
87
+ def lib_count
88
+ Cup::Directory.current.cupfile.javascripts[:lib].count
89
+ end
90
+
91
+ def src_count
92
+ Cup::Directory.current.cupfile.javascripts[:src].count
93
+ end
94
+
95
+ def file_list
96
+ Dir["#{Cup::Directory.current.path}/**/*"].select do |full_path|
97
+ File.file?(full_path)
98
+ end.map do |full_path|
99
+ File.relative_path(Cup::Directory.current.path, full_path)
100
+ end
101
+ end
102
+
103
+ def visuals
104
+ @server.visuals.values
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,33 @@
1
+ require 'yard'
2
+ require 'cup/directory'
3
+
4
+ module Cup
5
+ module Server
6
+ # not a member of Cup::Directory incase we ever want to search for visuals in arbitrary directories
7
+ module VisualSpecs
8
+ module_function
9
+
10
+ class VisualSpec
11
+ attr_accessor :href, :name, :full_path
12
+ end
13
+
14
+ def get(directory = Cup::Directory.current.path + 'spec' + 'visual')
15
+
16
+ visuals = {}
17
+
18
+ Dir["#{File.expand_path(directory)}/**/*.slim"].select { |path| File.file?(path) }.each do |full_path|
19
+
20
+ href = '/' + File.relative_path(Cup::Directory.current.path, full_path).match(/(.*)\.slim$/)[1]
21
+ name = File.relative_path(File.expand_path(directory), full_path).match(/(.*)\.slim$/)[1]
22
+
23
+ visuals[name] = VisualSpec.new.tap do |v|
24
+ v.href, v.name, v.full_path = href, name, full_path
25
+ end
26
+ end
27
+
28
+ visuals
29
+ end
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,3 @@
1
+ module Cup
2
+ VERSION = '0.0.3'
3
+ end
data/lib/cup.rb CHANGED
@@ -1,5 +1,57 @@
1
+ require 'cup/version'
2
+ require 'cup/directory'
3
+ require 'cup/cupfile'
4
+ require 'cup/builder'
5
+
1
6
  module Cup
2
- def create name, options={}
7
+ class << self
8
+
9
+ def version *params
10
+ directory.cupfile.version *params
11
+ end
12
+
13
+ def cup_name *params
14
+ directory.cupfile.name *params
15
+ end
16
+
17
+ def concatenated *params
18
+ directory.concatenated *params
19
+ end
20
+
21
+ def minified *params
22
+ directory.minified *params
23
+ end
24
+
25
+ def build! *params
26
+ Cup::Builder.new(directory).build! *params
27
+ end
28
+
29
+ def build *params
30
+ Cup::Builder.new(directory).build *params
31
+ end
3
32
 
33
+ def concatenate! *params
34
+ Cup::Builder.new(directory).concatenate! *params
35
+ end
36
+
37
+ def concatenate *params
38
+ Cup::Builder.new(directory).concatenate *params
39
+ end
40
+
41
+ def minify! *params
42
+ Cup::Builder.new(directory).minify! *params
43
+ end
44
+
45
+ def minify *params
46
+ Cup::Builder.new(directory).minify *params
47
+ end
48
+
49
+ def define &block
50
+ block
51
+ end
52
+ private
53
+ def directory
54
+ @directory ||= Cup::Directory.current
55
+ end
4
56
  end
5
- end
57
+ end