rapper 0.0.1

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.
Files changed (90) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +11 -0
  4. data/Gemfile.lock +24 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.markdown +140 -0
  7. data/Rakefile +45 -0
  8. data/VERSION +1 -0
  9. data/lib/rapper.rb +66 -0
  10. data/lib/rapper/compressors.rb +47 -0
  11. data/lib/rapper/config.rb +95 -0
  12. data/lib/rapper/errors.rb +23 -0
  13. data/lib/rapper/logging.rb +35 -0
  14. data/lib/rapper/utils.rb +106 -0
  15. data/lib/rapper/versioning.rb +37 -0
  16. data/lib/yui/css_compressor.rb +279 -0
  17. data/rapper.gemspec +167 -0
  18. data/spec/fixtures/config/assets.yml +25 -0
  19. data/spec/fixtures/config/assets/base/javascripts.yml +12 -0
  20. data/spec/fixtures/config/assets/base/stylesheets.yml +10 -0
  21. data/spec/fixtures/config/assets/base/validators.yml +9 -0
  22. data/spec/fixtures/javascripts/simple_1.js +5 -0
  23. data/spec/fixtures/javascripts/simple_2.js +5 -0
  24. data/spec/fixtures/stylesheets/simple_1.css +4 -0
  25. data/spec/fixtures/stylesheets/simple_2.css +4 -0
  26. data/spec/fixtures/test_cases/concatenation/assets.yml +5 -0
  27. data/spec/fixtures/test_cases/concatenation/definitions/css.yml +15 -0
  28. data/spec/fixtures/test_cases/concatenation/definitions/js.yml +15 -0
  29. data/spec/fixtures/test_cases/concatenation/expected/base.css +8 -0
  30. data/spec/fixtures/test_cases/concatenation/expected/base.js +10 -0
  31. data/spec/fixtures/test_cases/concatenation/expected/base_reversed.css +8 -0
  32. data/spec/fixtures/test_cases/concatenation/expected/base_reversed.js +10 -0
  33. data/spec/fixtures/yui_css/background-position.css +2 -0
  34. data/spec/fixtures/yui_css/background-position.css.min +1 -0
  35. data/spec/fixtures/yui_css/box-model-hack.css +9 -0
  36. data/spec/fixtures/yui_css/box-model-hack.css.min +1 -0
  37. data/spec/fixtures/yui_css/bug2527974.css +9 -0
  38. data/spec/fixtures/yui_css/bug2527974.css.min +1 -0
  39. data/spec/fixtures/yui_css/bug2527991.css +19 -0
  40. data/spec/fixtures/yui_css/bug2527991.css.min +1 -0
  41. data/spec/fixtures/yui_css/bug2527998.css +4 -0
  42. data/spec/fixtures/yui_css/bug2527998.css.min +1 -0
  43. data/spec/fixtures/yui_css/bug2528034.css +5 -0
  44. data/spec/fixtures/yui_css/bug2528034.css.min +1 -0
  45. data/spec/fixtures/yui_css/charset-media.css +9 -0
  46. data/spec/fixtures/yui_css/charset-media.css.min +1 -0
  47. data/spec/fixtures/yui_css/color.css +7 -0
  48. data/spec/fixtures/yui_css/color.css.min +1 -0
  49. data/spec/fixtures/yui_css/comment.css +3 -0
  50. data/spec/fixtures/yui_css/comment.css.min +1 -0
  51. data/spec/fixtures/yui_css/concat-charset.css +15 -0
  52. data/spec/fixtures/yui_css/concat-charset.css.min +1 -0
  53. data/spec/fixtures/yui_css/decimals.css +3 -0
  54. data/spec/fixtures/yui_css/decimals.css.min +1 -0
  55. data/spec/fixtures/yui_css/dollar-header.css +7 -0
  56. data/spec/fixtures/yui_css/dollar-header.css.min +3 -0
  57. data/spec/fixtures/yui_css/font-face.css +6 -0
  58. data/spec/fixtures/yui_css/font-face.css.min +1 -0
  59. data/spec/fixtures/yui_css/ie5mac.css +5 -0
  60. data/spec/fixtures/yui_css/ie5mac.css.min +1 -0
  61. data/spec/fixtures/yui_css/media-empty-class.css +16 -0
  62. data/spec/fixtures/yui_css/media-empty-class.css.min +1 -0
  63. data/spec/fixtures/yui_css/media-multi.css +5 -0
  64. data/spec/fixtures/yui_css/media-multi.css.min +1 -0
  65. data/spec/fixtures/yui_css/media-test.css +5 -0
  66. data/spec/fixtures/yui_css/media-test.css.min +1 -0
  67. data/spec/fixtures/yui_css/opacity-filter.css +14 -0
  68. data/spec/fixtures/yui_css/opacity-filter.css.min +1 -0
  69. data/spec/fixtures/yui_css/preserve-new-line.css +6 -0
  70. data/spec/fixtures/yui_css/preserve-new-line.css.min +3 -0
  71. data/spec/fixtures/yui_css/preserve-strings.css +7 -0
  72. data/spec/fixtures/yui_css/preserve-strings.css.min +1 -0
  73. data/spec/fixtures/yui_css/preserve_string.css +7 -0
  74. data/spec/fixtures/yui_css/preserve_string.css.min +1 -0
  75. data/spec/fixtures/yui_css/pseudo-first.css +16 -0
  76. data/spec/fixtures/yui_css/pseudo-first.css.min +1 -0
  77. data/spec/fixtures/yui_css/pseudo.css +4 -0
  78. data/spec/fixtures/yui_css/pseudo.css.min +1 -0
  79. data/spec/fixtures/yui_css/special-comments.css +13 -0
  80. data/spec/fixtures/yui_css/special-comments.css.min +9 -0
  81. data/spec/fixtures/yui_css/star-underscore-hacks.css +5 -0
  82. data/spec/fixtures/yui_css/star-underscore-hacks.css.min +1 -0
  83. data/spec/fixtures/yui_css/string-in-comment.css +8 -0
  84. data/spec/fixtures/yui_css/string-in-comment.css.min +1 -0
  85. data/spec/fixtures/yui_css/zeros.css +6 -0
  86. data/spec/fixtures/yui_css/zeros.css.min +1 -0
  87. data/spec/rapper_spec.rb +139 -0
  88. data/spec/spec_helper.rb +57 -0
  89. data/spec/vendor_spec.rb +36 -0
  90. metadata +349 -0
@@ -0,0 +1 @@
1
+ .color{me:#7b7b7b;impressed:#fed;filter:chroma(color="#FFFFFF");background:none repeat scroll 0 0 #ff0;alpha:rgba(1,2,3,4)}
@@ -0,0 +1,3 @@
1
+ html >/**/ body p {
2
+ color: blue;
3
+ }
@@ -0,0 +1 @@
1
+ html>/**/body p{color:blue}
@@ -0,0 +1,15 @@
1
+ /* This is invalid CSS, but frequently happens as a result of concatenation. */
2
+ @charset "utf-8";
3
+ #foo {
4
+ border-width:1px;
5
+ }
6
+ /*
7
+ Note that this is erroneous!
8
+ The actual CSS file can only have a single charset.
9
+ However, this is the job of the author/application.
10
+ The compressor should not get involved.
11
+ */
12
+ @charset "another one";
13
+ #bar {
14
+ border-width:10px;
15
+ }
@@ -0,0 +1 @@
1
+ @charset "utf-8";#foo{border-width:1px}#bar{border-width:10px}
@@ -0,0 +1,3 @@
1
+ ::selection {
2
+ margin: 0.6px 0.333pt 1.2em 8.8cm;
3
+ }
@@ -0,0 +1 @@
1
+ ::selection{margin:.6px .333pt 1.2em 8.8cm}
@@ -0,0 +1,7 @@
1
+ /*!
2
+ $Header: /temp/dirname/filename.css 3 2/02/08 3:37p JSmith $
3
+ */
4
+
5
+ foo {
6
+ bar: baz
7
+ }
@@ -0,0 +1,3 @@
1
+ /*!
2
+ $Header: /temp/dirname/filename.css 3 2/02/08 3:37p JSmith $
3
+ */foo{bar:baz}
@@ -0,0 +1,6 @@
1
+ @font-face {
2
+ font-family: 'gzipper';
3
+ src: url(yanone.eot);
4
+ src: local('gzipper'),
5
+ url(yanone.ttf) format('truetype');
6
+ }
@@ -0,0 +1 @@
1
+ @font-face{font-family:'gzipper';src:url(yanone.eot);src:local('gzipper'),url(yanone.ttf) format('truetype')}
@@ -0,0 +1,5 @@
1
+ /* Ignore the next rule in IE mac \*/
2
+ .selector {
3
+ color: khaki;
4
+ }
5
+ /* Stop ignoring in IE mac */
@@ -0,0 +1 @@
1
+ /*\*/.selector{color:khaki}/**/
@@ -0,0 +1,16 @@
1
+ /*! preserved */
2
+ emptiness {}
3
+
4
+ @import "another.css";
5
+ /* I'm empty - delete me */
6
+ empty { ;}
7
+
8
+ @media print {
9
+ .noprint { display: none; }
10
+ }
11
+
12
+ @media screen {
13
+ /* this rule should be removed, not simply minified.*/
14
+ .breakme {}
15
+ .printonly { display: none; }
16
+ }
@@ -0,0 +1 @@
1
+ /*! preserved */@import "another.css";@media print{.noprint{display:none}}@media screen{.printonly{display:none}}
@@ -0,0 +1,5 @@
1
+ @media only all and (max-width:50em), only all and (max-device-width:800px), only all and (max-width:780px) {
2
+ p{
3
+ some-css : here
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ @media only all and (max-width:50em),only all and (max-device-width:800px),only all and (max-width:780px){p{some-css:here}}
@@ -0,0 +1,5 @@
1
+ @media screen and (-webkit-min-device-pixel-ratio:0) {
2
+ p{
3
+ some-css : here
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ @media screen and (-webkit-min-device-pixel-ratio:0){p{some-css:here}}
@@ -0,0 +1,14 @@
1
+ /* example from https://developer.mozilla.org/en/CSS/opacity */
2
+ pre { /* make the box translucent (80% opaque) */
3
+ border: solid red;
4
+ opacity: 0.8; /* Firefox, Safari(WebKit), Opera */
5
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */
6
+ filter: PROGID:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE 4-7 */
7
+ zoom: 1; /* set "zoom", "width" or "height" to trigger "hasLayout" in IE 7 and lower */
8
+ }
9
+
10
+ /** and again */
11
+ code {
12
+ -ms-filter: "PROGID:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */
13
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE 4-7 */
14
+ }
@@ -0,0 +1 @@
1
+ pre{border:solid red;opacity:.8;-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80);zoom:1}code{-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80)}
@@ -0,0 +1,6 @@
1
+ #sel-o {
2
+ content: "on\"ce upon \
3
+ a time";
4
+ content: 'once upon \
5
+ a ti\'me';
6
+ }
@@ -0,0 +1,3 @@
1
+ #sel-o{content:"on\"ce upon \
2
+ a time";content:'once upon \
3
+ a ti\'me'}
@@ -0,0 +1,7 @@
1
+ /* preserving strings */
2
+ .sele {
3
+ content: "\"keep \" me";
4
+ something: '\\\' . . ';
5
+ else: 'empty{}';
6
+ content: "/* test */"; /* <---- this is not a comment, should be be kept */
7
+ }
@@ -0,0 +1 @@
1
+ .sele{content:"\"keep \" me";something:'\\\' . . ';else:'empty{}';content:"/* test */"}
@@ -0,0 +1,7 @@
1
+ /* preserving strings */
2
+ .sele {
3
+ content: "\"keep \" me";
4
+ something: '\\\' . . ';
5
+ else: 'empty{}';
6
+ content: "/* test */"; /* <---- this is not a comment, should be be kept */
7
+ }
@@ -0,0 +1 @@
1
+ .sele{content:"\"keep \" me";something:'\\\' . . ';else:'empty{}';content:"/* test */"}
@@ -0,0 +1,16 @@
1
+ /*
2
+ because of IE6 first-letter and first-line
3
+ must be followed by a space
4
+ http://reference.sitepoint.com/css/pseudoelement-firstletter
5
+ Thanks: P.Sorokin comment at http://www.phpied.com/cssmin-js/
6
+ */
7
+ p:first-letter{
8
+ buh: hum;
9
+ }
10
+ p:first-line{
11
+ baa: 1;
12
+ }
13
+
14
+ p:first-line,a,p:first-letter,b{
15
+ color: red;
16
+ }
@@ -0,0 +1 @@
1
+ p:first-letter {buh:hum}p:first-line {baa:1}p:first-line ,a,p:first-letter ,b{color:red}
@@ -0,0 +1,4 @@
1
+ p :link {
2
+ ba:zinga;;;
3
+ foo: bar;;;
4
+ }
@@ -0,0 +1 @@
1
+ p :link{ba:zinga;foo:bar}
@@ -0,0 +1,13 @@
1
+ /*!************88****
2
+ Preserving comments
3
+ as they are
4
+ ********************
5
+ Keep the initial !
6
+ *******************/
7
+ #yo {
8
+ ma: "ma";
9
+ }
10
+ /*!
11
+ I said
12
+ pre-
13
+ serve! */
@@ -0,0 +1,9 @@
1
+ /*!************88****
2
+ Preserving comments
3
+ as they are
4
+ ********************
5
+ Keep the initial !
6
+ *******************/#yo{ma:"ma"}/*!
7
+ I said
8
+ pre-
9
+ serve! */
@@ -0,0 +1,5 @@
1
+ #elementarr {
2
+ width: 1px;
3
+ *width: 3pt;
4
+ _width: 2em;
5
+ }
@@ -0,0 +1 @@
1
+ #elementarr{width:1px;*width:3pt;_width:2em}
@@ -0,0 +1,8 @@
1
+ /* te " st */
2
+ a{a:1}
3
+ /*!"preserve" me*/
4
+ b{content: "/**/"}
5
+ /* quite " quote ' \' \" */
6
+ /* ie mac \*/
7
+ c {c : 3}
8
+ /* end hiding */
@@ -0,0 +1 @@
1
+ a{a:1}/*!"preserve" me*/b{content:"/**/"}/*\*/c{c:3}/**/
@@ -0,0 +1,6 @@
1
+ a {
2
+ margin: 0px 0pt 0em 0%;
3
+ _padding-top: 0ex;
4
+ background-position: 0 0;
5
+ padding: 0in 0cm 0mm 0pc
6
+ }
@@ -0,0 +1 @@
1
+ a{margin:0;_padding-top:0;background-position:0 0;padding:0}
@@ -0,0 +1,139 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Rapper do
4
+ describe "setup" do
5
+ it "loads configuration and environment" do
6
+ lambda do
7
+ Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test" )
8
+ end.should_not raise_error
9
+ end
10
+
11
+ it "bombs out if given a bad configuration file" do
12
+ lambda do
13
+ Rapper::Engine.new( "spec/fixtures/config/fake.yml", "test" )
14
+ end.should raise_error( Errno::ENOENT )
15
+ end
16
+
17
+ it "bombs out if given an invalid environment" do
18
+ lambda do
19
+ Rapper::Engine.new( "spec/fixtures/config/assets.yml", "error" )
20
+ end.should raise_error( Rapper::Errors::InvalidEnvironment )
21
+ end
22
+
23
+ it "bombs out if no definition_root setting is provided" do
24
+ lambda do
25
+ Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test_no_definition_root" )
26
+ end.should raise_error( Rapper::Errors::NoDefinitionRoot )
27
+ end
28
+
29
+ it "uses the given environment's specific config" do
30
+ rapper = Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test" )
31
+ rapper.environment.should == "test"
32
+ # private
33
+ rapper.send( :env_config )["bundle"].should be_true
34
+ rapper.send( :env_config )["compress"].should be_true
35
+ rapper.send( :env_config )["version"].should be_false
36
+ end
37
+
38
+ it "uses default config when environment config isn't set for the setting" do
39
+ rapper = Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test_empty" )
40
+ # private
41
+ rapper.send( :get_config, "bundle" ).should be_true
42
+ rapper.send( :get_config, "compress" ).should be_true
43
+ rapper.send( :get_config, "versions" ).should be_true
44
+ rapper.send( :get_config, "closure_compiler" ).should == {
45
+ "compilation_level" => "SIMPLE_OPTIMIZATIONS"
46
+ }
47
+ end
48
+
49
+ it "loads asset definitions" do
50
+ rapper = Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test" )
51
+ rapper.send( :asset_types ).sort.should == ["javascripts", "stylesheets", "validators"]
52
+ rapper.definitions["stylesheets"]["source_root"].should == "spec/fixtures/stylesheets"
53
+ rapper.definitions["stylesheets"]["suffix"].should == "css"
54
+ # Using a YAML::OMap here, so it looks a bit weird
55
+ rapper.definitions["stylesheets"]["assets"].first.key?( "master" ).should be_true
56
+ rapper.definitions["stylesheets"]["assets"].first["master"].first["files"].should == ["reset", "base", "layout"]
57
+ end
58
+ end
59
+
60
+ describe "logging" do
61
+ it "is off by default" do
62
+ lambda do
63
+ Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test_empty" )
64
+ end.should_not have_stdout( /./ )
65
+ end
66
+
67
+ it "can log to stdout" do
68
+ lambda do
69
+ rapper = Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test_logging_stdout" )
70
+ rapper.send( :log, :info, "Derp" )
71
+ end.should have_stdout( "Derp" )
72
+ end
73
+
74
+ it "doesn't log verbose messages unless configured" do
75
+ lambda do
76
+ rapper = Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test_logging_stdout" )
77
+ rapper.send( :log, :verbose, "Derp" )
78
+ end.should_not have_stdout( "Derp" )
79
+ end
80
+
81
+ it "logs verbose messages if configured" do
82
+ lambda do
83
+ rapper = Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test_logging_verbose" )
84
+ rapper.send( :log, :verbose, "Derp" )
85
+ end.should have_stdout( "Derp" )
86
+ end
87
+
88
+ it "can log to a file" do
89
+ rapper = Rapper::Engine.new( "spec/fixtures/config/assets.yml", "test_logging_file" )
90
+ rapper.send( :log, :info, "Derp" )
91
+ File.read( "tmp/test_logging_file.log" ).should == "Derp\n"
92
+ end
93
+ end
94
+
95
+ describe "packaging test cases" do
96
+ Dir["spec/fixtures/test_cases/*"].each do |folder|
97
+ next unless File.directory?( folder )
98
+ name = folder.split( "/" ).last
99
+ results_path = "tmp/*.*"
100
+ expecteds_path = "#{folder}/expected/*.*"
101
+
102
+ it "passes the \"#{name}\" test case" do
103
+ rapper = Rapper::Engine.new( "#{folder}/assets.yml", "test" )
104
+ rapper.package
105
+
106
+ # Produces the same exact individual files
107
+ file_names( results_path ).should == file_names( expecteds_path )
108
+ # Contents are all the same
109
+ results = Dir[results_path]
110
+ expecteds = Dir[expecteds_path]
111
+
112
+ results.each_index do |i|
113
+ unless File.read( results[i] ) == File.read( expecteds[i] )
114
+ # p File.read( results[i] )
115
+ raise "#{results[i]} did not match #{expecteds[i]}"
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ describe "bundling" do
123
+ it "raises an error if a file doesn't exist"
124
+ end
125
+
126
+ describe "compressing" do
127
+ it "can be turned off"
128
+ end
129
+
130
+ describe "view helpers" do
131
+ it "returns tags for component files when bundling is off"
132
+ it "returns tabs for asset when bundling is on"
133
+ it "can return html"
134
+ it "can return xhtml"
135
+ it "can return html5"
136
+ it "adds a version number if versioning is on"
137
+ it "doesn't add a version number if versioning is off"
138
+ end
139
+ end
@@ -0,0 +1,57 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'spec'
4
+ require 'rapper'
5
+ require 'fileutils'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ # Setup and tear down tmp files.
10
+
11
+ config.before :all do
12
+ Dir::mkdir( "tmp" ) unless FileTest::directory?( "tmp" )
13
+ end
14
+
15
+ config.after :each do
16
+ Dir[ "tmp/*" ].each { |f| FileUtils.rm( f ) }
17
+ end
18
+ end
19
+
20
+ def file_names( path )
21
+ Dir[path].map do |path|
22
+ File.basename( path )
23
+ end
24
+ end
25
+
26
+ # Adapted from: https://github.com/wycats/ruby_decorators/blob/master/specs.rb
27
+
28
+ Spec::Matchers.define :have_stdout do |regex|
29
+ regex = /^#{Regexp.escape(regex)}$/ if regex.is_a?(String)
30
+
31
+ match do |proc|
32
+ $stdout = StringIO.new
33
+ proc.call
34
+ $stdout.rewind
35
+ @captured = $stdout.read
36
+
37
+ $stdout = STDOUT
38
+ @captured =~ regex
39
+ end
40
+
41
+ failure_message do |proc|
42
+ "Expected #{regex.inspect} but got #{@captured.inspect}"
43
+ end
44
+
45
+ failure_message do |proc|
46
+ "Expected #{@captured.inspect} not to match #{regex.inspect}"
47
+ end
48
+ end
49
+
50
+ # https://github.com/wycats/ruby_decorators/blob/master/specs.rb
51
+ module Kernel
52
+ def silence_stdout
53
+ $stdout = StringIO.new
54
+ yield
55
+ $stdout = STDOUT
56
+ end
57
+ end