epuber-stylus 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +10 -0
  3. data/LICENSE +22 -0
  4. data/README.md +154 -0
  5. data/lib/epuber-stylus.rb +174 -0
  6. data/lib/epuber-stylus/import_processor.rb +71 -0
  7. data/lib/epuber-stylus/railtie.rb +32 -0
  8. data/lib/epuber-stylus/runtime.rb +54 -0
  9. data/lib/epuber-stylus/runtime/compiler.js +40 -0
  10. data/lib/epuber-stylus/runtime/runner.js +20 -0
  11. data/lib/epuber-stylus/sprockets.rb +58 -0
  12. data/lib/epuber-stylus/tilt.rb +2 -0
  13. data/lib/epuber-stylus/tilt/rails.rb +51 -0
  14. data/lib/epuber-stylus/tilt/stylus.rb +52 -0
  15. data/lib/epuber-stylus/version.rb +3 -0
  16. data/lib/rails/generators/epuber-stylus/assets/assets_generator.rb +13 -0
  17. data/lib/rails/generators/epuber-stylus/assets/templates/stylesheet.css.styl +3 -0
  18. data/lib/rails/generators/epuber-stylus/scaffold/scaffold_generator.rb +11 -0
  19. data/spec/generators/assets_generator_spec.rb +11 -0
  20. data/spec/generators/controller_generator_spec.rb +12 -0
  21. data/spec/generators/scaffold_generator_spec.rb +17 -0
  22. data/spec/import_processor_spec.rb +67 -0
  23. data/spec/rails_spec.rb +46 -0
  24. data/spec/runtime_spec.rb +11 -0
  25. data/spec/spec_helper.rb +30 -0
  26. data/spec/sprockets_spec.rb +36 -0
  27. data/spec/stylus_spec.rb +118 -0
  28. data/spec/support/generators/test_case.rb +59 -0
  29. data/spec/support/generators/tmp/app/controllers/posts_controller.rb +58 -0
  30. data/spec/support/generators/tmp/app/helpers/posts_helper.rb +2 -0
  31. data/spec/support/generators/tmp/config/routes.rb +0 -0
  32. data/spec/support/helpers.rb +63 -0
  33. data/spec/support/matchers.rb +5 -0
  34. data/spec/tilt/rails_spec.rb +64 -0
  35. data/spec/tilt/stylus_spec.rb +24 -0
  36. metadata +137 -0
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stylus::Runtime do
4
+ it 'raises an error if the runtime is not available' do
5
+ allow(Stylus).to receive(:runtime) { double('An unavailable Runtime', available?: false) }
6
+
7
+ expect {
8
+ Stylus.version
9
+ }.to raise_error RuntimeError, %r[The Node.JS runtime is not available to Stylus.]
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require 'rails'
5
+ require 'rails/generators/test_case'
6
+
7
+ require 'active_support/railtie'
8
+ require 'action_controller/railtie'
9
+ require 'sprockets'
10
+ require 'sprockets/rails'
11
+ require 'epuber-stylus'
12
+
13
+ require 'active_support/core_ext/class/attribute_accessors'
14
+
15
+ require 'support/helpers'
16
+ require 'support/matchers'
17
+ require 'support/generators/test_case'
18
+
19
+ RSpec.configure do |config|
20
+ config.include Helpers
21
+
22
+ config.after :each do
23
+ Stylus.compress = false
24
+ Stylus.debug = false
25
+ Stylus.paths = []
26
+ Stylus.plugins.clear
27
+ Stylus.definitions.clear
28
+ Stylus.imports.clear
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Sprockets setup' do
4
+ let(:env) do
5
+ Sprockets::Environment.new do |assets|
6
+ assets.append_path fixture_root
7
+ assets.append_path 'javascripts'
8
+ end
9
+ end
10
+
11
+ it 'register the default Tilt template' do
12
+ expect(env).to receive(:register_engine).with('.styl', Tilt::StylusTemplate)
13
+ Stylus.setup(env)
14
+ end
15
+
16
+ it 'register a Rails specific Tilt template' do
17
+ expect(env).to receive(:register_engine).with('.styl', Stylus::Rails::StylusTemplate)
18
+ Stylus.setup(env, rails: true)
19
+ end
20
+
21
+ it 'register the import processor' do
22
+ expect(env).to receive(:register_preprocessor).with('text/css', Stylus::ImportProcessor)
23
+ Stylus.setup(env)
24
+ end
25
+
26
+ it 'copies the asset paths' do
27
+ Stylus.setup(env)
28
+ expect(Stylus.paths).to eq(env.paths)
29
+ end
30
+
31
+ it 'configure the debug and compress flags' do
32
+ Stylus.setup(env, debug: true, compress: true)
33
+ expect(Stylus.debug).to be_true
34
+ expect(Stylus.compress).to be_true
35
+ end
36
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stylus do
4
+ it 'compiles the given source' do
5
+ input, output = fixture(:simple)
6
+ expect(Stylus.compile(input)).to eq(output)
7
+ end
8
+
9
+ it 'accepts an IO object' do
10
+ input, output = fixture(:simple)
11
+ input = StringIO.new(input)
12
+ expect(Stylus.compile(input)).to eq(output)
13
+ end
14
+
15
+ it 'compress the file when the "compress" flag is given' do
16
+ input, output = fixture(:compressed)
17
+ expect(Stylus.compile(input, compress: true)).to eq(output.rstrip)
18
+ end
19
+
20
+ it 'handles the compress flag globally' do
21
+ Stylus.compress = true
22
+ input, output = fixture(:compressed)
23
+ expect(Stylus.compile(input)).to eq(output.rstrip)
24
+ end
25
+
26
+ it 'imports the given paths' do
27
+ path = fixture_root
28
+ input, output = fixture(:import)
29
+ expect(Stylus.compile(input, paths: path)).to eq(output)
30
+ end
31
+
32
+ it 'handles the import paths globally' do
33
+ Stylus.paths << fixture_root
34
+ input, output = fixture(:import)
35
+ expect(Stylus.compile(input)).to eq(output)
36
+ end
37
+
38
+ it 'implicit imports the given paths' do
39
+ path = File.expand_path('mixins/vendor.styl', fixture_root)
40
+ input, output = fixture(:implicit)
41
+ Stylus.import path
42
+ expect(Stylus.compile(input)).to eq(output)
43
+ end
44
+
45
+ it 'outputs both gem and library version' do
46
+ expect(Stylus.version).to match(/Stylus - gem .+ library .+/)
47
+ end
48
+
49
+ it 'converts CSS to Stylus' do
50
+ stylus, css = fixture(:stylesheet)
51
+ expect(Stylus.convert(css)).to eq(stylus)
52
+ end
53
+
54
+ it 'stores the given plugins' do
55
+ Stylus.use :one, :two, argument: true
56
+ expect(Stylus).to have(2).plugins
57
+ end
58
+
59
+ it 'includes the given plugins' do
60
+ Stylus.use :nib
61
+ input, output = fixture(:plugin)
62
+ expect(Stylus.compile(input)).to eq(output)
63
+ end
64
+
65
+ it 'stores the define calls' do
66
+ Stylus.define "mystring", "test"
67
+ expect(Stylus).to have(1).definitions
68
+ end
69
+
70
+ it 'defines a global variable string' do
71
+ Stylus.define "mystring", "test"
72
+ input, output = fixture(:definition)
73
+ expect(Stylus.compile(input)).to match(/content: 'test'/)
74
+ end
75
+
76
+ it 'defines a global variable literal' do
77
+ Stylus.define "mystring", "red", :literal => true
78
+ input, output = fixture(:definition)
79
+ expect(Stylus.compile(input)).to match(/content: red/)
80
+ end
81
+
82
+ it 'includes and imports "nib" automatically' do
83
+ Stylus.nib = true
84
+ input, output = fixture(:nib)
85
+ expect(Stylus.compile(input)).to eq(output)
86
+ end
87
+
88
+ it 'share variables between imported stylesheets' do
89
+ input, output = fixture(:variables)
90
+ path = fixture_root
91
+
92
+ expect(Stylus.compile(input, paths: path)).to eq(output)
93
+ end
94
+
95
+ describe 'The debug flag' do
96
+ let(:path) { fixture_path(:debug) }
97
+ let(:fixture) { File.read(path) }
98
+ let(:file) { File.new(path) }
99
+
100
+ before { Stylus.debug = true }
101
+
102
+ it 'turns the "linenos" option on' do
103
+ expect(Stylus.compile(file)).to match(/line 1 : #{path}/)
104
+ end
105
+
106
+ it 'skips the "linenos" option if no filename is given' do
107
+ expect(Stylus.compile(fixture)).to_not match(/line 1 : #{path}/)
108
+ end
109
+
110
+ it 'turns the "firebug" option on' do
111
+ expect(Stylus.compile(file)).to match(/@media -stylus-debug-info/)
112
+ end
113
+
114
+ it 'skips the "firebug" option if no filename is given' do
115
+ expect(Stylus.compile(fixture)).to_not match(/@media -stylus-debug-info/)
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,59 @@
1
+ # Extracted from generator_spec https://github.com/stevehodgkiss/generator_spec
2
+ # But `RSpec::Rails::RailsExampleGroup` loads a truckload of things from rails and rspec-rails
3
+ # That we don't need.
4
+
5
+ module Generators
6
+ module TestCase
7
+ extend ActiveSupport::Concern
8
+ include FileUtils
9
+
10
+ included do
11
+ cattr_accessor :test_case, :test_case_instance
12
+
13
+ self.test_case = Class.new(Rails::Generators::TestCase) do
14
+ def fake_test_case; end
15
+ def add_assertion; end
16
+ end
17
+ self.test_case_instance = self.test_case.new(:fake_test_case)
18
+ self.test_case.tests described_class
19
+
20
+ before do
21
+ prepare_destination
22
+ create_routes
23
+ run_generator
24
+ end
25
+
26
+ destination File.expand_path('../tmp', __FILE__)
27
+ end
28
+
29
+ module ClassMethods
30
+ def tests(klass)
31
+ self.test_case.generator_class = klass
32
+ end
33
+
34
+ def arguments(array)
35
+ self.test_case.default_arguments = array
36
+ end
37
+
38
+ def destination(path)
39
+ self.test_case.destination_root = path
40
+ end
41
+ end
42
+
43
+ def file(relative)
44
+ File.expand_path(relative, destination_root)
45
+ end
46
+
47
+ def method_missing(method_sym, *arguments, &block)
48
+ self.test_case_instance.send(method_sym, *arguments, &block)
49
+ end
50
+
51
+ def respond_to?(method_sym, include_private = false)
52
+ if self.test_case_instance.respond_to?(method_sym)
53
+ true
54
+ else
55
+ super
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,58 @@
1
+ class PostsController < ApplicationController
2
+ before_action :set_post, only: [:show, :edit, :update, :destroy]
3
+
4
+ # GET /posts
5
+ def index
6
+ @posts = Post.all
7
+ end
8
+
9
+ # GET /posts/1
10
+ def show
11
+ end
12
+
13
+ # GET /posts/new
14
+ def new
15
+ @post = Post.new
16
+ end
17
+
18
+ # GET /posts/1/edit
19
+ def edit
20
+ end
21
+
22
+ # POST /posts
23
+ def create
24
+ @post = Post.new(post_params)
25
+
26
+ if @post.save
27
+ redirect_to @post, notice: 'Post was successfully created.'
28
+ else
29
+ render action: 'new'
30
+ end
31
+ end
32
+
33
+ # PATCH/PUT /posts/1
34
+ def update
35
+ if @post.update(post_params)
36
+ redirect_to @post, notice: 'Post was successfully updated.'
37
+ else
38
+ render action: 'edit'
39
+ end
40
+ end
41
+
42
+ # DELETE /posts/1
43
+ def destroy
44
+ @post.destroy
45
+ redirect_to posts_url, notice: 'Post was successfully destroyed.'
46
+ end
47
+
48
+ private
49
+ # Use callbacks to share common setup or constraints between actions.
50
+ def set_post
51
+ @post = Post.find(params[:id])
52
+ end
53
+
54
+ # Only allow a trusted parameter "white list" through.
55
+ def post_params
56
+ params[:post]
57
+ end
58
+ end
@@ -0,0 +1,2 @@
1
+ module PostsHelper
2
+ end
File without changes
@@ -0,0 +1,63 @@
1
+ module Helpers
2
+ def create_routes
3
+ destination = File.join(destination_root, 'config')
4
+
5
+ FileUtils.mkdir_p(destination)
6
+ FileUtils.touch File.join(destination, 'routes.rb')
7
+ end
8
+
9
+ def create_app(options = {})
10
+ Rails.application = nil
11
+
12
+ Class.new(Rails::Application).tap do |app|
13
+ config = app.config.assets
14
+ assets = app.assets
15
+ config.paths = []
16
+
17
+ assets.cache = ActiveSupport::Cache.lookup_store(:null_store)
18
+ config.compress = options[:compress]
19
+ config.debug = options[:debug]
20
+ config.paths << fixture_root
21
+ config.paths << File.expand_path('javascripts')
22
+ yield(app) if block_given?
23
+
24
+ app.config.eager_load = false
25
+ app.config.active_support.deprecation = :log
26
+ app.initialize!
27
+ end
28
+ end
29
+
30
+ def fixture_root
31
+ File.expand_path('../../stylesheets', __FILE__)
32
+ end
33
+
34
+ def images_root
35
+ File.expand_path('../../images', __FILE__)
36
+ end
37
+
38
+ def output_root
39
+ File.expand_path('../../cases', __FILE__)
40
+ end
41
+
42
+ def fixture(name)
43
+ source = fixture_path(name)
44
+ output = css_path(name)
45
+ [source, output].map do |path|
46
+ File.read(path) if File.file?(path)
47
+ end
48
+ end
49
+
50
+ def css_path(name)
51
+ File.join(output_root, "#{name}.css")
52
+ end
53
+
54
+ def fixture_path(name)
55
+ File.join(fixture_root, "#{name}.styl")
56
+ end
57
+
58
+ def dependencies_on(asset)
59
+ context = env.context_class.new(env, asset.logical_path, asset.pathname)
60
+ context.evaluate(asset.pathname)
61
+ context._dependency_paths
62
+ end
63
+ end
@@ -0,0 +1,5 @@
1
+ RSpec::Matchers.define :exist do
2
+ match do |file_path|
3
+ File.exists?(file_path)
4
+ end
5
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'epuber-stylus/tilt/rails'
3
+
4
+ describe Stylus::Rails::StylusTemplate do
5
+ it 'registers the template for .styl files' do
6
+ expect(Tilt['application.styl']).to eq(Stylus::Rails::StylusTemplate)
7
+ end
8
+
9
+ it 'has a content-type' do
10
+ expect(Stylus::Rails::StylusTemplate.default_mime_type).to eq('text/css')
11
+ end
12
+
13
+ context 'when no resources other then css found' do
14
+ it 'compiles the given source without changes' do
15
+ result = fixture(:simple).last
16
+
17
+ app = create_app
18
+ expect(app.assets['simple'].to_s).to eq(result)
19
+ end
20
+ end
21
+
22
+
23
+ it 'substitutes asset_path with path' do
24
+ app = create_app do |app|
25
+ app.config.assets.paths << images_root
26
+ app.config.asset_host = 'http://localhost'
27
+ end
28
+ result = fixture(:asset_path).last
29
+ expect(app.assets['asset_path'].to_s).to eq(result)
30
+ end
31
+
32
+ it 'substitutes asset_url with url' do
33
+ app = create_app do |app|
34
+ app.config.assets.paths << images_root
35
+ app.config.asset_host = 'http://localhost'
36
+ end
37
+ result = fixture(:asset_url).last
38
+ expect(app.assets['asset_url'].to_s).to eq(result)
39
+ end
40
+
41
+ context 'when config.assets.digest = true' do
42
+ let(:app) do
43
+ create_app do |app|
44
+ app.config.assets.paths << images_root
45
+ app.config.asset_host = 'http://localhost'
46
+ app.config.assets.digest = true
47
+ end
48
+ end
49
+
50
+ it 'appends fingerprint to asset path' do
51
+ digested_image_path = app.assets['rails.png'].digest_path
52
+ expect(digested_image_path).to match(/^rails-(\w+)\.png$/)
53
+ asset = app.assets['digested_asset_path']
54
+ expect(asset.to_s).to eq("body {\n background-image: url(\"http://localhost/assets/#{digested_image_path}\");\n}\n")
55
+ end
56
+
57
+ it 'appends fingerprint to asset url' do
58
+ digested_image_path = app.assets['rails.png'].digest_path
59
+ expect(digested_image_path).to match(/^rails-(\w+)\.png$/)
60
+ asset = app.assets['digested_asset_url']
61
+ expect(asset.to_s).to eq("body {\n background-image: url(\"http://localhost/assets/#{digested_image_path}\");\n}\n")
62
+ end
63
+ end
64
+ end