polymer 1.0.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Gemfile +8 -0
  2. data/History.md +126 -0
  3. data/LICENSE +28 -0
  4. data/README.md +229 -0
  5. data/Rakefile +186 -0
  6. data/bin/polymer +10 -0
  7. data/lib/polymer/cache.rb +106 -0
  8. data/lib/polymer/cli.rb +340 -0
  9. data/lib/polymer/core_ext.rb +78 -0
  10. data/lib/polymer/css_generator.rb +32 -0
  11. data/lib/polymer/deviant_finder.rb +76 -0
  12. data/lib/polymer/dsl.rb +283 -0
  13. data/lib/polymer/man/polymer-bond.1 +60 -0
  14. data/lib/polymer/man/polymer-bond.1.txt +66 -0
  15. data/lib/polymer/man/polymer-init.1 +33 -0
  16. data/lib/polymer/man/polymer-init.1.txt +42 -0
  17. data/lib/polymer/man/polymer-optimise.1 +23 -0
  18. data/lib/polymer/man/polymer-optimise.1.txt +25 -0
  19. data/lib/polymer/man/polymer-position.1 +39 -0
  20. data/lib/polymer/man/polymer-position.1.txt +42 -0
  21. data/lib/polymer/man/polymer.1 +50 -0
  22. data/lib/polymer/man/polymer.1.txt +60 -0
  23. data/lib/polymer/man/polymer.5 +130 -0
  24. data/lib/polymer/man/polymer.5.txt +145 -0
  25. data/lib/polymer/optimisation.rb +130 -0
  26. data/lib/polymer/project.rb +164 -0
  27. data/lib/polymer/sass_generator.rb +38 -0
  28. data/lib/polymer/source.rb +55 -0
  29. data/lib/polymer/sprite.rb +130 -0
  30. data/lib/polymer/templates/polymer.tt +28 -0
  31. data/lib/polymer/templates/sass_mixins.erb +29 -0
  32. data/lib/polymer/templates/sources/one/book.png +0 -0
  33. data/lib/polymer/templates/sources/one/box-label.png +0 -0
  34. data/lib/polymer/templates/sources/one/calculator.png +0 -0
  35. data/lib/polymer/templates/sources/one/calendar-month.png +0 -0
  36. data/lib/polymer/templates/sources/one/camera.png +0 -0
  37. data/lib/polymer/templates/sources/one/eraser.png +0 -0
  38. data/lib/polymer/templates/sources/two/inbox-image.png +0 -0
  39. data/lib/polymer/templates/sources/two/magnet.png +0 -0
  40. data/lib/polymer/templates/sources/two/newspaper.png +0 -0
  41. data/lib/polymer/templates/sources/two/television.png +0 -0
  42. data/lib/polymer/templates/sources/two/wand-hat.png +0 -0
  43. data/lib/polymer/templates/sources/two/wooden-box-label.png +0 -0
  44. data/lib/polymer/version.rb +4 -0
  45. data/lib/polymer.rb +49 -0
  46. data/polymer.gemspec +94 -0
  47. metadata +206 -0
@@ -0,0 +1,60 @@
1
+ POLYMER(1) Polymer Manual POLYMER(1)
2
+
3
+
4
+
5
+ NAME
6
+ polymer - Image spriting for web applications
7
+
8
+ SYNOPSIS
9
+ polymer [--no-colour] COMMAND [ARGUMENTS]
10
+
11
+ DESCRIPTION
12
+ Polymer is a tool for creating sprite images which combine many smaller
13
+ sources into a single larger image. Spriting allows you to reduce the
14
+ number of HTTP requests required to load a web page, and as such can
15
+ result in reduced load times.
16
+
17
+ Polymer also creates the necessary CSS to position the sprite within an
18
+ HTML element so that only the desired source appears. Those writing
19
+ their website or application in Ruby can make use of Polymer's Sass
20
+ builder which creates a Sass mixin, further simplifying the use of your
21
+ sprites.
22
+
23
+ In order to reduce the amount of data transferred to clients loading
24
+ your pages, Polymer optimises the sprites it generates using PNGOUT,
25
+ OptiPNG, and PNGCrush.
26
+
27
+ OPTIONS
28
+ --no-colour
29
+ Disables the use of colour in output. This option is also avail-
30
+ able as --no-color.
31
+
32
+ COMMANDS
33
+ polymer init(1) polymer-init.1.html
34
+ Creates a new Polymer project in the current directory.
35
+
36
+ polymer bond(1) polymer-bond.1.html
37
+ Creates the sprites specified by your .polymer or polymer.rb
38
+ file, optimises the images, and creates any requested CSS or
39
+ Sass files.
40
+
41
+ polymer optimise(1) polymer-optimise.1.html
42
+ Given paths to PNG files as arguments, optimises them to reduce
43
+ the filesize as much as possible without compromising quality.
44
+ Also available as polymer optimize.
45
+
46
+ polymer position(1) polymer-position.1.html
47
+ Shows the position of a source within a sprite, and provides CSS
48
+ which you can use in your own stylesheets.
49
+
50
+ Detailed documentation for each of Polymer's commands can be viewed
51
+ with the polymer help command. For example, to view the documentation
52
+ for the bond command, run polymer help bond.
53
+
54
+ SEE ALSO
55
+ polymer(5) (polymer help .polymer) provides a description of the .poly-
56
+ mer configuration file format.
57
+
58
+
59
+
60
+ POLYMER 1.0.0.BETA.3 September 2010 POLYMER(1)
@@ -0,0 +1,130 @@
1
+ .\" generated with Ronn/v0.7.3
2
+ .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
+ .ad l
4
+ .
5
+ .TH "\.POLYMER" "5" "September 2010" "POLYMER 1.0.0.BETA.3" "Polymer Manual"
6
+ .
7
+ .SH "NAME"
8
+ \fB\.polymer\fR \- a format for describing image sprites and their sources
9
+ .
10
+ .SH "DESCRIPTION"
11
+ A \fB\.polymer\fR file describes the image sprites used in a Polymer project, and the source images which are used to create those sprites\.
12
+ .
13
+ .P
14
+ Placing a \fB\.polymer\fR file in the root directory of your project will allow the Polymer application to automate generation and optimisation of your sprite images\. In a Ruby project the \fB\.polymer\fR file should be in the same directory as your \fBRakefile\fR\.
15
+ .
16
+ .P
17
+ On systems where files beginning with a "\." are tricky to work with (e\.g\. Windows), you may instead use \fBpolymer\.rb\fR instead of \fB\.polymer\fR\.
18
+ .
19
+ .P
20
+ A \fB\.polymer\fR can be generated by running \fBpolymer init\fR\.
21
+ .
22
+ .SH "SYNTAX"
23
+ The \fB\.polymer\fR file is, at it\'s heart, a Ruby file and thus any valid Ruby code may be used in it\. This may seem intimidating to those who have never used Ruby, but the \fB\.polymer\fR syntax is very simple, and fairly self\-explanatory (the irony of saying that, then writing a man page, is not lost on me\.\.\.)\.
24
+ .
25
+ .SH "GLOBAL SETTINGS"
26
+ Global options are prefixed with "config\." and followed by the value you wish to set\. These settings are OPTIONAL, and Polymer will use it\'s own defaults if you choose not to define them\.
27
+ .
28
+ .TP
29
+ \fBconfig\.sass\fR "\fIstring\fR" or \fIfalse\fR
30
+ The path, relative to the \fB\.polymer\fR file, at which you want the Sass mixin file to be written\. You may also set this to \fIfalse\fR in order to disable generation of Sass files\. Default: "public/stylesheets/sass"
31
+ .
32
+ .TP
33
+ \fBconfig\.css\fR "\fIstring\fR" or \fIfalse\fR
34
+ The path, relative to the \fB\.polymer\fR file, at which you want the CSS file to be written\. You may also set this to \fIfalse\fR in order to disable generation of CSS files\. Default: false
35
+ .
36
+ .TP
37
+ \fBconfig\.url\fR "\fIstring\fR"
38
+ In order for stylesheets to link to the generated sprites, they must be able to create a URL for each sprite\. Typically this URL should be relative to the web root and prefixed with a "/", otherwise browsers will interpret the URL as being relative to the stylesheet\. The \fBurl\fR option accepts a ":filename" segment which Polymer will change to each sprite\'s filename (including the extension)\. Default: "/images/:filename"
39
+ .
40
+ .TP
41
+ \fBconfig\.padding\fR \fInumber\fR
42
+ Polymer stacks each source image on top of one another, with transparent padding being used to ensure that one source does not bleed into another when used as the background for an HTML element\. The \fBpadding\fR option sets the number of pixels to be used to separate each source, and may be set to 0 if no padding is desired\. Default: 20\.
43
+ .
44
+ .TP
45
+ \fBconfig\.cache\fR "\fIstring\fR" or \fIfalse\fR
46
+ Since optimising sprites can take some time, Polymer maintains a cache of each sprite, only generating and optimising those which have changed\. This cache is typically stored in your project root as "\.polymer\-cache"\. You may specify an alternate path here, or provide \fIfalse\fR if you want to disable the cache entirely (not recommended)\.
47
+ .
48
+ .SH "DEFINING SPRITES"
49
+ Sprites are defined using the \fIsprite\fR keyword (which is also aliased as \fIsprites\fR)\. The simplest way of defining a sprite is:
50
+ .
51
+ .IP "" 4
52
+ .
53
+ .nf
54
+
55
+ sprite "path/to/sources/*" => "path/to/sprite\.png"
56
+ .
57
+ .fi
58
+ .
59
+ .IP "" 0
60
+ .
61
+ .P
62
+ Both of the paths in the above example are relative to the \fB\.polymer\fR file\. In this case, we are telling Polymer to take source files from the "path/to/sources" directory, and composite them together in a sprite to be saved at "path/to/sprite\.png"\.
63
+ .
64
+ .P
65
+ If your source directory contains non\-images, you may need to be more specific:
66
+ .
67
+ .IP "" 4
68
+ .
69
+ .nf
70
+
71
+ sprite "path/to/sources/*\.{png,gif,jpg}" => "path/to/sprite\.png"
72
+ .
73
+ .fi
74
+ .
75
+ .IP "" 0
76
+ .
77
+ .P
78
+ Sprite definitions may contain a \fB:name\fR segment which Polymer will use to match any sub\-directory:
79
+ .
80
+ .IP "" 4
81
+ .
82
+ .nf
83
+
84
+ sprites "sources/:name/*" => "sprites/:name\.png"
85
+ .
86
+ .fi
87
+ .
88
+ .IP "" 0
89
+ .
90
+ .P
91
+ In this case, Polymer will look inside the "sources/" directory for sub\-directories\. The contents of sub\-directory will be used to create individual sprites where the final sprite name is the same as the directory name\. For example, given the following directory structure\.\.\.
92
+ .
93
+ .IP "" 4
94
+ .
95
+ .nf
96
+
97
+ sources/
98
+ one/
99
+ book\.png
100
+ calculator\.png
101
+ two/
102
+ magnet\.png
103
+ television\.png
104
+ .
105
+ .fi
106
+ .
107
+ .IP "" 0
108
+ .
109
+ .P
110
+ \&\.\.\. Polymer will create two sprites in the "sprites/" directory: one\.png will contain "book" and "calculator", while two\.png will contain "magnet" and "television"\.
111
+ .
112
+ .P
113
+ There may be cases where you need to customise an individual sprite and you don\'t want to change the global setting; \fBsprite\fR allows you to specify any of the global settings with the exception of "sass" and "css" like so:
114
+ .
115
+ .IP "" 4
116
+ .
117
+ .nf
118
+
119
+ sprite "path/to/sources/*" => "path/to/sprite\.png",
120
+ :padding => 50, :url => "/elsewhere/:filename"
121
+ .
122
+ .fi
123
+ .
124
+ .IP "" 0
125
+ .
126
+ .P
127
+ Each configuration option is prefixed with a colon rather than "config\.", is separated from the value with " => ", and all but the final option should be followed with a comma\.
128
+ .
129
+ .SH "SEE ALSO"
130
+ polymer(1), polymer\-init(1)
@@ -0,0 +1,145 @@
1
+ .POLYMER(5) Polymer Manual .POLYMER(5)
2
+
3
+
4
+
5
+ NAME
6
+ .polymer - a format for describing image sprites and their sources
7
+
8
+ DESCRIPTION
9
+ A .polymer file describes the image sprites used in a Polymer project,
10
+ and the source images which are used to create those sprites.
11
+
12
+ Placing a .polymer file in the root directory of your project will
13
+ allow the Polymer application to automate generation and optimisation
14
+ of your sprite images. In a Ruby project the .polymer file should be in
15
+ the same directory as your Rakefile.
16
+
17
+ On systems where files beginning with a "." are tricky to work with
18
+ (e.g. Windows), you may instead use polymer.rb instead of .polymer.
19
+
20
+ A .polymer can be generated by running polymer init.
21
+
22
+ SYNTAX
23
+ The .polymer file is, at it's heart, a Ruby file and thus any valid
24
+ Ruby code may be used in it. This may seem intimidating to those who
25
+ have never used Ruby, but the .polymer syntax is very simple, and
26
+ fairly self-explanatory (the irony of saying that, then writing a man
27
+ page, is not lost on me...).
28
+
29
+ GLOBAL SETTINGS
30
+ Global options are prefixed with "config." and followed by the value
31
+ you wish to set. These settings are OPTIONAL, and Polymer will use it's
32
+ own defaults if you choose not to define them.
33
+
34
+ config.sass "string" or false
35
+ The path, relative to the .polymer file, at which you want the
36
+ Sass mixin file to be written. You may also set this to false in
37
+ order to disable generation of Sass files. Default: "pub-
38
+ lic/stylesheets/sass"
39
+
40
+ config.css "string" or false
41
+ The path, relative to the .polymer file, at which you want the
42
+ CSS file to be written. You may also set this to false in order
43
+ to disable generation of CSS files. Default: false
44
+
45
+ config.url "string"
46
+ In order for stylesheets to link to the generated sprites, they
47
+ must be able to create a URL for each sprite. Typically this URL
48
+ should be relative to the web root and prefixed with a "/", oth-
49
+ erwise browsers will interpret the URL as being relative to the
50
+ stylesheet. The url option accepts a ":filename" segment which
51
+ Polymer will change to each sprite's filename (including the
52
+ extension). Default: "/images/:filename"
53
+
54
+ config.padding number
55
+ Polymer stacks each source image on top of one another, with
56
+ transparent padding being used to ensure that one source does
57
+ not bleed into another when used as the background for an HTML
58
+ element. The padding option sets the number of pixels to be used
59
+ to separate each source, and may be set to 0 if no padding is
60
+ desired. Default: 20.
61
+
62
+ config.cache "string" or false
63
+ Since optimising sprites can take some time, Polymer maintains a
64
+ cache of each sprite, only generating and optimising those which
65
+ have changed. This cache is typically stored in your project
66
+ root as ".polymer-cache". You may specify an alternate path
67
+ here, or provide false if you want to disable the cache entirely
68
+ (not recommended).
69
+
70
+ DEFINING SPRITES
71
+ Sprites are defined using the sprite keyword (which is also aliased as
72
+ sprites). The simplest way of defining a sprite is:
73
+
74
+
75
+
76
+ sprite "path/to/sources/*" => "path/to/sprite.png"
77
+
78
+
79
+
80
+ Both of the paths in the above example are relative to the .polymer
81
+ file. In this case, we are telling Polymer to take source files from
82
+ the "path/to/sources" directory, and composite them together in a
83
+ sprite to be saved at "path/to/sprite.png".
84
+
85
+ If your source directory contains non-images, you may need to be more
86
+ specific:
87
+
88
+
89
+
90
+ sprite "path/to/sources/*.{png,gif,jpg}" => "path/to/sprite.png"
91
+
92
+
93
+
94
+ Sprite definitions may contain a :name segment which Polymer will use
95
+ to match any sub-directory:
96
+
97
+
98
+
99
+ sprites "sources/:name/*" => "sprites/:name.png"
100
+
101
+
102
+
103
+ In this case, Polymer will look inside the "sources/" directory for
104
+ sub-directories. The contents of sub-directory will be used to create
105
+ individual sprites where the final sprite name is the same as the
106
+ directory name. For example, given the following directory structure...
107
+
108
+
109
+
110
+ sources/
111
+ one/
112
+ book.png
113
+ calculator.png
114
+ two/
115
+ magnet.png
116
+ television.png
117
+
118
+
119
+
120
+ ... Polymer will create two sprites in the "sprites/" directory:
121
+ one.png will contain "book" and "calculator", while two.png will con-
122
+ tain "magnet" and "television".
123
+
124
+ There may be cases where you need to customise an individual sprite and
125
+ you don't want to change the global setting; sprite allows you to spec-
126
+ ify any of the global settings with the exception of "sass" and "css"
127
+ like so:
128
+
129
+
130
+
131
+ sprite "path/to/sources/*" => "path/to/sprite.png",
132
+ :padding => 50, :url => "/elsewhere/:filename"
133
+
134
+
135
+
136
+ Each configuration option is prefixed with a colon rather than "con-
137
+ fig.", is separated from the value with " => ", and all but the final
138
+ option should be followed with a comma.
139
+
140
+ SEE ALSO
141
+ polymer(1), polymer-init(1)
142
+
143
+
144
+
145
+ POLYMER 1.0.0.BETA.3 September 2010 .POLYMER(5)
@@ -0,0 +1,130 @@
1
+ module Polymer
2
+ # Contains support for PNGOUT, OptiPNG, and PNGCrush.
3
+ module Optimisation
4
+
5
+ # Returns an array of optimisers supported on the current system.
6
+ #
7
+ # @return [Array<Polymer::Optimisation::Optimiser>]
8
+ #
9
+ def self.optimisers
10
+ @optimisers ||=
11
+ [PNGOut, OptiPNG, PNGCrush].select { |o| o.supported? }.map(&:new)
12
+ end
13
+
14
+ # Given a path to a file, runs all of the available optimisers until
15
+ # either:
16
+ #
17
+ # 1. No further optimisations could be found.
18
+ # 2. Each optimiser has been run three times.
19
+ #
20
+ # @param [Pathname] path
21
+ # Path to the file to be optimised.
22
+ #
23
+ # @return [Integer, false]
24
+ # Returns the number of bytes by which the filesize was reduced.
25
+ # @return [false]
26
+ # Returns false if the current machine has no optimisers available.
27
+ #
28
+ def self.optimise_file(path)
29
+ return false if optimisers.empty?
30
+
31
+ reduction = 0
32
+ skip = []
33
+
34
+ 3.times do |i|
35
+ before_iteration = reduction
36
+
37
+ optimisers.each do |optimiser|
38
+ next if skip.include?(optimiser)
39
+
40
+ if (opt_reduction = optimiser.run(path)) > 0
41
+ reduction += opt_reduction
42
+ else
43
+ # This optimiser can't find any more savings, don't run
44
+ # it again.
45
+ skip << optimiser
46
+ end
47
+ end # optimisers.each
48
+
49
+ # If the iteration found no savings, return immediately rather than
50
+ # running them again.
51
+ return reduction if before_iteration >= reduction
52
+ end # 3.times
53
+
54
+ reduction
55
+ end
56
+
57
+ # A base optimiser class.
58
+ class Optimiser
59
+ COMMAND = ''
60
+
61
+ # Runs the optimiser on a file once. Running again may yield further
62
+ # reductions in file size.
63
+ #
64
+ # @param [Pathname] path
65
+ # Path to the file to be optimised.
66
+ #
67
+ # @return [Integer]
68
+ # Returns the number of bytes by which the filesize was reduced.
69
+ #
70
+ # @see [Polymer::Optimisation.optimise_file]
71
+ #
72
+ def run(path)
73
+ before_size = path.size
74
+ `#{self.class::COMMAND.gsub(/\[PATH\]/, path.to_s)}`
75
+ before_size - path.size
76
+ end
77
+
78
+ # Tests if the optimiser is supported on the current system.
79
+ #
80
+ # @return [Boolean]
81
+ #
82
+ def self.supported?
83
+ unless defined?(@supported)
84
+ stdout = `which #{self::COMMAND.split(' ', 2).first}`
85
+ @supported = $?.exitstatus.zero? && stdout !~ /not found/
86
+ end
87
+
88
+ @supported
89
+ end
90
+ end # Optimiser
91
+
92
+ # An optimiser which uses PNGOUT. pngout may also be called
93
+ # "pngout-darwin" if installed using MacPorts.
94
+ class PNGOutDefault < Optimiser
95
+ COMMAND = 'pngout [PATH] [PATH] -s0 -k0 -y'
96
+ end
97
+
98
+ # MacPorts installs a pngout-darwin binary.
99
+ class PNGOutDarwin < PNGOutDefault
100
+ COMMAND = 'pngout-darwin [PATH] [PATH] -s0 -k0 -y'
101
+ end
102
+
103
+ # An optimiser which uses OptiPNG.
104
+ class OptiPNG < Optimiser
105
+ COMMAND = 'optipng [PATH]'
106
+ end # OptiPNG
107
+
108
+ # An optimiser which uses PNGCrush.
109
+ class PNGCrush < Optimiser
110
+ COMMAND = 'pngcrush -brute -e .png.tmp [PATH]'
111
+
112
+ # PNGCrush doesn't overwrite existing files. Instead the -e (extension)
113
+ # option is used to write to a temporary file, which is them moved over
114
+ # the new file.
115
+ def run(path)
116
+ super
117
+ FileUtils.rm(path)
118
+ FileUtils.mv(path.to_s + '.tmp', path)
119
+ end
120
+ end # PNGCrush
121
+
122
+ # Which PNGOUT should we use?
123
+ if not PNGOutDefault.supported? and PNGOutDarwin.supported?
124
+ PNGOut = PNGOutDarwin
125
+ else
126
+ PNGOut = PNGOutDefault
127
+ end
128
+
129
+ end # Optimisation
130
+ end # Polymer
@@ -0,0 +1,164 @@
1
+ module Polymer
2
+ # Represents a directory in which it is expected that there be a
3
+ # configuration file, and source images.
4
+ #
5
+ # The Project class exists mostly to make CLI tasks simpler; if you're using
6
+ # Polymer within your own library, you may prefer to create Sprite instances
7
+ # without using a Project.
8
+ #
9
+ class Project
10
+
11
+ # Defaults used by DSL when the user doesn't provide explicit values.
12
+ DEFAULTS = {
13
+ :sass => 'public/stylesheets/sass',
14
+ :url => "/images/:name.png",
15
+ :cache => '.polymer-cache',
16
+ :css => false,
17
+ :padding => 20
18
+ }
19
+
20
+ # Returns the path to the project root directory.
21
+ #
22
+ # @return [Pathname]
23
+ #
24
+ attr_reader :root
25
+
26
+ # @return [Pathname, false]
27
+ # The path to the Sass mixin file.
28
+ # @return [false]
29
+ # False if Sass has been disabled.
30
+ #
31
+ attr_reader :sass
32
+
33
+ # @return [Pathname, false]
34
+ # The path to the CSS file.
35
+ # @return [false]
36
+ # False if CSS generation has been disabled.
37
+ #
38
+ attr_reader :css
39
+
40
+ # An array containing all of the sprites in the project.
41
+ #
42
+ # @return [Array<Polymer::Sprite>]
43
+ #
44
+ attr_reader :sprites
45
+
46
+ # Creates a new Project.
47
+ #
48
+ # Note that +new+ does not validation of the given paths or options; it
49
+ # expects them to be correct. You're probably better using +DSL.build+.
50
+ #
51
+ # @param [Pathname] root_path
52
+ # Path to the root of the Polymer project. The .polymer config should
53
+ # reside in this directory.
54
+ # @param [Array<Polymer::Sprite>] sprites
55
+ # An array of sprites which belong to the project.
56
+ # @param [Hash] options
57
+ # Extra options for customising the behaviour of the Project.
58
+ #
59
+ # @option options [String, false] :css (false)
60
+ # Sets the path -- relative to +root_path+ -- at which the CSS
61
+ # file should be saved. Setting +:css+ to false will disable
62
+ # generation of CSS stylesheets.
63
+ # @option options [String, false] :sass (false)
64
+ # Sets the path -- relative to +root_path+ -- at which the Sass
65
+ # mixin file should be saved. Setting +:sass+ to false will
66
+ # disable generation of the mixin file.
67
+ #
68
+ def initialize(root_path, sprites, options = {})
69
+ @root = root_path
70
+ @sprites = sprites
71
+
72
+ @sass = extract_path :sass, options
73
+ @css = extract_path :css, options
74
+ @cachefile = extract_path :cache, options
75
+ end
76
+
77
+ # Returns the sprite whose name is +name+.
78
+ #
79
+ # @param [String] name
80
+ # The name of the sprite to be retrieved.
81
+ #
82
+ # @return [Polymer::Sprite] The sprite.
83
+ # @return [nil] If no such sprite exists.
84
+ #
85
+ def sprite(name)
86
+ sprites.detect { |sprite| sprite.name == name }
87
+ end
88
+
89
+ # Returns if the cache should be used.
90
+ #
91
+ # @return [true] If the cache should be used by CLI.
92
+ # @return [false] If the cache is disabled and should not be used.
93
+ #
94
+ def use_cache?
95
+ !! @cachefile
96
+ end
97
+
98
+ # Returns a Cache instance for this project.
99
+ #
100
+ # @return [Polymer::Cache]
101
+ #
102
+ def cache
103
+ @cache ||= Polymer::Cache.new(@cachefile)
104
+ end
105
+
106
+ private # ================================================================
107
+
108
+ # Extracts a path, typically specified in the DSL, and converts it to
109
+ # an absolute Pathname (by appending it on to +@root+).
110
+ #
111
+ # @param [Symbol] key
112
+ # The option key in which the value is expected.
113
+ # @param [Hash] options
114
+ # The options hash passed to #initialize.
115
+ #
116
+ # @return [Pathname]
117
+ # Returns the path appended to +@root+.
118
+ # @return [false, nil]
119
+ # When the option value was not a string.
120
+ #
121
+ def extract_path(key, options)
122
+ value = options.fetch(key, DEFAULTS[key])
123
+ value.is_a?(String) ? @root + value : value
124
+ end
125
+
126
+ # === Class Methods ======================================================
127
+
128
+ # Given a path to a directory, +find_config+ attempts to locate a
129
+ # suitable configuration file by looking for a ".polymer" or "polymer.rb"
130
+ # file. If no such file is found in the given directory, it ascends the
131
+ # directory structure until one is found, or it runs out of parent
132
+ # directories to check.
133
+ #
134
+ # If given a path to a file, +find_config+ assumes that this file is the
135
+ # config, and simply returns it as a Pathname.
136
+ #
137
+ # @param [Pathname, String] path
138
+ # The path to the directory or configuration file.
139
+ #
140
+ # @return [Pathname]
141
+ # The path to the found configuration.
142
+ #
143
+ # @raise [Polymer::MissingProject]
144
+ # Raised when +find_config+ could not find a suitable configuration
145
+ # file.
146
+ #
147
+ def self.find_config(path)
148
+ path, config_path = Pathname.new(path).expand_path, nil
149
+ return path if path.file?
150
+
151
+ path.ascend do |directory|
152
+ if (dot_polymer = directory + '.polymer').file?
153
+ return dot_polymer
154
+ elsif (polymer_rb = directory + 'polymer.rb').file?
155
+ return polymer_rb
156
+ end
157
+ end
158
+
159
+ raise MissingProject,
160
+ "Polymer couldn't find a configuration file at `#{path.to_s}'"
161
+ end
162
+
163
+ end # Project
164
+ end # Polymer
@@ -0,0 +1,38 @@
1
+ module Polymer
2
+ class SassGenerator
3
+
4
+ TEMPLATE = Pathname.new(__FILE__).dirname + 'templates/sass_mixins.erb'
5
+
6
+ # Given a project, generates a Sass mixin stylesheet which can can be
7
+ # included into your own Sass stylesheets.
8
+ #
9
+ # @param [Polymer::Project] project
10
+ # The project instance for which to generate a Sass stylesheet.
11
+ #
12
+ # @return [true]
13
+ # Returned when the stylesheet was generated and saved to the location
14
+ # specified by +project.sass+.
15
+ # @return [false]
16
+ # Returned when +project.sass+ evaluates to false, disabling generation
17
+ # of the Sass mixin file.
18
+ #
19
+ def self.generate(project)
20
+ return false unless project.sass
21
+
22
+ if project.sass.to_s[-5..-1] == '.sass'
23
+ project.sass.dirname.mkpath
24
+ save_to = project.sass
25
+ else
26
+ project.sass.mkpath
27
+ save_to = project.sass + '_polymer.sass'
28
+ end
29
+
30
+ File.open(save_to, 'w') do |file|
31
+ file.puts ERB.new(File.read(TEMPLATE), nil, '<>').result(binding)
32
+ end
33
+
34
+ true
35
+ end # self.generate
36
+
37
+ end # SassGenerator
38
+ end # Polymer