epuber-stylus 1.1.0

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 (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