-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds the current mapping file (which has been hand-crafted) and the scripts to update the Devicons. This also fixes Vorillaz' typo 'rasberry_pi' -> 'raspberry_pi'. Signed-off-by: Fini Jastrow <[email protected]>
- Loading branch information
Showing
4 changed files
with
493 additions
and
7 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,13 @@ | ||
# Devicons | ||
|
||
For more information have a look at the upstream website: https://github.com/vorillaz/devicons | ||
From the Devicons the non-linemark versions are selected and assembled into a custom | ||
icon font. This font guarantees that the codepoints of existing icons do not change | ||
when other icons are added or removed. | ||
|
||
This is taken directly from the repository default branch, which is ahead of release 1.8.0. | ||
We call it 1.8.1 here, but there is no such release. | ||
For more information have a look at the upstream website: https://github.com/devicon/devicons | ||
|
||
## Source bugs fixed | ||
The helper scripts need to be called in this order (note the individual prerequisites): | ||
* `analyze` | ||
* `generate` (possibly via `fontforge`) | ||
|
||
Glyph 0xE6B6 is defective in the original font. We hand optimized and fixed that. | ||
|
||
Version: 1.8.1 | ||
Version: 2.16.0.custom |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
#!/usr/bin/env python3 | ||
# coding=utf8 | ||
|
||
# Create a new mapping file by combining the information from | ||
# the old mapping and checking which icons got dropped; are new; | ||
# or get a different svg file. | ||
|
||
# PREREQUISITES: | ||
# $ curl -OL https://github.com/devicons/devicon/archive/refs/tags/v2.16.0.tar.gz | ||
# $ tar zxf v2.16.0.tar.gz | ||
# $ mv devicon-*/icons . | ||
# $ cp -r vorillaz icons | ||
|
||
import re, os, sys | ||
|
||
vectorsdir = 'icons' | ||
|
||
def filename_from_name(filename): | ||
""" Some icons have a name that is not the svg filename """ | ||
# Returns '-' if the icon is to be removed | ||
# Giving a full pathname selects a certain svg variant | ||
return { | ||
'aws': 'amazonwebservices', | ||
'backbone': 'backbonejs', | ||
'bower': 'bower/bower-line.svg', | ||
'clojure': 'clojure/clojure-line.svg', | ||
'composer': 'composer/composer-line.svg', | ||
'css3_full': 'css3/css3-plain-wordmark.svg', | ||
'digital_ocean': 'digitalocean', | ||
'dotnet': 'dot-net', | ||
'ghost': 'ghost/ghost-original-wordmark.svg', | ||
'ghost_small': 'ghost', | ||
'github': '-', | ||
'github_alt': '-', | ||
'github_badge': 'github', | ||
'github_full': 'github/github-original-wordmark.svg', | ||
'go': 'go/go-line.svg', | ||
'grunt': 'grunt/grunt-line.svg', | ||
'ie': 'ie10', | ||
'javascript_badge': 'javascript', | ||
'javascript': '-', | ||
'jekyll_small': 'jekyll', | ||
'krakenjs': '-', | ||
'krakenjs_badge': 'krakenjs', | ||
'meteorfull': 'meteor/meteor-plain-wordmark.svg', | ||
'nodejs': 'nodejs/nodejs-plain-wordmark.svg', | ||
'nodejs_small': 'nodejs', | ||
'raspberry_pi': 'raspberrypi', | ||
'ruby_on_rails': 'rails', | ||
'symfony': '-', | ||
'symfony_badge': 'symfony', | ||
'unity_small': 'unity', | ||
'windows': 'windows8', | ||
}.get(filename, filename) | ||
|
||
def get_aliases(names): | ||
""" For some icons we would like to have aliases """ | ||
# Returns a list with aliases, keep main name first element | ||
name = names[0] | ||
alias = { | ||
'digital_ocean': [ 'digitalocean' ], | ||
'github_badge': [ 'github' ], | ||
'javascript_badge': [ 'javascript' ], | ||
'jekyll_small': [ 'jekyll' ], | ||
'krakenjs_badge': [ 'krakenjs' ], | ||
'ruby_on_rails': [ 'rails' ], | ||
'symfony_badge': [ 'symfony' ], | ||
'unifiedmodelinglanguage': [ 'uml' ], | ||
}.get(name, [ ]) | ||
while name in alias: | ||
alias.remove(name) | ||
return [ name , *alias ] | ||
|
||
def file_with_ending(files, ending): | ||
""" Return the (first) file out of a list of files that has the desired ending """ | ||
# Returns False if no match at all | ||
matches = [ file for file in files if file.endswith(ending) ] | ||
if not matches: | ||
return False | ||
return matches[0] | ||
|
||
def suggest_new_filename(name): | ||
""" Return a specific svg filename for one icon, preferring some svg filename endings """ | ||
name = filename_from_name(name) | ||
subdir = vectorsdir + '/' + name | ||
if not os.path.exists(subdir): | ||
return False | ||
if os.path.isfile(subdir): | ||
return name | ||
svgs = os.listdir(subdir) | ||
filename = file_with_ending(svgs, 'plain.svg') | ||
if not filename: | ||
filename = file_with_ending(svgs, 'original.svg') | ||
if not filename: | ||
filename = file_with_ending(svgs, 'plain-wordmark.svg') | ||
if not filename: | ||
filename = file_with_ending(svgs, 'original-wordmark.svg') | ||
if not filename: | ||
return False | ||
return name + '/' + filename | ||
|
||
remix_mapping = [] | ||
with open('mapping', 'r') as f: | ||
for line in f.readlines(): | ||
if line.startswith('#'): | ||
continue | ||
c1, c2, n, *f = re.split(' +', line.strip()) | ||
remix_mapping.append((int(c1, 16), int(c2, 16), n, *f)) | ||
|
||
new_names = os.listdir(vectorsdir) | ||
new_names.sort() | ||
new_names.remove('vorillaz') # If this fails one prerequisite step is missing | ||
|
||
notes1 = '' | ||
notes2 = '' | ||
mapping = [] | ||
for orig_point, dest_point, filename, *names in remix_mapping: | ||
if not os.path.isfile(vectorsdir + '/' + filename): | ||
newfilename = suggest_new_filename(names[0]) | ||
if newfilename: | ||
notes1 += '# SVG change: code: {:04X} name: {}, old: {}, new: {}\n'.format( | ||
orig_point, names[0], filename, newfilename) | ||
filename = newfilename | ||
if filename: | ||
mapping.append((orig_point, dest_point, filename, *names)) | ||
dirname = os.path.dirname(filename) | ||
if dirname in new_names: | ||
new_names.remove(dirname) | ||
continue | ||
|
||
notes2 += '# Icon dropped: code: {:04X} name: {}\n'.format( | ||
orig_point, names[0]) | ||
|
||
index = 0xE700 | ||
taken_codes = set([ e[1] for e in mapping ]) | ||
for iconname in new_names: | ||
filename = suggest_new_filename(iconname) | ||
if not filename: | ||
sys.exit('Can not find svg for "{}"'.format(iconname)) | ||
while index in taken_codes: | ||
index = index + 1 | ||
mapping.append((index - 0x0100, index, filename, iconname)) | ||
taken_codes.add(index) | ||
|
||
with open('mapping', 'w', encoding = 'utf8') as f: | ||
f.write('# Devicons mapping file\n') | ||
f.write('#\n') | ||
f.write('# DEV-code NF-code filename name [alias [...]]\n') | ||
f.write('#\n') | ||
|
||
mapping.sort(key=(lambda x: x[1])) | ||
unique_names = set() | ||
for orig_point, dest_point, filename, *names in mapping: | ||
aliases = get_aliases(names) | ||
for n in aliases: | ||
if n not in unique_names: | ||
unique_names.add(n) | ||
else: | ||
sys.exit('ERROR name duplicate found: {}'.format(n)) | ||
f.write("{:04X} {:04X} {} {}\n".format(orig_point, dest_point, filename, ' '.join(aliases))) | ||
|
||
print(notes1) | ||
print(notes2) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/usr/bin/env python3 | ||
# coding=utf8 | ||
|
||
# PREREQUISITES: | ||
# Have a correct and up to date mappings file, updated maybe with analyze | ||
# $ analyze > mapping | ||
|
||
import sys | ||
import os | ||
import re | ||
import subprocess | ||
import fontforge | ||
|
||
# Double-quotes required here, for version-bump.sh: | ||
# version-bump.sh is not working here, need to adjust manually! | ||
version = "3.3.0" | ||
|
||
dev_version = 'v2.16.0' | ||
archive = '{}.tar.gz'.format(dev_version) | ||
|
||
vectorsdir = 'icons' | ||
fontdir = '.' | ||
fontfile = 'devicons.otf' | ||
glyphsetfile = 'i_dev.sh' | ||
glyphsetsdir = '../../../bin/scripts/lib' | ||
|
||
def addIcon(codepoint, name, filename): | ||
""" Add one outline file and rescale/move """ | ||
filename = os.path.join(vectorsdir, filename) | ||
glyph = font.createChar(codepoint, name) | ||
glyph.importOutlines(filename) | ||
xmin, ymin, xmax, ymax = glyph.boundingBox() | ||
glyph.width = int(xmax + xmin) # make left and right bearings equal | ||
glyph.manualHints = True | ||
|
||
def createGlyphInfo(icon_datasets, filepathname, into): | ||
""" Write the glyphinfo file """ | ||
with open(filepathname, 'w', encoding = 'utf8') as f: | ||
f.write(u'#!/usr/bin/env bash\n') | ||
f.write(intro) | ||
f.write(u'# Script Version: (autogenerated)\n') | ||
f.write(u'test -n "$__i_dev_loaded" && return || __i_dev_loaded=1\n') | ||
for _, codepoint, _, *name in icon_datasets: | ||
codepoint = int(codepoint, 16) | ||
f.write(u"i='{}' i_dev_{}=$i\n".format(chr(codepoint), name[0])) | ||
for more_names in name[1:]: | ||
f.write(u" i_dev_{}=$i\n".format(more_names)) | ||
f.write(u'unset i\n') | ||
|
||
print('\nReading mapping file') | ||
mapping = [] | ||
with open('mapping', 'r') as f: | ||
for line in f.readlines(): | ||
line = line.strip() | ||
if line.startswith('#') or len(line) < 1: | ||
continue | ||
mapping.append(tuple(re.split(' +', line.strip()))) | ||
print('Found {} entries'.format(len(mapping))) | ||
mapping.sort(key=(lambda x: x[1])) | ||
|
||
print('Fetching Devicons archive "{}"\n'.format(archive)) | ||
if False and subprocess.call('curl -OL https://github.com/devicons/devicon/archive/refs/tags/' + archive, shell=True): | ||
sys.exit('Error fetching Devicons archive') | ||
|
||
print('\nUnpacking Devicons archive') | ||
if False and subprocess.call('rm -rf devicon-* icons && tar zxf ' + archive + \ | ||
' && mv devicon-*/icons . && rm -rf v*.tar.gz', shell=True): | ||
sys.exit('Error unpacking archive') | ||
|
||
print('\nMixing Vorillaz Devicons in') | ||
if subprocess.call('cp -r vorillaz icons', shell=True): | ||
sys.exit('Error mixing ...') | ||
|
||
|
||
svg_dirs = os.listdir(vectorsdir) | ||
svgs = [] | ||
for d in svg_dirs: | ||
svgs += os.listdir(vectorsdir + '/' + d) | ||
print('Found {} svgs'.format(len(svgs))) | ||
|
||
font = fontforge.font() | ||
font.fontname = 'Devicons-NerdFont-Regular' | ||
font.fullname = 'Devicons Nerd Font Regular' | ||
font.familyname = 'Devicons Nerd Font' | ||
font.ascent = 1000 | ||
font.descent = 200 | ||
font.encoding = 'UnicodeFull' | ||
|
||
# Add valid space glyph to avoid "unknown character" box on IE11 | ||
glyph = font.createChar(32) | ||
glyph.width = 200 | ||
|
||
font.sfntRevision = None # Auto-set (refreshed) by fontforge | ||
font.version = version | ||
font.copyright = 'Fonticons, Inc' | ||
font.appendSFNTName('English (US)', 'Version', archive + '; ' + version) | ||
font.appendSFNTName('English (US)', 'Vendor URL', 'https://github.com/ryanoasis/nerd-fonts') | ||
font.appendSFNTName('English (US)', 'Copyright', 'See https://github.com/devicons/devicon') | ||
|
||
for _, codepoint, file, *names in mapping: | ||
codepoint = int(codepoint, 16) | ||
addIcon(codepoint, names[0], file) | ||
|
||
num_icons = len(mapping) | ||
|
||
print('Generating {} with {} glyphs'.format(fontfile, num_icons)) | ||
font.ascent = 1100 | ||
font.descent = 300 | ||
font.generate(os.path.join(fontdir, fontfile), flags=("no-FFTM-table",)) | ||
|
||
codepoints = [ int(p, 16) for _, p, *_ in mapping ] | ||
aliases = [ len(n) - 1 for _, _, _, *n in mapping ] | ||
intro = u'# Devicons (version {}, {} icons, {} aliases)\n'.format(dev_version, num_icons, sum(aliases)) | ||
intro += u'# Does not include all icons of the release\n' | ||
intro += u'# Codepoints: {:X}-{:X} with gaps\n'.format(min(codepoints), max(codepoints)) | ||
intro += u'# Nerd Fonts Version: {}\n'.format(version) | ||
|
||
print('Generating GlyphInfo {}'.format(glyphsetfile)) | ||
createGlyphInfo(mapping, os.path.join(glyphsetsdir, glyphsetfile), intro) | ||
print('Finished') |
Oops, something went wrong.