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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d394a232cd9bca5b67961598fe0696c677241fdf
4
- data.tar.gz: 33d86584a9255b4a937551c69342718bde7e7134
3
+ metadata.gz: 50485d013861fa91e2ae86ed2741630ad3b285ff
4
+ data.tar.gz: 5b30887bf48000f2faf726c1995fea6f2bcb9ba8
5
5
  SHA512:
6
- metadata.gz: f96ad328c2b67b55eb1379bb362ee42c6e2240a7566976dae7abb615b737da7d6c36d8f1fc23a13d6cb644e65ad8dab5b2d60a5a988c5e5776cc99c37bd0b667
7
- data.tar.gz: c1126c9542867c77421d60c04afacf87eaa9844747d833e5b6dc74c23a312212dcf846560ed2282efdc0e1ea015706ff1da5f2acbbcaab5fa8e154c05d6b3268
6
+ metadata.gz: ac4e3f33a7748d4884995e8bdd3725dfb71bc51c1642ebd4d57fd1c9a2ac695c6b1775c73d276aec5b973bbd4316c0bf2b304a5f5939ce3cc798b57dfb36af5e
7
+ data.tar.gz: a768dd51e28c43b2f3634ecb0b082edde1510a34f563c1598a4ee9add5e8708ab2141d867284c99759ee8628e8d47bff2190572932fcbe6e3d3611fbbc9f36e4
data/TODO.md CHANGED
@@ -1,6 +1,21 @@
1
- ## TODO
1
+ # 1.1.0 TODO
2
2
 
3
- * `clear_file` and `append_to_file` can probably be combined
4
- * Handle error through Fontcustom::Actions
5
- * Messages for improper config, default settings, etc.
6
- * Colors for thor :say
3
+ * Investigate initial update to .fontcustom-data
4
+ * Verify all templates work
5
+
6
+ * Include pull requests
7
+ * Allow absolute paths
8
+ * Abstract path expansion into Util
9
+ * Improve paths in messages (wrap in ticks)
10
+ * Improve error messages in Watcher and Fontcustom.rb
11
+
12
+ # Maybe
13
+
14
+ * Option to set icon canvas size (auto, string, or hash)
15
+ * `fontcustom clean`
16
+
17
+ * Have error messages `say_status` themselves?
18
+ * Change outputed filenames to reflect font name
19
+ * On install hook / message to remind about installing fontforge
20
+ * --silent instead of (or alongside?) --verbose
21
+ * Configure colors for thor say
data/lib/fontcustom.rb CHANGED
@@ -1,21 +1,59 @@
1
1
  require "fontcustom/version"
2
- require "fontcustom/options"
3
2
  require "fontcustom/error"
3
+ require "fontcustom/options"
4
4
  require "fontcustom/util"
5
- require "fontcustom/actions"
6
5
  require "fontcustom/generator/font"
7
6
  require "fontcustom/generator/template"
7
+ require "thor/core_ext/hash_with_indifferent_access"
8
8
 
9
9
  module Fontcustom
10
10
  ##
11
11
  # Clean Ruby API to workaround Thor
12
12
  def compile(options)
13
- opts = Fontcustom::Util.collect_options options
13
+ opts = Fontcustom::Options.new options
14
14
  Fontcustom::Generator::Font.start [opts]
15
15
  Fontcustom::Generator::Template.start [opts]
16
16
  rescue Fontcustom::Error => e
17
17
  puts "ERROR: #{e.message}"
18
18
  end
19
19
 
20
- module_function :compile
20
+ def gem_lib
21
+ File.expand_path(File.join(File.dirname(__FILE__), "fontcustom"))
22
+ end
23
+
24
+ module_function :compile, :gem_lib
25
+
26
+ ##
27
+ # These are used in Thor CLI but overridden when the Options class is built
28
+ EXAMPLE_OPTIONS = {
29
+ :project_root => "`pwd`",
30
+ :output => "PROJECT_ROOT/FONT_NAME"
31
+ }
32
+
33
+ ##
34
+ #
35
+ DEFAULT_OPTIONS = Thor::CoreExt::HashWithIndifferentAccess.new({
36
+ :project_root => Dir.pwd,
37
+ :input => nil,
38
+ :output => nil,
39
+ :config => nil,
40
+ :data_cache => nil,
41
+ :templates => %w|css preview|,
42
+ :font_name => "fontcustom",
43
+ :file_hash => true,
44
+ :css_prefix => "icon-",
45
+ :preprocessor_path => "",
46
+ :debug => false,
47
+ :verbose => true
48
+ })
49
+
50
+ DATA_MODEL = Thor::CoreExt::HashWithIndifferentAccess.new({
51
+ :fonts => [],
52
+ :templates => [],
53
+ :glyphs => [],
54
+ :paths => {
55
+ :css_to_fonts => "",
56
+ :preprocessor_to_fonts => ""
57
+ }
58
+ })
21
59
  end
@@ -5,53 +5,93 @@ require "fontcustom/watcher"
5
5
 
6
6
  module Fontcustom
7
7
  class CLI < Thor
8
- include Thor::Actions
9
-
10
- # Actual defaults are stored in Fontcustom::DEFAULT_OPTIONS instead of Thor
11
- class_option :project_root, :aliases => "-r", :desc => "The base directory that all inputs and outputs are relative to. Default: working directory"
12
- class_option :output, :aliases => "-o", :desc => "The output directory (will be created if it doesn't exist). Default: PROJECT_ROOT/FONT_NAME/"
13
- class_option :config, :aliases => "-c", :desc => "Path to an optional configuration file. Files at PROJECT_ROOT/fontcustom.yml and PROJECT_ROOT/config/fontcustom.yml are loaded automatically."
14
- class_option :templates, :aliases => "-t", :type => :array, :desc => "List of templates to compile alongside fonts. Accepts 'preview css scss bootstrap bootstrap-scss bootstrap-ie7 bootstrap-ie7-scss' or custom templates (advanced, run `fontcustom config` and read the example for more details). Default: 'css preview'"
15
- class_option :font_name, :aliases => "-n", :desc => "The font name used in your templates. Also determines the default OUTPUT directory name. Default: 'fontcustom'"
16
- class_option :file_hash, :aliases => "-h", :type => :boolean, :desc => "Option to generate font files with asset-busting hashes. Default: true"
17
- class_option :css_prefix, :aliases => "-p", :desc => "The prefix for each glyph's CSS class. Default: 'icon-'"
18
- class_option :preprocessor_font_path, :alias => "-s", :desc => "The font path passed to CSS preprocessors (used instead of normal paths in preprocessed CSS templates). Default: none"
19
- class_option :debug, :aliases => "-d", :type => :boolean, :desc => "Display debug messages from fontforge. Default: false"
20
- class_option :verbose, :aliases => "-v", :type => :boolean, :desc => "Display verbose messages. Default: true"
8
+ include Actions
9
+
10
+ default_task :show_help
11
+
12
+ class_option :project_root, :aliases => "-r", :type => :string,
13
+ :desc => "The root context for any relative paths (INPUT, OUTPUT, CONFIG).",
14
+ :default => EXAMPLE_OPTIONS[:project_root]
15
+
16
+ class_option :output, :aliases => "-o", :type => :string,
17
+ :desc => "Where generated files are saved. Can be fine-tuned if a configuration file is used.",
18
+ :default => EXAMPLE_OPTIONS[:output]
19
+
20
+ class_option :config, :aliases => "-c", :type => :string,
21
+ :desc => "Optional configuration file. PROJECT_ROOT/fontcustom.yml and PROJECT_ROOT/config/fontcustom.yml are loaded automatically."
22
+
23
+ class_option :data_cache, :aliases => "-d", :type => :string,
24
+ :desc => "Optional path to `.fontcustom-data`. Used for garbage collection."
25
+
26
+ class_option :templates, :aliases => "-t", :type => :array,
27
+ :desc => "Space-delinated array of templates to generate alongside fonts.",
28
+ :enum => %w|preview css scss scss-rails bootstrap bootstrap-scss bootstrap-ie7 bootstrap-ie7-scss|,
29
+ :default => DEFAULT_OPTIONS[:templates]
30
+
31
+ class_option :font_name, :aliases => "-f", :type => :string,
32
+ :desc => "Set the font's name.",
33
+ :default => DEFAULT_OPTIONS[:font_name]
34
+
35
+ class_option :css_prefix, :aliases => "-p", :type => :string,
36
+ :desc => "Prefix for each glyph's CSS class.",
37
+ :default => DEFAULT_OPTIONS[:css_prefix]
38
+
39
+ class_option :preprocessor_path, :aliases => "-s", :type => :string,
40
+ :desc => "Special path used in CSS proprocessor templates."
41
+
42
+ # TODO make this negative (no file hash)
43
+ class_option :file_hash, :type => :boolean,
44
+ :desc => "Option to generate font files with asset-busting hashes.",
45
+ :default => DEFAULT_OPTIONS[:file_hash]
46
+
47
+ class_option :debug, :type => :boolean,
48
+ :desc => "Display debug messages from fontforge.",
49
+ :default => DEFAULT_OPTIONS[:debug]
50
+
51
+ class_option :verbose, :type => :boolean,
52
+ :desc => "Display verbose messages.",
53
+ :default => DEFAULT_OPTIONS[:verbose]
21
54
 
22
55
  # Required for Thor::Actions#template
23
56
  def self.source_root
24
- File.join Fontcustom::Util.gem_lib_path, "templates"
57
+ File.join Fontcustom.gem_lib, "templates"
25
58
  end
26
59
 
27
- desc "compile [INPUT] [OPTIONS]", "Generates webfonts and CSS from *.svg and *.eps files in INPUT."
60
+ desc "compile [INPUT] [OPTIONS]", "Generates webfonts and templates from *.svg and *.eps files in INPUT. Default: `pwd`"
28
61
  def compile(input = nil)
29
62
  opts = options.merge :input => input
30
- opts = Fontcustom::Util.collect_options opts
63
+ opts = Fontcustom::Options.new(opts)
31
64
  Fontcustom::Generator::Font.start [opts]
32
65
  Fontcustom::Generator::Template.start [opts]
33
66
  rescue Fontcustom::Error => e
34
- puts "ERROR: #{e.message}"
67
+ say_status :error, e.message
35
68
  end
36
69
 
37
- desc "watch [INPUT] [OPTIONS]", "Watches INPUT for changes and regenerates files automatically. Ctrl + C to stop."
38
- method_option :skip_first, :aliases => "-s", :type => :boolean, :desc => "Skip the initial compile upon watching. Default: false"
70
+ desc "watch [INPUT] [OPTIONS]", "Watches INPUT for changes and regenerates files automatically. Ctrl + C to stop. Default: `pwd`"
71
+ method_option :skip_first, :type => :boolean,
72
+ :desc => "Skip the initial compile upon watching.",
73
+ :default => false
39
74
  def watch(input = nil)
40
75
  opts = options.merge :input => input, :skip_first => !! options[:skip_first]
41
- opts = Fontcustom::Util.collect_options opts
76
+ opts = Fontcustom::Options.new(opts)
42
77
  Fontcustom::Watcher.new(opts).watch
43
78
  rescue Fontcustom::Error => e
44
- puts "ERROR: #{e.message}"
79
+ say_status :error, e.message
45
80
  end
46
81
 
47
- desc "config [DIR]", "Adds an annotated fontcustom.yml to DIR. Default: working directory"
82
+ desc "config [DIR]", "Generates an annotated configuration file (fontcustom.yml) in DIR. Default: `pwd`"
48
83
  def config(dir = Dir.pwd)
49
84
  template "fontcustom.yml", File.join(dir, "fontcustom.yml")
50
85
  end
51
86
 
52
- desc "version", "Shows the version information."
53
- def version
54
- puts "fontcustom-#{Fontcustom::VERSION}"
87
+ desc "hidden", "hidden", :hide => true
88
+ method_option :version, :aliases => "-v", :type => :boolean, :default => false
89
+ def show_help
90
+ if options[:version]
91
+ puts "fontcustom-#{Fontcustom::VERSION}"
92
+ else
93
+ help
94
+ end
55
95
  end
56
96
  end
57
97
  end
@@ -1,35 +1,36 @@
1
1
  require "json"
2
2
  require "thor"
3
3
  require "thor/group"
4
+ require "thor/actions"
4
5
  require "thor/core_ext/hash_with_indifferent_access"
5
6
 
6
7
  module Fontcustom
7
8
  module Generator
8
9
  class Font < Thor::Group
9
- include Actions
10
+ include Util
11
+ include Thor::Actions
10
12
 
11
- # Instead of passing each option individually we're passing the entire options hash as an argument.
13
+ # Instead of passing each option individually we're passing the entire options hash as an argument.
12
14
  # This is DRYier, easier to maintain.
13
- argument :opts
15
+ argument :opts
14
16
 
15
17
  def prepare_output_dirs
16
- dirs = opts[:output].values.uniq
18
+ dirs = opts.output.values.uniq
17
19
  dirs.each do |dir|
18
20
  unless File.directory? dir
19
- empty_directory dir, :verbose => opts[:verbose]
21
+ empty_directory dir, :verbose => opts.verbose
20
22
  end
21
23
  end
22
24
  end
23
25
 
24
26
  def get_data
25
- datafile = File.join opts[:project_root], ".fontcustom-data"
26
- if File.exists? datafile
27
+ if File.exists? opts.data_cache
27
28
  begin
28
- data = File.read datafile
29
+ data = File.read opts.data_cache
29
30
  data = JSON.parse(data, :symbolize_names => true) unless data.empty?
30
31
  @data = data.is_a?(Hash) ? Thor::CoreExt::HashWithIndifferentAccess.new(data) : Fontcustom::DATA_MODEL.dup
31
32
  rescue JSON::ParserError
32
- raise Fontcustom::Error, "The .fontcustom-data file at #{datafile} is corrupted. Fix the JSON or delete the file to start from scratch."
33
+ raise Fontcustom::Error, "#{opts.data_cache} is corrupted. Fix the JSON or delete the file to start from scratch."
33
34
  end
34
35
  else
35
36
  @data = Fontcustom::DATA_MODEL.dup
@@ -40,38 +41,39 @@ module Fontcustom
40
41
  return if @data[:fonts].empty?
41
42
  begin
42
43
  deleted = []
43
- @data[:fonts].each do |file|
44
+ @data[:fonts].each do |file|
44
45
  remove_file file, :verbose => false
45
46
  deleted << file
46
47
  end
47
48
  ensure
48
49
  @data[:fonts] = @data[:fonts] - deleted
49
50
  json = JSON.pretty_generate @data
50
- file = File.join(opts[:project_root], ".fontcustom-data")
51
- clear_file(file)
52
- append_to_file file, json, :verbose => false
53
- say_changed :removed, deleted
51
+ overwrite_file opts.data_cache, json
52
+ say_changed :delete, deleted
54
53
  end
55
54
  end
56
-
55
+
57
56
  def generate
58
57
  # TODO align option naming conventions with python script
59
58
  # TODO remove name arg if default is already set in python (or rm from python)
60
- name = opts[:font_name] ? " --name " + opts[:font_name] : ""
61
- hash = opts[:file_hash] ? "" : " --nohash"
62
- cmd = "fontforge -script #{Fontcustom::Util.gem_lib_path}/scripts/generate.py #{opts[:input][:vectors]} #{opts[:output][:fonts] + name + hash} 2>&1"
59
+ name = opts.font_name ? " --name " + opts.font_name : ""
60
+ hash = opts.file_hash ? "" : " --nohash"
61
+ cmd = "fontforge -script #{Fontcustom.gem_lib}/scripts/generate.py #{opts.input[:vectors]} #{opts.output[:fonts] + name + hash} 2>&1"
63
62
 
64
63
  output = `#{cmd}`.split("\n")
65
64
  @json = output[3] # JSON
65
+
66
+ # fontforge wrongly returns the following error message if only a single glyph.
67
+ # We can strip it out and ignore it.
66
68
  if @json == 'Warning: Font contained no glyphs'
67
69
  @json = output[4]
68
- output = output[5..-1] # Strip fontforge message
70
+ output = output[5..-1]
69
71
  else
70
72
  @json = output[3]
71
- output = output[4..-1] # Strip fontforge message
73
+ output = output[4..-1]
72
74
  end
73
75
 
74
- if opts[:debug]
76
+ if opts.debug
75
77
  shell.say "DEBUG: (raw output from fontforge)"
76
78
  shell.say output
77
79
  end
@@ -85,18 +87,16 @@ module Fontcustom
85
87
  @json = JSON.parse(@json, :symbolize_names => true)
86
88
  @data.merge! @json
87
89
  @data[:glyphs].map! { |glyph| glyph.gsub(/\W/, "-") }
88
- @data[:fonts].map! { |font| File.join(@opts[:output][:fonts], font) }
90
+ @data[:fonts].map! { |font| File.join(opts.output[:fonts], font) }
89
91
  end
90
92
 
91
93
  def announce_files
92
- say_changed :created, @data[:fonts]
94
+ say_changed :create, @data[:fonts]
93
95
  end
94
96
 
95
97
  def save_data
96
98
  json = JSON.pretty_generate @data
97
- file = File.join(opts[:project_root], ".fontcustom-data")
98
- clear_file(file)
99
- append_to_file file, json, :verbose => false
99
+ overwrite_file opts.data_cache, json
100
100
  end
101
101
  end
102
102
  end
@@ -2,11 +2,13 @@ require "json"
2
2
  require "pathname"
3
3
  require "thor"
4
4
  require "thor/group"
5
+ require "thor/actions"
5
6
 
6
7
  module Fontcustom
7
8
  module Generator
8
9
  class Template < Thor::Group
9
- include Actions
10
+ include Util
11
+ include Thor::Actions
10
12
 
11
13
  # Instead of passing each option individually we're passing the entire options hash as an argument.
12
14
  # This is DRYier, easier to maintain.
@@ -14,19 +16,18 @@ module Fontcustom
14
16
 
15
17
  # Required for Thor::Actions#template
16
18
  def self.source_root
17
- File.join Fontcustom::Util.gem_lib_path, "templates"
19
+ File.join Fontcustom.gem_lib, "templates"
18
20
  end
19
21
 
20
22
  def get_data
21
- data = File.join(opts[:project_root], ".fontcustom-data")
22
- if File.exists? data
23
- @data = JSON.parse(File.read(data), :symbolize_names => true)
23
+ if File.exists? opts.data_cache
24
+ @data = JSON.parse(File.read(opts.data_cache), :symbolize_names => true)
24
25
  else
25
- raise Fontcustom::Error, "There's no .fontcustom-data file in #{opts[:project_root]}. Try again?"
26
+ raise Fontcustom::Error, "#{relative_to_root(opts.data_cache)} is required to generate templates, but I couldn't find it."
26
27
  end
27
28
  rescue JSON::ParserError
28
29
  # Catches both empty and and malformed files
29
- raise Fontcustom::Error, "The .fontcustom-data file in #{opts[:project_root]} is empty or corrupted. Try deleting the file and running Fontcustom::Generator::Font again to regenerate .fontcustom-data."
30
+ raise Fontcustom::Error, "#{relative_to_root(opts.data_cache)} is empty or corrupted. Try deleting the file and running Fontcustom::Generator::Font again to regenerate the data file. Old generated files may need to be deleted manually."
30
31
  end
31
32
 
32
33
  def reset_output
@@ -40,54 +41,52 @@ module Fontcustom
40
41
  ensure
41
42
  @data[:templates] = @data[:templates] - deleted
42
43
  json = JSON.pretty_generate @data
43
- file = File.join(opts[:project_root], ".fontcustom-data")
44
- clear_file(file)
45
- append_to_file file, json, :verbose => false
46
- say_changed :removed, deleted
44
+ overwrite_file opts.data_cache, json
45
+ say_changed :delete, deleted
47
46
  end
48
47
  end
49
48
 
50
49
  def make_relative_paths
51
50
  name = File.basename @data[:fonts].first, File.extname(@data[:fonts].first)
52
- fonts = Pathname.new opts[:output][:fonts]
53
- css = Pathname.new opts[:output][:css]
54
- preview = Pathname.new opts[:output][:preview]
51
+ fonts = Pathname.new opts.output[:fonts]
52
+ css = Pathname.new opts.output[:css]
53
+ preview = Pathname.new opts.output[:preview]
55
54
  @data[:paths][:css_to_fonts] = File.join fonts.relative_path_from(css).to_s, name
56
- @data[:paths][:preview_to_css] = File.join css.relative_path_from(preview).to_s, "fontcustom.css"
57
- @data[:paths][:preprocessor_to_fonts] = if opts[:preprocessor_font_path] != ""
58
- File.join opts[:preprocessor_font_path], name
59
- else
55
+ @data[:paths][:preview_to_fonts] = File.join fonts.relative_path_from(preview).to_s, name
56
+ @data[:paths][:preprocessor_to_fonts] = if opts.preprocessor_path != ""
57
+ File.join opts.preprocessor_path, name
58
+ else
60
59
  @data[:paths][:css_to_fonts]
61
60
  end
62
61
  end
63
62
 
64
63
  def generate
65
- @opts = opts # make available to templates
64
+ @glyphs = @data[:glyphs]
65
+ @font_path = @data[:paths][:css_to_fonts]
66
+ @font_path_pre = @data[:paths][:preprocessor_to_fonts]
66
67
  begin
67
68
  created = []
68
- opts[:templates].each do |source|
69
+ opts.templates.each do |source|
69
70
  name = File.basename source
70
- ext = File.extname name
71
- target = if opts[:output].keys.include? name
72
- File.join opts[:output][name], name
71
+ ext = File.extname source
72
+ target = if opts.output.keys.include? name
73
+ File.join opts.output[name], name
73
74
  elsif %w|.css .scss .sass .less .stylus|.include? ext
74
- File.join opts[:output][:css], name
75
+ File.join opts.output[:css], name
75
76
  elsif name == "fontcustom-preview.html"
76
- File.join opts[:output][:preview], name
77
+ File.join opts.output[:preview], name
77
78
  else
78
- File.join opts[:output][:fonts], name
79
+ File.join opts.output[:fonts], name
79
80
  end
80
81
 
81
82
  template source, target, :verbose => false
82
83
  created << target
83
84
  end
84
85
  ensure
86
+ say_changed :create, created
85
87
  @data[:templates] = (@data[:templates] + created).uniq
86
88
  json = JSON.pretty_generate @data
87
- file = File.join(opts[:project_root], ".fontcustom-data")
88
- clear_file(file)
89
- append_to_file file, json, :verbose => false
90
- say_changed :created, created
89
+ overwrite_file opts.data_cache, json
91
90
  end
92
91
  end
93
92
  end