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
@@ -0,0 +1,128 @@
|
|
1
|
+
import fontforge
|
2
|
+
import os
|
3
|
+
import subprocess
|
4
|
+
import tempfile
|
5
|
+
import json
|
6
|
+
|
7
|
+
#
|
8
|
+
# Manifest / Options
|
9
|
+
# Older Pythons don't have argparse, so we use optparse instead
|
10
|
+
#
|
11
|
+
|
12
|
+
try:
|
13
|
+
import argparse
|
14
|
+
parser = argparse.ArgumentParser()
|
15
|
+
parser.add_argument('manifest', help='Path to .fontcustom-manifest.json')
|
16
|
+
args = parser.parse_args()
|
17
|
+
manifestfile = open(args.manifest, 'r+')
|
18
|
+
except ImportError:
|
19
|
+
import optparse
|
20
|
+
parser = optparse.OptionParser()
|
21
|
+
(nothing, args) = parser.parse_args()
|
22
|
+
manifestfile = open(args[0], 'r+')
|
23
|
+
|
24
|
+
manifest = json.load(manifestfile)
|
25
|
+
options = manifest['options']
|
26
|
+
|
27
|
+
#
|
28
|
+
# Font
|
29
|
+
#
|
30
|
+
|
31
|
+
design_px = options['font_em'] / options['font_design_size']
|
32
|
+
|
33
|
+
font = fontforge.font()
|
34
|
+
font.encoding = 'UnicodeFull'
|
35
|
+
font.design_size = options['font_design_size']
|
36
|
+
font.em = options['font_em']
|
37
|
+
font.ascent = options['font_ascent']
|
38
|
+
font.descent = options['font_descent']
|
39
|
+
font.fontname = options['font_name']
|
40
|
+
font.familyname = options['font_name']
|
41
|
+
font.fullname = options['font_name']
|
42
|
+
if options['autowidth']:
|
43
|
+
font.autoWidth(0, 0, options['font_em'])
|
44
|
+
|
45
|
+
#
|
46
|
+
# Glyphs
|
47
|
+
#
|
48
|
+
|
49
|
+
def removeSwitchFromSvg( file ):
|
50
|
+
svgfile = open(file, 'r')
|
51
|
+
svgtext = svgfile.read()
|
52
|
+
svgfile.close()
|
53
|
+
tmpsvgfile = tempfile.NamedTemporaryFile(suffix=".svg", delete=False)
|
54
|
+
svgtext = svgtext.replace('<switch>', '')
|
55
|
+
svgtext = svgtext.replace('</switch>', '')
|
56
|
+
tmpsvgfile.file.write(svgtext)
|
57
|
+
tmpsvgfile.file.close()
|
58
|
+
|
59
|
+
return tmpsvgfile.name
|
60
|
+
|
61
|
+
def createGlyph( name, source, code ):
|
62
|
+
frag, ext = os.path.splitext(source)
|
63
|
+
|
64
|
+
if ext == '.svg':
|
65
|
+
temp = removeSwitchFromSvg(source)
|
66
|
+
glyph = font.createChar(code)
|
67
|
+
glyph.importOutlines(temp)
|
68
|
+
os.unlink(temp)
|
69
|
+
|
70
|
+
if options['autowidth']:
|
71
|
+
glyph.left_side_bearing = glyph.right_side_bearing = 0
|
72
|
+
glyph.round()
|
73
|
+
else:
|
74
|
+
glyph.width = options['font_em']
|
75
|
+
width = glyph.width - glyph.left_side_bearing - glyph.right_side_bearing
|
76
|
+
aligned_to_pixel_grid = (width % design_px == 0)
|
77
|
+
if (aligned_to_pixel_grid):
|
78
|
+
shift = glyph.left_side_bearing % design_px
|
79
|
+
glyph.left_side_bearing = glyph.left_side_bearing - shift
|
80
|
+
glyph.right_side_bearing = glyph.right_side_bearing + shift
|
81
|
+
|
82
|
+
for glyph, data in manifest['glyphs'].iteritems():
|
83
|
+
name = createGlyph(glyph, data['source'], data['codepoint'])
|
84
|
+
|
85
|
+
#
|
86
|
+
# Generate Files
|
87
|
+
#
|
88
|
+
|
89
|
+
try:
|
90
|
+
fontfile = options['output']['fonts'] + '/' + options['font_name']
|
91
|
+
if not options['no_hash']:
|
92
|
+
fontfile += '_' + manifest['checksum']['current'][:32]
|
93
|
+
|
94
|
+
# Generate TTF and SVG
|
95
|
+
font.generate(fontfile + '.ttf')
|
96
|
+
font.generate(fontfile + '.svg')
|
97
|
+
manifest['fonts'].append(fontfile + '.ttf')
|
98
|
+
manifest['fonts'].append(fontfile + '.svg')
|
99
|
+
|
100
|
+
# Fix SVG header for webkit
|
101
|
+
# from: https://github.com/fontello/font-builder/blob/master/bin/fontconvert.py
|
102
|
+
svgfile = open(fontfile + '.svg', 'r+')
|
103
|
+
svgtext = svgfile.read()
|
104
|
+
svgfile.seek(0)
|
105
|
+
svgfile.write(svgtext.replace('''<svg>''', '''<svg xmlns="http://www.w3.org/2000/svg">'''))
|
106
|
+
svgfile.close()
|
107
|
+
|
108
|
+
# Convert WOFF
|
109
|
+
scriptPath = os.path.dirname(os.path.realpath(__file__))
|
110
|
+
try:
|
111
|
+
subprocess.Popen([scriptPath + '/sfnt2woff', fontfile + '.ttf'], stdout=subprocess.PIPE)
|
112
|
+
except OSError:
|
113
|
+
# If the local version of sfnt2woff fails (i.e., on Linux), try to use the
|
114
|
+
# global version. This allows us to avoid forcing OS X users to compile
|
115
|
+
# sfnt2woff from source, simplifying install.
|
116
|
+
subprocess.call(['sfnt2woff', fontfile + '.ttf'])
|
117
|
+
manifest['fonts'].append(fontfile + '.woff')
|
118
|
+
|
119
|
+
# Convert EOT for IE7
|
120
|
+
subprocess.call('python ' + scriptPath + '/eotlitetool.py ' + fontfile + '.ttf -o ' + fontfile + '.eot', shell=True)
|
121
|
+
subprocess.call('mv ' + fontfile + '.eotlite ' + fontfile + '.eot', shell=True)
|
122
|
+
manifest['fonts'].append(fontfile + '.eot')
|
123
|
+
|
124
|
+
finally:
|
125
|
+
manifestfile.seek(0)
|
126
|
+
manifestfile.write(json.dumps(manifest, indent=2, sort_keys=True))
|
127
|
+
manifestfile.truncate()
|
128
|
+
manifestfile.close()
|
Binary file
|
@@ -0,0 +1,14 @@
|
|
1
|
+
//
|
2
|
+
// Icon Font: <%= font_name %>
|
3
|
+
//
|
4
|
+
|
5
|
+
<%= font_face(url: "font-url", path: @font_path_alt) %>
|
6
|
+
|
7
|
+
[data-icon]:before { content: attr(data-icon); }
|
8
|
+
|
9
|
+
[data-icon]:before,
|
10
|
+
<%= glyph_selectors %> {
|
11
|
+
<%= glyph_properties %>
|
12
|
+
}
|
13
|
+
|
14
|
+
<%= glyphs %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
//
|
2
|
+
// Icon Font: <%= font_name %>
|
3
|
+
//
|
4
|
+
|
5
|
+
<%= font_face(path: @font_path_alt) %>
|
6
|
+
|
7
|
+
[data-icon]:before { content: attr(data-icon); }
|
8
|
+
|
9
|
+
[data-icon]:before,
|
10
|
+
<%= glyph_selectors %> {
|
11
|
+
<%= glyph_properties %>
|
12
|
+
}
|
13
|
+
|
14
|
+
<%= glyphs %>
|
15
|
+
<% @glyphs.each do |name, value| %>
|
16
|
+
$font-<%= font_name.gsub(/[^\w\d_]/, '-') %>-<%= name.to_s %>: "\<%= value[:codepoint].to_s(16) %>";<% end %>
|
@@ -0,0 +1,174 @@
|
|
1
|
+
<% scale = %w|12 14 16 18 21 24 36 48 60 72| %><!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title><%= font_name %> glyphs preview</title>
|
5
|
+
|
6
|
+
<style>
|
7
|
+
/* Page Styles */
|
8
|
+
|
9
|
+
* {
|
10
|
+
-moz-box-sizing: border-box;
|
11
|
+
-webkit-box-sizing: border-box;
|
12
|
+
box-sizing: border-box;
|
13
|
+
margin: 0;
|
14
|
+
padding: 0;
|
15
|
+
}
|
16
|
+
|
17
|
+
body {
|
18
|
+
background: #fff;
|
19
|
+
color: #444;
|
20
|
+
font: 16px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
|
21
|
+
}
|
22
|
+
|
23
|
+
a,
|
24
|
+
a:visited {
|
25
|
+
color: #888;
|
26
|
+
text-decoration: underline;
|
27
|
+
}
|
28
|
+
a:hover,
|
29
|
+
a:focus { color: #000; }
|
30
|
+
|
31
|
+
header {
|
32
|
+
border-bottom: 2px solid #ddd;
|
33
|
+
margin-bottom: 20px;
|
34
|
+
overflow: hidden;
|
35
|
+
padding: 20px 0;
|
36
|
+
}
|
37
|
+
|
38
|
+
header h1 {
|
39
|
+
color: #888;
|
40
|
+
float: left;
|
41
|
+
font-size: 36px;
|
42
|
+
font-weight: 300;
|
43
|
+
}
|
44
|
+
|
45
|
+
header a {
|
46
|
+
float: right;
|
47
|
+
font-size: 14px;
|
48
|
+
}
|
49
|
+
|
50
|
+
.container {
|
51
|
+
margin: 0 auto;
|
52
|
+
max-width: 1200px;
|
53
|
+
min-width: 960px;
|
54
|
+
padding: 0 40px;
|
55
|
+
width: 90%;
|
56
|
+
}
|
57
|
+
|
58
|
+
.glyph {
|
59
|
+
border-bottom: 1px dotted #ccc;
|
60
|
+
padding: 10px 0 20px;
|
61
|
+
margin-bottom: 20px;
|
62
|
+
}
|
63
|
+
|
64
|
+
.preview-glyphs { vertical-align: bottom; }
|
65
|
+
|
66
|
+
.preview-scale {
|
67
|
+
color: #888;
|
68
|
+
font-size: 12px;
|
69
|
+
margin-top: 5px;
|
70
|
+
}
|
71
|
+
|
72
|
+
.step {
|
73
|
+
display: inline-block;
|
74
|
+
line-height: 1;
|
75
|
+
position: relative;
|
76
|
+
width: 10%;
|
77
|
+
}
|
78
|
+
|
79
|
+
.step .letters,
|
80
|
+
.step i {
|
81
|
+
-webkit-transition: opacity .3s;
|
82
|
+
-moz-transition: opacity .3s;
|
83
|
+
-ms-transition: opacity .3s;
|
84
|
+
-o-transition: opacity .3s;
|
85
|
+
transition: opacity .3s;
|
86
|
+
}
|
87
|
+
|
88
|
+
.step:hover .letters { opacity: 1; }
|
89
|
+
.step:hover i { opacity: .3; }
|
90
|
+
|
91
|
+
.letters {
|
92
|
+
opacity: .3;
|
93
|
+
position: absolute;
|
94
|
+
}
|
95
|
+
|
96
|
+
.characters-off .letters { display: none; }
|
97
|
+
.characters-off .step:hover i { opacity: 1; }
|
98
|
+
|
99
|
+
<% scale.each do |n| %>
|
100
|
+
.size-<%= n %> { font-size: <%= n %>px; }
|
101
|
+
<% end %>
|
102
|
+
|
103
|
+
.usage { margin-top: 10px; }
|
104
|
+
|
105
|
+
.usage input {
|
106
|
+
font-family: monospace;
|
107
|
+
margin-right: 3px;
|
108
|
+
padding: 2px 5px;
|
109
|
+
text-align: center;
|
110
|
+
}
|
111
|
+
|
112
|
+
.usage .point { width: 150px; }
|
113
|
+
|
114
|
+
.usage .class { width: 250px; }
|
115
|
+
|
116
|
+
footer {
|
117
|
+
color: #888;
|
118
|
+
font-size: 12px;
|
119
|
+
padding: 20px 0;
|
120
|
+
}
|
121
|
+
|
122
|
+
/* Icon Font: <%= font_name %> */
|
123
|
+
|
124
|
+
<%= font_face(path: @font_path_preview) %>
|
125
|
+
|
126
|
+
[data-icon]:before { content: attr(data-icon); }
|
127
|
+
|
128
|
+
[data-icon]:before,
|
129
|
+
<%= glyph_selectors %> {
|
130
|
+
<%= glyph_properties %>
|
131
|
+
}
|
132
|
+
|
133
|
+
<%= glyphs %>
|
134
|
+
</style>
|
135
|
+
|
136
|
+
<!--[if lte IE 8]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
|
137
|
+
|
138
|
+
<script>
|
139
|
+
function toggleCharacters() {
|
140
|
+
var body = document.getElementsByTagName('body')[0];
|
141
|
+
body.className = body.className === 'characters-off' ? '' : 'characters-off';
|
142
|
+
}
|
143
|
+
</script>
|
144
|
+
</head>
|
145
|
+
|
146
|
+
<body class="characters-off">
|
147
|
+
<div id="page" class="container">
|
148
|
+
<header>
|
149
|
+
<h1><%= font_name %> contains <%= @glyphs.length %> glyphs:</h1>
|
150
|
+
<a onclick="toggleCharacters(); return false;" href="#">Toggle Preview Characters</a>
|
151
|
+
</header>
|
152
|
+
|
153
|
+
<% @glyphs.each do |name, value|
|
154
|
+
selector = @options[:css_selector].sub('{{glyph}}', name.to_s) %>
|
155
|
+
<div class="glyph">
|
156
|
+
<div class="preview-glyphs">
|
157
|
+
<% scale.each do |n| %><span class="step size-<%= n %>"><span class="letters">Pp</span><i id="<%= selector[1..-1] %>" class="<%= selector[1..-1].gsub('.', ' ') %>"></i></span><% end %>
|
158
|
+
</div>
|
159
|
+
<div class="preview-scale">
|
160
|
+
<% scale.each do |n| %><span class="step"><%= n %></span><% end %>
|
161
|
+
</div>
|
162
|
+
<div class="usage">
|
163
|
+
<input class="class" type="text" readonly="readonly" onClick="this.select();" value="<%= selector %>" />
|
164
|
+
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&#x<%= value[:codepoint].to_s(16) %>;" />
|
165
|
+
</div>
|
166
|
+
</div>
|
167
|
+
<% end %>
|
168
|
+
|
169
|
+
<footer>
|
170
|
+
Made with love using <a href="http://fontcustom.com">Font Custom</a>.
|
171
|
+
</footer>
|
172
|
+
</div>
|
173
|
+
</body>
|
174
|
+
</html>
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# =============================================================================
|
2
|
+
# Font Custom Configuration
|
3
|
+
# This file should live in the directory where you run `fontcustom compile`.
|
4
|
+
# For more info, visit <https://github.com/FontCustom/fontcustom>.
|
5
|
+
# =============================================================================
|
6
|
+
|
7
|
+
|
8
|
+
# -----------------------------------------------------------------------------
|
9
|
+
# Project Info
|
10
|
+
# -----------------------------------------------------------------------------
|
11
|
+
|
12
|
+
# The font's name. Also determines the file names of generated templates.
|
13
|
+
#font_name: icons
|
14
|
+
|
15
|
+
# Format of CSS selectors. {{glyph}} is substituted for the glyph name.
|
16
|
+
#css_selector: .i-{{glyph}}
|
17
|
+
|
18
|
+
# Generate fonts without asset-busting hashes.
|
19
|
+
#no_hash: true
|
20
|
+
|
21
|
+
# Encode WOFF fonts into the generated CSS.
|
22
|
+
#base64: true
|
23
|
+
|
24
|
+
# Forces compilation, even if inputs have not changed
|
25
|
+
#force: true
|
26
|
+
|
27
|
+
# Display (possibly useful) debugging messages.
|
28
|
+
#debug: true
|
29
|
+
|
30
|
+
# Hide status messages.
|
31
|
+
#quiet: true
|
32
|
+
|
33
|
+
|
34
|
+
# -----------------------------------------------------------------------------
|
35
|
+
# Input / Output Locations
|
36
|
+
# You can save generated fonts, CSS, and other files to different locations
|
37
|
+
# here. Font Custom can also read input vectors and templates from different
|
38
|
+
# places.
|
39
|
+
#
|
40
|
+
# NOTE:
|
41
|
+
# - Be sure to preserve the whitespace in these YAML hashes.
|
42
|
+
# - INPUT[:vectors] and OUTPUT[:fonts] are required. Everything else is
|
43
|
+
# optional.
|
44
|
+
# - Specify output locations for custom templates by including their file
|
45
|
+
# names as the key.
|
46
|
+
# -----------------------------------------------------------------------------
|
47
|
+
|
48
|
+
#input:
|
49
|
+
# vectors: my/vectors
|
50
|
+
# templates: my/templates
|
51
|
+
|
52
|
+
#output:
|
53
|
+
# fonts: app/assets/fonts
|
54
|
+
# css: app/assets/stylesheets
|
55
|
+
# preview: app/views/styleguide
|
56
|
+
# my-custom-template.yml: path/to/template/output
|
57
|
+
|
58
|
+
|
59
|
+
# -----------------------------------------------------------------------------
|
60
|
+
# Templates
|
61
|
+
# A YAML array of templates and files to generate alongside fonts. Custom
|
62
|
+
# templates should be saved in the INPUT[:templates] directory and referenced
|
63
|
+
# by their base file name.
|
64
|
+
#
|
65
|
+
# For Rails and Compass templates, set `preprocessor_path` as the relative
|
66
|
+
# path from OUTPUT[:css] to OUTPUT[:fonts]. By default, these are the same
|
67
|
+
# directory.
|
68
|
+
#
|
69
|
+
# Included in Font Custom: preview, css, scss, scss-rails
|
70
|
+
# Default: css, preview
|
71
|
+
# -----------------------------------------------------------------------------
|
72
|
+
|
73
|
+
#templates:
|
74
|
+
#- scss-rails
|
75
|
+
#- preview
|
76
|
+
#- my-custom-template.yml
|
77
|
+
|
78
|
+
#preprocessor_path: ../fonts/
|
79
|
+
|
80
|
+
|
81
|
+
# -----------------------------------------------------------------------------
|
82
|
+
# Font Settings (defaults shown)
|
83
|
+
# -----------------------------------------------------------------------------
|
84
|
+
|
85
|
+
# Size (in pica points) for which your font is designed.
|
86
|
+
#font_design_size: 16
|
87
|
+
|
88
|
+
# The em size. Setting this will scale the entire font to the given size.
|
89
|
+
#font_em: 512
|
90
|
+
|
91
|
+
# The font's descent and descent. Used to calculate the baseline.
|
92
|
+
#font_ascent: 448
|
93
|
+
#font_descent: 64
|
94
|
+
|
95
|
+
# Horizontally fit glyphs to their individual vector widths.
|
96
|
+
#autowidth: false
|