Last active
October 19, 2016 13:20
-
-
Save rock3r/e05816517b7b66bc8d75d8a5b6f7b9a4 to your computer and use it in GitHub Desktop.
Rip fonts from Google Fonts for self-hosting, EZ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
#coding: utf-8 | |
import argparse, os, tinycss, requests | |
def parse_cli_arguments(): | |
parser = argparse.ArgumentParser(description='Downlads all available variants of a font from Google Fonts') | |
parser.add_argument('fontname', type=str, help='The name of the font. E.g., "Roboto", "Product Sans"') | |
return parser.parse_args() | |
def download_css(font): | |
url = 'https://fonts.googleapis.com/css?family={font}:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese'.format(font = font) | |
# This useragent tricks Google Fonts into delivering us a TTF version | |
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.54.16 (KHTML, like Gecko) Version/5.1.4 Safari/534.54.16' } | |
r = requests.get(url, headers = headers) | |
print "CSS downloaded: " | |
print r.text | |
return r.text | |
def font_name(font_face): | |
if font_face.style == 'normal': | |
return font_face.family_name + '.ttf' | |
else: | |
return font_face.family_name + '-' + font_face.style + '.ttf' | |
def download_font_file(font_face): | |
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.54.16 (KHTML, like Gecko) Version/5.1.4 Safari/534.54.16' } | |
r = requests.get(font_face.url, headers) | |
file_name = font_name(font_face) | |
with open(file_name, "w") as font_file: | |
font_file.write(r.content) | |
return os.path.abspath(file_name) | |
def extract_family_name(values): | |
for value in values: | |
try: | |
if value.function_name == 'local': | |
return value.content[0].value | |
except AttributeError as e: | |
continue | |
def extract_url(values): | |
for value in values: | |
if value.type == 'URI': | |
return value.value | |
def parse_font_face(rule): | |
if rule.at_keyword != '@font-face': | |
raise Exception("Not a @font-face rule") | |
font_face = FontFace() | |
for declaration in rule.declarations: | |
if declaration.name == 'font-style': | |
font_face.style = declaration.value[0].value | |
elif declaration.name == 'src': | |
font_face.family_name = extract_family_name(declaration.value) | |
font_face.url = extract_url(declaration.value) | |
print " Rule parsed: {}".format(vars(font_face)) | |
return font_face | |
class FontFace(object): | |
__attrs__ = [ | |
'family_name', 'style', 'url' | |
] | |
def __init__(self, family_name, style, url): | |
super(FontFace, self).__init__() | |
self.family_name = family_name | |
self.style = style | |
self.url = url | |
def __init__(self): | |
super(FontFace, self).__init__() | |
pass | |
############################################################################################### | |
############################################################################################### | |
args = parse_cli_arguments() | |
css = download_css(args.fontname) | |
print 'Parsing CSS...' | |
parser = tinycss.make_parser('fonts3') | |
css = parser.parse_stylesheet(css) | |
for rule in css.rules: | |
print " > @font-face rule found at {line}:{column}".format(line = rule.line, column = rule.column) | |
try: | |
font_face = parse_font_face(rule) | |
except Exception as e: | |
print " Skipping rule, parsing error" | |
continue | |
print " Downloading font..." | |
output_path = download_font_file(font_face) | |
print u" Font downloaded to {}! ✨".format(output_path) | |
print u"All done yay 🎉" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment