fontcustom 1.1.0.pre → 1.1.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/TODO.md +20 -5
  3. data/lib/fontcustom.rb +42 -4
  4. data/lib/fontcustom/cli.rb +65 -25
  5. data/lib/fontcustom/generator/font.rb +26 -26
  6. data/lib/fontcustom/generator/template.rb +29 -30
  7. data/lib/fontcustom/options.rb +207 -23
  8. data/lib/fontcustom/templates/_fontcustom-bootstrap-ie7.scss +9 -9
  9. data/lib/fontcustom/templates/_fontcustom-bootstrap.scss +19 -19
  10. data/lib/fontcustom/templates/_fontcustom-rails.scss +28 -0
  11. data/lib/fontcustom/templates/_fontcustom.scss +11 -11
  12. data/lib/fontcustom/templates/fontcustom-bootstrap-ie7.css +9 -9
  13. data/lib/fontcustom/templates/fontcustom-bootstrap.css +19 -19
  14. data/lib/fontcustom/templates/fontcustom-preview.html +34 -7
  15. data/lib/fontcustom/templates/fontcustom.css +11 -11
  16. data/lib/fontcustom/templates/fontcustom.yml +11 -6
  17. data/lib/fontcustom/util.rb +38 -159
  18. data/lib/fontcustom/version.rb +1 -1
  19. data/lib/fontcustom/watcher.rb +16 -14
  20. data/spec/fixtures/generators/.fontcustom-data-corrupted +18 -0
  21. data/spec/fixtures/generators/fontcustom.yml +1 -0
  22. data/spec/fixtures/{util/fontcustom.yml → options/any-file-name.yml} +0 -0
  23. data/spec/fixtures/{util → options}/config-is-in-dir/fontcustom.yml +0 -0
  24. data/spec/fixtures/options/fontcustom-empty.yml +1 -0
  25. data/spec/fixtures/{util → options}/fontcustom-malformed.yml +0 -0
  26. data/spec/fixtures/options/fontcustom.yml +1 -0
  27. data/spec/fixtures/options/no-config-here/.gitkeep +0 -0
  28. data/spec/fixtures/{util → options}/rails-like/config/fontcustom.yml +0 -0
  29. data/spec/fontcustom/generator/font_spec.rb +31 -15
  30. data/spec/fontcustom/generator/template_spec.rb +20 -18
  31. data/spec/fontcustom/options_spec.rb +428 -0
  32. data/spec/fontcustom/util_spec.rb +38 -336
  33. data/spec/fontcustom/watcher_spec.rb +7 -2
  34. data/spec/spec_helper.rb +1 -2
  35. metadata +23 -13
  36. data/lib/fontcustom/actions.rb +0 -28
  37. data/spec/fontcustom/actions_spec.rb +0 -22
@@ -1,27 +1,211 @@
1
+ require "yaml"
2
+ require "thor/shell"
3
+ require "thor/shell/basic"
4
+ require "thor/shell/color"
1
5
  require "thor/core_ext/hash_with_indifferent_access"
6
+ require "fontcustom/util"
2
7
 
3
8
  module Fontcustom
4
- # :output and :config are build from arguments
5
- DEFAULT_OPTIONS = Thor::CoreExt::HashWithIndifferentAccess.new({
6
- :project_root => Dir.pwd,
7
- :input => "",
8
- :templates => %w|css preview|,
9
- :font_name => "fontcustom",
10
- :file_hash => true,
11
- :css_prefix => "icon-",
12
- :preprocessor_font_path => "",
13
- :debug => false,
14
- :verbose => true
15
- })
16
-
17
- DATA_MODEL = Thor::CoreExt::HashWithIndifferentAccess.new({
18
- :fonts => [],
19
- :templates => [],
20
- :glyphs => [],
21
- :paths => {
22
- :css_to_fonts => "",
23
- :preprocessor_to_fonts => "",
24
- :preview_to_css => ""
25
- }
26
- })
9
+ class Options
10
+ include Util
11
+
12
+ attr_reader :project_root, :input, :output, :config, :data_cache, :templates,
13
+ :font_name, :file_hash, :css_prefix, :preprocessor_path, :skip_first, :debug, :verbose
14
+
15
+ def initialize(options = {})
16
+ check_fontforge
17
+
18
+ # Overwrite example defaults (used in Thor's help) with real defaults, if unchanged
19
+ EXAMPLE_OPTIONS.keys.each do |key|
20
+ options.delete(key) if options[key] == EXAMPLE_OPTIONS[key]
21
+ end
22
+ @cli_options = DEFAULT_OPTIONS.dup.merge options
23
+
24
+ @shell = Thor::Shell::Color.new
25
+ set_options
26
+ end
27
+
28
+ private
29
+
30
+ def set_options
31
+ set_config_path
32
+ load_config
33
+ merge_options
34
+ set_data_path
35
+ set_input_paths
36
+ set_output_paths
37
+ set_template_paths
38
+ end
39
+
40
+ def set_config_path
41
+ @config = if @cli_options[:config]
42
+ path = File.expand_path File.join(@cli_options[:project_root], @cli_options[:config])
43
+
44
+ # :config is the path to fontcustom.yml
45
+ if File.exists?(path) && ! File.directory?(path)
46
+ path
47
+
48
+ # :config is a dir containing fontcustom.yml
49
+ elsif File.exists? File.join(path, "fontcustom.yml")
50
+ File.join path, "fontcustom.yml"
51
+
52
+ else
53
+ raise Fontcustom::Error, "The configuration file was not found. Check #{relative_to_root(path)} and try again."
54
+ end
55
+ else
56
+ # fontcustom.yml is in the project_root
57
+ if File.exists? File.join(@cli_options[:project_root], "fontcustom.yml")
58
+ File.join @cli_options[:project_root], "fontcustom.yml"
59
+
60
+ # config/fontcustom.yml is in the project_root
61
+ elsif File.exists? File.join(@cli_options[:project_root], "config", "fontcustom.yml")
62
+ File.join @cli_options[:project_root], "config", "fontcustom.yml"
63
+
64
+ else
65
+ false
66
+ end
67
+ end
68
+ end
69
+
70
+ def load_config
71
+ @config_options = {}
72
+ return unless @config
73
+ begin
74
+ config = YAML.load File.open(@config)
75
+ @config_options = config if config # empty file returns false
76
+ rescue Exception => e
77
+ raise Fontcustom::Error, "The configuration file failed to load. Message: #{e.message}"
78
+ end
79
+ end
80
+
81
+ def merge_options
82
+ @cli_options.delete_if { |key, val| val == DEFAULT_OPTIONS[key] }
83
+
84
+ options = DEFAULT_OPTIONS.dup
85
+ options = options.merge @config_options
86
+ options = options.merge @cli_options
87
+ remove_instance_variable :@config_options
88
+ remove_instance_variable :@cli_options
89
+
90
+ # :config is excluded since it's already been set
91
+ keys = %w|project_root input output data_cache templates font_name file_hash css_prefix preprocessor_path skip_first debug verbose|
92
+ keys.each { |key| instance_variable_set("@#{key}", options[key]) }
93
+
94
+ @font_name = @font_name.strip.gsub(/\W/, '-')
95
+ end
96
+
97
+ def set_data_path
98
+ @data_cache = if ! @data_cache.nil?
99
+ File.expand_path File.join(@project_root, @data_cache)
100
+ elsif @config
101
+ File.join File.dirname(@config), '.fontcustom-data'
102
+ else
103
+ File.join @project_root, '.fontcustom-data'
104
+ end
105
+ end
106
+
107
+ def set_input_paths
108
+ if @input.is_a? Hash
109
+ @input = Thor::CoreExt::HashWithIndifferentAccess.new @input
110
+
111
+ if @input.has_key? "vectors"
112
+ @input[:vectors] = File.expand_path File.join(@project_root, @input[:vectors])
113
+ unless File.directory? input[:vectors]
114
+ raise Fontcustom::Error, "INPUT[\"vectors\"] should be a directory. Check #{relative_to_root(input[:vectors])} and try again."
115
+ end
116
+ else
117
+ raise Fontcustom::Error, "INPUT (as a hash) should contain a \"vectors\" key."
118
+ end
119
+
120
+ if @input.has_key? "templates"
121
+ @input[:templates] = File.expand_path File.join(@project_root, @input[:templates])
122
+ unless File.directory? @input[:templates]
123
+ raise Fontcustom::Error, "INPUT[\"templates\"] should be a directory. Check #{relative_to_root(input[:templates])} and try again."
124
+ end
125
+ else
126
+ @input[:templates] = @input[:vectors]
127
+ end
128
+ elsif @input.is_a? String
129
+ input = File.expand_path File.join(@project_root, @input)
130
+ unless File.directory? input
131
+ raise Fontcustom::Error, "INPUT (as a string) should be a directory. Check #{relative_to_root(input)} and try again."
132
+ end
133
+ @input = Thor::CoreExt::HashWithIndifferentAccess.new({
134
+ :vectors => input,
135
+ :templates => input
136
+ })
137
+ end
138
+
139
+ if Dir[File.join(@input[:vectors], "*.{svg,eps}")].empty?
140
+ raise Fontcustom::Error, "#{relative_to_root(@input[:vectors])} doesn't contain any vectors (*.svg or *.eps files)."
141
+ end
142
+ end
143
+
144
+ def set_output_paths
145
+ if @output.is_a? Hash
146
+ @output = Thor::CoreExt::HashWithIndifferentAccess.new @output
147
+ raise Fontcustom::Error, "OUTPUT (as a hash) should contain a \"fonts\" key." unless @output.has_key? "fonts"
148
+
149
+ @output.each do |key, val|
150
+ @output[key] = File.expand_path File.join(@project_root, val)
151
+ if File.exists?(val) && ! File.directory?(val)
152
+ raise Fontcustom::Error, "OUTPUT[\"#{key}\"] should be a directory, not a file. Check #{relative_to_root(val)} and try again."
153
+ end
154
+ end
155
+
156
+ @output[:css] ||= @output[:fonts]
157
+ @output[:preview] ||= @output[:fonts]
158
+ else
159
+ if @output.is_a? String
160
+ output = File.expand_path File.join(@project_root, @output)
161
+ if File.exists?(output) && ! File.directory?(output)
162
+ raise Fontcustom::Error, "OUTPUT should be a directory, not a file. Check #{relative_to_root(output)} and try again."
163
+ end
164
+ else
165
+ output = File.join @project_root, @font_name
166
+ say_message :status, "All generated files will be added into `#{relative_to_root(output)}/` by default."
167
+ end
168
+
169
+ @output = Thor::CoreExt::HashWithIndifferentAccess.new({
170
+ :fonts => output,
171
+ :css => output,
172
+ :preview => output
173
+ })
174
+ end
175
+ end
176
+
177
+ # Translates shorthand to full path of packages templates, otherwise,
178
+ # it checks input and pwd for the template.
179
+ #
180
+ # Could arguably belong in Generator::Template, however, it's nice to
181
+ # be able to catch template errors before any generator runs.
182
+ def set_template_paths
183
+ template_path = File.join Fontcustom.gem_lib, "templates"
184
+
185
+ @templates = @templates.map do |template|
186
+ case template
187
+ when "preview"
188
+ File.join template_path, "fontcustom-preview.html"
189
+ when "css"
190
+ File.join template_path, "fontcustom.css"
191
+ when "scss"
192
+ File.join template_path, "_fontcustom.scss"
193
+ when "scss-rails"
194
+ File.join template_path, "_fontcustom-rails.scss"
195
+ when "bootstrap"
196
+ File.join template_path, "fontcustom-bootstrap.css"
197
+ when "bootstrap-scss"
198
+ File.join template_path, "_fontcustom-bootstrap.scss"
199
+ when "bootstrap-ie7"
200
+ File.join template_path, "fontcustom-bootstrap-ie7.css"
201
+ when "bootstrap-ie7-scss"
202
+ File.join template_path, "_fontcustom-bootstrap-ie7.scss"
203
+ else
204
+ path = File.expand_path File.join(@input[:templates], template)
205
+ raise Fontcustom::Error, "The custom template at #{relative_to_root(path)} does not exist." unless File.exists? path
206
+ path
207
+ end
208
+ end
209
+ end
210
+ end
27
211
  end
@@ -1,22 +1,22 @@
1
1
  //
2
- // Icon Font: <%= @opts[:font_name] %>
2
+ // Icon Font: <%= @opts.font_name %>
3
3
  // Bootstrap IE7 Enabler
4
4
  //
5
5
 
6
- [class^="<%= @opts[:css_prefix] %>"],
7
- [class*=" <%= @opts[:css_prefix] %>"] {
8
- font-family: "<%= @opts[:font_name] %>";
6
+ [class^="<%= @opts.css_prefix %>"],
7
+ [class*=" <%= @opts.css_prefix %>"] {
8
+ font-family: "<%= @opts.font_name %>";
9
9
  font-style: normal;
10
10
  font-weight: normal;
11
11
  }
12
12
 
13
- .btn.dropdown-toggle [class^="<%= @opts[:css_prefix] %>"],
14
- .btn.dropdown-toggle [class*=" <%= @opts[:css_prefix] %>"] {
13
+ .btn.dropdown-toggle [class^="<%= @opts.css_prefix %>"],
14
+ .btn.dropdown-toggle [class*=" <%= @opts.css_prefix %>"] {
15
15
  line-height: 1.4em;
16
16
  }
17
17
 
18
- .<%= @opts[:css_prefix] %>large {
18
+ .<%= @opts.css_prefix %>large {
19
19
  font-size: 1.3333em;
20
20
  }
21
- <% @data[:glyphs].each_with_index do |name, index| %>
22
- .<%= @opts[:css_prefix] + name %> { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x<%= (61696+index).to_s(16) %>;&nbsp;'); }<% end %>
21
+ <% @glyphs.each_with_index do |name, index| %>
22
+ .<%= @opts.css_prefix + name %> { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x<%= (61696+index).to_s(16) %>;&nbsp;'); }<% end %>
@@ -1,63 +1,63 @@
1
1
  //
2
- // Icon Font: <%= @opts[:font_name] %>
2
+ // Icon Font: <%= @opts.font_name %>
3
3
  // Bootstrap Override
4
4
  //
5
5
 
6
6
  @font-face {
7
- font-family: "<%= @opts[:font_name] %>";
8
- src: url("<%= @data[:paths][:preprocessor_to_fonts] %>.eot");
9
- src: url("<%= @data[:paths][:preprocessor_to_fonts] %>.eot?#iefix") format("embedded-opentype"),
10
- url("<%= @data[:paths][:preprocessor_to_fonts] %>.woff") format("woff"),
11
- url("<%= @data[:paths][:preprocessor_to_fonts] %>.ttf") format("truetype"),
12
- url("<%= @data[:paths][:preprocessor_to_fonts] %>.svg#<%= @opts[:font_name] %>") format("svg");
7
+ font-family: "<%= @opts.font_name %>";
8
+ src: url("<%= @font_path_pre %>.eot");
9
+ src: url("<%= @font_path_pre %>.eot?#iefix") format("embedded-opentype"),
10
+ url("<%= @font_path_pre %>.woff") format("woff"),
11
+ url("<%= @font_path_pre %>.ttf") format("truetype"),
12
+ url("<%= @font_path_pre %>.svg#<%= @opts.font_name %>") format("svg");
13
13
  font-weight: normal;
14
14
  font-style: normal;
15
15
  }
16
16
 
17
- [class^="<%= @opts[:css_prefix] %>"]:before, [class*=" <%= @opts[:css_prefix] %>"]:before {
18
- font-family: "<%= @opts[:font_name] %>";
17
+ [class^="<%= @opts.css_prefix %>"]:before, [class*=" <%= @opts.css_prefix %>"]:before {
18
+ font-family: "<%= @opts.font_name %>";
19
19
  font-weight: normal;
20
20
  font-style: normal;
21
21
  display: inline-block;
22
22
  text-decoration: inherit;
23
23
  }
24
24
 
25
- a [class^="<%= @opts[:css_prefix] %>"], a [class*=" <%= @opts[:css_prefix] %>"] {
25
+ a [class^="<%= @opts.css_prefix %>"], a [class*=" <%= @opts.css_prefix %>"] {
26
26
  display: inline-block;
27
27
  text-decoration: inherit;
28
28
  }
29
29
 
30
- .<%= @opts[:css_prefix] %>large:before {
30
+ .<%= @opts.css_prefix %>large:before {
31
31
  vertical-align: top;
32
32
  font-size: 1.333em;
33
33
  }
34
34
 
35
- .btn [class^="<%= @opts[:css_prefix] %>"], .btn [class*=" <%= @opts[:css_prefix] %>"] {
35
+ .btn [class^="<%= @opts.css_prefix %>"], .btn [class*=" <%= @opts.css_prefix %>"] {
36
36
  line-height: 0.9em;
37
37
  }
38
38
 
39
- li [class^="<%= @opts[:css_prefix] %>"], li [class*=" <%= @opts[:css_prefix] %>"] {
39
+ li [class^="<%= @opts.css_prefix %>"], li [class*=" <%= @opts.css_prefix %>"] {
40
40
  display: inline-block;
41
41
  width: 1.25em;
42
42
  text-align: center;
43
43
  }
44
44
 
45
- li .<%= @opts[:css_prefix] %>large[class^="<%= @opts[:css_prefix] %>"], li .<%= @opts[:css_prefix] %>large[class*=" <%= @opts[:css_prefix] %>"] {
45
+ li .<%= @opts.css_prefix %>large[class^="<%= @opts.css_prefix %>"], li .<%= @opts.css_prefix %>large[class*=" <%= @opts.css_prefix %>"] {
46
46
  width: 1.875em;
47
47
  }
48
48
 
49
- li[class^="<%= @opts[:css_prefix] %>"], li[class*=" <%= @opts[:css_prefix] %>"] {
49
+ li[class^="<%= @opts.css_prefix %>"], li[class*=" <%= @opts.css_prefix %>"] {
50
50
  margin-left: 0;
51
51
  list-style-type: none;
52
52
  }
53
53
 
54
- li[class^="<%= @opts[:css_prefix] %>"]:before, li[class*=" <%= @opts[:css_prefix] %>"]:before {
54
+ li[class^="<%= @opts.css_prefix %>"]:before, li[class*=" <%= @opts.css_prefix %>"]:before {
55
55
  text-indent: -2em;
56
56
  text-align: center;
57
57
  }
58
58
 
59
- li[class^="<%= @opts[:css_prefix] %>"].<%= @opts[:css_prefix] %>large:before, li[class*=" <%= @opts[:css_prefix] %>"].<%= @opts[:css_prefix] %>large:before {
59
+ li[class^="<%= @opts.css_prefix %>"].<%= @opts.css_prefix %>large:before, li[class*=" <%= @opts.css_prefix %>"].<%= @opts.css_prefix %>large:before {
60
60
  text-indent: -1.333em;
61
61
  }
62
- <% @data[:glyphs].each_with_index do |name, index| %>
63
- .<%= @opts[:css_prefix] + name %>:before { content: "\<%= (61696+index).to_s(16) %>"; }<% end %>
62
+ <% @glyphs.each_with_index do |name, index| %>
63
+ .<%= @opts.css_prefix + name %>:before { content: "\<%= (61696+index).to_s(16) %>"; }<% end %>
@@ -0,0 +1,28 @@
1
+ //
2
+ // Icon Font: <%= @opts.font_name %>
3
+ //
4
+
5
+ @font-face {
6
+ font-family: "<%= @opts.font_name %>";
7
+ src: font-url("<%= @font_path_pre %>.eot");
8
+ src: font-url("<%= @font_path_pre %>.eot?#iefix") format("embedded-opentype"),
9
+ font-url("<%= @font_path_pre %>.woff") format("woff"),
10
+ font-url("<%= @font_path_pre %>.ttf") format("truetype"),
11
+ font-url("<%= @font_path_pre %>.svg#<%= @opts.font_name %>") format("svg");
12
+ font-weight: normal;
13
+ font-style: normal;
14
+ }
15
+
16
+ <%= @glyphs.map {|name| ".#{@opts.css_prefix + name}:before"}.join(",\n") %> {
17
+ font-family: "<%= @opts.font_name %>";
18
+ font-style: normal;
19
+ font-weight: normal;
20
+ font-variant: normal;
21
+ text-transform: none;
22
+ line-height: 1;
23
+ -webkit-font-smoothing: antialiased;
24
+ display: inline-block;
25
+ text-decoration: inherit;
26
+ }
27
+ <% @glyphs.each_with_index do |name, index| %>
28
+ .<%= @opts.css_prefix + name %>:before { content: "\<%= (61696+index).to_s(16) %>"; }<% end %>
@@ -1,20 +1,20 @@
1
1
  //
2
- // Icon Font: <%= @opts[:font_name] %>
2
+ // Icon Font: <%= @opts.font_name %>
3
3
  //
4
4
 
5
5
  @font-face {
6
- font-family: "<%= @opts[:font_name] %>";
7
- src: url("<%= @data[:paths][:preprocessor_to_fonts] %>.eot");
8
- src: url("<%= @data[:paths][:preprocessor_to_fonts] %>.eot?#iefix") format("embedded-opentype"),
9
- url("<%= @data[:paths][:preprocessor_to_fonts] %>.woff") format("woff"),
10
- url("<%= @data[:paths][:preprocessor_to_fonts] %>.ttf") format("truetype"),
11
- url("<%= @data[:paths][:preprocessor_to_fonts] %>.svg#<%= @opts[:font_name] %>") format("svg");
6
+ font-family: "<%= @opts.font_name %>";
7
+ src: url("<%= @font_path_pre %>.eot");
8
+ src: url("<%= @font_path_pre %>.eot?#iefix") format("embedded-opentype"),
9
+ url("<%= @font_path_pre %>.woff") format("woff"),
10
+ url("<%= @font_path_pre %>.ttf") format("truetype"),
11
+ url("<%= @font_path_pre %>.svg#<%= @opts.font_name %>") format("svg");
12
12
  font-weight: normal;
13
13
  font-style: normal;
14
14
  }
15
15
 
16
- <%= @data[:glyphs].map {|name| ".#{@opts[:css_prefix] + name}:before"}.join(",\n") %> {
17
- font-family: "<%= @opts[:font_name] %>";
16
+ <%= @glyphs.map {|name| ".#{@opts.css_prefix + name}:before"}.join(",\n") %> {
17
+ font-family: "<%= @opts.font_name %>";
18
18
  font-style: normal;
19
19
  font-weight: normal;
20
20
  font-variant: normal;
@@ -24,5 +24,5 @@
24
24
  display: inline-block;
25
25
  text-decoration: inherit;
26
26
  }
27
- <% @data[:glyphs].each_with_index do |name, index| %>
28
- .<%= @opts[:css_prefix] + name %>:before { content: "\<%= (61696+index).to_s(16) %>"; }<% end %>
27
+ <% @glyphs.each_with_index do |name, index| %>
28
+ .<%= @opts.css_prefix + name %>:before { content: "\<%= (61696+index).to_s(16) %>"; }<% end %>
@@ -1,22 +1,22 @@
1
1
  /*
2
- Icon Font: <%= @opts[:font_name] %>
2
+ Icon Font: <%= @opts.font_name %>
3
3
  Bootstrap IE7 Enabler
4
4
  */
5
5
 
6
- [class^="<%= @opts[:css_prefix] %>"],
7
- [class*=" <%= @opts[:css_prefix] %>"] {
8
- font-family: "<%= @opts[:font_name] %>";
6
+ [class^="<%= @opts.css_prefix %>"],
7
+ [class*=" <%= @opts.css_prefix %>"] {
8
+ font-family: "<%= @opts.font_name %>";
9
9
  font-style: normal;
10
10
  font-weight: normal;
11
11
  }
12
12
 
13
- .btn.dropdown-toggle [class^="<%= @opts[:css_prefix] %>"],
14
- .btn.dropdown-toggle [class*=" <%= @opts[:css_prefix] %>"] {
13
+ .btn.dropdown-toggle [class^="<%= @opts.css_prefix %>"],
14
+ .btn.dropdown-toggle [class*=" <%= @opts.css_prefix %>"] {
15
15
  line-height: 1.4em;
16
16
  }
17
17
 
18
- .<%= @opts[:css_prefix] %>large {
18
+ .<%= @opts.css_prefix %>large {
19
19
  font-size: 1.3333em;
20
20
  }
21
- <% @data[:glyphs].each_with_index do |name, index| %>
22
- .<%= @opts[:css_prefix] + name %> { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x<%= (61696+index).to_s(16) %>;&nbsp;'); }<% end %>
21
+ <% @glyphs.each_with_index do |name, index| %>
22
+ .<%= @opts.css_prefix + name %> { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x<%= (61696+index).to_s(16) %>;&nbsp;'); }<% end %>