fontcustom 0.0.2 → 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,12 @@
1
+ ## 0.1.0 (12/2/2012)
2
+
3
+ * Changed API to use Thor `class_option`s
4
+ * Added option to change the name of the font and generated files ([#6](https://github.com/endtwist/fontcustom/issues/6))
5
+ * Added option to disable the file name hash ([#13](https://github.com/endtwist/fontcustom/issues/13))
6
+ * `fontcustom watch` compiles automatically on the first run
7
+ * Better help messages
8
+
9
+ ## 0.0.2 (11/26/2012)
10
+
11
+ * Fixed gemspec dependency bug ([#2](https://github.com/endtwist/fontcustom/pull/2))
12
+ * Fixed Windows Chrome PUA bug ([#1](https://github.com/endtwist/fontcustom/issues/1))
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- FontCustom v0.0.1
1
+ FontCustom v0.0.2
2
2
  ==========
3
3
 
4
4
  **Generate custom icon webfonts from the comfort of the command line.**
data/Rakefile CHANGED
@@ -2,8 +2,8 @@ require "bundler/gem_tasks"
2
2
  require 'rake/testtask'
3
3
 
4
4
  Rake::TestTask.new do |t|
5
- t.libs << 'lib/fontcustom'
6
- t.test_files = FileList['test/lib/fontcustom/*_test.rb']
5
+ t.libs = t.libs + ['lib/fontcustom', 'spec', 'spec/fixtures']
6
+ t.test_files = FileList['spec/fontcustom/*_spec.rb']
7
7
  t.verbose = true
8
8
  end
9
9
 
@@ -3,14 +3,10 @@ require 'fontcustom/generator'
3
3
  require 'fontcustom/watcher'
4
4
 
5
5
  module Fontcustom
6
- # Both .compile and .watch take the following arguments:
7
- #
8
- # @param [String] the input dir
9
- # @param [String] the output dir (optional, defaults to fontcustom/ adjacent to the input dir)
10
- # @param [Hash] options for Thor (not working)
6
+ # Usage:
7
+ # Fontcustom.compile 'path/to/vectors', '-o', 'path/to/output'
11
8
  def compile(*args)
12
- config = args.last.is_a?(::Hash) ? args.pop : {}
13
- Fontcustom::Generator.start(args, config)
9
+ Fontcustom::Generator.start(args) # as array
14
10
  end
15
11
 
16
12
  def watch(*args)
@@ -3,14 +3,22 @@ require 'fontcustom'
3
3
 
4
4
  module Fontcustom
5
5
  class CLI < Thor
6
- desc 'compile INPUT_DIR [OUTPUT_DIR]', 'Generates icon webfonts and a corresponding CSS file from a collection of vector images.'
7
- def compile(input, output = nil)
8
- Fontcustom.compile(input, output)
6
+ # duplicated from Fontcustom::Generator so as to also appear under `fontcustom help` command
7
+ class_option :output, :aliases => '-o', :desc => 'Specify an output directory. Default: $DIR/fontcustom'
8
+ class_option :name, :aliases => '-n', :desc => 'Specify a font name. This will be used in the generated fonts and CSS. Default: fontcustom'
9
+ class_option :nohash, :type => :boolean, :default => false, :desc => 'Disable filename hashes. Default: false'
10
+
11
+ desc 'compile DIR [options]', 'Generates webfonts and CSS from *.svg and *.eps files in DIR.'
12
+ def compile(*args)
13
+ # workaround to pass arguments from one Thor class to another
14
+ ARGV.shift
15
+ Fontcustom.compile(*ARGV)
9
16
  end
10
17
 
11
- desc 'watch INPUT_DIR [OUTPUT_DIR]', 'Watches a directory of vector images for changes and regenerates icon webfonts and CSS when there are.'
12
- def watch(input, output = nil)
13
- Fontcustom.watch(input, output)
18
+ desc 'watch DIR [options]', 'Watches DIR for changes and regenerates webfonts and CSS automatically.'
19
+ def watch(*args)
20
+ ARGV.shift
21
+ Fontcustom.watch(*ARGV)
14
22
  end
15
23
  end
16
24
  end
@@ -8,12 +8,20 @@ module Fontcustom
8
8
  desc 'Generates webfonts from given directory of vectors.'
9
9
 
10
10
  argument :input, :type => :string
11
- argument :output, :type => :string, :optional => true
11
+ class_option :output, :aliases => '-o'
12
+ class_option :name, :aliases => '-n'
13
+ class_option :nohash, :type => :boolean, :default => false
12
14
 
13
15
  def self.source_root
14
16
  File.dirname(__FILE__)
15
17
  end
16
18
 
19
+ def verify_fontforge
20
+ if `which fontforge` == ''
21
+ raise Thor::Error, 'Please install fontforge first.'
22
+ end
23
+ end
24
+
17
25
  def verify_input_dir
18
26
  if ! File.directory?(input)
19
27
  raise Thor::Error, "#{input} doesn't exist or isn't a directory."
@@ -23,32 +31,56 @@ module Fontcustom
23
31
  end
24
32
 
25
33
  def verify_or_create_output_dir
26
- @output = output.nil? ? File.join(File.dirname(input), 'fontcustom') : output
34
+ @output = options.output.nil? ? File.join(File.dirname(input), 'fontcustom') : options.output
27
35
  empty_directory(@output) unless File.directory?(@output)
28
36
  end
29
37
 
30
- def cleanup_output_dir
31
- originals = Dir[File.join(@output, 'fontcustom*.{css,woff,ttf,eot,svg}')]
32
- originals.each do |file|
33
- remove_file file
38
+ def normalize_name
39
+ @name = if options.name
40
+ options.name.gsub(/\W/, '-').downcase
41
+ else
42
+ 'fontcustom'
34
43
  end
35
44
  end
36
45
 
46
+ def cleanup_output_dir
47
+ css = File.join(@output, 'fontcustom.css')
48
+ old_name = if File.exists? css
49
+ line = IO.readlines(css)[5] # font-family: "Example Font";
50
+ line.scan(/".+"/)[0][1..-2].gsub(/\W/, '-').downcase # => 'example-font'
51
+ else
52
+ 'fontcustom'
53
+ end
54
+
55
+ old_files = Dir[File.join(@output, old_name + '-*.{woff,ttf,eot,svg}')]
56
+ old_files << css if File.exists?(css)
57
+ old_files.each {|file| remove_file file }
58
+ end
59
+
37
60
  def generate
38
61
  gem_file_path = File.expand_path(File.join(File.dirname(__FILE__)))
39
- @font = %x| fontforge -script #{gem_file_path}/scripts/generate.py #{input} #{@output} 2>&1 /dev/null |
40
- @font = JSON.parse(@font.split("\n").last)
62
+ name = options.name ? ' --name ' + @name : ''
63
+ nohash = options.nohash ? ' --nohash' : ''
64
+
65
+ # suppress fontforge message
66
+ # TODO get font name and classes from script (without showing fontforge message)
67
+ `fontforge -script #{gem_file_path}/scripts/generate.py #{input} #{@output + name + nohash} > /dev/null 2>&1`
41
68
  end
42
69
 
43
70
  def show_paths
44
- path = @font['file']
71
+ file = Dir[File.join(@output, @name + '*.ttf')].first
72
+ @path = file.chomp('.ttf')
73
+
45
74
  ['woff','ttf','eot','svg'].each do |type|
46
- say_status(:create, path + '.' + type)
75
+ say_status(:create, @path + '.' + type)
47
76
  end
48
77
  end
49
78
 
50
79
  def create_stylesheet
51
- @font['file'] = File.basename(@font['file'])
80
+ files = Dir[File.join(input, '*.{svg,eps}')]
81
+ @classes = files.map {|file| File.basename(file)[0..-5].gsub(/\W/, '-').downcase }
82
+ @path = File.basename(@path)
83
+
52
84
  template('templates/fontcustom.css', File.join(@output, 'fontcustom.css'))
53
85
  end
54
86
  end
@@ -6,7 +6,9 @@ import json
6
6
  from subprocess import call
7
7
 
8
8
  parser = argparse.ArgumentParser(description='Convert a directory of svg and eps files into a unified font file.')
9
- parser.add_argument('dir', metavar='directory', type=unicode, nargs='+', help='directory of vector files')
9
+ parser.add_argument('dir', metavar='directory', type=unicode, nargs=2, help='directory of vector files')
10
+ parser.add_argument('--name', metavar='fontname', type=unicode, nargs='?', default='fontcustom', help='reference name of the font (no spaces)')
11
+ parser.add_argument('--nohash', '-n', action='store_true', help='disable hash fingerprinting of font files')
10
12
  args = parser.parse_args()
11
13
 
12
14
  f = fontforge.font()
@@ -39,10 +41,15 @@ for dirname, dirnames, filenames in os.walk(args.dir[0]):
39
41
  files.append(name)
40
42
  cp += 1
41
43
 
42
- hashStr = m.hexdigest()
43
- fontfile = args.dir[1] + '/fontcustom-' + hashStr
44
+ if args.nohash:
45
+ fontfile = args.dir[1] + '/' + args.name
46
+ else:
47
+ hashStr = m.hexdigest()
48
+ fontfile = args.dir[1] + '/' + args.name + '-' + hashStr
44
49
 
45
- f.fontname = 'fontcustom'
50
+ f.fontname = args.name
51
+ f.familyname = args.name
52
+ f.fullname = args.name
46
53
  f.generate(fontfile + '.ttf')
47
54
  f.generate(fontfile + '.svg')
48
55
 
@@ -59,5 +66,3 @@ call(scriptPath + '/ttf2eot ' + fontfile + '.ttf > ' + fontfile + '.eot', shell=
59
66
 
60
67
  # Hint the TTF file
61
68
  call(scriptPath + '/ttfautohint -s -n ' + fontfile + '.ttf ' + fontfile + '-hinted.ttf && mv ' + fontfile + '-hinted.ttf ' + fontfile + '.ttf', shell=True)
62
-
63
- print json.dumps({'file': fontfile, 'names': files})
@@ -1,23 +1,23 @@
1
1
  /*
2
- Font Custom - icon webfonts made simple
2
+ Font Custom - icon webfonts made simple
3
3
  */
4
4
 
5
5
  @font-face {
6
- font-family: "fontcustom";
7
- src: url("<%= @font['file'] %>.eot?#iefix") format("embedded-opentype"),
8
- url("<%= @font['file'] %>.woff") format("woff"),
9
- url("<%= @font['file'] %>.ttf") format("truetype"),
10
- url("<%= @font['file'] %>.svg#fontcustom") format("svg");
6
+ font-family: "<%= @name %>";
7
+ src: url("<%= @path %>.eot?#iefix") format("embedded-opentype"),
8
+ url("<%= @path %>.woff") format("woff"),
9
+ url("<%= @path %>.ttf") format("truetype"),
10
+ url("<%= @path %>.svg#<%= @name %>") format("svg");
11
11
  font-weight: normal;
12
12
  font-style: normal;
13
13
  }
14
14
 
15
15
  /*
16
- Bootstrap Overrides
16
+ Bootstrap Overrides
17
17
  */
18
18
 
19
19
  [class^="icon-"]:before, [class*=" icon-"]:before {
20
- font-family: "fontcustom";
20
+ font-family: "<%= @name %>";
21
21
  font-weight: normal;
22
22
  font-style: normal;
23
23
  display: inline-block;
@@ -66,7 +66,7 @@ li[class^="icon-"].icon-large:before, li[class*=" icon-"].icon-large:before {
66
66
  }
67
67
 
68
68
  /*
69
- Icon Classes
69
+ Icon Classes
70
70
  */
71
- <% @font['names'].each_with_index do |name, index| %>
72
- .icon-<%= name.downcase %>:before { content: "\<%= (61696+index).to_s(16) %>"; }<% end %>
71
+ <% @classes.each_with_index do |name, index| %>
72
+ .icon-<%= name %>:before { content: "\<%= (61696+index).to_s(16) %>"; }<% end %>
@@ -1,3 +1,3 @@
1
1
  module Fontcustom
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -17,6 +17,7 @@ module Fontcustom
17
17
 
18
18
  begin
19
19
  puts "Fontcustom is watching your icons at " + dir
20
+ Fontcustom.compile(*args)
20
21
  @listener.start()
21
22
 
22
23
  # Catches Cmd/Ctrl + C
@@ -8,17 +8,19 @@ describe Fontcustom do
8
8
  context 'when ouput_dir already contains files' do
9
9
  # Compile, add non-fontcustom file, change input vectors, recompile
10
10
  before(:all) do
11
- Fontcustom.compile(input_dir, output_dir)
11
+ # originals
12
+ Fontcustom.compile(input_dir, '-o', output_dir, '-n', 'Original Font')
12
13
  FileUtils.touch(fake_file, :verbose => true)
13
14
  @original_fonts = Dir[output_dir + '/fontcustom-*.{woff,eot,ttf,svg}']
14
15
  @original_css = File.read(output_dir + '/fontcustom.css')
15
- FileUtils.mv(input_dir + '/B.svg', input_dir + '/E.svg', :verbose => true)
16
- Fontcustom.compile(input_dir, output_dir)
16
+
17
+ FileUtils.mv(input_dir + '/C.svg', input_dir + '/E.svg', :verbose => true)
18
+ Fontcustom.compile(input_dir, '-o', output_dir)
17
19
  end
18
20
 
19
21
  after(:all) do
20
22
  cleanup(output_dir)
21
- FileUtils.mv(input_dir + '/E.svg', input_dir + '/B.svg', :verbose => true)
23
+ FileUtils.mv(input_dir + '/E.svg', input_dir + '/C.svg', :verbose => true)
22
24
  end
23
25
 
24
26
  it 'should delete previous fontcustom generated files' do
@@ -5,7 +5,7 @@ describe Fontcustom::Generator do
5
5
  let(:output_dir) { 'tmp' }
6
6
 
7
7
  context 'normally' do
8
- before(:all) { Fontcustom::Generator.start([input_dir, output_dir]) }
8
+ before(:all) { Fontcustom::Generator.start([input_dir, '-o', output_dir]) }
9
9
  after(:all) { cleanup(output_dir) }
10
10
 
11
11
  it 'should create webfonts' do
@@ -27,7 +27,7 @@ describe Fontcustom::Generator do
27
27
 
28
28
  it 'should print icon-* CSS classes in fontcustom.css' do
29
29
  stylesheet = File.read(output_dir + '/fontcustom.css')
30
- icon_names = Dir[input_dir + '/*'].map { |file| File.basename(file, '.svg').downcase }
30
+ icon_names = Dir[input_dir + '/*'].map { |file| File.basename(file)[0..-5].gsub(/\W/, '-').downcase }
31
31
 
32
32
  icon_names.each do |name|
33
33
  stylesheet.should include('.icon-' + name)
@@ -39,7 +39,7 @@ describe Fontcustom::Generator do
39
39
  let(:fake_input_dir) { 'does/not/exist' }
40
40
 
41
41
  it 'should raise an error' do
42
- results = capture(:stderr) { Fontcustom::Generator.start([fake_input_dir, output_dir]) }
42
+ results = capture(:stderr) { Fontcustom::Generator.start([fake_input_dir, '-o', output_dir]) }
43
43
  results.should =~ /doesn't exist or isn't a directory/
44
44
  end
45
45
  end
@@ -52,4 +52,24 @@ describe Fontcustom::Generator do
52
52
  results.should =~ /doesn't contain any vectors/
53
53
  end
54
54
  end
55
+
56
+ context 'when flags are passed' do
57
+ it 'should save output files with a custom name' do
58
+ Fontcustom::Generator.start([input_dir, '-o', output_dir, '-n', 'customname'])
59
+
60
+ file = Dir[File.join(output_dir, 'customname-*.ttf')].first
61
+ File.exists?(file).should be_true
62
+
63
+ cleanup(output_dir)
64
+ end
65
+
66
+ it 'should exclude the filename hash' do
67
+ Fontcustom::Generator.start([input_dir, '-o', output_dir, '--nohash'])
68
+
69
+ file = File.join(output_dir, 'fontcustom.ttf')
70
+ File.exists?(file).should be_true
71
+
72
+ cleanup(output_dir)
73
+ end
74
+ end
55
75
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fontcustom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-11-26 00:00:00.000000000 Z
13
+ date: 2012-12-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -199,6 +199,7 @@ extensions: []
199
199
  extra_rdoc_files: []
200
200
  files:
201
201
  - .gitignore
202
+ - CHANGELOG.md
202
203
  - Gemfile
203
204
  - Guardfile
204
205
  - LICENSES.txt
@@ -217,9 +218,9 @@ files:
217
218
  - lib/fontcustom/version.rb
218
219
  - lib/fontcustom/watcher.rb
219
220
  - spec/fixtures/empty/no_vectors_here.txt
220
- - spec/fixtures/vectors/B.svg
221
221
  - spec/fixtures/vectors/C.svg
222
222
  - spec/fixtures/vectors/D.svg
223
+ - spec/fixtures/vectors/a_R3ally-eXotic f1Le Name.svg
223
224
  - spec/fontcustom/fontcustom_spec.rb
224
225
  - spec/fontcustom/generator_spec.rb
225
226
  - spec/fontcustom/watcher_spec.rb.off
@@ -238,7 +239,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
239
  version: '0'
239
240
  segments:
240
241
  - 0
241
- hash: 2573476005248431582
242
+ hash: 4274866861207866495
242
243
  required_rubygems_version: !ruby/object:Gem::Requirement
243
244
  none: false
244
245
  requirements:
@@ -247,7 +248,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
247
248
  version: '0'
248
249
  segments:
249
250
  - 0
250
- hash: 2573476005248431582
251
+ hash: 4274866861207866495
251
252
  requirements: []
252
253
  rubyforge_project:
253
254
  rubygems_version: 1.8.24
@@ -256,9 +257,9 @@ specification_version: 3
256
257
  summary: Generate custom icon webfonts from the comfort of the command line.
257
258
  test_files:
258
259
  - spec/fixtures/empty/no_vectors_here.txt
259
- - spec/fixtures/vectors/B.svg
260
260
  - spec/fixtures/vectors/C.svg
261
261
  - spec/fixtures/vectors/D.svg
262
+ - spec/fixtures/vectors/a_R3ally-eXotic f1Le Name.svg
262
263
  - spec/fontcustom/fontcustom_spec.rb
263
264
  - spec/fontcustom/generator_spec.rb
264
265
  - spec/fontcustom/watcher_spec.rb.off