├── .gitignore ├── FiraCode-Medium.otf ├── README.md ├── images ├── banner.png ├── menlo.png └── sf-mono.png ├── input-fonts ├── Anonymous_Pro.ttf ├── CamingoCode Regular.ttf ├── Cousine-Regular.ttf ├── DejaVuSansMono.ttf ├── DroidSansMono.ttf ├── Hack-Regular.otf ├── IBMPlexMono-Regular.otf ├── IBMPlexMono-SemiBold.otf ├── Inconsolata-Regular.ttf ├── Inconsolata-g.otf ├── Inconsolata.otf ├── MesloLGL-Regular.ttf ├── MesloLGLDZ-Regular.ttf ├── MesloLGM-Regular.ttf ├── MesloLGMDZ-Regular.ttf ├── MesloLGS-Regular.ttf ├── MesloLGSDZ-Regular.ttf ├── OxygenMono-Regular.ttf ├── RobotoMono-Regular.ttf ├── SFMono-Regular.otf ├── SFMono-Semibold.otf ├── UbuntuMono-Regular.ttf └── edlo.ttf ├── ligaturize.py └── output-fonts ├── Anonymous_Pro.ttf ├── CamingoCode.ttf ├── Cousine.ttf ├── DejaVuSansMono.ttf ├── DroidSansMono.ttf ├── Hack.ttf ├── IBMPlexMono-SemiBold.ttf ├── IBMPlexMono.ttf ├── Inconsolata-g.ttf ├── Inconsolata.ttf ├── MesloLGL.ttf ├── MesloLGLDZ.ttf ├── MesloLGM.ttf ├── MesloLGMDZ.ttf ├── MesloLGS.ttf ├── MesloLGSDZ.ttf ├── OxygenMono.ttf ├── RobotoMono.ttf ├── SFMono-Semibold.ttf ├── SFMono.ttf ├── UbuntuMono.ttf └── edlo.ttf /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/font,linux,macos,python,fontforge,pycharm+all,sublimetext,visualstudiocode 3 | 4 | ### FontForge ### 5 | *.sfd-* 6 | *.sfd~ 7 | 8 | # No Binaries 9 | 10 | *.ttc 11 | *.pfb 12 | *.pfa 13 | *.pt3 14 | *.suit 15 | 16 | ### Linux ### 17 | *~ 18 | 19 | # temporary files which can be created if a process still has a handle open of a deleted file 20 | .fuse_hidden* 21 | 22 | # KDE directory preferences 23 | .directory 24 | 25 | # Linux trash folder which might appear on any partition or disk 26 | .Trash-* 27 | 28 | # .nfs files are created when an open file is removed but is still being accessed 29 | .nfs* 30 | 31 | ### macOS ### 32 | *.DS_Store 33 | .AppleDouble 34 | .LSOverride 35 | 36 | # Icon must end with two \r 37 | Icon 38 | 39 | # Thumbnails 40 | ._* 41 | 42 | # Files that might appear in the root of a volume 43 | .DocumentRevisions-V100 44 | .fseventsd 45 | .Spotlight-V100 46 | .TemporaryItems 47 | .Trashes 48 | .VolumeIcon.icns 49 | .com.apple.timemachine.donotpresent 50 | 51 | # Directories potentially created on remote AFP share 52 | .AppleDB 53 | .AppleDesktop 54 | Network Trash Folder 55 | Temporary Items 56 | .apdisk 57 | 58 | ### PyCharm+all ### 59 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 60 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 61 | 62 | # User-specific stuff: 63 | .idea/**/workspace.xml 64 | .idea/**/tasks.xml 65 | .idea/dictionaries 66 | 67 | # Sensitive or high-churn files: 68 | .idea/**/dataSources/ 69 | .idea/**/dataSources.ids 70 | .idea/**/dataSources.xml 71 | .idea/**/dataSources.local.xml 72 | .idea/**/sqlDataSources.xml 73 | .idea/**/dynamic.xml 74 | .idea/**/uiDesigner.xml 75 | 76 | # Gradle: 77 | .idea/**/gradle.xml 78 | .idea/**/libraries 79 | 80 | # CMake 81 | cmake-build-debug/ 82 | 83 | # Mongo Explorer plugin: 84 | .idea/**/mongoSettings.xml 85 | 86 | ## File-based project format: 87 | *.iws 88 | 89 | ## Plugin-specific files: 90 | 91 | # IntelliJ 92 | /out/ 93 | 94 | # mpeltonen/sbt-idea plugin 95 | .idea_modules/ 96 | 97 | # JIRA plugin 98 | atlassian-ide-plugin.xml 99 | 100 | # Cursive Clojure plugin 101 | .idea/replstate.xml 102 | 103 | # Crashlytics plugin (for Android Studio and IntelliJ) 104 | com_crashlytics_export_strings.xml 105 | crashlytics.properties 106 | crashlytics-build.properties 107 | fabric.properties 108 | 109 | ### PyCharm+all Patch ### 110 | # Ignores the whole idea folder 111 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 112 | 113 | .idea/ 114 | 115 | ### Python ### 116 | # Byte-compiled / optimized / DLL files 117 | __pycache__/ 118 | *.py[cod] 119 | *$py.class 120 | 121 | # C extensions 122 | *.so 123 | 124 | # Distribution / packaging 125 | .Python 126 | env/ 127 | build/ 128 | develop-eggs/ 129 | dist/ 130 | downloads/ 131 | eggs/ 132 | .eggs/ 133 | lib/ 134 | lib64/ 135 | parts/ 136 | sdist/ 137 | var/ 138 | wheels/ 139 | *.egg-info/ 140 | .installed.cfg 141 | *.egg 142 | 143 | # PyInstaller 144 | # Usually these files are written by a python script from a template 145 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 146 | *.manifest 147 | *.spec 148 | 149 | # Installer logs 150 | pip-log.txt 151 | pip-delete-this-directory.txt 152 | 153 | # Unit test / coverage reports 154 | htmlcov/ 155 | .tox/ 156 | .coverage 157 | .coverage.* 158 | .cache 159 | nosetests.xml 160 | coverage.xml 161 | *,cover 162 | .hypothesis/ 163 | 164 | # Translations 165 | *.mo 166 | *.pot 167 | 168 | # Django stuff: 169 | *.log 170 | local_settings.py 171 | 172 | # Flask stuff: 173 | instance/ 174 | .webassets-cache 175 | 176 | # Scrapy stuff: 177 | .scrapy 178 | 179 | # Sphinx documentation 180 | docs/_build/ 181 | 182 | # PyBuilder 183 | target/ 184 | 185 | # Jupyter Notebook 186 | .ipynb_checkpoints 187 | 188 | # pyenv 189 | .python-version 190 | 191 | # celery beat schedule file 192 | celerybeat-schedule 193 | 194 | # SageMath parsed files 195 | *.sage.py 196 | 197 | # dotenv 198 | .env 199 | 200 | # virtualenv 201 | .venv 202 | venv/ 203 | ENV/ 204 | 205 | # Spyder project settings 206 | .spyderproject 207 | .spyproject 208 | 209 | # Rope project settings 210 | .ropeproject 211 | 212 | # mkdocs documentation 213 | /site 214 | 215 | ### SublimeText ### 216 | # cache files for sublime text 217 | *.tmlanguage.cache 218 | *.tmPreferences.cache 219 | *.stTheme.cache 220 | 221 | # workspace files are user-specific 222 | *.sublime-workspace 223 | 224 | # project files should be checked into the repository, unless a significant 225 | # proportion of contributors will probably not be using SublimeText 226 | # *.sublime-project 227 | 228 | # sftp configuration file 229 | sftp-config.json 230 | 231 | # Package control specific files 232 | Package Control.last-run 233 | Package Control.ca-list 234 | Package Control.ca-bundle 235 | Package Control.system-ca-bundle 236 | Package Control.cache/ 237 | Package Control.ca-certs/ 238 | Package Control.merged-ca-bundle 239 | Package Control.user-ca-bundle 240 | oscrypto-ca-bundle.crt 241 | bh_unicode_properties.cache 242 | 243 | # Sublime-github package stores a github token in this file 244 | # https://packagecontrol.io/packages/sublime-github 245 | GitHub.sublime-settings 246 | 247 | ### VisualStudioCode ### 248 | .vscode/* 249 | !.vscode/settings.json 250 | !.vscode/tasks.json 251 | !.vscode/launch.json 252 | !.vscode/extensions.json 253 | .history 254 | 255 | # End of https://www.gitignore.io/api/font,linux,macos,python,fontforge,pycharm+all,sublimetext,visualstudiocode -------------------------------------------------------------------------------- /FiraCode-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/FiraCode-Medium.otf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ligaturizer # 2 | 3 | ![](images/banner.png) 4 | 5 | **Add ligatures to any coding font!** 6 | 7 | **This repo contains 2 things:** 8 | 1. Programming fonts with ligatures added (in `output-fonts/`), including: 9 | * [Anonymous Pro](output-fonts/Anonymous_Pro.ttf) 10 | * [CamingoCode](output-fonts/CamingoCode.ttf) 11 | * [Cousine](output-fonts/Cousine.ttf) 12 | * [DejaVu Sans Mono](output-fonts/DejaVuSansMono.ttf) 13 | * [Droid Sans Mono](output-fonts/DroidSansMono.ttf) 14 | * [edlo](output-fonts/edlo.ttf) 15 | * [Hack](output-fonts/Hack.ttf) 16 | * [Inconsolata](output-fonts/Inconsolata.ttf) & [Inconsolata-g](output-fonts/Inconsolata-g.ttf) 17 | * IBM Plex Mono: [Regular](output-fonts/IBMPlexMono.ttf), [Semibold](output-fonts/IBMPlexMono-SemiBold.ttf) 18 | * Meslo ([LGL](output-fonts/MesloLGL.ttf), [LGLDZ](output-fonts/MesloLGLDZ.ttf), [LGM](output-fonts/MesloLGM.ttf), [LGMDZ](output-fonts/MesloLGMDZ.ttf), [LGS](output-fonts/MesloLGS.ttf), [LGSDZ](output-fonts/MesloLGSDZ.ttf)) 19 | * [Oxygen Mono](output-fonts/OxygenMono.ttf) 20 | * [Roboto Mono](output-fonts/RobotoMono.ttf) 21 | * SF Mono: [Regular](output-fonts/SFMono.ttf), [Semibold](output-fonts/SFMono-Semibold.ttf) 22 | * [Ubuntu Mono](output-fonts/UbuntuMono.ttf) 23 | 24 | 2. A fontforge python script ([ligaturize.py](ligaturize.py)) that adds the ligatures from [Fira Code](https://github.com/tonsky/FiraCode) to a font without ligatures 25 | 26 | Here's a couple examples of the fonts generated: SF Mono with ligatures (note the `!=` and `->`): 27 | ![](images/sf-mono.png) 28 | ![](images/menlo.png) 29 | 30 | **Credit** 31 | This awesome script was written by [IlyaSkriblovsky](https://github.com/IlyaSkriblovsky) for adding ligatures to Deja Vu Sans Mono ([dv-code-font](https://github.com/IlyaSkriblovsky/dv-code-font)). I made a few changes to generalize the script so that it works for any font, so that I could add ligatures to my favorite fonts. 32 | 33 | ## Requirements ## 34 | **Using the Fonts**: See the [FiraCode README](https://github.com/tonsky/FiraCode) for a list of supported editors. 35 | 36 | **Script**: This script requires FontForge python bindings. For Debian/Ubuntu they are available in `python-fontforge` package. For macOS, 37 | they are available via brew (`brew install fontforge`). 38 | 39 | ## Using the Script ## 40 | 1. Move/copy the font you want to ligaturize into `input-fonts/` 41 | 2. Run the script: `$ fontforge -lang=py ligaturize.py` 42 | 3. You'll be prompted for the name of the font, and the name for the generated font. 43 | Example: 44 | 45 | ```shell 46 | ❯ fontforge -lang=py ligaturize.py 47 | ... 48 | Enter the source font filename (including extension): RobotoMono-Regular.ttf 49 | Enter a name for your ligaturized font -- or press ENTER to use the same name: 50 | ... 51 | Generated ligaturized font Roboto Mono L in ligaturized-fonts/RobotoMono.ttf 52 | ``` 53 | 54 | ```shell 55 | ❯ fontforge -lang=py ligaturize.py 56 | ... 57 | Enter the source font filename (including extension): RobotoMono-Regular.ttf 58 | Enter a name for your ligaturized font -- or press ENTER to use the same name: RobotoMonoL 59 | ... 60 | Generated ligaturized font Roboto Mono L in ligaturized-fonts/RobotoMonoL.ttf 61 | ``` 62 | 63 | If you don't provide a name for the new font, it will have the same name as the input font. 64 | 65 | ## Misc. ## 66 | 67 | For more awesome programming fonts with ligatures, check out: 68 | 1. [FiraCode](https://github.com/tonsky/FiraCode) 69 | 2. [Hasklig](https://github.com/i-tu/Hasklig) 70 | -------------------------------------------------------------------------------- /images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/images/banner.png -------------------------------------------------------------------------------- /images/menlo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/images/menlo.png -------------------------------------------------------------------------------- /images/sf-mono.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/images/sf-mono.png -------------------------------------------------------------------------------- /input-fonts/Anonymous_Pro.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/Anonymous_Pro.ttf -------------------------------------------------------------------------------- /input-fonts/CamingoCode Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/CamingoCode Regular.ttf -------------------------------------------------------------------------------- /input-fonts/Cousine-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/Cousine-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/DejaVuSansMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/DejaVuSansMono.ttf -------------------------------------------------------------------------------- /input-fonts/DroidSansMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/DroidSansMono.ttf -------------------------------------------------------------------------------- /input-fonts/Hack-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/Hack-Regular.otf -------------------------------------------------------------------------------- /input-fonts/IBMPlexMono-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/IBMPlexMono-Regular.otf -------------------------------------------------------------------------------- /input-fonts/IBMPlexMono-SemiBold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/IBMPlexMono-SemiBold.otf -------------------------------------------------------------------------------- /input-fonts/Inconsolata-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/Inconsolata-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/Inconsolata-g.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/Inconsolata-g.otf -------------------------------------------------------------------------------- /input-fonts/Inconsolata.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/Inconsolata.otf -------------------------------------------------------------------------------- /input-fonts/MesloLGL-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/MesloLGL-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/MesloLGLDZ-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/MesloLGLDZ-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/MesloLGM-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/MesloLGM-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/MesloLGMDZ-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/MesloLGMDZ-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/MesloLGS-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/MesloLGS-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/MesloLGSDZ-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/MesloLGSDZ-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/OxygenMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/OxygenMono-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/RobotoMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/RobotoMono-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/SFMono-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/SFMono-Regular.otf -------------------------------------------------------------------------------- /input-fonts/SFMono-Semibold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/SFMono-Semibold.otf -------------------------------------------------------------------------------- /input-fonts/UbuntuMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/UbuntuMono-Regular.ttf -------------------------------------------------------------------------------- /input-fonts/edlo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemeb/a-better-ligaturizer/1137cbea085388a722debfdb1752825e7b0d09d9/input-fonts/edlo.ttf -------------------------------------------------------------------------------- /ligaturize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import fontforge 4 | import os 5 | 6 | # Constants 7 | SOURCE_FONT_DIR = "input-fonts" 8 | OUTPUT_FONT_DIR = "output-fonts" 9 | COPYRIGHT = '\nProgramming ligatures added by Ilya Skriblovsky from FiraCode\nFiraCode Copyright (c) 2015 by Nikita Prokopov' 10 | 11 | def get_input_fontname(): 12 | return input('Enter the source font filename (including extension): ') 13 | 14 | def get_input_path(input_fontname): 15 | return SOURCE_FONT_DIR + "/" + input_fontname 16 | 17 | # "RobotoMono-Regular.ttf" -> "RobotoMono-Regular" 18 | def name_without_file_extension(fontname): 19 | return fontname[:-4] if fontname.endswith(('.otf', '.ttf')) else fontname 20 | 21 | # "RobotoMono-Regular" -> "RobotoMono" 22 | def name_without_width_variant(fontname): 23 | no_variant = fontname 24 | if fontname.endswith("Regular"): 25 | no_variant = fontname[:-7] 26 | elif fontname.endswith("Book"): 27 | no_variant = fontname[:-4] 28 | return no_variant[:-1] if (no_variant.endswith(" ") or no_variant.endswith("-")) else no_variant 29 | 30 | def get_output_fontname(input_name): 31 | new_fontname = input('Enter a name for your ligaturized font -- or press ENTER to use the same name: ') 32 | if new_fontname == "": 33 | new_fontname = input_name 34 | return name_without_width_variant(name_without_file_extension(new_fontname)) 35 | 36 | def get_output_font_details(fontname): 37 | name_with_spaces = split_camel_case(fontname) 38 | return { 39 | 'filename': fontname + '.ttf', 40 | 'fontname': fontname, 41 | 'fullname': name_with_spaces, 42 | 'familyname': name_with_spaces, 43 | 'copyright_add': COPYRIGHT, 44 | 'unique_id': name_with_spaces, 45 | } 46 | 47 | # Add spaces to UpperCamelCase: 'DVCode' -> 'DV Code' 48 | def split_camel_case(str): 49 | acc = '' 50 | for (i, ch) in enumerate(str): 51 | prevIsSpace = i > 0 and acc[-1] == ' ' 52 | nextIsLower = i + 1 < len(str) and str[i + 1].islower() 53 | isLast = i + 1 == len(str) 54 | if i != 0 and ch.isupper() and (nextIsLower or isLast) and not prevIsSpace: 55 | acc += ' ' + ch 56 | elif ch == '-' or ch == '_' or ch == '.': 57 | acc += ' ' 58 | else: 59 | acc += ch 60 | return acc 61 | 62 | config = { 63 | 'firacode_ttf': 'FiraCode-Regular.otf', 64 | 65 | 'add_ligatures': [ 66 | { # <- 67 | 'chars': ['less', 'hyphen'], 68 | 'firacode_ligature_name': 'less_hyphen.liga', 69 | }, 70 | { # <-- 71 | 'chars': ['less', 'hyphen', 'hyphen'], 72 | 'firacode_ligature_name': 'less_hyphen_hyphen.liga', 73 | }, 74 | { # -> 75 | 'chars': ['hyphen', 'greater'], 76 | 'firacode_ligature_name': 'hyphen_greater.liga', 77 | }, 78 | { # --> 79 | 'chars': ['hyphen', 'hyphen', 'greater'], 80 | 'firacode_ligature_name': 'hyphen_hyphen_greater.liga', 81 | }, 82 | { # <> 83 | 'chars': ['less', 'greater'], 84 | 'firacode_ligature_name': 'less_greater.liga', 85 | }, 86 | { # <-> 87 | 'chars': ['less', 'hyphen', 'greater'], 88 | 'firacode_ligature_name': 'less_hyphen_greater.liga', 89 | }, 90 | { # => 91 | 'chars': ['equal', 'greater'], 92 | 'firacode_ligature_name': 'equal_greater.liga', 93 | }, 94 | { # ==> 95 | 'chars': ['equal', 'equal', 'greater'], 96 | 'firacode_ligature_name': 'equal_equal_greater.liga', 97 | }, 98 | { # <== 99 | 'chars': ['less', 'equal', 'equal'], 100 | 'firacode_ligature_name': 'less_equal_equal.liga', 101 | }, 102 | { # ?= 103 | 'chars': ['question', 'equal'], 104 | 'firacode_ligature_name': 'question_equal.liga', 105 | }, 106 | { # != 107 | 'chars': ['exclam', 'equal'], 108 | 'firacode_ligature_name': 'exclam_equal.liga', 109 | }, 110 | { # == 111 | 'chars': ['equal', 'equal'], 112 | 'firacode_ligature_name': 'equal_equal.liga', 113 | }, 114 | { # <= 115 | 'chars': ['less', 'equal'], 116 | 'firacode_ligature_name': 'equal_less.liga', 117 | }, 118 | { # >= 119 | 'chars': ['greater', 'equal'], 120 | 'firacode_ligature_name': 'greater_equal.liga', 121 | }, 122 | { # :: 123 | 'chars': ['colon', 'colon'], 124 | 'firacode_ligature_name': 'colon_colon.liga', 125 | }, 126 | { # === 127 | 'chars': ['equal', 'equal', 'equal'], 128 | 'firacode_ligature_name': 'equal_equal_equal.liga', 129 | }, 130 | { # !== 131 | 'chars': ['exclam', 'equal', 'equal'], 132 | 'firacode_ligature_name': 'exclam_equal_equal.liga', 133 | }, 134 | { # ?? 135 | 'chars': ['question', 'question'], 136 | 'firacode_ligature_name': 'question_question.liga', 137 | }, 138 | { # !! 139 | 'chars': ['exclam', 'exclam'], 140 | 'firacode_ligature_name': 'exclam_exclam.liga', 141 | }, 142 | { # -- 143 | 'chars': ['hyphen', 'hyphen'], 144 | 'firacode_ligature_name': 'hyphen_hyphen.liga', 145 | }, 146 | { # --- 147 | 'chars': ['hyphen', 'hyphen', 'hyphen'], 148 | 'firacode_ligature_name': 'hyphen_hyphen_hyphen.liga', 149 | }, 150 | { # /* 151 | 'chars': ['slash', 'asterisk'], 152 | 'firacode_ligature_name': 'slash_asterisk.liga', 153 | }, 154 | { # /** 155 | 'chars': ['slash', 'asterisk', 'asterisk'], 156 | 'firacode_ligature_name': 'slash_asterisk_asterisk.liga', 157 | }, 158 | { # */ 159 | 'chars': ['asterisk', 'slash'], 160 | 'firacode_ligature_name': 'asterisk_slash.liga', 161 | }, 162 | { # // 163 | 'chars': ['slash', 'slash'], 164 | 'firacode_ligature_name': 'slash_slash.liga', 165 | }, 166 | { # /// 167 | 'chars': ['slash', 'slash', 'slash'], 168 | 'firacode_ligature_name': 'slash_slash_slash.liga', 169 | }, 170 | { # || 171 | 'chars': ['bar', 'bar'], 172 | 'firacode_ligature_name': 'bar_bar.liga', 173 | }, 174 | { # ||= 175 | 'chars': ['bar', 'bar', 'equal'], 176 | 'firacode_ligature_name': 'bar_bar_equal.liga', 177 | }, 178 | { # |= 179 | 'chars': ['bar', 'equal'], 180 | 'firacode_ligature_name': 'bar_equal.liga', 181 | }, 182 | { # ^= 183 | 'chars': ['asciicircum', 'equal'], 184 | 'firacode_ligature_name': 'asciicircum_equal.liga', 185 | }, 186 | { # ~= 187 | 'chars': ['asciitilde', 'equal'], 188 | 'firacode_ligature_name': 'asciitilde_equal.liga', 189 | }, 190 | { # =~ 191 | 'chars': ['equal', 'asciitilde'], 192 | 'firacode_ligature_name': 'equal_asciitilde.liga', 193 | }, 194 | { # ~> 195 | 'chars': ['asciitilde', 'greater'], 196 | 'firacode_ligature_name': 'asciitilde_greater.liga', 197 | }, 198 | { # ~~> 199 | 'chars': ['asciitilde', 'asciitilde', 'greater'], 200 | 'firacode_ligature_name': 'asciitilde_asciitilde_greater.liga', 201 | }, 202 | { # << 203 | 'chars': ['less', 'less'], 204 | 'firacode_ligature_name': 'less_less.liga', 205 | }, 206 | { # >> 207 | 'chars': ['greater', 'greater'], 208 | 'firacode_ligature_name': 'greater_greater.liga', 209 | }, 210 | { #