docs-matrix-spec/assets/css/fonts/download_google_fonts_css.py
Kévin Commaille 0ce83512fc
Update Inter font and set display: swap (#2000)
The version of Inter is updated to use a variable font, which is supported widely among modern browsers.

Using `display: swap` means that the browser will render the text of the spec even before Inter is loaded, making the website appear to load faster on mobile.

Allow the browser to use the local Inter font if it exists.
2024-11-19 22:01:27 +00:00

131 lines
4.9 KiB
Python
Executable file

#!/usr/bin/env python3
# Copyright 2021 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This script takes a google fonts CSS URL, downloads the referenced fonts locally
# and spits out a modified CSS file which now points to those local fonts.
#
# Purely for the purposes of converting a website to use local font files instead of
# making requests to Google Fonts.
import re
import requests
import subprocess
import sys
# Pull the font filename to process and output directory to point at
if len(sys.argv) < 4:
print(f"""
Error: Not enough arguments.
Usage: {sys.argv[0]} google_fonts_url font_directory css_font_path
* google fonts url: A URL leading to a google font css file (i.e https://fonts.googleapis.com/css?family=Inter)
* font directory: The location that font files will be downloaded to (i.e ../../fonts)
* font path: The directory the resulting CSS will be pointing to, relative to site root (i.e /unstable/css/fonts).
This is where the browser will look for fonts.
""")
sys.exit(1)
google_fonts_url = sys.argv[1]
font_output_dir = sys.argv[2]
css_font_path = sys.argv[3]
# Get font name
if google_fonts_url.count(":") > 1:
# Account for font weights specified in the URL
# (i.e https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i)
url_match = re.match(r".*family=(.*):", google_fonts_url)
else:
url_match = re.match(r".*family=(.*)", google_fonts_url)
if not url_match:
print("Unable to extract font name, invalid google fonts URL:", google_fonts_url)
print("URL should look something like: https://fonts.googleapis.com/css?family=Inter...")
sys.exit(1)
font_name = url_match.group(1)
# Ensure font paths end with a trailing slash
if not font_output_dir.endswith("/"):
font_output_dir += "/"
if not css_font_path.endswith("/"):
css_font_path += "/"
# Download the css file and split by newline
resp = requests.get(
google_fonts_url,
# We need to set a believable user-agent, else google fonts won't give us
# all of the font weights we requested for some reason
headers={
"User-Agent": "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0"
}
)
if resp.status_code != 200:
print("Failed to download:", google_fonts_url, resp.status_code)
sys.exit(1)
original_contents = resp.text.split("\n")
# Download all referenced font files and write out new font file
new_css_file_lines = []
# Store metadata for helping give friendly names to each font file
font_lang = None
font_family = None
font_style = None
for line in original_contents:
# Check if this line contains a font URL
match = re.match(r".*url\((.*)\) format.*", line)
if match:
# Download the font file
font_url = match.group(1)
print("Downloading font:", font_url)
resp = requests.get(font_url)
if resp.status_code == 200:
# Save the font file
filename = "%s-%s-%s.woff2" % (
font_family, font_lang, font_style
)
font_filepath = font_output_dir + filename
with open(font_filepath, "wb") as f:
print("Writing font file:", font_filepath)
f.write(resp.content)
# Replace google URL with local URL and allow the browser to load the
# local font if it exists.
line = re.sub(r"url\(.+?\)", f"local('{font_family}'), url({css_font_path + filename})", line)
else:
print("Warning: failed to download font file:", font_url)
# Check for font metadata. If there is some, we'll note it down and use it to help
# name font files when we write them out.
# Makes for nicer font filenames than fvQtMwCp50KnMw2boKod... etc.
font_lang_match = re.match(r"^/\* (.+) \*/$", line)
if font_lang_match:
font_lang = font_lang_match.group(1)
font_family_match = re.match(r".*font-family: '(.+)';$", line)
if font_family_match:
font_family = font_family_match.group(1)
font_style_match = re.match(r".*font-style: (.+);$", line)
if font_style_match:
font_style = font_style_match.group(1)
# Append the potentially modified line to the new css file
new_css_file_lines.append(line)
# Write out the new font css file
with open(font_name + ".css", "w") as f:
new_css_file_contents = "\n".join(new_css_file_lines)
f.write(new_css_file_contents)