├── .rspec ├── evil-front ├── spec │ ├── sass │ │ ├── empty.txt │ │ ├── ruble.sass │ │ ├── inline-ruble.sass │ │ ├── size.sass │ │ ├── load.sass │ │ └── media.sass │ ├── spec_helper.rb │ ├── english_spec.rb │ ├── sass_spec.rb │ ├── russian_spec.rb │ └── helpers_spec.rb ├── .rspec ├── lib │ ├── evil-front │ │ ├── version.rb │ │ ├── slim.rb │ │ ├── helpers │ │ │ ├── capitalize_first.rb │ │ │ ├── head_content.rb │ │ │ ├── ruble.rb │ │ │ ├── tel.rb │ │ │ ├── typograph_by_locale.rb │ │ │ ├── standard_assets.rb │ │ │ ├── disable_mobile_zoom.rb │ │ │ ├── auto_flying_quotes.rb │ │ │ ├── flying_quotes.rb │ │ │ ├── english_typograph.rb │ │ │ ├── russian_typograph.rb │ │ │ ├── title.rb │ │ │ ├── head_tag.rb │ │ │ └── title_tag.rb │ │ ├── helpers.rb │ │ ├── english.rb │ │ ├── typograph.rb │ │ └── russian.rb │ ├── assets │ │ ├── javascripts │ │ │ ├── evil-front │ │ │ │ ├── core.js │ │ │ │ ├── detect-3d.js │ │ │ │ ├── shortcuts.js │ │ │ │ ├── after.js │ │ │ │ ├── every.js │ │ │ │ ├── links.js │ │ │ │ ├── http.js │ │ │ │ ├── transform3d.js │ │ │ │ ├── queue.js │ │ │ │ ├── outside.js │ │ │ │ ├── jquery.js │ │ │ │ ├── tappable.js │ │ │ │ └── ajax.js │ │ │ └── evil-front.js │ │ └── stylesheets │ │ │ ├── evil-front │ │ │ ├── to-px.sass │ │ │ ├── flying-quotes.sass │ │ │ ├── hover.sass │ │ │ ├── clearfix.sass │ │ │ ├── size.sass │ │ │ ├── stroke-text.sass │ │ │ ├── height.sass │ │ │ ├── colors.sass │ │ │ ├── no-tap-highlight.sass │ │ │ ├── styled-taps.sass │ │ │ ├── no-hover.sass │ │ │ ├── reset.sass │ │ │ ├── sticky-footer.sass │ │ │ ├── media.sass │ │ │ ├── easings.sass │ │ │ └── import-ruble.sass │ │ │ └── evil-front.sass │ └── evil-front.rb ├── vendor │ └── assets │ │ └── fonts │ │ └── evil-front │ │ ├── alsrubl-arial-bold.woff │ │ ├── alsrubl-arial-italic.woff │ │ ├── alsrubl-arial-regular.woff │ │ └── alsrubl-arial-bolditalic.woff ├── Rakefile ├── evil-front.gemspec ├── LICENSE └── ChangeLog.md ├── .gitignore ├── .travis.yml ├── evil-front-all ├── lib │ ├── evil-front │ │ └── all │ │ │ └── version.rb │ └── evil-front-all.rb ├── Rakefile ├── ChangeLog.md ├── LICENSE └── evil-front-all.gemspec ├── evil-front-rails ├── lib │ ├── evil-front │ │ └── rails │ │ │ └── version.rb │ └── evil-front-rails.rb ├── Rakefile ├── ChangeLog.md ├── evil-front-rails.gemspec └── LICENSE ├── Gemfile ├── Rakefile └── README.md /.rspec: -------------------------------------------------------------------------------- 1 | --colour 2 | -------------------------------------------------------------------------------- /evil-front/spec/sass/empty.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /evil-front/.rspec: -------------------------------------------------------------------------------- 1 | --format documentation --colour 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | *~ 3 | 4 | pkg/ 5 | 6 | .bundle 7 | Gemfile.lock 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | rvm: 4 | - 2.2.2 5 | - 2.3.0 6 | -------------------------------------------------------------------------------- /evil-front/spec/sass/ruble.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front" 2 | 3 | +import-ruble("PT Sans, sans-serif") 4 | -------------------------------------------------------------------------------- /evil-front/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require_relative '../lib/evil-front' 2 | 3 | I18n.enforce_available_locales = false 4 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/version.rb: -------------------------------------------------------------------------------- 1 | module EvilFront 2 | VERSION = '0.5.1' unless defined? EvilFront::VERSION 3 | end 4 | -------------------------------------------------------------------------------- /evil-front/spec/sass/inline-ruble.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front" 2 | 3 | +import-ruble("PT Sans, sans-serif", $italic: "inline") 4 | -------------------------------------------------------------------------------- /evil-front-all/lib/evil-front/all/version.rb: -------------------------------------------------------------------------------- 1 | module EvilFront 2 | module All 3 | VERSION = '0.5.0' unless defined? EvilFront::All::VERSION 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/core.js: -------------------------------------------------------------------------------- 1 | // Add global `evil` namespace and common shortcuts. 2 | 3 | if ( !window.evil ) { 4 | window.evil = { }; 5 | } 6 | -------------------------------------------------------------------------------- /evil-front/spec/sass/size.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front" 2 | 3 | .all 4 | +size(10px, 20px) 5 | 6 | .one 7 | +size(30px) 8 | 9 | .no-unit 10 | +size(15) 11 | -------------------------------------------------------------------------------- /evil-front-rails/lib/evil-front/rails/version.rb: -------------------------------------------------------------------------------- 1 | module EvilFront 2 | module Rails 3 | VERSION = '0.5.0' unless defined? EvilFront::Rails::VERSION 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /evil-front/spec/sass/load.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front" 2 | 3 | a 4 | content: inline("empty.txt") 5 | background: black(0.5) 6 | transition: all 1s $easeInSine 7 | +clearfix 8 | -------------------------------------------------------------------------------- /evil-front/spec/sass/media.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front" 2 | 3 | .one 4 | +max-width(100) 5 | color: black 6 | 7 | .two 8 | +min-width(200px) 9 | color: white 10 | -------------------------------------------------------------------------------- /evil-front/vendor/assets/fonts/evil-front/alsrubl-arial-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai/evil-front/HEAD/evil-front/vendor/assets/fonts/evil-front/alsrubl-arial-bold.woff -------------------------------------------------------------------------------- /evil-front/vendor/assets/fonts/evil-front/alsrubl-arial-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai/evil-front/HEAD/evil-front/vendor/assets/fonts/evil-front/alsrubl-arial-italic.woff -------------------------------------------------------------------------------- /evil-front/vendor/assets/fonts/evil-front/alsrubl-arial-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai/evil-front/HEAD/evil-front/vendor/assets/fonts/evil-front/alsrubl-arial-regular.woff -------------------------------------------------------------------------------- /evil-front/vendor/assets/fonts/evil-front/alsrubl-arial-bolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai/evil-front/HEAD/evil-front/vendor/assets/fonts/evil-front/alsrubl-arial-bolditalic.woff -------------------------------------------------------------------------------- /evil-front/lib/evil-front/slim.rb: -------------------------------------------------------------------------------- 1 | module EvilFront 2 | # Set default options to Slim 3 | def self.set_slim_options! 4 | Slim::Engine.set_options(pretty: true, format: :html) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/detect-3d.js: -------------------------------------------------------------------------------- 1 | //= require evil-front/transform3d 2 | 3 | // Detect support 3D transform and add `transform3d` or `transform2s` class 4 | // to body. 5 | evil.transform3d.init(); 6 | -------------------------------------------------------------------------------- /evil-front-all/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | require 'bundler/setup' 4 | Bundler::GemHelper.install_tasks 5 | 6 | task :clobber_package do 7 | rm_r 'pkg' rescue nil 8 | end 9 | task clobber: [:clobber_package] 10 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/to-px.sass: -------------------------------------------------------------------------------- 1 | // Add "px" if unit is unitless. Used in +media and +size. 2 | @function to-px($var) 3 | @if unitless($var) 4 | @return $var * 1px 5 | @else 6 | @return $var 7 | -------------------------------------------------------------------------------- /evil-front-rails/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | require 'bundler/setup' 4 | Bundler::GemHelper.install_tasks 5 | 6 | task :clobber_package do 7 | rm_r 'pkg' rescue nil 8 | end 9 | task clobber: [:clobber_package] 10 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/flying-quotes.sass: -------------------------------------------------------------------------------- 1 | // Mark quotes to move first quote before the text line. 2 | @mixin flying-quotes 3 | .space-before-quote 4 | margin-right: 0.35em 5 | .quotes 6 | margin-left: -0.35em 7 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/shortcuts.js: -------------------------------------------------------------------------------- 1 | //= require evil-front/core 2 | 3 | evil.win = $(window), 4 | evil.doc = $(document), 5 | evil.body = null; 6 | 7 | evil.doc.ready(function() { 8 | evil.body = $('body'); 9 | }); 10 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front.js: -------------------------------------------------------------------------------- 1 | // Load libraries and core files. 2 | 3 | //= require evil-front/core 4 | //= require evil-front/jquery 5 | //= require evil-front/shortcuts 6 | //= require evil-front/after 7 | 8 | //= require evil-blocks 9 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/hover.sass: -------------------------------------------------------------------------------- 1 | // Alias for focus and hover states 2 | // 3 | // a 4 | // +no-hover 5 | // color: blue 6 | // +hover 7 | // color: red 8 | @mixin hover 9 | &:hover, &:focus 10 | @content 11 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/after.js: -------------------------------------------------------------------------------- 1 | // Alternate syntax for `setTimeout`, to be more useful in CoffeeScript. 2 | // 3 | // after 1000, -> 4 | // addSecond() 5 | window.after = function (ms, callback) { 6 | return setTimeout(callback, ms); 7 | }; 8 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/every.js: -------------------------------------------------------------------------------- 1 | // Alternate syntax for `setInterval`, to be more useful in CoffeeScript. 2 | // 3 | // every 1000, -> 4 | // addSecond() 5 | window.every = function (ms, callback) { 6 | return setInterval(callback, ms); 7 | }; 8 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/clearfix.sass: -------------------------------------------------------------------------------- 1 | // Clearfix to set block size from float inners. 2 | // 3 | // Based on http://nicolasgallagher.com/micro-clearfix-hack/ 4 | @mixin clearfix 5 | &:after 6 | content: "" 7 | display: table 8 | clear: both 9 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/capitalize_first.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Capitalize only first letter (like titles in Russian). 3 | # 4 | # = capitalize_first post.title 5 | def capitalize_first(text) 6 | EvilFront::Russian.capitalize_first(text) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | gem 'rails', '>= 4' 5 | 6 | gem 'rspec-rails' 7 | 8 | gem 'evil-front', path: 'evil-front/' 9 | gem 'evil-front-all', path: 'evil-front-all/', require: false 10 | gem 'evil-front-rails', path: 'evil-front-rails/', require: false 11 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/size.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front/to-px" 2 | 3 | // Shortcut to set width and height 4 | // 5 | // +size(200, 100) 6 | // +size(32) 7 | // +size(50%, 10em) 8 | @mixin size($width, $height: $width) 9 | width: to-px($width) 10 | height: to-px($height) 11 | -------------------------------------------------------------------------------- /evil-front/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | require 'bundler/setup' 4 | Bundler::GemHelper.install_tasks 5 | 6 | require 'rspec/core/rake_task' 7 | RSpec::Core::RakeTask.new 8 | task default: :spec 9 | 10 | task :clobber_package do 11 | rm_r 'pkg' rescue nil 12 | end 13 | task clobber: [:clobber_package] 14 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/links.js: -------------------------------------------------------------------------------- 1 | //= require evil-front/core 2 | // Prevent default in AJAX link with only # in href 3 | 4 | evil.doc.ready(function() { 5 | evil.body.on('click', 'a', function (e) { 6 | if ( this.getAttribute('href') == '#' ) { 7 | e.preventDefault(); 8 | } 9 | }); 10 | }) 11 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/stroke-text.sass: -------------------------------------------------------------------------------- 1 | // Stroke text by some shadow. Useful, when you white on transparent background. 2 | // 3 | // .banner 4 | // background: black(0.2) 5 | // color: white 6 | // +stroke-text(black) 7 | @mixin stroke-text($color) 8 | text-shadow: 1px 1px 1px $color, 1px -1px 1px $color, -1px 1px 1px $color, -1px -1px 1px $color 9 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/height.sass: -------------------------------------------------------------------------------- 1 | // Shortcut to set `height` and `line-height` to vertical text centering. 2 | // You can also set `$line-diff` to have different `line-height`. 3 | // 4 | // .button 5 | // display: inline-block 6 | // +height(24px) 7 | @mixin height($height, $line-diff: 0) 8 | height: $height 9 | line-height: $height + $line-diff 10 | -------------------------------------------------------------------------------- /evil-front-rails/ChangeLog.md: -------------------------------------------------------------------------------- 1 | ## 0.5 “Chryse Planitia” 2 | 3 | * Remove `clean-css`. 4 | 5 | ## 0.4 “Schiaparelli Crater” 6 | 7 | * Add Sprockets 3 support. 8 | 9 | ## 0.3 “Samara Vallis” 10 | 11 | * Bump version to use latest Evil Front core. 12 | 13 | ## 0.2 “Ptolemaeus Crater” 14 | 15 | * Fix gem dependencies. 16 | 17 | ## 0.1 “Hellespontus Montes” 18 | 19 | * Initial release. 20 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/head_content.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Add content to head tag. Will be useful in page views. 3 | # 4 | # - head_content do 5 | # meta name="description" content=page.seo.description 6 | # meta name="keywords" content=page.seo.keywords 7 | def head_content(&block) 8 | content_for(:evil_front_head, &block) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/colors.sass: -------------------------------------------------------------------------------- 1 | // Shorcut to set black color with alpha in rgba() 2 | // 3 | // box-shadow: 0 0 5px black(0.7) 4 | @function black($opacity) 5 | @return rgba(0, 0, 0, $opacity) 6 | 7 | // Shorcut to set white color with alpha in rgba() 8 | // 9 | // box-shadow: 0 0 5px white(0.7) 10 | @function white($opacity) 11 | @return rgba(255, 255, 255, $opacity) 12 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/no-tap-highlight.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front/colors" 2 | 3 | // Hide link tap highlight on mobile browsers. Use it only if you define your 4 | // own pressed styles. 5 | // 6 | // .button 7 | // +no-tap-highlight 8 | // 9 | // If you disable all taps highlight, use `styled-taps` mixin. 10 | @mixin no-tap-highlight 11 | -webkit-tap-highlight-color: white(0) 12 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/ruble.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module EvilFront::Helpers 4 | # Insert symbol of Russian currency. 5 | # 6 | # = order.price 7 | # = ruble 8 | # 9 | # Don’t forget to import ruble’s fonts and class in you Sass: 10 | # 11 | # +import-ruble("PT Sans, sans-serif", $regular: inline) 12 | def ruble 13 | EvilFront.html_safe('Р') 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/styled-taps.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front/no-tap-highlight" 2 | 3 | // Disable standard browser tap highlight and transitions for hover and tapped 4 | // states. 5 | // 6 | // +styled-taps 7 | // 8 | // Must be used with `evil-front/tappable` JS and `no-hover` Sass mixin. 9 | @mixin styled-taps 10 | .is-tapped, :active 11 | transition: none !important 12 | body 13 | +no-tap-highlight 14 | -------------------------------------------------------------------------------- /evil-front-all/ChangeLog.md: -------------------------------------------------------------------------------- 1 | ## 0.5 “Chryse Planitia” 2 | 3 | * Remove `clean-css`. 4 | 5 | ## 0.4 “Schiaparelli Crater” 6 | 7 | * Add Sprockets 3 support. 8 | 9 | ## 0.3.1 10 | 11 | * Use new API for Autoprefixer 3.0. 12 | 13 | ## 0.3 “Samara Vallis” 14 | 15 | * Bump version to use latest Evil Front core. 16 | 17 | ## 0.2 “Ptolemaeus Crater” 18 | 19 | * Bump version to be used in Evil Front Rails. 20 | 21 | ## 0.1 “Hellespontus Montes” 22 | 23 | * Initial release. 24 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/tel.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Render link with phone number. It will remove all non-digits symbols from 3 | # phone number and format `tel:` protocol URI. 4 | # 5 | # label Contact us: 6 | # = tel('+7 (495) 660−83−79') 7 | def tel(number, args = { }) 8 | args[:href] = "tel:" + number.gsub(/[^\d\+]/, '') 9 | args[:class] = (['tel', args[:class]]).compact.join(' ') 10 | content_tag(:a, number, args) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/typograph_by_locale.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Add typograph rules to text by language in current locale. 3 | # 4 | # typograph_by_locale(post.body) 5 | def typograph_by_locale(text = nil, &block) 6 | text = capture(&block) if block_given? 7 | 8 | if I18n.locale == :ru 9 | russian_typograph(text) 10 | elsif I18n.locale == :en 11 | english_typograph(text) 12 | else 13 | text 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/standard_assets.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Add `application.css`, jQuery from Google CDN and `application.js`. 3 | # 4 | # html 5 | # = head_tag do 6 | # = standard_assets 7 | def standard_assets(attributes = { }) 8 | stylesheet_link_tag('application', media: 'all') + 9 | include_jquery(attributes.dup) + 10 | content_for(:evil_libraries) + 11 | javascript_include_tag('application', attributes) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/disable_mobile_zoom.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Disable user zoom in mobile browsers. You should use it only if your styles 3 | # are special optimized for mobile screens. 4 | # 5 | # html 6 | # head 7 | # = disable_mobile_zoom 8 | def disable_mobile_zoom 9 | html = '' 11 | EvilFront.html_safe(html) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/auto_flying_quotes.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Find quotes and add tags to flying quotes 3 | # 4 | # = auto_flying_quotes post.body 5 | # 6 | # Don’t forget to install styles by `quotes` Sass mixin. 7 | def auto_flying_quotes(text = nil, &block) 8 | text = if block_given? 9 | capture(&block).strip 10 | else 11 | EvilFront.escape(text) 12 | end 13 | text = EvilFront::Russian.auto_flying_quotes(text) 14 | EvilFront.html_safe(text) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/no-hover.sass: -------------------------------------------------------------------------------- 1 | // Add normal state, to prevent hover on touched elements 2 | // 3 | // a 4 | // display: inline-block 5 | // +no-hover 6 | // color: black 7 | // &:hover 8 | // color: gray 9 | // &:active, &.is-tapped 10 | // background: black 11 | // 12 | // To enable `.is-tapped` state, you need to require `evil-front/tappable` JS. 13 | // Don’t forget to disable transitions in `.is-tapped` and `:active` states by 14 | // `+styled-taps` mixin. 15 | @mixin no-hover 16 | &, &.was-tapped:hover, &.was-tapped:active 17 | @content 18 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/flying_quotes.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Mark quotes to move first quote before the text line. 3 | # 4 | # = flying_quotes feedback.text 5 | # 6 | # You can send block: 7 | # 8 | # = flying_quotes do 9 | # a href=course.url 10 | # = course.name 11 | def flying_quotes(text = nil, options = { }, &block) 12 | text = if block_given? 13 | capture(&block).strip 14 | else 15 | EvilFront.escape(text) 16 | end 17 | text = EvilFront::Russian.flying_quotes(text, options) 18 | EvilFront.html_safe(text) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/reset.sass: -------------------------------------------------------------------------------- 1 | // Normalize browser default styles and clean some unnecessary styles 2 | // 3 | // +evil-reset 4 | 5 | @mixin evil-reset 6 | * 7 | margin: 0 8 | padding: 0 9 | 10 | a img 11 | border: none 12 | 13 | body 14 | background: white 15 | color: black 16 | line-height: 1.4 17 | 18 | a, input, textarea, button 19 | &:focus 20 | outline: none 21 | ::-moz-focus-inner 22 | border: 0 23 | 24 | h1, h2, h3, h4, h5, h6 25 | font-weight: normal 26 | 27 | li 28 | list-style: none 29 | 30 | cite 31 | font-style: normal 32 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/sticky-footer.sass: -------------------------------------------------------------------------------- 1 | // Sticky footer, which show on bottom of screen if content height is less, 2 | // that screen content 3 | // 4 | // +sticky-footer(100px) 5 | // 6 | // You can specify footer selector (`.footer-layout` by default): 7 | // 8 | // +sticky-footer(100px, 'footer') 9 | @mixin sticky-footer($height, $footer: unquote(".footer-layout")) 10 | html 11 | position: relative 12 | min-height: 100% 13 | body 14 | margin-bottom: $height 15 | #{$footer} 16 | position: absolute 17 | left: 0 18 | bottom: 0 19 | height: $height 20 | width: 100% 21 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front.sass: -------------------------------------------------------------------------------- 1 | @import "rails-sass-images" 2 | 3 | @import "evil-front/to-px" 4 | 5 | @import "evil-front/size" 6 | @import "evil-front/hover" 7 | @import "evil-front/reset" 8 | @import "evil-front/media" 9 | @import "evil-front/colors" 10 | @import "evil-front/height" 11 | @import "evil-front/easings" 12 | @import "evil-front/no-hover" 13 | @import "evil-front/clearfix" 14 | @import "evil-front/styled-taps" 15 | @import "evil-front/stroke-text" 16 | @import "evil-front/import-ruble" 17 | @import "evil-front/flying-quotes" 18 | @import "evil-front/sticky-footer" 19 | @import "evil-front/no-tap-highlight" 20 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/english_typograph.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Insert non-break spaces and mark quotes to have nice text. 3 | # Work only with English language. 4 | # 5 | # = english_typograph user.description 6 | # 7 | # You can send block: 8 | # 9 | # = english_typograph do 10 | # = user.name 11 | # = user.profession 12 | def english_typograph(text = nil, &block) 13 | text = if block_given? 14 | capture(&block) 15 | else 16 | EvilFront.escape(text) 17 | end 18 | text = EvilFront::English.typograph_html(text) 19 | EvilFront.html_safe(text) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/russian_typograph.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Insert non-break spaces and mark quotes to have nice text. 3 | # Work only with Russian language. 4 | # 5 | # = russian_typograph user.description 6 | # 7 | # You can send block: 8 | # 9 | # = russian_typograph do 10 | # = user.name 11 | # = user.profession 12 | def russian_typograph(text = nil, &block) 13 | text = if block_given? 14 | capture(&block) 15 | else 16 | EvilFront.escape(text) 17 | end 18 | text = EvilFront::Russian.typograph_html(text) 19 | EvilFront.html_safe(text) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/title.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Add page title. Will be used with site title in document title tag by 3 | # `title_tag`. 4 | # 5 | # - title 'FAQ' 6 | # 7 | # You can set subtitles (order will be reversed): 8 | # 9 | # - title 'FAQ', 'Ask' 10 | # 11 | # By default `title_tag` will add site name to page title. You can show only 12 | # page title by `no_site` option: 13 | # 14 | # - title 'Site Home', no_site: true 15 | def title(*titles) 16 | options = titles.extract_options! 17 | @evil_front_no_site_in_title = true if options[:no_site] 18 | 19 | @evil_front_titles ||= [] 20 | @evil_front_titles += titles 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers.rb: -------------------------------------------------------------------------------- 1 | module EvilFront 2 | HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<' } 3 | 4 | # Call `html_safe` if String has this methods. 5 | def self.html_safe(string) 6 | if string.respond_to?(:html_safe) 7 | string.html_safe 8 | else 9 | string.to_s 10 | end 11 | end 12 | 13 | # Escape unsafe strings 14 | def self.escape(string) 15 | string = string.to_s 16 | if not string.respond_to?(:html_safe?) or string.html_safe? 17 | string 18 | else 19 | string.gsub(/[&><]/, HTML_ESCAPE).html_safe 20 | end 21 | end 22 | end 23 | 24 | dir = Pathname(__FILE__).dirname.join('helpers') 25 | Dir.glob(dir.join('*.rb').to_s) { |helper| require helper } 26 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/english.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'rubypants-unicode' 4 | 5 | module EvilFront 6 | # Helpers to work with English text. 7 | module English 8 | extend Typograph 9 | 10 | private 11 | 12 | # Replace symbols to right ones, like m-dash, quotes, etc. 13 | def self.use_right_symbols(text) 14 | RubyPants.new(text).to_html 15 | end 16 | 17 | # Small words to insert non-break space before them 18 | def self.tiny_words 19 | @tiny_words ||= begin 20 | tiny = %w(to is be the a an no if at on of in or and) 21 | tiny += tiny.map(&:capitalize) 22 | tiny.map { |i| Regexp.new("( | )(#{Regexp.quote i}) ") } 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /evil-front/spec/english_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require_relative 'spec_helper' 4 | 5 | describe EvilFront::English do 6 | def nbsp_mark_typograph(str) 7 | EvilFront::English.typograph(str).gsub(' ', '_') 8 | end 9 | 10 | describe 'typograph' do 11 | 12 | it 'changes quotes' do 13 | expect(nbsp_mark_typograph('"a".')).to eq '“a”.' 14 | end 15 | 16 | it 'changes dashes' do 17 | expect(nbsp_mark_typograph('a - b')).to eq 'a - b' 18 | end 19 | 20 | it 'changes ellipsis' do 21 | expect(nbsp_mark_typograph('a...')).to eq 'a…' 22 | end 23 | 24 | it 'inserts non-break spaces' do 25 | expect(nbsp_mark_typograph('he is a hero')).to eq 'he is_a_hero' 26 | end 27 | 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/media.sass: -------------------------------------------------------------------------------- 1 | @import "evil-front/to-px" 2 | 3 | // Shortcuts for CSS Media Queries 4 | 5 | @mixin max-width($width) 6 | @media all and (max-width: to-px($width)) 7 | @content 8 | 9 | @mixin min-width($width) 10 | @media all and (min-width: to-px($width)) 11 | @content 12 | 13 | @mixin range-width($min-width, $max-width) 14 | @media all and (min-width: to-px($min-width)) and (max-width: to-px($max-width)) 15 | @content 16 | 17 | @mixin max-height($height) 18 | @media all and (max-height: to-px($height)) 19 | @content 20 | 21 | @mixin min-height($height) 22 | @media all and (min-height: to-px($height)) 23 | @content 24 | 25 | @mixin range-height($min-height, $max-height) 26 | @media all and (min-height: to-px($min-height)) and (max-height: to-px($max-height)) 27 | @content 28 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/head_tag.rb: -------------------------------------------------------------------------------- 1 | module EvilFront::Helpers 2 | # Add content from `head_content` and statistics counter in production, 3 | # if you set `:stats` option. 4 | # 5 | # html 6 | # head 7 | # = head_tag do 8 | # = title_tag(t.title) 9 | # = standard_assets 10 | # 11 | # You can disable statistics counter by options: 12 | # 13 | # = head_tag(statistics: false) do 14 | def head_tag(options = { }, &block) 15 | head = tag(:meta, charset: 'UTF-8') 16 | head += capture(&block) if block_given? 17 | head += content_for(:evil_front_head) 18 | 19 | options[:statistics] = true unless options.has_key? :statistics 20 | if options[:statistics] and Rails.env.production? 21 | head += render('layouts/statistics') rescue '' 22 | end 23 | 24 | content_tag(:head, head) 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /evil-front-all/lib/evil-front-all.rb: -------------------------------------------------------------------------------- 1 | require 'evil-front' 2 | 3 | require 'uglifier' 4 | require 'jquery-cdn' 5 | require 'coffee_script' 6 | require 'evil-blocks-rails' 7 | require 'autoprefixer-rails' 8 | 9 | module EvilFront 10 | # Install Evil Front, Autoprefixer, Evil Blocks, Rails Sass Images 11 | # and Csso to Sprockets. 12 | def self.install_all(sprockets, options = {}) 13 | autoprefixer = { } 14 | autoprefixer[:browsers] = options[:browsers] if options.has_key? :browsers 15 | 16 | AutoprefixerRails.install(sprockets, autoprefixer) 17 | EvilBlocks.install(sprockets) 18 | JqueryCdn.install(sprockets) 19 | install(sprockets) 20 | 21 | EvilFront.set_slim_options! 22 | end 23 | 24 | unless defined? ::Rails 25 | module Helpers 26 | include JqueryCdn::Helpers 27 | end 28 | end 29 | end 30 | 31 | require_relative 'evil-front/all/version' 32 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/helpers/title_tag.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'i18n' 4 | 5 | module EvilFront::Helpers 6 | # Return title tag with current page title. It will just join page titles 7 | # from `title` helper and `site` name. 8 | # 9 | # By default, separator will be m-dash for Russian and n-dash for others. 10 | # 11 | # html 12 | # head 13 | # = title_tag('Foo Company') 14 | # 15 | # Separator will be taken by current locale. But, you can change it by 16 | # `separator` option: 17 | # 18 | # = title_tag('Foo Company', separator: ' * ') 19 | def title_tag(*site) 20 | options = site.extract_options! 21 | separator = options[:separator] || (I18n.locale == :ru ? ' — ' : ' - ') 22 | 23 | site = [] if @evil_front_no_site_in_title 24 | 25 | @evil_front_titles ||= [] 26 | titles = (@evil_front_titles + site).compact 27 | titles = titles.join(separator) 28 | EvilFront.html_safe("#{ EvilFront.escape(titles) }") 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front.rb: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | 3 | require 'slim' 4 | require 'sass' 5 | require 'sprockets' 6 | require 'rails-sass-images' 7 | 8 | module EvilFront 9 | autoload :Typograph, 'evil-front/typograph' 10 | autoload :Russian, 'evil-front/russian' 11 | autoload :English, 'evil-front/english' 12 | 13 | if defined?(::Rails) 14 | # Enable `lib/assets/` and `vendor/assets/` in Rails app. 15 | class Engine < ::Rails::Engine 16 | end 17 | end 18 | 19 | # Install Evil Front to standalone Sprockets environment. 20 | def self.install(sprockets) 21 | RailsSassImages.install(sprockets) 22 | 23 | root = Pathname(__FILE__).dirname.join('..') 24 | sprockets.append_path(root.join('lib/assets/javascripts')) 25 | sprockets.append_path(root.join('lib/assets/stylesheets')) 26 | sprockets.append_path(root.join('vendor/assets/fonts')) 27 | end 28 | end 29 | 30 | require_relative 'evil-front/version' 31 | require_relative 'evil-front/helpers' 32 | require_relative 'evil-front/slim' 33 | -------------------------------------------------------------------------------- /evil-front-rails/evil-front-rails.gemspec: -------------------------------------------------------------------------------- 1 | require File.expand_path('../lib/evil-front/rails/version', __FILE__) 2 | 3 | Gem::Specification.new do |s| 4 | s.platform = Gem::Platform::RUBY 5 | s.name = 'evil-front-rails' 6 | s.version = EvilFront::Rails::VERSION 7 | s.date = Time.now.strftime('%Y-%m-%d') 8 | s.summary = 'Helpers, Sass mixins, JS shortcuts, workflow and ' + 9 | 'Rails settings from Evil Martians' 10 | 11 | s.author = 'Andrey Sitnik' 12 | s.email = 'andrey@sitnik.ru' 13 | s.homepage = 'https://github.com/ai/evil-front' 14 | s.license = 'MIT' 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.extra_rdoc_files = ['LICENSE'] 18 | s.require_path = 'lib' 19 | 20 | min = EvilFront::Rails::VERSION.split('.')[0..1].concat(['0']).join('.') 21 | s.add_runtime_dependency 'evil-front-all', "~> #{min}" 22 | 23 | s.add_dependency 'rails', '>= 3' 24 | s.add_dependency 'sass-rails', '>= 3.2.6' 25 | s.add_dependency 'slim-rails', '>= 1.1.0' 26 | s.add_dependency 'coffee-rails', '>= 3.2.2' 27 | end 28 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/http.js: -------------------------------------------------------------------------------- 1 | //= require evil-front/core 2 | // Add `evil.patch`, `evil.del`, `evil.put`, `evil.post` to send AJAX request 3 | // with RESTful HTTP verb by Rails X-HTTP-Method-Override header 4 | // and with CSRF token. 5 | 6 | (function($) { 7 | var props = { patch: 'PATCH', put: 'PUT', del: 'DELETE', post: 'POST' } 8 | $.each(props, function(prop, method) { 9 | evil[prop] = function(url, data, callback, type) { 10 | if ($.isFunction(data)) { 11 | type = type || callback; 12 | callback = data; 13 | data = { }; 14 | } 15 | 16 | return $.ajax({ 17 | headers: { 18 | 'X-HTTP-Method-Override': method, 19 | 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') 20 | }, 21 | type: 'POST', 22 | url: url, 23 | data: data, 24 | success: callback, 25 | dataType: type 26 | }); 27 | } 28 | }) 29 | })(jQuery); 30 | -------------------------------------------------------------------------------- /evil-front/evil-front.gemspec: -------------------------------------------------------------------------------- 1 | require File.expand_path('../lib/evil-front/version', __FILE__) 2 | 3 | Gem::Specification.new do |s| 4 | s.platform = Gem::Platform::RUBY 5 | s.name = 'evil-front' 6 | s.version = EvilFront::VERSION 7 | s.date = Time.now.strftime('%Y-%m-%d') 8 | s.summary = 'Helpers, Sass mixins and JS shortcuts from Evil Martians' 9 | 10 | s.author = 'Andrey Sitnik' 11 | s.email = 'andrey@sitnik.ru' 12 | s.homepage = 'https://github.com/ai/evil-front' 13 | s.license = 'MIT' 14 | 15 | s.files = `git ls-files`.split("\n") 16 | s.extra_rdoc_files = ['LICENSE'] 17 | s.require_path = 'lib' 18 | 19 | s.add_dependency 'i18n', '>= 0' 20 | s.add_dependency 'slim', '>= 1.3.9' 21 | s.add_dependency 'sass', '>= 3.2.9' 22 | s.add_dependency 'nokogiri', '>= 1' 23 | s.add_dependency 'sprockets', '>= 1' 24 | s.add_dependency 'unicode_utils', '>= 1.4' 25 | s.add_dependency 'rubypants-unicode', '>= 0' 26 | s.add_dependency 'rails-sass-images', '>= 0.3' 27 | s.add_dependency 'standalone_typograf', '>= 3.0.1' 28 | end 29 | -------------------------------------------------------------------------------- /evil-front-all/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2013 Andrey Sitnik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /evil-front/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2013 Andrey Sitnik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /evil-front-rails/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2013 Andrey Sitnik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /evil-front-rails/lib/evil-front-rails.rb: -------------------------------------------------------------------------------- 1 | require 'evil-front-all' 2 | 3 | require 'sass-rails' 4 | require 'slim-rails' 5 | 6 | module EvilFront 7 | class Railtie < ::Rails::Railtie 8 | initializer 'evil_front.config' do |app| 9 | # Disable assets and helper per controller 10 | app.config.generators.stylesheets = false 11 | app.config.generators.javascripts = false 12 | app.config.generators.helper = false 13 | 14 | # Precompile all JS/CSS in root of app assets dirs. 15 | app.config.assets.precompile += 16 | Dir[::Rails.root.join('app/assets/*/*.{js,css,coffee,sass,scss}*')]. 17 | map { |i| File.basename(i).sub(/(\.js)?\.coffee$/, '.js') }. 18 | map { |i| File.basename(i).sub(/(\.css)?\.(sass|scss)$/, '.css') }. 19 | reject { |i| i =~ /^application\.(js|css)$/ } 20 | 21 | # Sass debug in Chrome 22 | if ::Rails.env.development? 23 | app.config.sass.debug_info = true 24 | end 25 | end 26 | 27 | initializer 'evil_front.action_view' do 28 | ActiveSupport.on_load(:action_view) { include Helpers } 29 | end 30 | end 31 | end 32 | 33 | require_relative 'evil-front/rails/version' 34 | -------------------------------------------------------------------------------- /evil-front-all/evil-front-all.gemspec: -------------------------------------------------------------------------------- 1 | require File.expand_path('../lib/evil-front/all/version', __FILE__) 2 | 3 | Gem::Specification.new do |s| 4 | s.platform = Gem::Platform::RUBY 5 | s.name = 'evil-front-all' 6 | s.version = EvilFront::All::VERSION 7 | s.date = Time.now.strftime('%Y-%m-%d') 8 | s.summary = 'Helpers, Sass mixins, JS shortcuts and workflow ' + 9 | 'from Evil Martians' 10 | 11 | s.author = 'Andrey Sitnik' 12 | s.email = 'andrey@sitnik.ru' 13 | s.homepage = 'https://github.com/ai/evil-front' 14 | s.license = 'MIT' 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.extra_rdoc_files = ['LICENSE'] 18 | s.require_path = 'lib' 19 | 20 | min = EvilFront::All::VERSION.split('.')[0..1].concat(['0']).join('.') 21 | s.add_runtime_dependency 'evil-front', "~> #{min}" 22 | 23 | s.add_dependency 'uglifier', '>= 2.1.1' 24 | s.add_dependency 'sprockets', '>= 1' 25 | s.add_dependency 'jquery-cdn', '>= 1' 26 | s.add_dependency 'coffee-script', '>= 2.2.0' 27 | s.add_dependency 'evil-blocks-rails', '>= 0.2' 28 | s.add_dependency 'autoprefixer-rails', '>= 3.0' 29 | end 30 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/transform3d.js: -------------------------------------------------------------------------------- 1 | //= require evil-front/core 2 | 3 | (function() { 4 | var cache = undefined; 5 | var inited = false; 6 | 7 | evil.transform3d = { 8 | 9 | // Check support for 3D transforms. 10 | check: function () { 11 | if ( typeof(cache) != 'undefined' ) { 12 | return cache; 13 | } 14 | 15 | var cache = typeof(evil.body.css('perspective')) != 'undefined'; 16 | var style = document.body; 17 | if ( cache && typeof(style.webkitPerspective) != 'undefined' ) { 18 | cache = matchMedia("(transform-3d), (-webkit-transform-3d)"); 19 | cache = cache.matches; 20 | } 21 | return cache; 22 | }, 23 | 24 | // Add `transform3d` or `transform2s` class to body. 25 | init: function () { 26 | if ( inited ) { 27 | return; 28 | } 29 | inited = true; 30 | 31 | evil.doc.ready(function () { 32 | var type = evil.transform3d.check() ? '3d' : '2d' 33 | evil.body.addClass('transform-' + type); 34 | }); 35 | } 36 | } 37 | 38 | })(); 39 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/queue.js: -------------------------------------------------------------------------------- 1 | //= evil-front/core 2 | 3 | (function() { 4 | // Call `callback` only after previous callback of `name` queue 5 | // will be finished. It is useful to animation. 6 | // 7 | // b.link.click -> 8 | // evil.queue 'link', (done) -> 9 | // $.get $(@).url, (html) -> 10 | // animation html, -> 11 | // done() 12 | evil.queue = function(name, callback) { 13 | if ( typeof(name) == 'function' ) { 14 | callback = name; 15 | name = 'default'; 16 | } 17 | 18 | if ( typeof(waiters[name]) == 'undefined' ) { 19 | waiting[name] = false; 20 | waiters[name] = []; 21 | } 22 | 23 | if ( waiting[name] ) { 24 | waiters[name].push(callback); 25 | } else { 26 | call(name, callback); 27 | } 28 | }; 29 | 30 | var waiting = { }; 31 | var waiters = { }; 32 | 33 | var call = function(name, callback) { 34 | waiting[name] = true; 35 | callback(function () { 36 | waiting[name] = false; 37 | var waiter = waiters[name].pop(); 38 | if ( waiter ) { 39 | call(name, waiter); 40 | } 41 | }); 42 | }; 43 | })(); 44 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/outside.js: -------------------------------------------------------------------------------- 1 | //= require evil-front/jquery 2 | 3 | (function() { 4 | evil.$.extend('outside', function (callback) { 5 | var parent = this; 6 | 7 | var event = function(e) { 8 | var el = $(e.target); 9 | if ( !el.closest(parent).length ) { 10 | callback(); 11 | off(); 12 | } 13 | }; 14 | 15 | if ( document.body.addEventListener ) { 16 | var set = function () { 17 | document.body.addEventListener('click', event, true); 18 | document.body.addEventListener('focus', event, true); 19 | } 20 | var off = function () { 21 | document.body.removeEventListener('click', event, true); 22 | document.body.removeEventListener('focus', event, true); 23 | }; 24 | 25 | } else { 26 | var name = '.evil-outside-' + (new Date()).valueOf(); 27 | 28 | var set = function () { 29 | evil.body.on('click' + name + ' focus' + name, event); 30 | } 31 | var off = function () { 32 | evil.body.off(name); 33 | }; 34 | } 35 | 36 | setTimeout(set, 10); 37 | return off; 38 | }); 39 | 40 | })(); 41 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | 4 | GEMS = %w(evil-front evil-front-rails evil-front-all) 5 | SPECS = GEMS - ['evil-front-all', 'evil-front-rails'] 6 | 7 | def each_gem(&block) 8 | GEMS.each do |dir| 9 | Dir.chdir(dir, &block) 10 | end 11 | end 12 | 13 | def rake(task) 14 | sh "#{Rake::DSL::RUBY} -S bundle exec rake #{task}", verbose: false 15 | end 16 | 17 | def each_rake(task) 18 | each_gem { rake task } 19 | end 20 | 21 | require 'rspec/core/rake_task' 22 | 23 | class SubgemSpecTask < RSpec::Core::RakeTask 24 | attr_accessor :gem 25 | 26 | def initialize(gem) 27 | @gem = gem 28 | super("spec_#{@gem}") 29 | end 30 | 31 | def desc(text); end # Monkey patch to hide task desc 32 | 33 | def pattern 34 | "#{@gem}/spec{,/*/**}/*_spec.rb" 35 | end 36 | end 37 | 38 | SPECS.each { |gem| SubgemSpecTask.new(gem) } 39 | 40 | desc 'Run all specs' 41 | task :spec => (SPECS.map { |i| "spec_#{i}" }) 42 | task :default => :spec 43 | 44 | 45 | task :build do 46 | each_rake 'build' 47 | end 48 | 49 | desc 'Build gems and push thems to RubyGems' 50 | task :release => [:clobber, :build] do 51 | each_gem { sh 'gem push `ls pkg/*`' } 52 | each_rake 'clobber' 53 | end 54 | 55 | desc 'Remove all generated files' 56 | task :clobber do 57 | rm_r 'log' if File.exists? 'log' 58 | each_rake 'clobber' 59 | end 60 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/jquery.js: -------------------------------------------------------------------------------- 1 | //= require evil-front/core 2 | 3 | (function ($) { 4 | 5 | // Create namespace for jQuery 6 | evil.jquery = function(global, namespace) { 7 | // Namespace inside jQuery. 8 | global.$ = function (nodes) { 9 | this.nodes = nodes; 10 | }; 11 | 12 | // Syntax sugar to add own method to `$.fn.evil`. 13 | global.$.extend = function (name, value) { 14 | if ( $.isPlainObject(name) ) { 15 | for ( key in name ) { 16 | global.$.extend(key, name[key]); 17 | } 18 | return; 19 | } 20 | 21 | if ( $.isFunction(value) ) { 22 | var callback = value; 23 | value = function () { 24 | return callback.apply(this.nodes, arguments); 25 | }; 26 | } 27 | this.prototype[name] = value; 28 | }; 29 | 30 | // Hack to add `$.fn.evil` namespace. 31 | var originaljQuery = $.fn.init; 32 | $.fn.init = function () { 33 | nodes = originaljQuery.apply(this, arguments); 34 | nodes[namespace] = new global.$(nodes); 35 | return nodes; 36 | }; 37 | $.fn.init.prototype = originaljQuery.prototype; 38 | }; 39 | 40 | // Create `evil.$` namespace. 41 | evil.jquery(evil, 'evil'); 42 | 43 | })(jQuery); 44 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/easings.sass: -------------------------------------------------------------------------------- 1 | // Variables with easings Bezier curves 2 | // 3 | // transition: all 1s $easeInOutBack 4 | 5 | $easeInSine: cubic-bezier(0.47, 0, 0.745, 0.715) 6 | $easeOutSine: cubic-bezier(0.39, 0.575, 0.565, 1) 7 | $easeInOutSine: cubic-bezier(0.445, 0.05, 0.55, 0.95) 8 | 9 | $easeInQuad: cubic-bezier(0.55, 0.085, 0.68, 0.53) 10 | $easeOutQuad: cubic-bezier(0.25, 0.46, 0.45, 0.94) 11 | $easeInOutQuad: cubic-bezier(0.455, 0.03, 0.515, 0.955) 12 | 13 | $easeInCubic: cubic-bezier(0.55, 0.055, 0.675, 0.19) 14 | $easeOutCubic: cubic-bezier(0.215, 0.61, 0.355, 1) 15 | $easeInOutCubic: cubic-bezier(0.645, 0.045, 0.355, 1) 16 | 17 | $easeInQuart: cubic-bezier(0.895, 0.03, 0.685, 0.22) 18 | $easeOutQuart: cubic-bezier(0.165, 0.84, 0.44, 1) 19 | $easeInOutQuart: cubic-bezier(0.77, 0, 0.175, 1) 20 | 21 | $easeInQuint: cubic-bezier(0.755, 0.05, 0.855, 0.06) 22 | $easeOutQuint: cubic-bezier(0.23, 1, 0.32, 1) 23 | $easeInOutQuint: cubic-bezier(0.86, 0, 0.07, 1) 24 | 25 | $easeInExpo: cubic-bezier(0.95, 0.05, 0.795, 0.035) 26 | $easeOutExpo: cubic-bezier(0.19, 1, 0.22, 1) 27 | $easeInOutExpo: cubic-bezier(1, 0, 0, 1) 28 | 29 | $easeInCirc: cubic-bezier(0.6, 0.04, 0.98, 0.335) 30 | $easeOutCirc: cubic-bezier(0.075, 0.82, 0.165, 1) 31 | $easeInOutCirc: cubic-bezier(0.785, 0.135, 0.15, 0.86) 32 | 33 | $easeInBack: cubic-bezier(0.6, -0.28, 0.735, 0.045) 34 | $easeOutBack: cubic-bezier(0.175, 0.885, 0.32, 1.275) 35 | $easeInOutBack: cubic-bezier(0.68, -0.55, 0.265, 1.55) 36 | -------------------------------------------------------------------------------- /evil-front/ChangeLog.md: -------------------------------------------------------------------------------- 1 | ## 0.5.1 2 | 3 | * Fix `evil.body` initializing (by Vladimir Dementyev). 4 | 5 | ## 0.5 “Chryse Planitia” 6 | 7 | * Remove `clean-css`. 8 | 9 | ## 0.4 “Schiaparelli Crater” 10 | 11 | * Add Sprockets 3 support. 12 | 13 | ## 0.3.10 14 | 15 | * Add Slim 3.0 support. 16 | 17 | ## 0.3.9 18 | 19 | * Fix typograph on new line before m-dash. 20 | 21 | ## 0.3.8 22 | 23 | * Import all inner dependenies in mixins to import only necessary mixin. 24 | 25 | ## 0.3.7 26 | 27 | * Use non-break dash only in Russian words. 28 | 29 | ## 0.3.6 30 | 31 | * Russian typograph inserts non-break space before m-dash. 32 | 33 | ## 0.3.5 34 | 35 | * `$.fn.evil.ajax` and `$.fn.evil.tappable` return element’s jQuery node 36 | to be used in chains. 37 | 38 | ## 0.3.4 39 | 40 | * Add `no_site` option to `title` helper. 41 | * Better `+stroke-text` by Vadim Sikora. 42 | 43 | ## 0.3.3 44 | 45 | * Fix `+hover` mixin loading. 46 | 47 | ## 0.3.2 48 | 49 | * Add `+hover` Sass mixin. 50 | 51 | ## 0.3.1 52 | 53 | * Add labels to tappable by default. 54 | 55 | ## 0.3 “Samara Vallis” 56 | 57 | * Russian typograph doesn’t insert flying quotes tag anymore. 58 | * Add separated `auto_flying_quotes` helper. 59 | 60 | ## 0.2.1 61 | 62 | * Fix encoding issue with Nokogiri in `english_typograph`. 63 | 64 | ## 0.2 “Ptolemaeus Crater” 65 | 66 | * Add `english_typograph` helper. 67 | * Add `typograph_by_locale` helper to use typographer for current I18n locale. 68 | * Increase `russian_typograph` speed. 69 | * Increase `evil-front/links.js` speed. 70 | 71 | ## 0.1 “Hellespontus Montes” 72 | 73 | * Initial release. 74 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/tappable.js: -------------------------------------------------------------------------------- 1 | //= require evil-front/jquery 2 | 3 | // Add events to add special class on touch events. It will much faster, than 4 | // `:hover` selector. It returns jQuery node of element for chains. 5 | // 6 | // By default it add listener to all links and inputs on body. 7 | // But you can add it to any elements: 8 | // 9 | // $('.pseudolink').evil.tappable(); 10 | // 11 | // Or you can set listeners as “live” delegate: 12 | // 13 | // $('.ajax-updated').evil.tappable('.pseudolink'); 14 | // 15 | // Don’t forget about `no-hover` and `styled-taps` Sass mixins. 16 | (function () { 17 | var start = function () { 18 | this.classList.add('is-tapped'); 19 | }; 20 | var end = function () { 21 | var link = $(this); 22 | setTimeout(function () { 23 | link.removeClass('is-tapped'). 24 | addClass('was-tapped'). 25 | one('mouseenter', function () { 26 | link.removeClass('was-tapped'); 27 | }); 28 | }, 100); 29 | }; 30 | 31 | evil.$.extend({ 32 | tappable: function (selector) { 33 | if ( selector ) { 34 | this.on('touchstart', selector, start); 35 | this.on('touchend touchmove', selector, end); 36 | } else { 37 | this.on('touchstart', start); 38 | this.on('touchend touchmove', end); 39 | } 40 | return this; 41 | } 42 | }); 43 | 44 | evil.doc.ready(function ($) { 45 | evil.body.evil.tappable('a, input, label'); 46 | }); 47 | })(); 48 | -------------------------------------------------------------------------------- /evil-front/lib/assets/stylesheets/evil-front/import-ruble.sass: -------------------------------------------------------------------------------- 1 | // Define special class and fonts for Russian currency symbol. 2 | // 3 | // You must set you body fonts for `$defaults` argument. Also you can inline 4 | // in `data:uri` fonts styles, which you will use. 5 | // 6 | // +import-ruble("PT Sans, sans-serif", $regular: inline) 7 | @mixin import-ruble($defaults: sans-serif, $regular: false, $italic: false, $bold: false, $bolditalic: false) 8 | @font-face 9 | font-family: 'ALSRubl-Arial' 10 | @if $regular 11 | src: inline("evil-front/alsrubl-arial-regular.woff") format("woff") 12 | @else 13 | src: font-url("evil-front/alsrubl-arial-regular.woff") format("woff") 14 | 15 | @font-face 16 | font-family: 'ALSRubl-Arial' 17 | font-style: italic 18 | @if $italic 19 | src: inline("evil-front/alsrubl-arial-italic.woff") format("woff") 20 | @else 21 | src: font-url("evil-front/alsrubl-arial-italic.woff") format("woff") 22 | 23 | @font-face 24 | font-family: 'ALSRubl-Arial' 25 | font-weight: bold 26 | @if $bold 27 | src: inline("evil-front/alsrubl-arial-bold.woff") format("woff") 28 | @else 29 | src: font-url("evil-front/alsrubl-arial-bold.woff") format("woff") 30 | 31 | @font-face 32 | font-family: 'ALSRubl-Arial' 33 | font-style: italic 34 | font-weight: bold 35 | @if $bolditalic 36 | src: inline("evil-front/alsrubl-arial-bolditalic.woff") format("woff") 37 | @else 38 | src: font-url("evil-front/alsrubl-arial-bolditalic.woff") format("woff") 39 | 40 | .ruble 41 | font-family: ALSRubl-Arial, unquote($defaults) 42 | line-height: 1 43 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/typograph.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'nokogiri' 4 | 5 | module EvilFront 6 | # Abstract module to be used in `Russian` and `English` typographs. 7 | module Typograph 8 | # Like `typograph`, but process only text nodes in HTML. 9 | # 10 | # EvilFront::Russian.typograph_html(article.html) 11 | def typograph_html(html) 12 | process_html(html) { |text| typograph(text) } 13 | end 14 | 15 | # Insert non-break spaces and mark quotes to have nice text. 16 | # 17 | # EvilFront::Russian.typograph(article) 18 | def typograph(text) 19 | return text if text.nil? or text.empty? 20 | 21 | text.gsub! '"', '"' 22 | text = use_right_symbols(text) 23 | tiny_words.each { |regexp| text.gsub! regexp, "\\1\\2 " } 24 | 25 | text 26 | end 27 | 28 | private 29 | 30 | # Parse HTML and run block only on texts 31 | def process_html(html, &block) 32 | return html if html.nil? or html.empty? 33 | 34 | if html.include? '<' 35 | nodes = Nokogiri::HTML::DocumentFragment.parse(html, 'utf-8') 36 | process_node!(nodes, &block) 37 | nodes.to_html 38 | else 39 | yield(html) 40 | end 41 | end 42 | 43 | # Run block on every text node recursively 44 | def process_node!(node, &block) 45 | return if %w(pre code kbd script style math).include? node.name 46 | 47 | node.children.each do |child| 48 | if child.is_a? Nokogiri::XML::Text 49 | text = EvilFront.escape(child.content) 50 | child.replace( yield(text) ) 51 | else 52 | process_node! child, &block 53 | end 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /evil-front/lib/assets/javascripts/evil-front/ajax.js: -------------------------------------------------------------------------------- 1 | //= evil-front/jquery 2 | 3 | // Change selected form to be sent by AJAX. 4 | // It returns jQuery node of form for chains. 5 | // 6 | // $('form').evil.ajax 7 | // success: -> message('success') 8 | // error: (text) -> message('error' + text) 9 | // 10 | // While AJAX is loading, form will has `is-submitting` class. 11 | // Don’t forget to show loader. 12 | evil.$.extend('ajax', function (opts) { 13 | if ( !opts ) { 14 | opts = { }; 15 | } 16 | 17 | return this.submit(function (event) { 18 | if ( event.isPropagationStopped() ) { 19 | return false; 20 | } 21 | 22 | var form = $(this); 23 | 24 | if ( form.hasClass('is-submitting') ) { 25 | return false; 26 | } 27 | form.addClass('is-submitting'); 28 | 29 | var check = true; 30 | if ( opts.submitting ) { 31 | check = opts.submitting(form); 32 | } 33 | if ( !check ) { 34 | return false; 35 | } 36 | 37 | $.ajax({ 38 | url: form.attr('action'), 39 | type: form.attr('method').toUpperCase(), 40 | data: form.serialize(), 41 | success: function (data) { 42 | if ( opts.success ) { 43 | opts.success(data, form); 44 | } 45 | }, 46 | error: function (e) { 47 | if ( e.status == 500 ) { 48 | if ( opts.serverError ) { 49 | opts.serverError(form); 50 | } 51 | } else if ( opts.error ) { 52 | opts.error(e.responseText, form); 53 | } 54 | }, 55 | complete: function () { 56 | form.removeClass('is-submitting'); 57 | } 58 | }); 59 | 60 | return false; 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /evil-front/lib/evil-front/russian.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'unicode_utils' 4 | # encoding: utf-8 5 | 6 | require 'standalone_typograf' 7 | 8 | module EvilFront 9 | # Helpers to work with Russian text. 10 | module Russian 11 | extend Typograph 12 | 13 | # Capitalize only first letter (like titles in Russian). 14 | # 15 | # = EvilFront::Russian.capitalize_first(title) 16 | def self.capitalize_first(text) 17 | UnicodeUtils.upcase(text[0]) + text[1..-1] 18 | end 19 | 20 | # Find quotes in text and make them flying 21 | def self.auto_flying_quotes(html) 22 | process_html(html) do |text| 23 | text.gsub(/\s«[^»]+»/) { |i| flying_quotes i[2..-2], space: i[0] }. 24 | gsub(/^«[^»]+»/) { |i| flying_quotes i[1..-2], space: '' } 25 | end 26 | end 27 | 28 | # Mark quotes to move first quote before the text line. 29 | def self.flying_quotes(text, options = { }) 30 | sp = options[:space] || ' ' 31 | sp = "#{sp}" if sp != '' 32 | "#{ sp }«#{ text }»" 33 | end 34 | 35 | private 36 | 37 | # Small words to insert non-break space before them 38 | def self.tiny_words 39 | @tiny_words ||= begin 40 | tiny = %w(ни не и но а или да как из-за про по за для 41 | на до при меж о у в во с со от ото из без 42 | безо к ко об обо под подо над перед передо это) 43 | tiny += tiny.map { |i| capitalize_first(i) } 44 | tiny.map { |i| Regexp.new("( | )(#{Regexp.quote i}) ") } 45 | end 46 | end 47 | 48 | # Replace symbols to right ones, like m-dash, quotes, etc. 49 | def self.use_right_symbols(text) 50 | StandaloneTypograf::Typograf.new(text) 51 | .processor(:dashes, :quotes, :mnemonics, :fractions, :ellipsis) 52 | .gsub(' —', ' —') # nbsp before m-dash 53 | .gsub(/([а-яА-Я])-([а-яА-Я])/, '\1‑\2') # non-break dash 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /evil-front/spec/sass_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative 'spec_helper' 2 | 3 | describe 'Sass Helpers' do 4 | before(:all) do 5 | @assets = Sprockets::Environment.new 6 | @assets.append_path File.expand_path('../sass', __FILE__) 7 | EvilFront.install(@assets) 8 | 9 | @assets.context_class.class_eval do 10 | def asset_path(path, options = {}) 11 | '' 12 | end 13 | end 14 | end 15 | 16 | it 'loads Rails Sass Images' do 17 | expect(@assets['load'].to_s).to match(/data:text\/plain/) 18 | end 19 | 20 | it 'loads variables, functions and mixins' do 21 | load = @assets['load'].to_s 22 | expect(load).to match(/rgba\(0, 0, 0, 0.5\)/) 23 | expect(load).to match(/cubic-bezier\(0.47, 0, 0.745, 0.715\)/) 24 | expect(load).to match(/a:after/) 25 | end 26 | 27 | describe '+import-ruble' do 28 | 29 | it 'adds font-faces and .ruble' do 30 | ruble = @assets['ruble'].to_s 31 | expect(ruble).to match(/font-family: ALSRubl-Arial, PT Sans, sans-serif/) 32 | expect(ruble).not_to match(/font-woff;base64/) 33 | end 34 | 35 | it 'inlines specified fonts' do 36 | ruble = @assets['inline-ruble'].to_s 37 | expect(ruble).to match(/font-style: italic;\s*src: url\('data/n) 38 | end 39 | 40 | end 41 | 42 | describe 'media mixins' do 43 | before(:all) do 44 | @media = @assets['media'].to_s 45 | end 46 | 47 | it 'receives size without units' do 48 | expect(@media).to match(/max-width: 100px/) 49 | end 50 | 51 | it 'receives size with units' do 52 | expect(@media).to match(/min-width: 200px/) 53 | end 54 | 55 | end 56 | 57 | describe '+size' do 58 | before(:all) do 59 | @size = @assets['size'].to_s 60 | end 61 | 62 | it 'receives 2 sizes' do 63 | expect(@size).to match(/.all {\s*width: 10px;\s*height: 20px; }/) 64 | end 65 | 66 | it 'receives 1 sizes' do 67 | expect(@size).to match(/.one {\s*width: 30px;\s*height: 30px; }/) 68 | end 69 | 70 | it 'receives size without unit' do 71 | expect(@size).to match(/.no-unit {\s*width: 15px;\s*height: 15px; }/) 72 | end 73 | 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /evil-front/spec/russian_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require_relative 'spec_helper' 4 | 5 | describe EvilFront::Russian do 6 | 7 | describe 'capitalize_first' do 8 | 9 | it 'capitalizes first letter in russian text' do 10 | expect(EvilFront::Russian.capitalize_first('тест тест')).to eq 'Тест тест' 11 | end 12 | 13 | end 14 | 15 | describe 'flying_quotes' do 16 | 17 | it 'inserts tags and quotes with space by default' do 18 | expect(EvilFront::Russian.flying_quotes('тест')).to eq( 19 | ' ' + 20 | '«тест»') 21 | end 22 | 23 | it 'inserts specified space' do 24 | expect(EvilFront::Russian.flying_quotes('тест', space: '-')).to eq( 25 | '-' + 26 | '«тест»') 27 | end 28 | 29 | it 'ignores space on request' do 30 | expect(EvilFront::Russian.flying_quotes('тест', space: '')).to eq( 31 | '«тест»') 32 | end 33 | 34 | end 35 | 36 | describe 'auto_flying_quotes' do 37 | 38 | it 'replaces quotes on start' do 39 | expect(EvilFront::Russian.auto_flying_quotes('«тест»')).to eq( 40 | '«тест»') 41 | end 42 | 43 | it 'replaces quotes in middle' do 44 | expect(EvilFront::Russian.auto_flying_quotes('на «тесте».')).to eq( 45 | 'на ' + 46 | '«тесте».') 47 | end 48 | 49 | it 'works with HTML' do 50 | expect(EvilFront::Russian.auto_flying_quotes('«ссылка»')).to eq( 51 | '«ссылка»') 52 | end 53 | 54 | end 55 | 56 | describe 'typograph' do 57 | def nbsp_mark_typograph(str) 58 | EvilFront::Russian.typograph(str).gsub(' ', '_') 59 | end 60 | 61 | it 'changes quotes' do 62 | expect(nbsp_mark_typograph('сказал "смотри "зорко"".')).to eq( 63 | 'сказал «смотри „зорко“».') 64 | end 65 | 66 | it 'changes dashes' do 67 | expect(nbsp_mark_typograph('а - это б')).to eq 'а_— это_б' 68 | end 69 | 70 | it 'changes ellipsis' do 71 | expect(nbsp_mark_typograph('а...')).to eq 'а…' 72 | end 73 | 74 | it 'keeps new line before dash' do 75 | expect(nbsp_mark_typograph("- Что?\n- То!")).to eq "— Что?\n— То!" 76 | end 77 | 78 | it 'uses non-break dash on for Russian' do 79 | expect(nbsp_mark_typograph('web-standards.ru')).to eq 'web-standards.ru' 80 | expect(nbsp_mark_typograph('а-то')).to eq 'а‑то' 81 | end 82 | 83 | end 84 | 85 | describe 'typograph_html' do 86 | 87 | it 'typographs plain text' do 88 | expect(EvilFront::Russian.typograph_html('а...')).to eq 'а…' 89 | end 90 | 91 | it 'typographs only in text nodes' do 92 | expect(EvilFront::Russian.typograph_html('а...')). 93 | to eq 'а…' 94 | end 95 | 96 | it 'ignores code tags' do 97 | expect(EvilFront::Russian.typograph_html('а...')). 98 | to eq 'а...' 99 | end 100 | 101 | it 'keeps escaping' do 102 | expect(EvilFront::Russian.typograph_html('<a>')). 103 | to eq '<a>' 104 | end 105 | 106 | end 107 | 108 | end 109 | -------------------------------------------------------------------------------- /evil-front/spec/helpers_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require_relative 'spec_helper' 4 | require 'slim' 5 | 6 | describe EvilFront::Helpers do 7 | include EvilFront::Helpers 8 | 9 | describe 'capitalize_first' do 10 | 11 | it 'capitalizes Russian' do 12 | expect(capitalize_first('тест')).to eq 'Тест' 13 | end 14 | 15 | end 16 | 17 | describe 'disable_mobile_zoom' do 18 | 19 | it 'returns viewport meta tag' do 20 | expect(disable_mobile_zoom).to match(/^ ' + 30 | '«a»') 31 | end 32 | 33 | it 'escapes HTML' do 34 | expect(flying_quotes('
')).to eq( 35 | ' ' + 36 | '«<br>»') 37 | end 38 | 39 | end 40 | 41 | describe 'auto_flying_quotes' do 42 | 43 | it 'set quotes to text' do 44 | expect(auto_flying_quotes('от «a»')).to eq( 45 | 'от ' + 46 | '«a»') 47 | end 48 | 49 | it 'escapes HTML' do 50 | expect(auto_flying_quotes('от «
»')).to eq( 51 | 'от ' + 52 | '«<br>»') 53 | end 54 | 55 | end 56 | 57 | describe 'ruble' do 58 | 59 | it 'returns span' do 60 | expect(ruble).to be_a(String) 61 | end 62 | 63 | end 64 | 65 | describe 'russian_typograph' do 66 | 67 | it 'typographs text inside tags' do 68 | tag = 'а...'.html_safe 69 | expect(russian_typograph(tag)).to eq'а…' 70 | end 71 | 72 | it 'escapes HTML' do 73 | expect(russian_typograph('')).to eq '<a>' 74 | end 75 | 76 | end 77 | 78 | describe 'english_typograph' do 79 | 80 | it 'typographs text inside tags' do 81 | tag = 'a...'.html_safe 82 | expect(english_typograph(tag)).to eq 'a…' 83 | end 84 | 85 | it 'escapes HTML' do 86 | expect(english_typograph('')).to eq '<a>' 87 | end 88 | 89 | end 90 | 91 | describe 'typograph_by_locale' do 92 | after do 93 | I18n.locale = :en 94 | end 95 | 96 | it 'typographs by current locale' do 97 | I18n.locale = :en 98 | expect(typograph_by_locale('"a"')).to eq '“a”' 99 | 100 | I18n.locale = :ru 101 | expect(typograph_by_locale('"a"')).to eq '«a»' 102 | end 103 | 104 | it 'returns origin text on unknown locale' do 105 | I18n.locale = :fr 106 | expect(typograph_by_locale('"a"')).to eq '"a"' 107 | end 108 | 109 | end 110 | 111 | describe 'title' do 112 | after do 113 | I18n.locale = :en 114 | @evil_front_titles = nil 115 | end 116 | 117 | it 'shows site name' do 118 | expect(title_tag('Site')).to eq 'Site' 119 | end 120 | 121 | it 'shows site names' do 122 | expect(title_tag('One', 'Two')).to eq 'One - Two' 123 | end 124 | 125 | it 'shows page name' do 126 | title 'Page', 'Section' 127 | expect(title_tag('Site')).to eq 'Page - Section - Site' 128 | end 129 | 130 | it 'shows Russian separator' do 131 | I18n.locale = :ru 132 | title 'Страница', 'Раздел' 133 | expect(title_tag('Сайт')).to eq 'Страница — Раздел — Сайт' 134 | end 135 | 136 | it 'shows custom separator' do 137 | title 'One', 'Two' 138 | expect(title_tag(separator: ' | ')).to eq 'One | Two' 139 | end 140 | 141 | it 'escapes HTML' do 142 | title '' 143 | expect(title_tag).to eq '<B>' 144 | end 145 | 146 | it 'hides site name on request' do 147 | title 'Page', no_site: true 148 | expect(title_tag('Site')).to eq 'Page' 149 | end 150 | 151 | end 152 | 153 | end 154 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Evil Front [![Build Status](https://travis-ci.org/ai/evil-front.svg)](https://travis-ci.org/ai/evil-front) 2 | 3 | Helpers, shortcuts and my common frontend workflows 4 | from [Evil Martians](http://evilmartians.com/). 5 | 6 | The project is separated into 3 gems: 7 | * [Evil Front](evil-front/) only contains helpers and doesn’t change 8 | the application environment. 9 | * [Evil Front All](evil-front-all/) loads the workflow gems: Autoprefixer, Csso, 10 | Slim, JqueryCdn, Evil Blocks, Uglifier. 11 | * [Evil Front Rails](evil-front-rails/) loads the workflow gems and changes\ 12 | Rails settings to create my common frontend workflow 13 | with a single line of code. 14 | 15 | You can safely use Evil Front Core, but the other two gems have side effects, 16 | so I recommend to only use them for new projects. 17 | 18 | Some of the view helpers from Evil Front Core may require Rails, but most of them 19 | work with any Ruby application. 20 | 21 | 22 | Sponsored by Evil Martians 23 | 24 | 25 | ## Helpers 26 | 27 | The Evil Front Core gem contains assets and view helpers: 28 | 29 | ### View Helpers 30 | 31 | #### Typography 32 | 33 | * [russian_typograph](evil-front/lib/evil-front/helpers/russian_typograph.rb) 34 | to add typographical symbols (like Russian quotes, em-dash), 35 | non-breaking spaces. 36 | * [english_typograph](evil-front/lib/evil-front/helpers/english_typograph.rb) 37 | to add typographical symbols (like quotes, ellipsis), non-breaking spaces. 38 | * [typograph_by_locale](evil-front/lib/evil-front/helpers/typograph_by_locale.rb) 39 | uses `russian_typograph` or `english_typograph` depend on current locale. 40 | * [auto_flying_quotes](evil-front/lib/evil-front/helpers/auto_flying_quotes.rb) 41 | add tags to quotes to move it from text left horizontal line. 42 | * [ruble](evil-front/lib/evil-front/helpers/ruble.rb) to insert the Russian 43 | currency character. 44 | * [capitalize_first](evil-front/lib/evil-front/helpers/capitalize_first.rb) 45 | to capitalize only first letter. 46 | 47 | #### Head Tags 48 | 49 | * [title](evil-front/lib/evil-front/helpers/title.rb) to set page title 50 | in view file and [title_tag](evil-front/lib/evil-front/helpers/title_tag.rb) 51 | to use title from view in layout. 52 | * [standard_assets](evil-front/lib/evil-front/helpers/standard_assets.rb) 53 | shortcut to add `application.css`, jQuery from CDN and `application.js`. 54 | * [head_content](evil-front/lib/evil-front/helpers/head_content.rb) 55 | to add some tags to head from view and 56 | [head_tag](evil-front/lib/evil-front/helpers/head_tag.rb) to use views 57 | head tags in layout. 58 | * [disable_mobile_zoom](evil-front/lib/evil-front/helpers/disable_mobile_zoom.rb) 59 | shortcut for common viewport usage. 60 | 61 | #### Other 62 | 63 | * [tel](evil-front/lib/evil-front/helpers/tel.rb) to insert phone numbers as 64 | links with the `tel:` protocol. 65 | 66 | ### Sass Helpers 67 | 68 | * `black(alpha)` and `white(alpha)` shortcut 69 | [functions](evil-front/lib/assets/stylesheets/evil-front/colors.sass). 70 | * [+import-ruble](evil-front/lib/assets/stylesheets/evil-front/import-ruble.sass) 71 | mixin to enable `ruble` helper. 72 | * [+flying-quotes](evil-front/lib/assets/stylesheets/evil-front/flying-quotes.sass) 73 | mixin to enable `auto_flying_quotes` helper. 74 | * [+no-hover](evil-front/lib/assets/stylesheets/evil-front/no-hover.sass), 75 | [+hover](evil-front/lib/assets/stylesheets/evil-front/hover.sass) and 76 | [+styled-taps](evil-front/lib/assets/stylesheets/evil-front/styled-taps.sass) 77 | mixin to work with hover/tap styles on touch devices. 78 | * [Variables](evil-front/lib/assets/stylesheets/evil-front/easings.sass) 79 | with [easings](http://easings.net/). 80 | * CSS Media Queries 81 | [shortcuts](evil-front/lib/assets/stylesheets/evil-front/media.sass). 82 | * [+stroke-text(color)](evil-front/lib/assets/stylesheets/evil-front/stroke-text.sass) 83 | shortuct to add text shadow for every side of text. 84 | * [+height(size)](evil-front/lib/assets/stylesheets/evil-front/height.sass) 85 | shortcut to set `height` and `line-height` properties. 86 | * [+size(width, height)](evil-front/lib/assets/stylesheets/evil-front/size.sass) 87 | shortcut. 88 | * Compact and nice 89 | [+sticky-footer](evil-front/lib/assets/stylesheets/evil-front/sticky-footer.sass) 90 | mixin. 91 | * [+clearfix](evil-front/lib/assets/stylesheets/evil-front/clearfix.sass) 92 | by `::after` with `clear: both`. 93 | 94 | ### JS Helpers 95 | 96 | * [after(ms, callback)](evil-front/lib/assets/javascripts/evil-front/after.js) 97 | and 98 | [every(ms, callback)](evil-front/lib/assets/javascripts/evil-front/every.js) 99 | syntax sugar to clean up `setTimeout` and `setInterval` in CoffeeScript. 100 | * [Script](evil-front/lib/assets/javascripts/evil-front/links.js) to prevent 101 | default behavior for AJAX links with `href="#"` to clean event listeners from 102 | noisy `return false`. 103 | * [$.fn.evil.outside](evil-front/lib/assets/javascripts/evil-front/outside.js) 104 | to listen click outside element. 105 | * [$.fn.evil.ajax(opts)](evil-front/lib/assets/javascripts/evil-front/ajax.js) 106 | to create AJAX forms. 107 | * [evil.queue(name, callback)](evil-front/lib/assets/javascripts/evil-front/queue.js) 108 | to synchronizate animations. 109 | * [Script](evil-front/lib/assets/javascripts/evil-front/tappable.js) 110 | to enable tapped styles for touch devices. 111 | * [Script](evil-front/lib/assets/javascripts/evil-front/detect-3d.js) 112 | to detect 3D support. 113 | * `evil.post`, `evil.del` and `evil.put` 114 | [shortcuts](evil-front/lib/assets/javascripts/evil-front/http.js). 115 | * `evil.win`, `evil.body` and `evil.doc` 116 | [shortcuts](evil-front/lib/assets/javascripts/evil-front/core.js). 117 | 118 | ## Workflow 119 | 120 | The Evil Front All gem loads my must-have tools: 121 | 122 | * [Sass](http://sass-lang.com/) to write pretty styles. 123 | * [Slim](http://slim-lang.com/) to write pretty views. 124 | * [CoffeeScript](http://coffeescript.org/) to write pretty scripts. 125 | * [Uglifier](https://github.com/lautis/uglifier) to compress JS. 126 | * [CSSO](http://bem.info/tools/csso/) to compress CSS. 127 | * [Sprockets](https://github.com/sstephenson/sprockets) to work with assets 128 | in best way. 129 | * [jQueryCDN](https://github.com/ai/jquery-cdn) to load latest jQuery 130 | in best way. 131 | * [Autoprefixer](https://github.com/ai/autoprefixer) to add CSS3 prefixes. 132 | * [Rails Sass Images](https://github.com/ai/rails-sass-images) to inline images 133 | and get their sizes from Sass. 134 | * [Evil Blocks](https://github.com/ai/evil-blocks) to manage your scripts. 135 | 136 | ## Rails Settings 137 | 138 | The Evil Front Rails gem changes default Rails settings: 139 | 140 | * **Autoprecompile** adds all files in root of `app/assets/stylesheets` 141 | and `app/assets/javascripts` to precompile. You should only store loadable 142 | files in subdirs. 143 | * **Disable assets generation** on controller and action generation. 144 | --------------------------------------------------------------------------------