gkh-fontcustom 1.3.7
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 +7 -0
- data/.gitignore +21 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.md +137 -0
- data/CONTRIBUTING.md +50 -0
- data/Gemfile +4 -0
- data/LICENSES.txt +60 -0
- data/README.md +112 -0
- data/Rakefile +8 -0
- data/bin/fontcustom +5 -0
- data/fontcustom.gemspec +28 -0
- data/gemfiles/Gemfile.listen_1 +6 -0
- data/lib/fontcustom.rb +43 -0
- data/lib/fontcustom/base.rb +54 -0
- data/lib/fontcustom/cli.rb +110 -0
- data/lib/fontcustom/error.rb +4 -0
- data/lib/fontcustom/generator/font.rb +109 -0
- data/lib/fontcustom/generator/template.rb +222 -0
- data/lib/fontcustom/manifest.rb +75 -0
- data/lib/fontcustom/options.rb +192 -0
- data/lib/fontcustom/scripts/eotlitetool.py +466 -0
- data/lib/fontcustom/scripts/generate.py +128 -0
- data/lib/fontcustom/scripts/sfnt2woff +0 -0
- data/lib/fontcustom/templates/_fontcustom-rails.scss +14 -0
- data/lib/fontcustom/templates/_fontcustom.scss +16 -0
- data/lib/fontcustom/templates/fontcustom-preview.html +174 -0
- data/lib/fontcustom/templates/fontcustom.css +14 -0
- data/lib/fontcustom/templates/fontcustom.yml +96 -0
- data/lib/fontcustom/utility.rb +117 -0
- data/lib/fontcustom/version.rb +3 -0
- data/lib/fontcustom/watcher.rb +90 -0
- data/spec/fixtures/example/_example-rails.scss +50 -0
- data/spec/fixtures/example/example-preview.html +253 -0
- data/spec/fixtures/example/example.css +50 -0
- data/spec/fixtures/example/example.eot +0 -0
- data/spec/fixtures/example/example.svg +75 -0
- data/spec/fixtures/example/example.ttf +0 -0
- data/spec/fixtures/example/example.woff +0 -0
- data/spec/fixtures/generators/.fontcustom-manifest-corrupted.json +25 -0
- data/spec/fixtures/generators/.fontcustom-manifest-empty.json +0 -0
- data/spec/fixtures/generators/.fontcustom-manifest.json +52 -0
- data/spec/fixtures/generators/fontcustom.yml +1 -0
- data/spec/fixtures/generators/mixed-output/another-font.ttf +0 -0
- data/spec/fixtures/generators/mixed-output/dont-delete-me.bro +0 -0
- data/spec/fixtures/generators/mixed-output/fontcustom.css +108 -0
- data/spec/fixtures/generators/mixed-output/fontcustom_82a59e769bc60192484f2620570bbb59.eot +0 -0
- data/spec/fixtures/generators/mixed-output/fontcustom_82a59e769bc60192484f2620570bbb59.svg +56 -0
- data/spec/fixtures/generators/mixed-output/fontcustom_82a59e769bc60192484f2620570bbb59.ttf +0 -0
- data/spec/fixtures/generators/mixed-output/fontcustom_82a59e769bc60192484f2620570bbb59.woff +0 -0
- data/spec/fixtures/options/any-file-name.yml +1 -0
- data/spec/fixtures/options/config-is-in-dir/fontcustom.yml +1 -0
- data/spec/fixtures/options/fontcustom-empty.yml +1 -0
- data/spec/fixtures/options/fontcustom-malformed.yml +1 -0
- data/spec/fixtures/options/fontcustom.yml +1 -0
- data/spec/fixtures/options/no-config-here/.gitkeep +0 -0
- data/spec/fixtures/options/rails-like/config/fontcustom.yml +1 -0
- data/spec/fixtures/shared/not-a-dir +0 -0
- data/spec/fixtures/shared/templates/custom.css +4 -0
- data/spec/fixtures/shared/templates/regular.css +4 -0
- data/spec/fixtures/shared/vectors-empty/no_vectors_here.txt +0 -0
- data/spec/fixtures/shared/vectors/C.svg +14 -0
- data/spec/fixtures/shared/vectors/D.svg +15 -0
- data/spec/fixtures/shared/vectors/a_R3ally-eXotic f1Le Name.svg +6 -0
- data/spec/fontcustom/base_spec.rb +45 -0
- data/spec/fontcustom/cli_spec.rb +30 -0
- data/spec/fontcustom/generator/font_spec.rb +72 -0
- data/spec/fontcustom/generator/template_spec.rb +99 -0
- data/spec/fontcustom/manifest_spec.rb +17 -0
- data/spec/fontcustom/options_spec.rb +315 -0
- data/spec/fontcustom/utility_spec.rb +82 -0
- data/spec/fontcustom/watcher_spec.rb +121 -0
- data/spec/spec_helper.rb +103 -0
- metadata +252 -0
data/lib/fontcustom.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "fontcustom/version"
|
2
|
+
require "fontcustom/error"
|
3
|
+
require "fontcustom/utility"
|
4
|
+
require "fontcustom/base"
|
5
|
+
require "fontcustom/manifest"
|
6
|
+
require "fontcustom/options"
|
7
|
+
require "fontcustom/generator/font"
|
8
|
+
require "fontcustom/generator/template"
|
9
|
+
|
10
|
+
module Fontcustom
|
11
|
+
def gem_lib
|
12
|
+
File.expand_path(File.join(File.dirname(__FILE__), "fontcustom"))
|
13
|
+
end
|
14
|
+
module_function :gem_lib
|
15
|
+
|
16
|
+
##
|
17
|
+
# Hack to get Thor to show more helpful defaults in `fontcustom help`. These
|
18
|
+
# are overwritten in Fontcustom::Options.
|
19
|
+
EXAMPLE_OPTIONS = {
|
20
|
+
:output => "./FONT_NAME",
|
21
|
+
:config => "./fontcustom.yml -or- ./config/fontcustom.yml",
|
22
|
+
:templates => "css preview"
|
23
|
+
}
|
24
|
+
|
25
|
+
DEFAULT_OPTIONS = {
|
26
|
+
:input => nil,
|
27
|
+
:output => nil,
|
28
|
+
:config => nil,
|
29
|
+
:templates => %w|css preview|,
|
30
|
+
:font_name => "fontcustom",
|
31
|
+
:font_design_size => 16,
|
32
|
+
:font_em => 512,
|
33
|
+
:font_ascent => 448,
|
34
|
+
:font_descent => 64,
|
35
|
+
:css_selector => ".icon-{{glyph}}",
|
36
|
+
:preprocessor_path => nil,
|
37
|
+
:autowidth => false,
|
38
|
+
:no_hash => false,
|
39
|
+
:debug => false,
|
40
|
+
:force => false,
|
41
|
+
:quiet => false
|
42
|
+
}
|
43
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "digest/sha2"
|
2
|
+
|
3
|
+
module Fontcustom
|
4
|
+
class Base
|
5
|
+
include Utility
|
6
|
+
|
7
|
+
def initialize(raw_options)
|
8
|
+
check_fontforge
|
9
|
+
manifest = ".fontcustom-manifest.json"
|
10
|
+
raw_options[:manifest] = manifest
|
11
|
+
@options = Fontcustom::Options.new(raw_options).options
|
12
|
+
@manifest = Fontcustom::Manifest.new(manifest, @options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def compile
|
16
|
+
current = checksum
|
17
|
+
previous = @manifest.get(:checksum)[:previous]
|
18
|
+
|
19
|
+
say_message :status, "Forcing compile." if @options[:force]
|
20
|
+
if @options[:force] || current != previous
|
21
|
+
@manifest.set :checksum, {:previous => previous, :current => current}
|
22
|
+
start_generators
|
23
|
+
@manifest.reload
|
24
|
+
@manifest.set :checksum, {:previous => current, :current => current}
|
25
|
+
else
|
26
|
+
say_message :status, "No changes detected. Skipping compile."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def check_fontforge
|
33
|
+
fontforge = `which fontforge`
|
34
|
+
if fontforge == "" || fontforge == "fontforge not found"
|
35
|
+
raise Fontcustom::Error, "Please install fontforge first. Visit <http://fontcustom.com> for instructions."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Calculates a hash of vectors, options, and templates (content and filenames)
|
40
|
+
def checksum
|
41
|
+
files = Dir.glob(File.join(@options[:input][:vectors], "*.svg")).select { |fn| File.file?(fn) }
|
42
|
+
files += Dir.glob(File.join(@options[:input][:templates], "*")).select { |fn| File.file?(fn) }
|
43
|
+
content = files.map { |file| File.read(file) }.join
|
44
|
+
content << files.join
|
45
|
+
content << @options.flatten(2).join
|
46
|
+
Digest::SHA2.hexdigest(content).to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
def start_generators
|
50
|
+
Fontcustom::Generator::Font.new(@manifest.manifest).generate
|
51
|
+
Fontcustom::Generator::Template.new(@manifest.manifest).generate
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "thor/actions"
|
3
|
+
require "fontcustom"
|
4
|
+
require "fontcustom/watcher"
|
5
|
+
|
6
|
+
module Fontcustom
|
7
|
+
class CLI < Thor
|
8
|
+
include Utility
|
9
|
+
|
10
|
+
default_task :show_help
|
11
|
+
|
12
|
+
class_option :output, :aliases => "-o", :type => :string,
|
13
|
+
:desc => "Where generated files are saved. Set different locations for different file types via a configuration file.",
|
14
|
+
:default => EXAMPLE_OPTIONS[:output]
|
15
|
+
|
16
|
+
class_option :config, :aliases => "-c", :type => :string,
|
17
|
+
:desc => "Optional path to a configuration file.",
|
18
|
+
:default => EXAMPLE_OPTIONS[:config]
|
19
|
+
|
20
|
+
class_option :templates, :aliases => "-t", :type => :array,
|
21
|
+
:desc => "Space-delinated list of files to generate alongside fonts. Use stock templates or choose your own.",
|
22
|
+
:enum => %w|preview css scss scss-rails|,
|
23
|
+
:default => EXAMPLE_OPTIONS[:templates]
|
24
|
+
|
25
|
+
class_option :font_name, :aliases => %w|--name -n|, :type => :string,
|
26
|
+
:desc => "The font's name. Also determines the file names of generated templates.",
|
27
|
+
:default => DEFAULT_OPTIONS[:font_name]
|
28
|
+
|
29
|
+
class_option :font_design_size, :aliases => %s|--size -s|, :type => :numeric,
|
30
|
+
:desc => "Size (in pica points) for which this font is designed.",
|
31
|
+
:default => DEFAULT_OPTIONS[:font_design_size]
|
32
|
+
|
33
|
+
class_option :font_em, :aliases => %w|--em -e|, :type => :numeric,
|
34
|
+
:desc => "The em size. Setting this will scale the entire font to the given size.",
|
35
|
+
:default => DEFAULT_OPTIONS[:font_em]
|
36
|
+
|
37
|
+
class_option :font_ascent, :aliases => %w|--ascent -a|, :type => :numeric,
|
38
|
+
:desc => "The font's ascent. Used to calculate the baseline.",
|
39
|
+
:default => DEFAULT_OPTIONS[:font_ascent]
|
40
|
+
|
41
|
+
class_option :font_descent, :aliases => %w|--descent -d|, :type => :numeric,
|
42
|
+
:desc => "The font's descent. Used to calculate the baseline.",
|
43
|
+
:default => DEFAULT_OPTIONS[:font_descent]
|
44
|
+
|
45
|
+
class_option :css_selector, :aliases => %w|--selector -S|, :type => :string,
|
46
|
+
:desc => "Format of CSS selectors. \"{{glyph}}\" is substituted for the glyph name.",
|
47
|
+
:default => DEFAULT_OPTIONS[:css_selector]
|
48
|
+
|
49
|
+
class_option :preprocessor_path, :aliases => %w|--prepath -p|, :type => :string,
|
50
|
+
:desc => "For Rails and Compass templates, set this as the relative path from your compiled CSS to your font output directory."
|
51
|
+
|
52
|
+
class_option :autowidth, :aliases => "-A", :type => :boolean,
|
53
|
+
:desc => "Horizontally fit glyphs to their individual vector widths."
|
54
|
+
|
55
|
+
class_option :no_hash, :aliases => "-h", :type => :boolean,
|
56
|
+
:desc => "Generate fonts without asset-busting hashes."
|
57
|
+
|
58
|
+
class_option :base64, :aliases => "-b", :type => :boolean,
|
59
|
+
:desc => "Encode WOFF fonts into the generated CSS."
|
60
|
+
|
61
|
+
class_option :debug, :aliases => "-D", :type => :boolean,
|
62
|
+
:desc => "Display (possibly useful) debugging messages."
|
63
|
+
|
64
|
+
class_option :force, :aliases => "-F", :type => :boolean,
|
65
|
+
:desc => "Forces compilation, even if inputs have not changed."
|
66
|
+
|
67
|
+
class_option :quiet, :aliases => "-q", :type => :boolean,
|
68
|
+
:desc => "Hide status messages."
|
69
|
+
|
70
|
+
# Required for Thor::Actions#template
|
71
|
+
def self.source_root
|
72
|
+
File.join Fontcustom.gem_lib, "templates"
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "compile [INPUT] [OPTIONS]", "Generates webfonts and templates from *.svg files in INPUT. Default: `pwd`"
|
76
|
+
def compile(input = nil)
|
77
|
+
Base.new(options.merge(:input => input)).compile
|
78
|
+
rescue Fontcustom::Error => e
|
79
|
+
say_status :error, e.message, :red
|
80
|
+
puts e.backtrace.join("\n") if options[:debug]
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "watch [INPUT] [OPTIONS]", "Watches INPUT for changes and regenerates files automatically. Ctrl + C to stop. Default: `pwd`"
|
84
|
+
method_option :skip_first, :type => :boolean,
|
85
|
+
:desc => "Skip the initial compile upon watching.",
|
86
|
+
:default => false
|
87
|
+
def watch(input = nil)
|
88
|
+
say "Font Custom is watching your icons. Press Ctrl + C to stop.", :yellow unless options[:quiet]
|
89
|
+
opts = options.merge :input => input, :skip_first => !! options[:skip_first]
|
90
|
+
Watcher.new(opts).watch
|
91
|
+
rescue Fontcustom::Error => e
|
92
|
+
say_status :error, e.message, :red
|
93
|
+
end
|
94
|
+
|
95
|
+
desc "config [DIR]", "Generates a starter configuration file (fontcustom.yml) in DIR. Default: `pwd`"
|
96
|
+
def config(dir = Dir.pwd)
|
97
|
+
template "fontcustom.yml", File.join(dir, "fontcustom.yml")
|
98
|
+
end
|
99
|
+
|
100
|
+
desc "hidden", "hidden", :hide => true
|
101
|
+
method_option :version, :aliases => "-v", :type => :boolean, :default => false
|
102
|
+
def show_help
|
103
|
+
if options[:version]
|
104
|
+
puts "fontcustom-#{VERSION}"
|
105
|
+
else
|
106
|
+
help
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require "json"
|
2
|
+
require "open3"
|
3
|
+
|
4
|
+
module Fontcustom
|
5
|
+
module Generator
|
6
|
+
class Font
|
7
|
+
include Utility
|
8
|
+
|
9
|
+
attr_reader :manifest
|
10
|
+
|
11
|
+
def initialize(manifest)
|
12
|
+
@manifest = Fontcustom::Manifest.new manifest
|
13
|
+
@options = @manifest.get :options
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate
|
17
|
+
create_output_dirs
|
18
|
+
delete_old_fonts
|
19
|
+
set_glyph_info
|
20
|
+
create_fonts
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def create_output_dirs
|
26
|
+
dirs = @options[:output].values.uniq
|
27
|
+
dirs.each do |dir|
|
28
|
+
unless File.directory? dir
|
29
|
+
empty_directory dir, :verbose => false
|
30
|
+
say_message :create, dir
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete_old_fonts
|
36
|
+
@manifest.delete :fonts
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_glyph_info
|
40
|
+
manifest_glyphs = @manifest.get :glyphs
|
41
|
+
codepoint = if ! manifest_glyphs.empty?
|
42
|
+
codepoints = manifest_glyphs.values.map { |data| data[:codepoint] }
|
43
|
+
codepoints.max + 1
|
44
|
+
else
|
45
|
+
# Offset to work around Chrome Windows bug
|
46
|
+
# https://github.com/FontCustom/fontcustom/issues/1
|
47
|
+
0xf100
|
48
|
+
end
|
49
|
+
|
50
|
+
files = Dir.glob File.join(@options[:input][:vectors], "*.svg")
|
51
|
+
glyphs = {}
|
52
|
+
files.each do |file|
|
53
|
+
next if File.symlink?(file)
|
54
|
+
name = File.basename file, ".svg"
|
55
|
+
name = name.strip.gsub(/\W/, "-")
|
56
|
+
glyphs[name.to_sym] = { :source => file }
|
57
|
+
if File.read(file).include? "rgba"
|
58
|
+
say_message :warn, "`#{file}` contains transparency and will be skipped."
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
files.each do |file|
|
63
|
+
next unless File.symlink?(file)
|
64
|
+
linked_name = File.readlink(file)
|
65
|
+
linked_name = File.basename linked_name, ".svg"
|
66
|
+
linked_name = linked_name.strip.gsub(/\W/, "-")
|
67
|
+
glyphs[linked_name.to_sym][:aliases] ||= []
|
68
|
+
alias_name = File.basename file, ".svg"
|
69
|
+
alias_name = alias_name.strip.gsub(/\W/, "-")
|
70
|
+
glyphs[linked_name.to_sym][:aliases] << alias_name
|
71
|
+
end
|
72
|
+
|
73
|
+
# Dir.glob returns a different order depending on ruby
|
74
|
+
# version/platform, so we have to sort it first
|
75
|
+
glyphs = Hash[glyphs.sort_by { |key, val| key.to_s }]
|
76
|
+
glyphs.each do |name, data|
|
77
|
+
if manifest_glyphs.has_key? name
|
78
|
+
data[:codepoint] = manifest_glyphs[name][:codepoint]
|
79
|
+
else
|
80
|
+
data[:codepoint] = codepoint
|
81
|
+
codepoint = codepoint + 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
@manifest.set :glyphs, glyphs
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_fonts
|
88
|
+
cmd = "fontforge -script #{Fontcustom.gem_lib}/scripts/generate.py #{@manifest.manifest}"
|
89
|
+
stdout, stderr, status = Open3::capture3(cmd)
|
90
|
+
stdout = stdout.split("\n")
|
91
|
+
stdout = stdout[1..-1] if stdout[0] == "CreateAllPyModules()"
|
92
|
+
|
93
|
+
debug_msg = " Try again with --debug for more details."
|
94
|
+
if @options[:debug]
|
95
|
+
messages = stderr.split("\n") + stdout
|
96
|
+
say_message :debug, messages.join(line_break)
|
97
|
+
debug_msg = ""
|
98
|
+
end
|
99
|
+
|
100
|
+
if status.success?
|
101
|
+
@manifest.reload
|
102
|
+
say_changed :create, @manifest.get(:fonts)
|
103
|
+
else
|
104
|
+
raise Fontcustom::Error, "`fontforge` compilation failed.#{debug_msg}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require "json"
|
2
|
+
require "pathname"
|
3
|
+
require "base64"
|
4
|
+
|
5
|
+
module Fontcustom
|
6
|
+
module Generator
|
7
|
+
class Template
|
8
|
+
include Utility
|
9
|
+
|
10
|
+
attr_reader :manifest
|
11
|
+
|
12
|
+
def initialize(manifest)
|
13
|
+
@manifest = Fontcustom::Manifest.new manifest
|
14
|
+
@options = @manifest.get :options
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate
|
18
|
+
if ! @manifest.get(:fonts).empty?
|
19
|
+
delete_old_templates
|
20
|
+
set_relative_paths
|
21
|
+
create_files
|
22
|
+
else
|
23
|
+
raise Fontcustom::Error, "No generated fonts were detected - aborting template generation."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def delete_old_templates
|
30
|
+
@manifest.delete :templates
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_relative_paths
|
34
|
+
fonts = @manifest.get :fonts
|
35
|
+
name = File.basename fonts.first, File.extname(fonts.first)
|
36
|
+
fonts_path = Pathname.new(@options[:output][:fonts]).realdirpath
|
37
|
+
css_path = Pathname.new(@options[:output][:css]).realdirpath
|
38
|
+
preview_path = Pathname.new(@options[:output][:preview]).realdirpath
|
39
|
+
@font_path = File.join fonts_path.relative_path_from(css_path).to_s, name
|
40
|
+
@font_path_alt = if @options[:preprocessor_path].nil?
|
41
|
+
@font_path
|
42
|
+
elsif ! @options[:preprocessor_path] || @options[:preprocessor_path].empty?
|
43
|
+
name
|
44
|
+
else
|
45
|
+
File.join(@options[:preprocessor_path], name)
|
46
|
+
end
|
47
|
+
@font_path_preview = File.join fonts_path.relative_path_from(preview_path).to_s, name
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_files
|
51
|
+
@glyphs = @manifest.get :glyphs
|
52
|
+
existing = @manifest.get :templates
|
53
|
+
created = []
|
54
|
+
begin
|
55
|
+
@options[:templates].each do |template_name|
|
56
|
+
begin
|
57
|
+
source = get_source_path(template_name)
|
58
|
+
target = get_target_path(source)
|
59
|
+
template source, target, :verbose => false, :force => true
|
60
|
+
end
|
61
|
+
created << target
|
62
|
+
end
|
63
|
+
ensure
|
64
|
+
say_changed :create, created
|
65
|
+
@manifest.set :templates, (existing + created).uniq
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_source_path(template)
|
70
|
+
template_path = File.join Fontcustom.gem_lib, "templates"
|
71
|
+
|
72
|
+
case template
|
73
|
+
when "preview"
|
74
|
+
File.join template_path, "fontcustom-preview.html"
|
75
|
+
when "css"
|
76
|
+
File.join template_path, "fontcustom.css"
|
77
|
+
when "scss"
|
78
|
+
File.join template_path, "_fontcustom.scss"
|
79
|
+
when "scss-rails"
|
80
|
+
File.join template_path, "_fontcustom-rails.scss"
|
81
|
+
else
|
82
|
+
File.join @options[:input][:templates], template
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_target_path(source)
|
87
|
+
ext = File.extname source
|
88
|
+
base = File.basename source
|
89
|
+
css_exts = %w|.css .scss .sass .less .stylus|
|
90
|
+
packaged = %w|fontcustom-preview.html fontcustom.css _fontcustom.scss _fontcustom-rails.scss|
|
91
|
+
|
92
|
+
target = if @options[:output].keys.include? base.to_sym
|
93
|
+
File.join @options[:output][base.to_sym], base
|
94
|
+
elsif ext && css_exts.include?(ext)
|
95
|
+
File.join @options[:output][:css], base
|
96
|
+
elsif source.match(/fontcustom-preview\.html/)
|
97
|
+
File.join @options[:output][:preview], base
|
98
|
+
else
|
99
|
+
File.join @options[:output][:fonts], base
|
100
|
+
end
|
101
|
+
|
102
|
+
if packaged.include?(base) && @options[:font_name] != DEFAULT_OPTIONS[:font_name]
|
103
|
+
target.sub! DEFAULT_OPTIONS[:font_name], @options[:font_name]
|
104
|
+
end
|
105
|
+
|
106
|
+
target
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Template Helpers
|
111
|
+
#
|
112
|
+
|
113
|
+
def font_name
|
114
|
+
@options[:font_name]
|
115
|
+
end
|
116
|
+
|
117
|
+
def font_face(style = {})
|
118
|
+
if style.is_a?(Symbol)
|
119
|
+
if style == :preprocessor
|
120
|
+
url = "font-url"
|
121
|
+
path = @font_path_alt
|
122
|
+
elsif style == :preview
|
123
|
+
url = "url"
|
124
|
+
path = @font_path_preview
|
125
|
+
else
|
126
|
+
url = "url"
|
127
|
+
path = @font_path
|
128
|
+
end
|
129
|
+
say_message :warn, "`font_face(:#{style})` is deprecated. Use `font_face(url:'url', path:'path')` instead."
|
130
|
+
else
|
131
|
+
style = {:url => "url", :path => @font_path}.merge(style)
|
132
|
+
url = style[:url]
|
133
|
+
path = style[:path]
|
134
|
+
end
|
135
|
+
|
136
|
+
# Bulletproof @Font-Face <http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax>
|
137
|
+
# With and without Base64
|
138
|
+
if @options[:base64]
|
139
|
+
string = %Q|@font-face {
|
140
|
+
font-family: "#{font_name}";
|
141
|
+
src: #{url}("#{path}.eot?") format("embedded-opentype");
|
142
|
+
font-weight: normal;
|
143
|
+
font-style: normal;
|
144
|
+
}
|
145
|
+
|
146
|
+
@font-face {
|
147
|
+
font-family: "#{font_name}";
|
148
|
+
src: url("data:application/x-font-woff;charset=utf-8;base64,#{woff_base64}") format("woff"),
|
149
|
+
#{url}("#{path}.ttf") format("truetype"),
|
150
|
+
#{url}("#{path}.svg##{font_name}") format("svg");
|
151
|
+
font-weight: normal;
|
152
|
+
font-style: normal;
|
153
|
+
}|
|
154
|
+
else
|
155
|
+
string = %Q|@font-face {
|
156
|
+
font-family: "#{font_name}";
|
157
|
+
src: #{url}("#{path}.eot");
|
158
|
+
src: #{url}("#{path}.eot?#iefix") format("embedded-opentype"),
|
159
|
+
#{url}("#{path}.woff") format("woff"),
|
160
|
+
#{url}("#{path}.ttf") format("truetype"),
|
161
|
+
#{url}("#{path}.svg##{font_name}") format("svg");
|
162
|
+
font-weight: normal;
|
163
|
+
font-style: normal;
|
164
|
+
}|
|
165
|
+
end
|
166
|
+
|
167
|
+
# For Windows/Chrome <http://stackoverflow.com/a/19247378/1202445>
|
168
|
+
string << %Q|
|
169
|
+
|
170
|
+
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
171
|
+
@font-face {
|
172
|
+
font-family: "#{font_name}";
|
173
|
+
src: #{url}("#{path}.svg##{font_name}") format("svg");
|
174
|
+
}
|
175
|
+
}|
|
176
|
+
string
|
177
|
+
end
|
178
|
+
|
179
|
+
def woff_base64
|
180
|
+
woff_path = File.join(@options[:output][:fonts], "#{@font_path}.woff")
|
181
|
+
Base64.encode64(File.binread(File.join(woff_path))).gsub("\n", "")
|
182
|
+
end
|
183
|
+
|
184
|
+
def glyph_selectors
|
185
|
+
output = @glyphs.map do |name, value|
|
186
|
+
aliases = []
|
187
|
+
aliases = @glyphs[name][:aliases].map do |alias_name|
|
188
|
+
@options[:css_selector].sub("{{glyph}}", alias_name.to_s) + ":before,\n"
|
189
|
+
end if @glyphs[name][:aliases]
|
190
|
+
aliases.join + @options[:css_selector].sub("{{glyph}}", name.to_s) + ":before"
|
191
|
+
end
|
192
|
+
output.join ",\n"
|
193
|
+
end
|
194
|
+
|
195
|
+
def glyph_properties
|
196
|
+
%Q| display: inline-block;
|
197
|
+
font-family: "#{font_name}";
|
198
|
+
font-style: normal;
|
199
|
+
font-weight: normal;
|
200
|
+
font-variant: normal;
|
201
|
+
line-height: 1;
|
202
|
+
text-decoration: inherit;
|
203
|
+
text-rendering: optimizeLegibility;
|
204
|
+
text-transform: none;
|
205
|
+
-moz-osx-font-smoothing: grayscale;
|
206
|
+
-webkit-font-smoothing: antialiased;
|
207
|
+
font-smoothing: antialiased;|
|
208
|
+
end
|
209
|
+
|
210
|
+
def glyphs
|
211
|
+
output = @glyphs.map do |name, value|
|
212
|
+
aliases = []
|
213
|
+
aliases = @glyphs[name][:aliases].map do |alias_name|
|
214
|
+
%Q|#{@options[:css_selector].sub('{{glyph}}', alias_name.to_s)}:before, |
|
215
|
+
end if @glyphs[name][:aliases]
|
216
|
+
aliases.join + %Q|#{@options[:css_selector].sub('{{glyph}}', name.to_s)}:before { content: "\\#{value[:codepoint].to_s(16)}"; }|
|
217
|
+
end
|
218
|
+
output.join "\n"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|