From 7d0eef9b1b705f4f9dd8312524542de9b4ed2fd1 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Tue, 17 Apr 2018 23:15:42 +0800 Subject: Add make-fontawesome5.py to create latex style for Font Awesome 5 NOTE: Font Awesome 5 split the icons into 3 different fonts: * solid: generic icons in solid style (main) * regular: generic icons in regular style (much less than the solid style) * brands: icons of various brands --- fontawesome5/make-fontawesome5.py | 220 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100755 fontawesome5/make-fontawesome5.py diff --git a/fontawesome5/make-fontawesome5.py b/fontawesome5/make-fontawesome5.py new file mode 100755 index 0000000..88a8064 --- /dev/null +++ b/fontawesome5/make-fontawesome5.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2018 Weitian LI +# MIT License +# + +""" +Create Font Awesome v5 mapping for XeLaTeX. + +Credits: +* FontAwesome + https://github.com/FortAwesome/Font-Awesome +* FontAwesome 5.0.0-beta.6 mapping for XeLaTeX + https://gist.github.com/phyllisstein/b790f853dac935060087f78839043b36 +* Awesome-CV / fontawesome.sty + https://github.com/posquit0/Awesome-CV/blob/master/fontawesome.sty +* LaTeX - Creating Packages + https://en.wikibooks.org/wiki/LaTeX/Creating_Packages +""" + +import os +import sys +import argparse +import yaml +import urllib.request +from datetime import datetime + + +FA_URL = "https://github.com/FortAwesome/Font-Awesome" +ICONS_URL = FA_URL + "/raw/master/advanced-options/metadata/icons.yml" +ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + +# Fonts styles +FONTS = { + "regular": "FontAwesomeRegular", + "solid": "FontAwesomeSolid", + "brands": "FontAwesomeBrands", +} + +# LaTeX style template +STY_TEMPLATE = """%% +%% Font Awesome v5 mapping for XeLaTeX +%% +%% Generated by: %(program)s +%% Date: %(date)s +%% +%% Usage +%% ----- +%% 1. \\usepackage{fontawesome} %% default to *solid* style +%% or +%% \\usepackage[regular]{fontawesome} %% use *regular* style +%% 2. use an icon, e.g., \\faGitHub +%% + +\\NeedsTeXFormat{LaTeX2e}[1994/06/01] +\\ProvidesPackage{fontawesome5}[%(date)s Font Awesome 5] + +\\RequirePackage{fontspec} + +\\DeclareOption{regular}{\\def\\FA@regular{true}} +\\ProcessOptions\\relax + +%% Declare all variants +%% Solid (default) +\\newfontfamily\\FontAwesomeSolid[ + BoldFont=Font Awesome 5 Free Solid, +]{Font Awesome 5 Free Solid} +%% Regular +\\newfontfamily\\FontAwesomeRegular[ + BoldFont=Font Awesome 5 Free, +]{Font Awesome 5 Free} +%% Brands +\\newfontfamily\\FontAwesomeBrands[ + BoldFont=Font Awesome 5 Brands, +]{Font Awesome 5 Brands} + +%% Generic command displaying an icon by its name +\\newcommand*{\\faicon}[1]{{ + \FA\csname faicon@#1\endcsname +}} + +%% Mappings +%(mappings)s + +%% TeX commands +\\ifundef{\\FA@regular}{ +%% [Solid] fallback to Regular style +%(cmds_solid)s +}{ +%% [Regular] fallback to Solid style +%(cmds_regular)s +} +%% [Brands] +%(cmds_brands)s + +\\endinput +%% EOF +""" + + +def get_icons_yml(url=ICONS_URL): + print("Downloading icons.yml from: %s" % url) + resp = urllib.request.urlopen(url) + data = resp.read() + return data.decode("utf-8") + + +def make_cmdname(name): + cmdname = [] + upper = False + for i, c in enumerate(name): + if c == "-": + upper = True + continue + if i == 0: + upper = True + if upper: + cmdname.append(c.upper()) + else: + cmdname.append(c) + upper = False + return "".join(cmdname) + + +def make_map(name, symbol): + """ + Map Font Awesome icon names to unicode symbols + """ + return '\\expandafter\\def\\csname faicon@%(name)s\\endcsname{\\symbol{"%(symbol)s}}' % { + "name": name, + "symbol": symbol.upper(), + } + + +def make_cmd(name, icon, style="solid"): + """ + Create LaTeX command to use Font Awesome icons + """ + cmdname = make_cmdname(name) + if style == "solid": + fallback = "regular" + elif style == "regular": + fallback = "solid" + elif style == "brands": + fallback = None + else: + raise ValueError("Invalid style: %s" % style) + + if style in icon["styles"]: + font = FONTS[style] + elif fallback in icon["styles"]: + font = FONTS[fallback] + else: + return None + + return '\\def\\fa%(cmdname)s{{\\%(font)s\\csname faicon@%(name)s\\endcsname}}' % { + "font": font, + "cmdname": cmdname, + "name": name, + } + + +def main(): + parser = argparse.ArgumentParser( + description="Create Font Awesome v5 mapping for XeLaTeX") + parser.add_argument("-C", "--clobber", action="store_true", + help="overwrite existing output file") + parser.add_argument("-i", "--infile", + help="input icons.yml file of icons information " + + "(default: download from FontAwesome's repo)") + parser.add_argument("-o", "--outfile", default="fontawesome5.sty", + help="output LaTeX style file " + + "(default: fontawesome5.sty)") + args = parser.parse_args() + + if os.path.exists(args.outfile): + if args.clobber: + os.remove(args.outfile) + print("Removed existing file: %s" % args.outfile) + else: + raise OSError("File already exists: %s" % args.outfile) + + if args.infile: + data = open(args.infile).read() + else: + data = get_icons_yml() + + print("Loading icons data ...") + icons = yaml.load(data) + icon_list = sorted(icons.keys()) + print("Number of icons: %d" % len(icon_list)) + + mappings = [make_map(name, icons[name]["unicode"]) + for name in icon_list] + cmds_regular = [make_cmd(name, icons[name], style="regular") + for name in icon_list] + cmds_solid = [make_cmd(name, icons[name], style="solid") + for name in icon_list] + cmds_brands = [make_cmd(name, icons[name], style="brands") + for name in icon_list] + # Exclude None's + cmds_regular = [cmd for cmd in cmds_regular if cmd] + cmds_solid = [cmd for cmd in cmds_solid if cmd] + cmds_brands = [cmd for cmd in cmds_brands if cmd] + + data = { + "program": os.path.basename(sys.argv[0]), + "date": datetime.now().strftime("%Y/%m/%d"), + "mappings": "\n".join(mappings), + "cmds_regular": "\n".join(cmds_regular), + "cmds_solid": "\n".join(cmds_solid), + "cmds_brands": "\n".join(cmds_brands), + } + + open(args.outfile, "w").write(STY_TEMPLATE % data) + print("Mapping writen to file: %s" % args.outfile) + + +if __name__ == "__main__": + main() -- cgit v1.2.2