fontcustom 1.1.0.pre → 1.1.0.pre2
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.
- checksums.yaml +4 -4
- data/TODO.md +20 -5
- data/lib/fontcustom.rb +42 -4
- data/lib/fontcustom/cli.rb +65 -25
- data/lib/fontcustom/generator/font.rb +26 -26
- data/lib/fontcustom/generator/template.rb +29 -30
- data/lib/fontcustom/options.rb +207 -23
- data/lib/fontcustom/templates/_fontcustom-bootstrap-ie7.scss +9 -9
- data/lib/fontcustom/templates/_fontcustom-bootstrap.scss +19 -19
- data/lib/fontcustom/templates/_fontcustom-rails.scss +28 -0
- data/lib/fontcustom/templates/_fontcustom.scss +11 -11
- data/lib/fontcustom/templates/fontcustom-bootstrap-ie7.css +9 -9
- data/lib/fontcustom/templates/fontcustom-bootstrap.css +19 -19
- data/lib/fontcustom/templates/fontcustom-preview.html +34 -7
- data/lib/fontcustom/templates/fontcustom.css +11 -11
- data/lib/fontcustom/templates/fontcustom.yml +11 -6
- data/lib/fontcustom/util.rb +38 -159
- data/lib/fontcustom/version.rb +1 -1
- data/lib/fontcustom/watcher.rb +16 -14
- data/spec/fixtures/generators/.fontcustom-data-corrupted +18 -0
- data/spec/fixtures/generators/fontcustom.yml +1 -0
- data/spec/fixtures/{util/fontcustom.yml → options/any-file-name.yml} +0 -0
- data/spec/fixtures/{util → options}/config-is-in-dir/fontcustom.yml +0 -0
- data/spec/fixtures/options/fontcustom-empty.yml +1 -0
- data/spec/fixtures/{util → options}/fontcustom-malformed.yml +0 -0
- data/spec/fixtures/options/fontcustom.yml +1 -0
- data/spec/fixtures/options/no-config-here/.gitkeep +0 -0
- data/spec/fixtures/{util → options}/rails-like/config/fontcustom.yml +0 -0
- data/spec/fontcustom/generator/font_spec.rb +31 -15
- data/spec/fontcustom/generator/template_spec.rb +20 -18
- data/spec/fontcustom/options_spec.rb +428 -0
- data/spec/fontcustom/util_spec.rb +38 -336
- data/spec/fontcustom/watcher_spec.rb +7 -2
- data/spec/spec_helper.rb +1 -2
- metadata +23 -13
- data/lib/fontcustom/actions.rb +0 -28
- data/spec/fontcustom/actions_spec.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50485d013861fa91e2ae86ed2741630ad3b285ff
|
4
|
+
data.tar.gz: 5b30887bf48000f2faf726c1995fea6f2bcb9ba8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac4e3f33a7748d4884995e8bdd3725dfb71bc51c1642ebd4d57fd1c9a2ac695c6b1775c73d276aec5b973bbd4316c0bf2b304a5f5939ce3cc798b57dfb36af5e
|
7
|
+
data.tar.gz: a768dd51e28c43b2f3634ecb0b082edde1510a34f563c1598a4ee9add5e8708ab2141d867284c99759ee8628e8d47bff2190572932fcbe6e3d3611fbbc9f36e4
|
data/TODO.md
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
-
|
1
|
+
# 1.1.0 TODO
|
2
2
|
|
3
|
-
*
|
4
|
-
*
|
5
|
-
|
6
|
-
*
|
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::
|
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
|
-
|
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
|
data/lib/fontcustom/cli.rb
CHANGED
@@ -5,53 +5,93 @@ require "fontcustom/watcher"
|
|
5
5
|
|
6
6
|
module Fontcustom
|
7
7
|
class CLI < Thor
|
8
|
-
include
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
class_option :
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
class_option :
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
class_option :
|
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
|
57
|
+
File.join Fontcustom.gem_lib, "templates"
|
25
58
|
end
|
26
59
|
|
27
|
-
desc "compile [INPUT] [OPTIONS]", "Generates webfonts and
|
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::
|
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
|
-
|
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, :
|
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::
|
76
|
+
opts = Fontcustom::Options.new(opts)
|
42
77
|
Fontcustom::Watcher.new(opts).watch
|
43
78
|
rescue Fontcustom::Error => e
|
44
|
-
|
79
|
+
say_status :error, e.message
|
45
80
|
end
|
46
81
|
|
47
|
-
desc "config [DIR]", "
|
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 "
|
53
|
-
|
54
|
-
|
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
|
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
|
18
|
+
dirs = opts.output.values.uniq
|
17
19
|
dirs.each do |dir|
|
18
20
|
unless File.directory? dir
|
19
|
-
empty_directory dir, :verbose => opts
|
21
|
+
empty_directory dir, :verbose => opts.verbose
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
24
26
|
def get_data
|
25
|
-
|
26
|
-
if File.exists? datafile
|
27
|
+
if File.exists? opts.data_cache
|
27
28
|
begin
|
28
|
-
data = File.read
|
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, "
|
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
|
-
|
51
|
-
|
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
|
61
|
-
hash = opts
|
62
|
-
cmd = "fontforge -script #{Fontcustom
|
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]
|
70
|
+
output = output[5..-1]
|
69
71
|
else
|
70
72
|
@json = output[3]
|
71
|
-
output = output[4..-1]
|
73
|
+
output = output[4..-1]
|
72
74
|
end
|
73
75
|
|
74
|
-
if opts
|
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(
|
90
|
+
@data[:fonts].map! { |font| File.join(opts.output[:fonts], font) }
|
89
91
|
end
|
90
92
|
|
91
93
|
def announce_files
|
92
|
-
say_changed :
|
94
|
+
say_changed :create, @data[:fonts]
|
93
95
|
end
|
94
96
|
|
95
97
|
def save_data
|
96
98
|
json = JSON.pretty_generate @data
|
97
|
-
|
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
|
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
|
19
|
+
File.join Fontcustom.gem_lib, "templates"
|
18
20
|
end
|
19
21
|
|
20
22
|
def get_data
|
21
|
-
|
22
|
-
|
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, "
|
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, "
|
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
|
-
|
44
|
-
|
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
|
53
|
-
css = Pathname.new opts
|
54
|
-
preview = Pathname.new opts
|
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][:
|
57
|
-
@data[:paths][:preprocessor_to_fonts] = if opts
|
58
|
-
File.join opts
|
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
|
-
@
|
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
|
69
|
+
opts.templates.each do |source|
|
69
70
|
name = File.basename source
|
70
|
-
ext = File.extname
|
71
|
-
target = if opts
|
72
|
-
File.join opts
|
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
|
75
|
+
File.join opts.output[:css], name
|
75
76
|
elsif name == "fontcustom-preview.html"
|
76
|
-
File.join opts
|
77
|
+
File.join opts.output[:preview], name
|
77
78
|
else
|
78
|
-
File.join opts
|
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
|
-
|
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
|