sassmagic 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: