├── .gitignore
├── Gemfile
├── Gemfile.lock
├── README.md
├── Rakefile
├── common
├── _statistics.html
├── fonts.sass
├── layout.slim
├── script.coffee
└── style.sass
├── covers
├── ask.jpg
├── postcss.jpg
├── practice.jpg
├── present.jpg
├── problem.jpg
├── sass.jpg
└── use.jpg
├── images
├── alistapart.png
├── amplifr.png
├── attacks.jpg
├── autoprefixer.svg
├── benfrain.jpg
├── colorbad.jpg
├── colorgood.jpg
├── ebay.svg
├── evolution.jpg
├── google.svg
├── groupon.svg
├── hewiki.jpg
├── logo.svg
├── markotto.jpg
├── martians.svg
├── russia.jpg
├── taobao.svg
├── tj.jpg
├── twitter.svg
├── wordpress.svg
└── yandex.svg
├── postcss.en.md
├── postcss.ru.md
├── postcss.sass
├── postcss_highlighter.rb
└── speech.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle/
2 | build/
3 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | source 'https://rails-assets.org'
3 |
4 | gem 'rake'
5 | gem 'sinatra'
6 | gem 'redcarpet'
7 | gem 'compass-core'
8 | gem 'therubyracer'
9 | gem 'activesupport'
10 | gem 'jquery-cdn', '>= 2.1.3'
11 | gem 'evil-front-all', '>= 0.3.1'
12 | gem 'term-ansicolor'
13 | gem 'autoprefixer-rails'
14 |
15 | gem 'rails-assets-shower-core'
16 | gem 'rails-assets-shower-bright'
17 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | remote: https://rails-assets.org/
4 | specs:
5 | activesupport (4.2.4)
6 | i18n (~> 0.7)
7 | json (~> 1.7, >= 1.7.7)
8 | minitest (~> 5.1)
9 | thread_safe (~> 0.3, >= 0.3.4)
10 | tzinfo (~> 1.1)
11 | autoprefixer-rails (5.2.1.3)
12 | execjs
13 | json
14 | coffee-script (2.4.1)
15 | coffee-script-source
16 | execjs
17 | coffee-script-source (1.9.1.1)
18 | compass-core (1.0.3)
19 | multi_json (~> 1.0)
20 | sass (>= 3.3.0, < 3.5)
21 | csso-rails (0.3.4)
22 | execjs (>= 1)
23 | dimensions (1.3.0)
24 | evil-blocks-rails (0.6.3)
25 | sprockets (>= 2)
26 | evil-front (0.3.10)
27 | i18n
28 | nokogiri (>= 1)
29 | rails-sass-images (>= 0.3)
30 | rubypants-unicode
31 | sass (>= 3.2.9)
32 | slim (>= 1.3.9)
33 | sprockets (>= 1)
34 | standalone_typograf (>= 3.0.1)
35 | unicode_utils (>= 1.4)
36 | evil-front-all (0.3.1)
37 | autoprefixer-rails (>= 3.0)
38 | coffee-script (>= 2.2.0)
39 | csso-rails (>= 0.3)
40 | evil-blocks-rails (>= 0.2)
41 | evil-front (~> 0.3.0)
42 | jquery-cdn (>= 1)
43 | sprockets (>= 1)
44 | uglifier (>= 2.1.1)
45 | execjs (2.6.0)
46 | i18n (0.7.0)
47 | jquery-cdn (2.1.4)
48 | sprockets (>= 2)
49 | json (1.8.3)
50 | libv8 (3.16.14.11)
51 | mime-types (2.6.1)
52 | mini_portile (0.6.2)
53 | minitest (5.8.0)
54 | multi_json (1.11.2)
55 | nokogiri (1.6.6.2)
56 | mini_portile (~> 0.6.0)
57 | rack (1.6.4)
58 | rack-protection (1.5.3)
59 | rack
60 | rails-assets-shower-bright (1.0.11)
61 | rails-assets-shower-core (1.0.7)
62 | rails-sass-images (0.5)
63 | dimensions (> 0)
64 | mime-types (> 0)
65 | sass (> 0)
66 | rake (10.4.2)
67 | redcarpet (3.3.2)
68 | ref (2.0.0)
69 | rubypants-unicode (0.2.5)
70 | sass (3.4.18)
71 | sinatra (1.4.6)
72 | rack (~> 1.4)
73 | rack-protection (~> 1.4)
74 | tilt (>= 1.3, < 3)
75 | slim (3.0.6)
76 | temple (~> 0.7.3)
77 | tilt (>= 1.3.3, < 2.1)
78 | sprockets (3.3.3)
79 | rack (~> 1.0)
80 | standalone_typograf (3.0.2)
81 | activesupport
82 | temple (0.7.6)
83 | term-ansicolor (1.3.2)
84 | tins (~> 1.0)
85 | therubyracer (0.12.2)
86 | libv8 (~> 3.16.14.0)
87 | ref
88 | thread_safe (0.3.5)
89 | tilt (2.0.1)
90 | tins (1.6.0)
91 | tzinfo (1.2.2)
92 | thread_safe (~> 0.1)
93 | uglifier (2.7.2)
94 | execjs (>= 0.3.0)
95 | json (>= 1.8.0)
96 | unicode_utils (1.4.0)
97 |
98 | PLATFORMS
99 | ruby
100 |
101 | DEPENDENCIES
102 | activesupport
103 | autoprefixer-rails
104 | compass-core
105 | evil-front-all (>= 0.3.1)
106 | jquery-cdn (>= 2.1.3)
107 | rails-assets-shower-bright
108 | rails-assets-shower-core
109 | rake
110 | redcarpet
111 | sinatra
112 | term-ansicolor
113 | therubyracer
114 |
115 | BUNDLED WITH
116 | 1.10.3
117 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Keynotes about PostCSS
2 |
3 | For my talks on [SPB Frontend](https://vk.com/spb_frontend),
4 | [WSD in Kiev](http://webstandardsdays.ru/2014/12/06/),
5 | [Stachka in Ulyanovsk](http://nastachku.ru/),
6 | [Frontend.fi in Helsinki](http://frontend.fi/april-meetup-2015/)
7 | and [CSSConf](https://2015.cssconf.com).
8 |
9 | * Russian: [ai.github.io/about-postcss](http://ai.github.io/about-postcss/).
10 | * English: [ai.github.io/about-postcss/en](http://ai.github.io/about-postcss/en).
11 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'pathname'
2 | require 'base64'
3 |
4 | ROOT = Pathname(__FILE__).dirname
5 | COMMON = ROOT.join('common')
6 |
7 | require 'redcarpet'
8 | require 'evil-front-all'
9 | require 'active_support'
10 | require 'active_support/core_ext'
11 | require 'rails-assets-shower-core'
12 | require 'rails-assets-shower-bright'
13 |
14 | JqueryCdn.local_url = proc { '/jquery.js' }
15 |
16 | class Slide
17 | attr_accessor :html, :types
18 |
19 | def initialize(builder, text, number)
20 | @builder = builder
21 | @types = []
22 |
23 | commands = []
24 | text.gsub!(/^!.*\n/) do |line|
25 | line = line.split(' ')
26 | name = line.first[1..-1]
27 | if respond_to? name
28 | send(name, *line[1..-1])
29 | else
30 | commands << [name, line[1..-1]]
31 | ''
32 | end
33 | end
34 |
35 | @html = @builder.markdown.render(text)
36 | @html = EvilFront::Russian.typograph_html(@html)
37 | @html = EvilFront::Russian.auto_flying_quotes(@html)
38 | @html.gsub!("
\n", '')
39 | commands.each { |(name, params)| send(name + '=', *params) }
40 | rescue => e
41 | $stderr.puts "Error in slide ##{ number + 1 }"
42 | $stderr.puts
43 | raise e
44 | end
45 |
46 | def type=(type)
47 | @types << type
48 | end
49 |
50 | def cover=(name)
51 | @html += image('covers/' + name)
52 | @types << 'cover h'
53 | end
54 |
55 | def image(name)
56 | url = if @builder.development?
57 | name
58 | else
59 | unless @builder.assets[name]
60 | $stderr.puts "No image #{ name }"
61 | exit(1)
62 | end
63 |
64 | @builder.inline_image(name)
65 | end
66 |
67 | "
"
68 | end
69 |
70 | def gem(path)
71 | name, path = path.split('/', 2)
72 | root = Gem::Specification.find_by_name(name).gem_dir
73 | Pathname(root).join(path).read
74 | end
75 | end
76 |
77 | module Helpers
78 | def standalone?
79 | @build_type == :standalone
80 | end
81 |
82 | def development?
83 | @build_type == :development
84 | end
85 |
86 | def inline_image(name)
87 | file = assets[name].pathname
88 | type = file_type(file)
89 | encode_image(file, type)
90 | end
91 |
92 | def encode_image(file, type)
93 | "data:#{type};base64," + Base64.encode64(file.read)
94 | end
95 |
96 | def file_type(file)
97 | MIME::Types.type_for(file.to_s).first.content_type
98 | end
99 |
100 | def include_statistics
101 | COMMON.join('_statistics.html').read
102 | end
103 | end
104 |
105 | class Highlighter < Redcarpet::Render::HTML
106 | def self.reload!
107 | if Object.const_defined? 'PostcssHighlighter'
108 | Object.send(:remove_const, 'PostcssHighlighter')
109 | end
110 | end
111 |
112 | def block_code(code, lang)
113 | if lang.start_with? 'steps:'
114 | steps = true
115 | lang = lang.sub(/^steps:/, '')
116 | end
117 |
118 | lines = code.lines.map do |line|
119 | line = EvilFront.escape(line)
120 |
121 | if lang and respond_to? lang
122 | send(lang, line)
123 | else
124 | default_highlight(line)
125 | end
126 | end
127 |
128 | '' + lines.map.with_index { |line, i|
129 | if not steps or line.strip.empty? or i.zero?
130 | "#{ line }
"
131 | else
132 | "#{ line }
"
133 | end
134 | }.join + '
'
135 | end
136 | end
137 |
138 | class Builder
139 | include EvilFront::Helpers
140 | include Helpers
141 |
142 | attr_reader :lang
143 |
144 | def self.load(lang = 'en')
145 | @cache ||= { }
146 | @cache[lang] ||= self.new(lang)
147 | end
148 |
149 | def initialize(lang, build_type = :development)
150 | @build_type = build_type
151 | @lang = lang
152 | end
153 |
154 | def assets
155 | @sprockets ||= begin
156 | Sprockets::Environment.new(ROOT) do |env|
157 | RailsAssets.load_paths.each { |i| env.append_path(i) }
158 |
159 | EvilFront.install_all(env)
160 |
161 | env.append_path(ROOT)
162 | env.append_path(COMMON)
163 | env.append_path(ROOT.join('images'))
164 |
165 | env.context_class.class_eval do
166 | def asset_path(path, options = {})
167 | ''
168 | end
169 | end
170 |
171 | if development?
172 | env.css_compressor = nil
173 | else
174 | env.js_compressor = Uglifier.new(copyright: false)
175 | env.css_compressor = Csso::Compressor.new
176 | end
177 | end
178 | end
179 | end
180 |
181 | def reload!
182 | @title = nil
183 | @slides = nil
184 | @caption = nil
185 | @sections = nil
186 | @renderer = nil
187 | Highlighter.reload!
188 | end
189 |
190 | def title
191 | @title ||= caption.match(/(.*)<\/h1>/m).try(:[], 1)
192 | end
193 |
194 | def caption
195 | @caption ||= markdown.render(sections.first)
196 | end
197 |
198 | def markdown
199 | @renderer ||= begin
200 | load ROOT.join('postcss_highlighter.rb').to_s
201 | Redcarpet::Markdown.new(PostcssHighlighter.new, fenced_code_blocks: true)
202 | end
203 | end
204 |
205 | def sections
206 | @sections ||= ROOT.join("postcss.#{ @lang }.md").read
207 | .split(/^##/).map.with_index do |text, index|
208 | index == 0 ? text : '##' + text
209 | end
210 | end
211 |
212 | def slides
213 | slides = sections[1..-1] || []
214 | @slides ||= slides.map.with_index { |s, i| Slide.new(self, s, i) }
215 | end
216 |
217 | def to_html
218 | layout = COMMON.join('layout.slim')
219 | options = { format: :html, disable_escape: true, pretty: false }
220 | Slim::Template.new(layout.to_s, options).render(self)
221 | end
222 | end
223 |
224 | require 'term/ansicolor'
225 | include Term::ANSIColor
226 |
227 | desc 'Remove generated files'
228 | task :clean do
229 | build = ROOT.join('./build/')
230 | build.rmtree if build.exist?
231 | end
232 |
233 | desc 'Build presentations all-in-one files'
234 | task :build => :clean do
235 | %w(ru en).each do |lang|
236 | html = ROOT.join("./build/postcss.#{lang}.html")
237 | html.dirname.mkpath
238 | html.open('w') { |io| io << Builder.new(lang, :standalone).to_html }
239 | print '.'
240 | end
241 | puts
242 | end
243 |
244 | desc 'Run server for development'
245 | task :server do
246 | require 'sinatra/base'
247 |
248 | class WebSlides < Sinatra::Base
249 | set :lock, true
250 |
251 | get '/' do
252 | 'English Русский'
253 | end
254 |
255 | {
256 | css: 'text/css', js: 'text/javascript', svg: 'image/svg+xml',
257 | png: 'image/png', jpg: 'image/jpeg', ico: 'image/vnd.microsoft.icon'
258 | }.each_pair do |ext, mime|
259 | get "/*.#{ ext }" do |path|
260 | content_type mime
261 |
262 | path = path + ".#{ ext }"
263 | asset = Builder.load.assets[path]
264 |
265 | if asset.nil?
266 | status 404
267 | "no #{path} asset"
268 | elsif ext == :css or ext == :js
269 | asset.to_s
270 | else
271 | send_file asset.pathname
272 | end
273 | end
274 | end
275 |
276 | get '/:lang' do
277 | builder = Builder.load(params[:lang])
278 | builder.reload!
279 | builder.to_html
280 | end
281 |
282 | def assets
283 | @assets ||= Builder.new.assets
284 | end
285 | end
286 |
287 | WebSlides.run!
288 | end
289 |
--------------------------------------------------------------------------------
/common/_statistics.html:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/common/fonts.sass:
--------------------------------------------------------------------------------
1 | @font-face
2 | font-family: "Open Sans"
3 | src: inline("shower-bright/fonts/OpenSans.woff") format("woff")
4 |
5 | @font-face
6 | font-family: "Open Sans"
7 | font-weight: bold
8 | src: inline("shower-bright/fonts/OpenSans.Bold.woff") format("woff")
9 |
10 | @font-face
11 | font-family: "Open Sans Light"
12 | src: inline("shower-bright/fonts/OpenSans.Light.woff") format("woff")
13 |
14 | @font-face
15 | font-family: "Anka Coder"
16 | src: inline("shower-bright/fonts/Anka.Coder.woff") format("woff")
17 |
--------------------------------------------------------------------------------
/common/layout.slim:
--------------------------------------------------------------------------------
1 | doctype 5
2 | html lang=lang
3 | head
4 | meta charset="UTF-8"
5 | link rel="icon" href="http://sitnik.ru/favicon.ico"
6 | title= title
7 | meta name="viewport" content="width=1274, user-scalable=no"
8 |
9 | - if development?
10 | link rel="stylesheet" href="/style.css"
11 | link rel="stylesheet" href="/postcss.css"
12 | link rel="stylesheet" href="/fonts.css"
13 | - else
14 | style
15 | = assets['style.css']
16 | = assets['postcss.css']
17 | = assets['fonts.css']
18 | = include_statistics
19 | body.list
20 | header.caption= caption
21 |
22 | - slides.each_with_index do |slide, i|
23 | section.slide id=(i + 1) class=slide.types.join(' ')
24 | div= slide.html
25 |
26 | .progress
27 | .progressbar
28 |
29 | - if development?
30 | script src="/jquery.js"
31 | script src="/script.js"
32 | - else
33 | script
34 | - if standalone?
35 | = assets['jquery.js']
36 | = assets['script.js']
37 |
--------------------------------------------------------------------------------
/common/script.coffee:
--------------------------------------------------------------------------------
1 | #= require shower-core/shower.min
2 |
3 | for link in document.querySelectorAll('a')
4 | link.target = '_blank' if link.attributes.href.value.match(/^http/)
5 |
6 | progress = document.querySelector('.progress')
7 | progressForCovers = ->
8 | if document.querySelector('.slide.active.cover')
9 | progress.classList.add('for-cover')
10 | else
11 | progress.classList.remove('for-cover')
12 |
13 | window.addEventListener('hashchange', progressForCovers)
14 | setTimeout(progressForCovers, 100)
15 |
--------------------------------------------------------------------------------
/common/style.sass:
--------------------------------------------------------------------------------
1 | @import "shower-bright"
2 | @import "evil-front"
3 |
4 | $color: #0080e0
5 |
6 | a
7 | color: $color
8 |
9 | .slide
10 | mark
11 | color: $color
12 | background: transparent
13 | mark.important
14 | padding: 3px 7px 0
15 | background: $color
16 | color: white
17 | mark
18 | color: white
19 | pre mark
20 | padding: 0
21 | pre mark.important
22 | background: $color
23 | pre mark.comment
24 | color: #888
25 |
26 | .caption
27 | color: black
28 |
29 | .caption a, .slide a
30 | background: none
31 | border-bottom: 0.09em solid rgba($color, 0.4)
32 | &:hover
33 | border-bottom-color: $color
34 |
35 | .caption a
36 | display: inline-block
37 | line-height: 1.2
38 |
39 | .slide::after
40 | text-align: right
41 | right: 50px
42 |
43 | .list .slide:after
44 | padding-top: 35px
45 | right: 0
46 | text-align: center
47 |
48 | .slide > div
49 | padding-top: 80px
50 | height: 560px
51 |
52 | .slide pre code:before
53 | display: none
54 |
55 | .slide h2
56 | a
57 | border-bottom-width: 0.05em
58 | em
59 | display: block
60 | position: absolute
61 | margin-top: -45px
62 | font-size: 35px
63 | font-style: normal
64 | font-weight: normal
65 | padding-bottom: 6px
66 | color: $color
67 |
68 | .cover h2
69 | font-family: "Open Sans"
70 | font-weight: bold
71 | color: white
72 | +stroke-text(black)
73 | font-size: 60px
74 | em
75 | color: white
76 |
77 | .progress.for-cover
78 | display: none
79 |
80 | @media screen
81 | .list .slide:target:before
82 | box-shadow: 0 0 10px 0 #3c99db, 0 0 0 12px $color
83 |
84 | .full .progress div
85 | background: $color
86 | height: 5px
87 |
--------------------------------------------------------------------------------
/covers/ask.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/covers/ask.jpg
--------------------------------------------------------------------------------
/covers/postcss.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/covers/postcss.jpg
--------------------------------------------------------------------------------
/covers/practice.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/covers/practice.jpg
--------------------------------------------------------------------------------
/covers/present.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/covers/present.jpg
--------------------------------------------------------------------------------
/covers/problem.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/covers/problem.jpg
--------------------------------------------------------------------------------
/covers/sass.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/covers/sass.jpg
--------------------------------------------------------------------------------
/covers/use.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/covers/use.jpg
--------------------------------------------------------------------------------
/images/alistapart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/alistapart.png
--------------------------------------------------------------------------------
/images/amplifr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/amplifr.png
--------------------------------------------------------------------------------
/images/attacks.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/attacks.jpg
--------------------------------------------------------------------------------
/images/autoprefixer.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/benfrain.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/benfrain.jpg
--------------------------------------------------------------------------------
/images/colorbad.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/colorbad.jpg
--------------------------------------------------------------------------------
/images/colorgood.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/colorgood.jpg
--------------------------------------------------------------------------------
/images/ebay.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
28 |
--------------------------------------------------------------------------------
/images/evolution.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/evolution.jpg
--------------------------------------------------------------------------------
/images/google.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/groupon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/images/hewiki.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/hewiki.jpg
--------------------------------------------------------------------------------
/images/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/markotto.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/markotto.jpg
--------------------------------------------------------------------------------
/images/martians.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/russia.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/russia.jpg
--------------------------------------------------------------------------------
/images/taobao.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/tj.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai/about-postcss/835f3f93e77074bc39e0b6e8328fbd3459c6e4e3/images/tj.jpg
--------------------------------------------------------------------------------
/images/twitter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/wordpress.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/yandex.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/postcss.en.md:
--------------------------------------------------------------------------------
1 | # PostCSS: the Future after Sass and Less
2 |
3 | [Andrey Sitnik](http://sitnik.ru/en), [Evil Martians](https://evilmartians.com/)
4 |
5 | ## **PostCSS** the Future after Sass and Less
6 | !type is-title
7 | !image logo.svg
8 |
9 | *Andrey Sitnik, Evil Martians*
10 |
11 | ## Russia
12 | !type cover
13 | !type h
14 |
15 | !image russia.jpg
16 |
17 |
18 | © Olga Barantseva
19 |
20 |
21 | ##
22 | !type cover
23 | !type h
24 |
25 | !image attacks.jpg
26 |
27 |
28 | © George Spigot
29 |
30 |
31 | ##
32 | !type with-martians
33 |
34 | !image martians.svg
35 |
36 | ## Worked on
37 | !type with-clients
38 |
39 | !image ebay.svg
40 | !image groupon.svg
41 | !image amplifr.png
42 |
43 | ## Open Source
44 | !type with-projects
45 |
46 | !image autoprefixer.svg
47 | !image logo.svg
48 |
49 | ## *Part 1* Problem
50 | !cover problem.jpg
51 |
52 | ## Evolution
53 |
54 | !image evolution.jpg
55 |
56 | ## How Evolution Works
57 |
58 |
59 |
Mutations
60 |
→
61 |
Selection
62 |
→
63 |
Inheritance
64 |
→
65 |
66 |
67 | ## Natural Selection?
68 |
69 | `