sassmagic 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,428 @@
1
+ ## use base.sass
2
+ ## $ git clone https://github.com/jsw0528/base.sass && cd base.sass && rake
3
+ ## License
4
+ ## Licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
5
+
6
+ #env
7
+ module Sass::Script::Functions
8
+
9
+ # Returns the value of environment variable associated with the given name.
10
+ # Returns null if the named variable does not exist.
11
+ #
12
+ # Examples:
13
+ # env(SASS_ENV) => development
14
+ # env(sass_env) => development
15
+ # env(sass-env) => development
16
+ def env(name)
17
+ assert_type name, :String
18
+ ruby_to_sass(ENV[name.value.gsub('-', '_').upcase])
19
+ end
20
+
21
+ # Returns the config associated with the given name.
22
+ # Configs are be grouped by `SASS_ENV` environment.
23
+ #
24
+ # Examples:
25
+ # $app-config: (
26
+ # development: (
27
+ # foo: bar
28
+ # ),
29
+ # production: (
30
+ # foo: baz
31
+ # )
32
+ # );
33
+ #
34
+ # $ sass --watch -r base.sass src:dist
35
+ # app-config(foo) => bar
36
+ #
37
+ # $ SASS_ENV=production sass --watch -r base.sass src:dist
38
+ # app-config(foo) => baz
39
+ def app_config(name)
40
+ assert_type name, :String
41
+ # debugger
42
+ config = environment.global_env.var('app-config')
43
+ return null unless config.is_a? Sass::Script::Value::Map
44
+
45
+ config = map_get(config, env(identifier('sass-env')))
46
+
47
+ map_get(config, name)
48
+ end
49
+
50
+ end
51
+
52
+ #strftime
53
+ module Sass::Script::Functions
54
+
55
+ # Formats time according to the directives in the given format string.
56
+ # Read more: http://www.ruby-doc.org/core-2.1.1/Time.html#method-i-strftime
57
+ #
58
+ # Examples:
59
+ # strftime() => 1399392214
60
+ # strftime('%FT%T%:z') => 2014-05-07T00:03:34+08:00
61
+ # strftime('at %I:%M%p') => at 12:03AM
62
+ def strftime(format = nil)
63
+ time = Time.now.localtime
64
+
65
+ if format
66
+ assert_type format, :String
67
+ identifier(time.strftime(format.value))
68
+ else
69
+ identifier(time.to_i.to_s)
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ #sass_to_ruby
76
+ module Sass::Script::Functions
77
+
78
+ protected
79
+
80
+ def sass_to_ruby(obj)
81
+ return to_ruby_hash(obj) if obj.is_a? Sass::Script::Value::Map
82
+ return to_ruby_array(obj) if obj.is_a? Sass::Script::Value::List
83
+ return obj.inspect if obj.is_a? Sass::Script::Value::Color
84
+ obj.value
85
+ end
86
+
87
+ def to_ruby_hash(sass_map)
88
+ sass_map.to_h.inject({}) do |memo, (k, v)|
89
+ memo[k.to_s] = sass_to_ruby(v)
90
+ memo
91
+ end
92
+ end
93
+
94
+ def to_ruby_array(sass_list)
95
+ sass_list.to_a.map do |item|
96
+ sass_to_ruby(item)
97
+ end
98
+ end
99
+
100
+ end
101
+
102
+ #ruby_to_sass
103
+ module Sass::Script::Functions
104
+
105
+ protected
106
+
107
+ def ruby_to_sass(obj)
108
+ return bool(obj) if obj.is_a?(TrueClass) || obj.is_a?(FalseClass)
109
+ return null if obj.nil?
110
+ return number(obj) if obj.is_a? Numeric
111
+ return to_sass_list(obj) if obj.is_a? Array
112
+ return to_sass_map(obj) if obj.is_a? Hash
113
+ identifier(obj.to_s)
114
+ end
115
+
116
+ def to_sass_map(ruby_hash)
117
+ sass_map = map({})
118
+
119
+ ruby_hash.each do |k, v|
120
+ sass_map = map_merge(
121
+ sass_map,
122
+ map(Hash[identifier(k.to_s), ruby_to_sass(v)])
123
+ )
124
+ end
125
+
126
+ sass_map
127
+ end
128
+
129
+ def to_sass_list(ruby_array)
130
+ list(ruby_array.map { |item|
131
+ ruby_to_sass(item)
132
+ }, :comma)
133
+ end
134
+
135
+ end
136
+
137
+
138
+ #inline_image 取图片base64编码
139
+ # module Sass::Script::Functions::InlineImage
140
+ #
141
+ # def inline_image(path, mime_type = nil)
142
+ # # path = path.value
143
+ # # real_path = File.join(Compass.configuration.images_path, path)
144
+ # inline_image_string(data(path), compute_mime_type(path, mime_type))
145
+ # end
146
+ #
147
+ # protected
148
+ # def inline_image_string(data, mime_type)
149
+ # data = [data].flatten.pack('m').gsub("\n","")
150
+ # url = "url('data:#{mime_type};base64,#{data}')"
151
+ # unquoted_string(url)
152
+ # end
153
+ #
154
+ # private
155
+ # def compute_mime_type(path, mime_type = nil)
156
+ # return mime_type.value if mime_type
157
+ # case path
158
+ # when /\.png$/i
159
+ # 'image/png'
160
+ # when /\.jpe?g$/i
161
+ # 'image/jpeg'
162
+ # when /\.gif$/i
163
+ # 'image/gif'
164
+ # when /\.svg$/i
165
+ # 'image/svg+xml'
166
+ # when /\.otf$/i
167
+ # 'font/opentype'
168
+ # when /\.eot$/i
169
+ # 'application/vnd.ms-fontobject'
170
+ # when /\.ttf$/i
171
+ # 'font/truetype'
172
+ # when /\.woff$/i
173
+ # 'application/font-woff'
174
+ # when /\.off$/i
175
+ # 'font/openfont'
176
+ # when /\.([a-zA-Z]+)$/
177
+ # "image/#{Regexp.last_match(1).downcase}"
178
+ # else
179
+ # raise Sass.logger.debug("A mime type could not be determined for #{path}, please specify one explicitly.")
180
+ # end
181
+ # end
182
+ #
183
+ # def data(real_path)
184
+ # debugger
185
+ # if File.readable?(real_path)
186
+ # File.open(real_path, "rb") {|io| io.read}
187
+ # else
188
+ # raise Sass.logger.debug("File not found or cannot be read: #{real_path}")
189
+ # end
190
+ # end
191
+ #
192
+ # end
193
+ #url重写
194
+ module Sass::Script::Functions
195
+ # include Sass::Script::Functions::InlineImage
196
+ # declare :inline_image, [], var_args: true, var_kwargs: true
197
+ FONT_TYPES = {
198
+ eot: 'embedded-opentype',
199
+ woff: 'woff',
200
+ ttf: 'truetype',
201
+ svg: 'svg'
202
+ }
203
+
204
+ MIME_TYPES = {
205
+ png: 'image/png',
206
+ jpg: 'image/jpeg',
207
+ jpeg: 'image/jpeg',
208
+ gif: 'image/gif',
209
+ eot: 'application/vnd.ms-fontobject',
210
+ woff: 'application/font-woff',
211
+ ttf: 'font/truetype',
212
+ svg: 'image/svg+xml'
213
+ }
214
+
215
+ PATH_REGEX = /^(.*)(\.\w+)(\??[^#]*)(#?.*)$/
216
+
217
+ # Reinforce the official `url()` in CSS to support multi url and data url.
218
+ # Activates only when all paths are wrapped with quotes.
219
+ #
220
+ # Examples:
221
+ # url(http://a.com/b.png) => url(http://a.com/b.png) # Did nothing
222
+ # url('http://a.com/b.png') => url(http://a.com/b.png?1399394203)
223
+ # url('a.png', 'b.png') => url(a.png?1399394203), url(b.png?1399394203)
224
+ # url('a.eot#iefix', 'b.woff') => url(a.eot?1399394203#iefix) format('embedded-opentype'), url(b.woff?1399394203) format('woff')
225
+ #
226
+ # url('a.png', $timestamp: false) => url(a.png)
227
+ # url('a.png', $timestamp: '1.0.0') => url(a.png?1.0.0)
228
+ #
229
+ # $app-config: (timestamp: '1.0.0');
230
+ # url('a.png') => url(a.png?1.0.0)
231
+ #
232
+ # $app-config: (timestamp: 'p1');
233
+ # url('a.png', $timestamp: 'p0') => url(a.png?p0)
234
+ #
235
+ # url('a.png', $base64: true) => url(data:image/png;base64,iVBORw...)
236
+ def url(*paths)
237
+ # debugger
238
+ kwargs = paths.last.is_a?(Hash) ? paths.pop : {}
239
+ raise Sass::SyntaxError, 'url() needs one path at least' if paths.empty?
240
+
241
+ encode = kwargs['base64'] == bool(true)
242
+ ts = timestamp(kwargs['timestamp'])
243
+
244
+ paths = paths.map { |path| sass_to_ruby(path) }.flatten
245
+ .map { |path| to_url(path, encode, ts) }
246
+
247
+ list(paths, :comma)
248
+ end
249
+ declare :url, [], var_args: true, var_kwargs: true
250
+
251
+
252
+ private
253
+
254
+ def timestamp(ts)
255
+ # no kwargs
256
+ if ts.nil?
257
+ cfg = app_config(identifier('timestamp'))
258
+ ts = cfg == null ? bool(true) : cfg
259
+ end
260
+
261
+ return nil unless ts.to_bool
262
+ return strftime.value if ts.is_a? Sass::Script::Value::Bool
263
+ ts.value.to_s
264
+ end
265
+
266
+ def sign(query)
267
+ case query.size
268
+ when 0
269
+ '?'
270
+ when 1
271
+ ''
272
+ else
273
+ '&'
274
+ end
275
+ end
276
+
277
+ def to_url(path, encode, ts)
278
+ output = "url(#{path})"
279
+ # debugger
280
+ $configHash = load_json(File.expand_path("#{File.dirname(options[:filename])}/sassmagic.json")) || Hash.new
281
+ if path.is_a?(String) && path =~ PATH_REGEX
282
+
283
+ path, ext, query, anchor = $1 + $2, $2[1..-1].downcase.to_sym, $3, $4
284
+
285
+ if MIME_TYPES.key? ext
286
+ # 网络地址
287
+ if path =~ /^(http:|https:)\/\//
288
+ output = output_path(path, ext, query, anchor, ts)
289
+ else
290
+ if $configHash["imageMaxSize"]
291
+ #替换图片地址
292
+ output = if encode
293
+ output_data(path, ext)
294
+ else
295
+ #替换图片
296
+ # debugger
297
+ filesize = File.size(File.expand_path("#{File.dirname(options[:filename])}/#{path}"))
298
+ if filesize < $configHash["imageMaxSize"].to_i
299
+ output_data(path, ext)
300
+ else
301
+ path = change_path(path)
302
+ output_path(path, ext, query, anchor, ts)
303
+ end
304
+ end
305
+ else
306
+ output = if encode
307
+ output_data(path, ext)
308
+ else
309
+ output_path(path, ext, query, anchor, ts)
310
+ end
311
+ end
312
+ end
313
+
314
+
315
+ end
316
+
317
+ end
318
+
319
+ if output.is_a? Array
320
+ list(output, :space)
321
+ else
322
+ identifier(output)
323
+ end
324
+ end
325
+
326
+ def output_data(path, ext)
327
+ data = [read_file(File.expand_path(File.expand_path("#{File.dirname(options[:filename])}/#{path}")))].pack('m').gsub(/\s/, '')
328
+ "url(data:#{MIME_TYPES[ext]};base64,#{data})"
329
+ end
330
+
331
+ def output_path(path, ext, query, anchor, ts)
332
+ query += sign(query) + ts unless ts.nil?
333
+
334
+ output = "url(#{path}#{query}#{anchor})"
335
+ return output unless FONT_TYPES.key? ext
336
+
337
+ [identifier(output), identifier("format('#{FONT_TYPES[ext]}')")]
338
+ end
339
+ def change_path(path)
340
+ # debugger
341
+ $configHash["imagesPath"] ||= Hash.new
342
+ if $configHash["imagesPath"].has_key?(File.expand_path("#{File.dirname(options[:filename])}/#{path}"))
343
+ return $configHash["imagesPath"][File.expand_path("#{File.dirname(options[:filename])}/#{path}")]
344
+ end
345
+ # 调用上传任务
346
+ # debugger
347
+ nodetask = $configHash["imageLoader"] || false
348
+ taskargs = File.expand_path("#{File.dirname(options[:filename])}/#{path}")
349
+ # debugger
350
+ if nodetask && File::exists?( File.expand_path("#{File.dirname(options[:filename])}/#{nodetask}") )
351
+ task = system('node '+File.expand_path("#{File.dirname(options[:filename])}/#{nodetask}")+' '+File.expand_path("#{File.dirname(options[:filename])}/sassmagic.json")+' '+taskargs)
352
+ if task
353
+ # puts 'nodetask success'
354
+ $configHash = load_json(File.expand_path("#{File.dirname(options[:filename])}/sassmagic.json"))
355
+ $configHash["imagesPath"] ||= Hash.new
356
+ if $configHash["imagesPath"].has_key?(path)
357
+ return $configHash["imagesPath"][path]
358
+ else
359
+ return path
360
+ end
361
+ else
362
+ # puts 'nodetask faile'
363
+ if $configHash["imagesPath"].has_key?(path)
364
+ return $configHash["imagesPath"][path]
365
+ else
366
+ return path
367
+ end
368
+ end
369
+ else
370
+ if $configHash["imagesPath"].has_key?(path)
371
+ return $configHash["imagesPath"][path]
372
+ else
373
+ return path
374
+ end
375
+ end
376
+
377
+
378
+
379
+ end
380
+ end
381
+
382
+
383
+ #parse_json load_json read_file
384
+ require 'json'
385
+
386
+ module Sass::Script::Functions
387
+
388
+ $cached_files = {}
389
+
390
+ # Parses a local json file, returns a map, and the result will be cached.
391
+ # If the `path` is not a absolute path, relative to current process directory.
392
+ #
393
+ # Examples:
394
+ # parse-json('~/Desktop/example.json')
395
+ # parse-json('package.json')
396
+ def parse_json(path)
397
+ assert_type path, :String
398
+ path = File.expand_path(path.value)
399
+
400
+ if $cached_files.key? path
401
+ Sass.logger.debug "Reading file from cache: #{path}"
402
+ $cached_files[path]
403
+ else
404
+ $cached_files[path] = ruby_to_sass(load_json(path))
405
+ end
406
+ end
407
+
408
+
409
+ #protected
410
+
411
+ def load_json(path)
412
+ if File::exists?( path )
413
+ JSON.load(
414
+ read_file(File.expand_path(path)).to_s.gsub(/(\\r|\\n)/, '')
415
+ )
416
+ end
417
+ end
418
+
419
+ def read_file(path)
420
+ raise Sass::SyntaxError, "File not found or cannot be read: #{path}" unless File.readable? path
421
+
422
+ Sass.logger.debug "Reading file: #{path}"
423
+ File.open(path, 'rb') { |f| f.read }
424
+ end
425
+ end
426
+
427
+
428
+
data/lib/sassmagic.rb ADDED
@@ -0,0 +1,20 @@
1
+ load_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'stylesheets'))
2
+
3
+ # Register on the Sass path via the environment.
4
+ ENV['SASS_PATH'] = [ENV['SASS_PATH'], load_path].compact.join(File::PATH_SEPARATOR)
5
+ ENV['SASS_ENV'] ||= 'development'
6
+
7
+ # Register as a Compass extension.
8
+ # begin
9
+ # require 'compass'
10
+ # Compass::Frameworks.register('sassmagic', stylesheets_directory: load_path)
11
+ # rescue LoadError
12
+ # end
13
+
14
+ $:.unshift"#{File.dirname(__FILE__)}"
15
+ # require 'debugger'
16
+ # debugger
17
+ # require 'sass'
18
+ require 'sassmagic/utils'
19
+ require 'sassmagic/reset'
20
+
@@ -0,0 +1,10 @@
1
+ //used by base.scss
2
+ @import 'functions/support';
3
+ @import 'functions/list';
4
+ @import 'mixins/placeholder-wrapper';
5
+ @import 'mixins/clearfix';
6
+ @import 'mixins/ellipsis-overflow';
7
+ @import 'mixins/float';
8
+ @import 'mixins/font-face';
9
+ @import 'mixins/image';
10
+ @import 'mixins/inline-block';
@@ -0,0 +1,27 @@
1
+ @function comma-list($list: ()) {
2
+ @return join((), $list, comma);
3
+ }
4
+
5
+
6
+ @function slice($list, $min: 1, $max: length($list)) {
7
+ $output: comma-list();
8
+ $length: length($list);
9
+
10
+ @if $max < 0 {
11
+ $max: $length + $max + 1;
12
+ }
13
+
14
+ @if $max > $length {
15
+ $max: $length;
16
+ }
17
+
18
+ @if $min >= 1 and $min <= $length and
19
+ $max >= 1 and $max <= $length and
20
+ $min <= $max {
21
+ @for $i from $min through $max {
22
+ $output: append($output, nth($list, $i));
23
+ }
24
+ }
25
+
26
+ @return $output;
27
+ }
@@ -0,0 +1,14 @@
1
+ // Examples:
2
+ // support-browser(ios)
3
+ // support-browser(ie 8)
4
+ @function support-browser($args) {
5
+ @if length($args) == 1 {
6
+ @return map-has-key($browser-supports, to-lower-case($args));
7
+ }
8
+ @else {
9
+ @return not not index(
10
+ map-get($browser-supports, to-lower-case(nth($args, 1))),
11
+ nth($args, 2)
12
+ );
13
+ }
14
+ }
@@ -0,0 +1,19 @@
1
+ @mixin clearfix {
2
+ $colon: unquote(if(support-browser(ie 8), ':', '::')) !global;
3
+
4
+ @include placeholder-wrapper('clearfix') {
5
+ &#{$colon}before,
6
+ &#{$colon}after {
7
+ content: '\20';
8
+ display: table;
9
+ }
10
+
11
+ &#{$colon}after {
12
+ clear: both;
13
+ }
14
+
15
+ @if support-browser(ie 7) {
16
+ *zoom: 1;
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,7 @@
1
+ @mixin ellipsis-overflow {
2
+ @include placeholder-wrapper('ellipsis-overflow') {
3
+ overflow: hidden;
4
+ text-overflow: ellipsis;
5
+ white-space: nowrap;
6
+ }
7
+ }
@@ -0,0 +1,8 @@
1
+ @mixin float($side, $important: false) {
2
+ $flag: if($important, ' !important', '');
3
+
4
+ float: unquote($side) + $flag;
5
+ @if support-browser(ie 6) {
6
+ _display: inline + $flag;
7
+ }
8
+ }
@@ -0,0 +1,20 @@
1
+ @mixin font-face($font-family, $paths...) {
2
+ $ie9-url: null;
3
+
4
+ @if support-browser(ie 9) {
5
+ @each $path in $paths {
6
+ @if str-index($path, '.eot') {
7
+ $i: str-index($path, '#');
8
+ $end: if($i, $i - 1, str-length($path));
9
+ $ie9-url: nth(nth(url(str-slice($path, 1, $end)), 1), 1);
10
+ }
11
+ }
12
+ }
13
+
14
+ @font-face {
15
+ font-family: $font-family;
16
+ @content;
17
+ src: $ie9-url;
18
+ src: url($paths);
19
+ }
20
+ }
@@ -0,0 +1,19 @@
1
+ @mixin img-retina {
2
+ @media
3
+ only screen and (-webkit-min-device-pixel-ratio: 2),
4
+ only screen and ( min--moz-device-pixel-ratio: 2),
5
+ only screen and ( -o-min-device-pixel-ratio: 2/1),
6
+ only screen and ( min-device-pixel-ratio: 2),
7
+ only screen and ( min-resolution: 192dpi),
8
+ only screen and ( min-resolution: 2dppx) {
9
+ @content;
10
+ }
11
+ }
12
+
13
+ @mixin img-responsive($display: block) {
14
+ @include placeholder-wrapper('img-responsive', $display) {
15
+ display: $display;
16
+ max-width: 100%;
17
+ height: auto;
18
+ }
19
+ }
@@ -0,0 +1,8 @@
1
+ @mixin inline-block {
2
+ display: inline-block;
3
+
4
+ @if support-browser(ie 7) {
5
+ *display: inline;
6
+ *zoom: 1;
7
+ }
8
+ }
@@ -0,0 +1,15 @@
1
+ $anonymous-placeholders: ();
2
+
3
+ @mixin placeholder-wrapper($name, $args...) {
4
+ $times: map-get($anonymous-placeholders, ($name, $args)) or 0;
5
+ $anonymous-placeholders: map-merge($anonymous-placeholders, (($name, $args): $times + 1)) !global;
6
+ $index: index($anonymous-placeholders, (($name, $args) ($times + 1)));
7
+
8
+ @if $times == 0 {
9
+ @at-root %-#{$name}-#{$index} {
10
+ @content;
11
+ }
12
+ }
13
+
14
+ @extend %-#{$name}-#{$index};
15
+ }
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sassmagic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - ringself
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-02-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sass
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.3.0
22
+ - - <
23
+ - !ruby/object:Gem::Version
24
+ version: '3.5'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 3.3.0
33
+ - - <
34
+ - !ruby/object:Gem::Version
35
+ version: '3.5'
36
+ description: Awesome features that you wanted
37
+ email: ringself@163.com
38
+ executables:
39
+ - sassmagic
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - bin/sassmagic
44
+ - lib/sassmagic/reset.rb
45
+ - lib/sassmagic/utils.rb
46
+ - lib/sassmagic.rb
47
+ - stylesheets/sassmagic/_+.scss
48
+ - stylesheets/sassmagic/functions/_list.scss
49
+ - stylesheets/sassmagic/functions/_support.scss
50
+ - stylesheets/sassmagic/mixins/_clearfix.scss
51
+ - stylesheets/sassmagic/mixins/_ellipsis-overflow.scss
52
+ - stylesheets/sassmagic/mixins/_float.scss
53
+ - stylesheets/sassmagic/mixins/_font-face.scss
54
+ - stylesheets/sassmagic/mixins/_image.scss
55
+ - stylesheets/sassmagic/mixins/_inline-block.scss
56
+ - stylesheets/sassmagic/mixins/_placeholder-wrapper.scss
57
+ - Changelog.md
58
+ - Readme.md
59
+ homepage: https://github.com/ringself/sassmagic
60
+ licenses:
61
+ - MIT
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '1.9'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 1.8.23.2
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Awesome Extensions For Sass
84
+ test_files: []
85
+ has_rdoc: