├── .ruby-version
├── Procfile
├── lib
├── css2sass
│ ├── version.rb
│ ├── convert.rb
│ ├── render.rb
│ ├── app.rb
│ └── flash.rb
└── css2sass.rb
├── public
├── images
│ ├── favicon.ico
│ ├── conv-arr.svg
│ ├── sass-icon.svg
│ └── scss-icon.svg
└── stylesheets
│ ├── text.css
│ ├── reset.css
│ ├── app.css
│ └── 960.css
├── .gitignore
├── Guardfile
├── .autotest
├── config.ru
├── config
└── puma.rb
├── Gemfile
├── CHANGELOG.md
├── views
├── index.haml
└── layout.haml
├── readme.md
├── Gemfile.lock
└── test
└── test_css2sass.rb
/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.6.4
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: bundle exec puma -C config/puma.rb
2 |
--------------------------------------------------------------------------------
/lib/css2sass/version.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | module Css2sass
3 | VERSION = '0.2.1'
4 | end
5 |
--------------------------------------------------------------------------------
/lib/css2sass.rb:
--------------------------------------------------------------------------------
1 | %w(flash convert render app version).each { |l| require_relative 'css2sass/' + l }
2 |
--------------------------------------------------------------------------------
/public/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpablobr/css2sass/HEAD/public/images/favicon.ico
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle
2 | .DS_Store
3 | */.DS_Store
4 | log/*.log
5 | .lock
6 | tmp/*
7 | TAGS
8 | .env
9 |
--------------------------------------------------------------------------------
/Guardfile:
--------------------------------------------------------------------------------
1 | # A sample Guardfile
2 | # More info at https://github.com/guard/guard#readme
3 | guard 'bundler' do
4 | watch('Gemfile')
5 | end
--------------------------------------------------------------------------------
/.autotest:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 |
3 | require 'autotest/restart'
4 | require 'autotest/timestamp'
5 |
6 | Autotest.add_hook :initialize do |at|
7 | at.testlib = 'minitest/unit'
8 | at.unit_diff
9 | end
10 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | $:.unshift File.expand_path('../', __FILE__)
2 | require 'rubygems'
3 | require 'sinatra'
4 | require './lib/css2sass'
5 |
6 | use Rack::Session::Cookie, :key => 'rack.session',
7 | :expire_after => 2592000,
8 | :secret => ENV['RACK_SESSION_COOKIE']
9 |
10 | run Css2sass::App
11 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | workers Integer(ENV['WEB_CONCURRENCY'] || 2)
2 | threads_count = Integer(ENV['MAX_THREADS'] || 5)
3 | threads threads_count, threads_count
4 |
5 | preload_app!
6 |
7 | rackup DefaultRackup
8 | port ENV['PORT'] || 3000
9 | environment ENV['RACK_ENV'] || 'development'
10 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | ruby '2.6.4'
4 |
5 | gem 'sinatra'
6 | gem 'hpricot'
7 | gem 'haml'
8 | gem 'sass'
9 | gem 'json'
10 | gem 'builder'
11 | gem 'erubis'
12 | gem 'ruby_parser'
13 | gem 'sinatra-redirect-with-flash'
14 | gem 'puma'
15 | gem 'foreman'
16 |
17 | group :test do
18 | gem 'rack-test'
19 | end
20 |
--------------------------------------------------------------------------------
/public/stylesheets/text.css:
--------------------------------------------------------------------------------
1 | body{font:13px/1.5 'Helvetica Neue',Arial,'Liberation Sans',FreeSans,sans-serif}a:focus{outline:1px dotted}hr{border:0 #ccc solid;border-top-width:1px;clear:both;height:0}h1{font-size:25px}h2{font-size:23px}h3{font-size:21px}h4{font-size:19px}h5{font-size:17px}h6{font-size:15px}ol{list-style:decimal}ul{list-style:disc}li{margin-left:30px}p,dl,hr,h1,h2,h3,h4,h5,h6,ol,ul,pre,table,address,fieldset{margin-bottom:20px}
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.2.0 (21/Sep/11)
2 |
3 | - Refactored app... css2sass has been breaked into several proper objects.
4 |
5 | ## 0.1.2 (21/Sep/11)
6 |
7 | - Migrated tests to minitest.
8 |
9 | ## 0.1.1 (Jun 21, 2011)
10 |
11 | - Added spec dir for setting up a better testing environment.
12 |
13 | ## 0.1.0 (Jun 21, 2011)
14 |
15 | - Updated readme, to many grammar error :/
16 | - `type.eql?("Convert 2 SCSS")`
17 | Stupid mistake, now it can convert properly to scss
18 | - added VERSION and CHANGELOG
19 |
--------------------------------------------------------------------------------
/lib/css2sass/convert.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'sass/css'
3 | module Css2sass
4 | class Convert
5 |
6 | def initialize(css)
7 | @css = css
8 | end
9 |
10 | def to_sass
11 | begin
12 | Sass::CSS.new(@css).render(:sass)
13 | rescue Sass::SyntaxError => e
14 | @error = e
15 | end
16 | end
17 |
18 | def to_scss
19 | begin
20 | Sass::CSS.new(@css).render(:scss)
21 | rescue Sass::SyntaxError => e
22 | @error = e
23 | end
24 | end
25 |
26 | end
27 |
28 | end
29 |
--------------------------------------------------------------------------------
/public/images/conv-arr.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/public/stylesheets/reset.css:
--------------------------------------------------------------------------------
1 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}:focus{outline:0}ins{text-decoration:none}del{text-decoration:line-through}table{border-collapse:collapse;border-spacing:0}
--------------------------------------------------------------------------------
/lib/css2sass/render.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'json'
3 | module Css2sass
4 | class Render
5 |
6 | def initialize(css=nil, output=nil)
7 | @css, @output = css, output
8 | end
9 |
10 | def xml
11 | xml = Builder::XmlMarkup.new
12 | xml.instruct!
13 | xml.page do
14 | xml.css do
15 | xml.cdata! @css.to_s
16 | end
17 | xml.sass do
18 | xml.cdata! @output.to_s
19 | end
20 | end
21 | end
22 |
23 | def json
24 | {:page =>
25 | {:css => @css,
26 | :sass => @output
27 | }
28 | }.to_json
29 | end
30 |
31 | end
32 |
33 | end
34 |
--------------------------------------------------------------------------------
/views/index.haml:
--------------------------------------------------------------------------------
1 | .app-section
2 | .tabs-section
3 | .tab.css
4 | %h2 css
5 | .tab.sass
6 | %h2 sass / scss
7 | .code-section
8 | %form{:method => "POST", :action => "/", :id => "page"}
9 | .code-container.left
10 | %label{:for => "page_css"}
11 | CSS (paste your CSS code and convert!)
12 | .notifications
13 | - if flash[:notice]
14 | %span.notice= flash[:notice]
15 | - if flash[:error]
16 | %span.error= flash[:error]
17 | %textarea{:id => "page_css", :name => "page[css]"}=h @css || ""
18 | .code-container.right
19 | %label{:for => "page_sass"}
20 | Your Syntactically Awesome StyleSheets code
21 | %textarea{:id => "page_sass", :name => "page[sass]"}=h @output || ""
22 | .code-actions
23 | %input.button.sass{:type => "submit", :name => "commit", :value => "Convert 2 SASS"}
24 | %input.button.scss{:type => "submit", :name => "commit", :value => "Convert 2 SCSS"}
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | css2sass
2 | ========
3 |
4 | [http://css2sass.heroku.com/](http://css2sass.heroku.com/)
5 |
6 | css2sass is a simple sinatra app which Convert CSS Snippets to Syntactically Awesome StyleSheets code.
7 |
8 | It's heavily inspired by the [html2haml app](http://html2haml.heroku.com/)
9 |
10 | ## Usage
11 |
12 | * Paste the CSS in the first box
13 | * click convert
14 | * Done!
15 |
16 | ## API
17 |
18 | json and xml.
19 |
20 | ## Testing
21 |
22 | See `test/test_css2sass.rb`
23 |
24 | ## TODO
25 |
26 | * Flash warnings TODO:!
27 | * More tests.
28 |
29 | ## Resources
30 |
31 | * [Sinatra](http://www.sinatrarb.com)
32 | * [SASS](http://sass-lang.com/)
33 |
34 | ## Note on Patches/Pull Requests
35 |
36 | Fork the project.
37 | Make your feature addition or bug fix.
38 | Add tests for it. This is important so I don’t break it in a future version unintentionally.
39 | Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
40 | Send me a pull request. Bonus points for topic branches.
41 |
42 | ## Copyright
43 |
44 | Copyright 2009 Jose Pablo Barrantes. MIT Licence, so go for it.
45 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | builder (3.2.4)
5 | erubis (2.7.0)
6 | ffi (1.13.1)
7 | foreman (0.87.2)
8 | haml (5.2.0)
9 | temple (>= 0.8.0)
10 | tilt
11 | hpricot (0.8.6)
12 | json (2.3.1)
13 | mustermann (1.1.1)
14 | ruby2_keywords (~> 0.0.1)
15 | nio4r (2.5.4)
16 | puma (5.0.4)
17 | nio4r (~> 2.0)
18 | rack (2.2.3)
19 | rack-protection (2.1.0)
20 | rack
21 | rack-test (1.1.0)
22 | rack (>= 1.0, < 3)
23 | rb-fsevent (0.10.4)
24 | rb-inotify (0.10.1)
25 | ffi (~> 1.0)
26 | ruby2_keywords (0.0.2)
27 | ruby_parser (3.15.0)
28 | sexp_processor (~> 4.9)
29 | sass (3.7.4)
30 | sass-listen (~> 4.0.0)
31 | sass-listen (4.0.0)
32 | rb-fsevent (~> 0.9, >= 0.9.4)
33 | rb-inotify (~> 0.9, >= 0.9.7)
34 | sexp_processor (4.15.1)
35 | sinatra (2.1.0)
36 | mustermann (~> 1.0)
37 | rack (~> 2.2)
38 | rack-protection (= 2.1.0)
39 | tilt (~> 2.0)
40 | sinatra-redirect-with-flash (0.2.1)
41 | sinatra (>= 1.0.0)
42 | temple (0.8.2)
43 | tilt (2.0.10)
44 |
45 | PLATFORMS
46 | ruby
47 |
48 | DEPENDENCIES
49 | builder
50 | erubis
51 | foreman
52 | haml
53 | hpricot
54 | json
55 | puma
56 | rack-test
57 | ruby_parser
58 | sass
59 | sinatra
60 | sinatra-redirect-with-flash
61 |
62 | RUBY VERSION
63 | ruby 2.6.4p104
64 |
65 | BUNDLED WITH
66 | 2.1.4
67 |
--------------------------------------------------------------------------------
/lib/css2sass/app.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'sinatra/base'
3 |
4 | module Css2sass
5 | class App < Sinatra::Base
6 | use Rack::Flash, :sweep => true
7 | enable :sessions
8 | set :show_exceptions, true if development?
9 | set :public_folder, Proc.new { settings.root + '/../../' + 'public' }
10 | set :views, Proc.new { settings.root + '/../../' + 'views' }
11 |
12 | helpers do
13 | include Rack::Utils
14 | alias_method :h, :escape_html
15 | end
16 |
17 | get "/" do
18 | haml :index
19 | end
20 |
21 | post "/*" do
22 | if params["page"]
23 | @css = params["page"]["css"]
24 | if params["commit"].eql?("Convert 2 SCSS")
25 | @output = Css2sass::Convert.new(@css).to_scss
26 | else
27 | @output = Css2sass::Convert.new(@css).to_sass
28 | end
29 | render_response
30 | end
31 | end
32 |
33 | def render_response
34 | if params[:splat].include?("json")
35 | Css2sass::Render.new(@css, @output).json
36 | elsif params[:splat].include?("xml")
37 | Css2sass::Render.new(@css, @output).xml
38 | else
39 | flash_if_successful
40 | haml :index
41 | end
42 | end
43 |
44 | def flash_if_successful
45 | if @output.class == Sass::SyntaxError
46 | flash_error
47 | else
48 | flash_notice
49 | end
50 | end
51 |
52 | # Flash lib is moronic!
53 | def flash_notice
54 | flash[:error] = ''
55 | flash[:success] = 'Creativity is a habit.'
56 | end
57 |
58 | def flash_error
59 | flash[:success] = ''
60 | flash[:error] = "Dude, nasty error! - #{@output}"
61 | @output = nil
62 | end
63 | end
64 |
65 | end
66 |
--------------------------------------------------------------------------------
/public/images/sass-icon.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/views/layout.haml:
--------------------------------------------------------------------------------
1 | %html
2 | %head
3 | %title css2sass | Convert CSS Snippets to Syntactically Awesome StyleSheets code
4 | - %w{ reset text 960 app }.each do |css|
5 | %link{ :href => "/stylesheets/#{css}.css", :rel => "stylesheet", :type => "text/css", :media => "screen", :charset => "utf-8" }
6 | %meta{ :name => 'description', :content => 'CSS2Sass | Convert CSS Snippets to Syntactically Awesome StyleSheets code' }
7 | %meta{ :name => 'keywords', :content => 'haml, ruby, html, rails, ruby on rails, Sass, SCSS' }
8 | %link{:href => "/images/favicon.ico", :rel => "shortcut icon", :type => "image/x-icon"}
9 | %link{:href => "http://fonts.googleapis.com/css?family=Montserrat:400,700", :rel => "stylesheet", :type => "text/css"}
10 | %link{:href => "http://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600,700", :rel => "stylesheet", :type => "text/css"}
11 | :javascript
12 | var _gaq = _gaq || [];
13 | _gaq.push(['_setAccount', 'UA-5087606-8']);
14 | _gaq.push(['_trackPageview']);
15 |
16 | (function() {
17 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
18 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
19 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
20 | })();
21 | %body
22 | .wrapper
23 | .top-section
24 | %header
25 | %h1
26 | css 2 sass/scss
27 | %span converter
28 | .top-info-section
29 | .version-info
30 | %a{:href => "http://sass-lang.com/"} Version
31 | = Sass.version[:string]
32 | .author-info
33 | %p
34 | %span idea & backend:
35 | %a{ :href => "http://jpablobr.com"} Jose Pablo Barrantes
36 | %span /
37 | %span design & frontend:
38 | %a{ :href => "http://hihayk.com"} Hayk
39 | = yield
--------------------------------------------------------------------------------
/public/images/scss-icon.svg:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/test/test_css2sass.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/css2sass'
2 | require 'minitest/autorun'
3 | require 'rack/test'
4 | require 'builder'
5 |
6 | class TestCss2sassApp < MiniTest::Unit::TestCase
7 | def setup
8 | @browser = Rack::Test::Session.new(Rack::MockSession.new(Css2sass::App))
9 | end
10 |
11 | def test_home_says_css2sass
12 | @browser.get '/'
13 | assert @browser.last_response.ok?
14 | assert_match home_title, @browser.last_response.body
15 | end
16 |
17 | def test_html_sass_response
18 | @browser.post '/', css2sass_post
19 | @browser.last_response.body
20 | assert_match html_sass_response, @browser.last_response.body
21 | end
22 |
23 | def test_html_scss_response
24 | @browser.post '/', css2scss_post
25 | assert_match html_scss_response, @browser.last_response.body
26 | end
27 |
28 | def test_api_speak_json_with_sass
29 | @browser.post '/json', css2sass_post
30 | assert_match json_sass_response, @browser.last_response.body
31 | end
32 |
33 | def test_api_speak_json_with_scss
34 | @browser.post '/json', css2scss_post
35 | assert_match json_scss_response, @browser.last_response.body
36 | end
37 |
38 | def test_api_speak_xml_with_sass
39 | @browser.post '/xml', css2sass_post
40 | assert_match xml_sass_response, @browser.last_response.body
41 | end
42 |
43 | def test_api_speak_xml_with_scss
44 | @browser.post '/xml', css2scss_post
45 | assert_match xml_scss_response, @browser.last_response.body
46 | end
47 |
48 | def home_title
49 | '
' +
50 | 'css2sass | Convert CSS Snippets to Syntactically Awesome StyleSheets code' +
51 | ''
52 | end
53 |
54 | def css2scss_post
55 | { :page =>
56 | { :css => ".content-navigation { border-color: #3bbfce; color: #2b9eab; }"
57 | },
58 | :commit => "Convert 2 SCSS"
59 | }
60 | end
61 |
62 | def css2sass_post
63 | { :page =>
64 | { :css => ".content-navigation { border-color: #3bbfce; color: #2b9eab; }"
65 | },
66 | :commit => "Convert 2 SASS"
67 | }
68 | end
69 |
70 | def json_sass_response
71 | '{"page":' +
72 | '{"css":".content-navigation { border-color: #3bbfce; color: #2b9eab; }",'+
73 | '"sass":".content-navigation\n border-color: #3bbfce\n color: #2b9eab\n"}}'
74 | end
75 |
76 | def json_scss_response
77 | '{"page":' +
78 | '{"css":".content-navigation { border-color: #3bbfce; color: #2b9eab; }",' +
79 | '"sass":".content-navigation {\n border-color: #3bbfce;\n color: #2b9eab; }\n"}}'
80 | end
81 |
82 | def xml_sass_response
83 | "" +
84 | "" +
85 | "" +
86 | "" +
87 | "" +
88 | "" +
89 | "" +
90 | "" +
91 | ""
92 | end
93 |
94 | def xml_scss_response
95 | ""+
96 | ""+
97 | ""+
98 | ""+
99 | ""+
100 | ""+
101 | ""+
102 | ""+
103 | ""
104 | end
105 |
106 | def html_sass_response
107 | ""
110 | end
111 |
112 | def html_scss_response
113 | ""
117 | end
118 |
119 | end
120 |
--------------------------------------------------------------------------------
/lib/css2sass/flash.rb:
--------------------------------------------------------------------------------
1 | module Rack
2 | class Flash
3 | # Raised when the session passed to FlashHash initialize is nil. This
4 | # is usually an indicator that session middleware is not in use.
5 | class SessionUnavailable < StandardError; end
6 |
7 | # Implements bracket accessors for storing and retrieving flash entries.
8 | class FlashHash
9 | attr_reader :flagged
10 |
11 | def initialize(store, opts={})
12 | raise Rack::Flash::SessionUnavailable \
13 | .new('Rack::Flash depends on session middleware.') unless store
14 |
15 | @opts = opts
16 | @store = store
17 |
18 | if accessors = @opts[:accessorize]
19 | accessors.each { |opt| def_accessor(opt) }
20 | end
21 | end
22 |
23 | # Remove an entry from the session and return its value. Cache result in
24 | # the instance cache.
25 | def [](key)
26 | key = key.to_sym
27 | cache[key] ||= values.delete(key)
28 | end
29 |
30 | # Store the entry in the session, updating the instance cache as well.
31 | def []=(key,val)
32 | key = key.to_sym
33 | cache[key] = values[key] = val
34 | end
35 |
36 | # Store a flash entry for only the current request, swept regardless of
37 | # whether or not it was actually accessed. Useful for AJAX requests, where
38 | # you want a flash message, even though you're response isn't redirecting.
39 | def now
40 | cache
41 | end
42 |
43 | # Checks for the presence of a flash entry without retrieving or removing
44 | # it from the cache or store.
45 | def has?(key)
46 | [cache, values].any? { |store| store.keys.include?(key.to_sym) }
47 | end
48 | alias_method :include?, :has?
49 |
50 | # Mark existing entries to allow for sweeping.
51 | def flag!
52 | @flagged = values.keys
53 | end
54 |
55 | # Remove flagged entries from flash session, clear flagged list.
56 | def sweep!
57 | Array(flagged).each { |key| values.delete(key) }
58 | flagged.clear
59 | end
60 |
61 | # Hide the underlying :__FLASH__ session key and only expose values stored
62 | # in the flash.
63 | def inspect
64 | '#' % [values.inspect, cache.inspect]
65 | end
66 |
67 | # Human readable for logging.
68 | def to_s
69 | values.inspect
70 | end
71 |
72 | private
73 |
74 | # Maintain an instance-level cache of retrieved flash entries. These
75 | # entries will have been removed from the session, but are still available
76 | # through the cache.
77 | def cache
78 | @cache ||= {}
79 | end
80 |
81 | # Helper to access flash entries from :__FLASH__ session value. This key
82 | # is used to prevent collisions with other user-defined session values.
83 | def values
84 | @store[:__FLASH__] ||= {}
85 | end
86 |
87 | # Generate accessor methods for the given entry key if :accessorize is true.
88 | def def_accessor(key)
89 | raise ArgumentError.new('Invalid entry type: %s' % key) if respond_to?(key)
90 |
91 | class << self; self end.class_eval do
92 | define_method(key) { |*args| val = args.first; val ? (self[key]=val) : self[key] }
93 | define_method("#{key}=") { |val| self[key] = val }
94 | define_method("#{key}!") { |val| cache[key] = val }
95 | end
96 | end
97 | end
98 |
99 | # -------------------------------------------------------------------------
100 | # - Rack Middleware implementation
101 |
102 | def initialize(app, opts={})
103 | if klass = app_class(app, opts)
104 | klass.class_eval do
105 | def flash; env['x-rack.flash'] end
106 | end
107 | end
108 |
109 | @app, @opts = app, opts
110 | end
111 |
112 | def call(env)
113 | env['x-rack.flash'] ||= Rack::Flash::FlashHash.new(env['rack.session'], @opts)
114 |
115 | if @opts[:sweep]
116 | env['x-rack.flash'].flag!
117 | end
118 |
119 | res = @app.call(env)
120 |
121 | if @opts[:sweep]
122 | env['x-rack.flash'].sweep!
123 | end
124 |
125 | res
126 | end
127 |
128 | private
129 |
130 | def app_class(app, opts)
131 | return nil if opts.has_key?(:helper) and not opts[:helper]
132 | opts[:flash_app_class] ||
133 | defined?(Sinatra::Base) && Sinatra::Base ||
134 | self.class.rack_builder.leaf_app.class
135 | end
136 | end
137 | end
138 |
--------------------------------------------------------------------------------
/public/stylesheets/app.css:
--------------------------------------------------------------------------------
1 | ::-moz-selection{
2 | background-color: black;
3 | color: #3fa9f5;
4 | }
5 | ::selection{
6 | background-color: black;
7 | color: #3fa9f5;
8 | }
9 | html{
10 | height: 100%;
11 | -webkit-font-smoothing: antialiased;
12 | -moz-osx-font-smoothing: grayscale;
13 | }
14 | body {
15 | margin: 0;
16 | font-family: "Source Code Pro", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
17 | font-size: 12px;
18 | height: 100%;
19 | }
20 | a{
21 | color: inherit;
22 | text-decoration: none;
23 | border-bottom: 1px solid #ccc;
24 | padding-bottom: 4px;
25 | -webkit-transition: all 0.3s ease;
26 | -moz-transition: all 0.3s ease;
27 | transition: all 0.3s ease;
28 | }
29 | a:hover{
30 | color: #3fa9f5;
31 | border-bottom: 1px solid #3fa9f5;
32 | }
33 | .wrapper{
34 | height: 100%;
35 | width: 100%;
36 | display: table;
37 | overflow: hidden;
38 | }
39 | .top-section{
40 | padding: 30px 0 20px;
41 | display: table-row;
42 | float: left;
43 | width: 100%;
44 | }
45 | header{
46 | border-bottom: 1px solid #e6e6e6;
47 | margin: 0 30px 10px;
48 | }
49 | h1{
50 | font-family: montserrat;
51 | font-size: 18px;
52 | text-transform: uppercase;
53 | color: #3fa9f5;
54 | font-weight: normal;
55 | }
56 | h1 span{
57 | color: #333;
58 | }
59 | .top-info-section{
60 | margin-bottom: 20px;
61 | color: #666;
62 | padding: 0 30px;
63 | }
64 | .version-info{
65 | float: left;
66 | }
67 | .author-info{
68 | float: right;
69 | }
70 | .author-info p{
71 | margin-bottom: 0;
72 | }
73 | .app-section{
74 | width: 100%;
75 | height: 100%;
76 | display: table-row;
77 | }
78 | .tabs-section{
79 | background-color: #e6e6e6;
80 | float: left;
81 | width: 100%;
82 | }
83 | .tab{
84 | float: left;
85 | position: relative;
86 | }
87 | .tab.css{
88 | width: 50%;
89 | }
90 | .tab.css:after{
91 | content: "";
92 | position: absolute;
93 | width: 1px;
94 | height: 100%;
95 | right: 0;
96 | top: 0;
97 | background-color: #ccc;
98 | }
99 | .tab.sass,
100 | .tab.scss
101 | {
102 | width: 25%;
103 | }
104 | .tab h2{
105 | font-family: montserrat;
106 | font-weight: normal;
107 | text-transform: uppercase;
108 | font-size: 18px;
109 | padding: 11px 30px;
110 | margin: 0;
111 | }
112 | .code-section{
113 | position: relative;
114 | background-color: #333;
115 | float: left;
116 | width: 100%;
117 | max-height: 100%;
118 | height: 100%;
119 | }
120 | .code-container.left:after{
121 | content: "";
122 | position: absolute;
123 | width: 1px;
124 | height: 100%;
125 | right: 0;
126 | top: 0;
127 | background-color: #252525;
128 | }
129 | .code-container.right textarea{
130 | -webkit-animation: highlight 1s;
131 | animation: highlight 1s;
132 | }
133 | @-webkit-keyframes highlight {
134 | from {color: #3fa9f5;}
135 | to {color: #eee;}
136 | }
137 | @keyframes highlight {
138 | from {color: #3fa9f5;}
139 | to {color: #eee;}
140 | }
141 | .code-container{
142 | width: 50%;
143 | float: left;
144 | height: 100%;
145 | position: relative;
146 | }
147 | .code-container label{
148 | position: absolute;
149 | top: 0;
150 | padding: 20px 30px;
151 | font-size: 14px;
152 | color: #999;
153 | background-color: #333;
154 | width: 100%;
155 | }
156 | .code-container textarea{
157 | width: 100%;
158 | height: 100%;
159 | padding: 60px 30px 80px 30px;
160 | font-family: inherit;
161 | font-size: 14px;
162 | color: #eee;
163 | background: none;
164 | border: 0;
165 | -webkit-font-smoothing: antialiased;
166 | -moz-osx-font-smoothing: grayscale;
167 | }
168 | .code-actions{
169 | width: 50px;
170 | height: 50px;
171 | position: absolute;
172 | background-color: #3fa9f5;
173 | background-image: url("/images/conv-arr.svg");
174 | background-size: 22px;
175 | background-repeat: no-repeat;
176 | background-position: center center;
177 | left: 0;
178 | right: 0;
179 | top: -45px;
180 | bottom: 0;
181 | margin: auto;
182 | border-radius: 50%;
183 | text-align: center;
184 | -webkit-transition: all 0.3s ease;
185 | -moz-transition: all 0.3s ease;
186 | transition: all 0.3s ease;
187 | }
188 | .code-actions:hover{
189 | width: 110px;
190 | height: 110px;
191 | background-position: 120px center;
192 | }
193 | .code-actions .button{
194 | background: transparent;
195 | overflow: hidden;
196 | cursor: pointer;
197 | color: transparent;
198 | font-family: montserrat;
199 | font-weight: normal;
200 | border: 0;
201 | opacity: 0;
202 | font-size: 16px;
203 | width: 100%;
204 | height: 50%;
205 | position: absolute;
206 | left: 0;
207 | right: 0;
208 | margin: 0;
209 | background-repeat: no-repeat;
210 | -webkit-transition: all 0.3s ease;
211 | -moz-transition: all 0.3s ease;
212 | transition: all 0.3s ease;
213 | }
214 | .button.scss{
215 | border-bottom-right-radius: 55px;
216 | border-bottom-left-radius: 55px;
217 | background-image: url("/images/scss-icon.svg");
218 | background-position: center 20px;
219 | }
220 | .button.sass{
221 | border-top-right-radius: 55px;
222 | border-top-left-radius: 55px;
223 | background-image: url("/images/sass-icon.svg");
224 | background-position: center bottom 20px;
225 | }
226 | .code-actions .button:hover{
227 | background-color: #1782cf;
228 | }
229 | .code-actions .button.scss{
230 | bottom: 0;
231 | }
232 | .code-actions .button.sass{
233 | top: 0;
234 | }
235 | .code-actions:hover .button{
236 | opacity: 1;
237 | }
238 | .code-actions:hover .arrow svg{
239 | margin-left: 120px;
240 | opacity: 0;
241 | }
242 | .notifications{
243 | position: absolute;
244 | top: 15px;
245 | left: 0;
246 | width: 99%;
247 | margin: auto;
248 | z-index: 2;
249 | padding: 0;
250 | height: auto;
251 | font-size: 14px;
252 | }
253 | .notifications span{
254 | padding: 0 10px;
255 | background-color: #333;
256 | float: left;
257 | padding-left: 30px;
258 | padding-right: 30px;
259 | }
260 | .notice{
261 | color: orange;
262 | }
263 | .error{
264 | color: #FF7B7B;
265 | }
266 | .success{
267 | color: green;
268 | }
269 |
--------------------------------------------------------------------------------
/public/stylesheets/960.css:
--------------------------------------------------------------------------------
1 | .container_12,.container_16 {
2 | margin-left: auto;
3 | margin-right: auto;
4 | width: 960px
5 | }
6 | .grid_1,.grid_2,.grid_3,.grid_4,.grid_5,.grid_6,.grid_7,.grid_8,.grid_9,.grid_10,.grid_11,.grid_12,.grid_13,.grid_14,.grid_15,.grid_16 {
7 | display: inline;
8 | float: left;
9 | position: relative;
10 | margin-left: 10px;
11 | margin-right: 10px
12 | }
13 | .container_12 .grid_3,.container_16 .grid_4 {
14 | width: 220px
15 | }
16 | .container_12 .grid_6,.container_16 .grid_8 {
17 | width: 460px
18 | }
19 | .container_12 .grid_9,.container_16 .grid_12 {
20 | width: 700px
21 | }
22 | .container_12 .grid_12,.container_16 .grid_16 {
23 | width: 940px
24 | }
25 | .alpha {
26 | margin-left: 0
27 | }
28 | .omega {
29 | margin-right: 0
30 | }
31 | .container_12 .grid_1 {
32 | width: 60px
33 | }
34 | .container_12 .grid_2 {
35 | width: 140px
36 | }
37 | .container_12 .grid_4 {
38 | width: 300px
39 | }
40 | .container_12 .grid_5 {
41 | width: 380px
42 | }
43 | .container_12 .grid_7 {
44 | width: 540px
45 | }
46 | .container_12 .grid_8 {
47 | width: 620px
48 | }
49 | .container_12 .grid_10 {
50 | width: 780px
51 | }
52 | .container_12 .grid_11 {
53 | width: 860px
54 | }
55 | .container_16 .grid_1 {
56 | width: 40px
57 | }
58 | .container_16 .grid_2 {
59 | width: 100px
60 | }
61 | .container_16 .grid_3 {
62 | width: 160px
63 | }
64 | .container_16 .grid_5 {
65 | width: 280px
66 | }
67 | .container_16 .grid_6 {
68 | width: 340px
69 | }
70 | .container_16 .grid_7 {
71 | width: 400px
72 | }
73 | .container_16 .grid_9 {
74 | width: 520px
75 | }
76 | .container_16 .grid_10 {
77 | width: 580px
78 | }
79 | .container_16 .grid_11 {
80 | width: 640px
81 | }
82 | .container_16 .grid_13 {
83 | width: 760px
84 | }
85 | .container_16 .grid_14 {
86 | width: 820px
87 | }
88 | .container_16 .grid_15 {
89 | width: 880px
90 | }
91 | .container_12 .prefix_3,.container_16 .prefix_4 {
92 | padding-left: 240px
93 | }
94 | .container_12 .prefix_6,.container_16 .prefix_8 {
95 | padding-left: 480px
96 | }
97 | .container_12 .prefix_9,.container_16 .prefix_12 {
98 | padding-left: 720px
99 | }
100 | .container_12 .prefix_1 {
101 | padding-left: 80px
102 | }
103 | .container_12 .prefix_2 {
104 | padding-left: 160px
105 | }
106 | .container_12 .prefix_4 {
107 | padding-left: 320px
108 | }
109 | .container_12 .prefix_5 {
110 | padding-left: 400px
111 | }
112 | .container_12 .prefix_7 {
113 | padding-left: 560px
114 | }
115 | .container_12 .prefix_8 {
116 | padding-left: 640px
117 | }
118 | .container_12 .prefix_10 {
119 | padding-left: 800px
120 | }
121 | .container_12 .prefix_11 {
122 | padding-left: 880px
123 | }
124 | .container_16 .prefix_1 {
125 | padding-left: 60px
126 | }
127 | .container_16 .prefix_2 {
128 | padding-left: 120px
129 | }
130 | .container_16 .prefix_3 {
131 | padding-left: 180px
132 | }
133 | .container_16 .prefix_5 {
134 | padding-left: 300px
135 | }
136 | .container_16 .prefix_6 {
137 | padding-left: 360px
138 | }
139 | .container_16 .prefix_7 {
140 | padding-left: 420px
141 | }
142 | .container_16 .prefix_9 {
143 | padding-left: 540px
144 | }
145 | .container_16 .prefix_10 {
146 | padding-left: 600px
147 | }
148 | .container_16 .prefix_11 {
149 | padding-left: 660px
150 | }
151 | .container_16 .prefix_13 {
152 | padding-left: 780px
153 | }
154 | .container_16 .prefix_14 {
155 | padding-left: 840px
156 | }
157 | .container_16 .prefix_15 {
158 | padding-left: 900px
159 | }
160 | .container_12 .suffix_3,.container_16 .suffix_4 {
161 | padding-right: 240px
162 | }
163 | .container_12 .suffix_6,.container_16 .suffix_8 {
164 | padding-right: 480px
165 | }
166 | .container_12 .suffix_9,.container_16 .suffix_12 {
167 | padding-right: 720px
168 | }
169 | .container_12 .suffix_1 {
170 | padding-right: 80px
171 | }
172 | .container_12 .suffix_2 {
173 | padding-right: 160px
174 | }
175 | .container_12 .suffix_4 {
176 | padding-right: 320px
177 | }
178 | .container_12 .suffix_5 {
179 | padding-right: 400px
180 | }
181 | .container_12 .suffix_7 {
182 | padding-right: 560px
183 | }
184 | .container_12 .suffix_8 {
185 | padding-right: 640px
186 | }
187 | .container_12 .suffix_10 {
188 | padding-right: 800px
189 | }
190 | .container_12 .suffix_11 {
191 | padding-right: 880px
192 | }
193 | .container_16 .suffix_1 {
194 | padding-right: 60px
195 | }
196 | .container_16 .suffix_2 {
197 | padding-right: 120px
198 | }
199 | .container_16 .suffix_3 {
200 | padding-right: 180px
201 | }
202 | .container_16 .suffix_5 {
203 | padding-right: 300px
204 | }
205 | .container_16 .suffix_6 {
206 | padding-right: 360px
207 | }
208 | .container_16 .suffix_7 {
209 | padding-right: 420px
210 | }
211 | .container_16 .suffix_9 {
212 | padding-right: 540px
213 | }
214 | .container_16 .suffix_10 {
215 | padding-right: 600px
216 | }
217 | .container_16 .suffix_11 {
218 | padding-right: 660px
219 | }
220 | .container_16 .suffix_13 {
221 | padding-right: 780px
222 | }
223 | .container_16 .suffix_14 {
224 | padding-right: 840px
225 | }
226 | .container_16 .suffix_15 {
227 | padding-right: 900px
228 | }
229 | .container_12 .push_3,.container_16 .push_4 {
230 | left: 240px
231 | }
232 | .container_12 .push_6,.container_16 .push_8 {
233 | left: 480px
234 | }
235 | .container_12 .push_9,.container_16 .push_12 {
236 | left: 720px
237 | }
238 | .container_12 .push_1 {
239 | left: 80px
240 | }
241 | .container_12 .push_2 {
242 | left: 160px
243 | }
244 | .container_12 .push_4 {
245 | left: 320px
246 | }
247 | .container_12 .push_5 {
248 | left: 400px
249 | }
250 | .container_12 .push_7 {
251 | left: 560px
252 | }
253 | .container_12 .push_8 {
254 | left: 640px
255 | }
256 | .container_12 .push_10 {
257 | left: 800px
258 | }
259 | .container_12 .push_11 {
260 | left: 880px
261 | }
262 | .container_16 .push_1 {
263 | left: 60px
264 | }
265 | .container_16 .push_2 {
266 | left: 120px
267 | }
268 | .container_16 .push_3 {
269 | left: 180px
270 | }
271 | .container_16 .push_5 {
272 | left: 300px
273 | }
274 | .container_16 .push_6 {
275 | left: 360px
276 | }
277 | .container_16 .push_7 {
278 | left: 420px
279 | }
280 | .container_16 .push_9 {
281 | left: 540px
282 | }
283 | .container_16 .push_10 {
284 | left: 600px
285 | }
286 | .container_16 .push_11 {
287 | left: 660px
288 | }
289 | .container_16 .push_13 {
290 | left: 780px
291 | }
292 | .container_16 .push_14 {
293 | left: 840px
294 | }
295 | .container_16 .push_15 {
296 | left: 900px
297 | }
298 | .container_12 .pull_3,.container_16 .pull_4 {
299 | left: -240px
300 | }
301 | .container_12 .pull_6,.container_16 .pull_8 {
302 | left: -480px
303 | }
304 | .container_12 .pull_9,.container_16 .pull_12 {
305 | left: -720px
306 | }
307 | .container_12 .pull_1 {
308 | left: -80px
309 | }
310 | .container_12 .pull_2 {
311 | left: -160px
312 | }
313 | .container_12 .pull_4 {
314 | left: -320px
315 | }
316 | .container_12 .pull_5 {
317 | left: -400px
318 | }
319 | .container_12 .pull_7 {
320 | left: -560px
321 | }
322 | .container_12 .pull_8 {
323 | left: -640px
324 | }
325 | .container_12 .pull_10 {
326 | left: -800px
327 | }
328 | .container_12 .pull_11 {
329 | left: -880px
330 | }
331 | .container_16 .pull_1 {
332 | left: -60px
333 | }
334 | .container_16 .pull_2 {
335 | left: -120px
336 | }
337 | .container_16 .pull_3 {
338 | left: -180px
339 | }
340 | .container_16 .pull_5 {
341 | left: -300px
342 | }
343 | .container_16 .pull_6 {
344 | left: -360px
345 | }
346 | .container_16 .pull_7 {
347 | left: -420px
348 | }
349 | .container_16 .pull_9 {
350 | left: -540px
351 | }
352 | .container_16 .pull_10 {
353 | left: -600px
354 | }
355 | .container_16 .pull_11 {
356 | left: -660px
357 | }
358 | .container_16 .pull_13 {
359 | left: -780px
360 | }
361 | .container_16 .pull_14 {
362 | left: -840px
363 | }
364 | .container_16 .pull_15 {
365 | left: -900px
366 | }
367 | .clear {
368 | clear: both;
369 | display: block;
370 | overflow: hidden;
371 | visibility: hidden;
372 | width: 0;
373 | height: 0
374 | }
375 | .clearfix:after {
376 | clear: both;
377 | content: ' ';
378 | display: block;
379 | font-size: 0;
380 | line-height: 0;
381 | visibility: hidden;
382 | width: 0;
383 | height: 0
384 | }
385 | * html .clearfix {
386 | height: 1%
387 | }
388 |
--------------------------------------------------------------------------------