Fixed social plugin crashing on Windows when downloading fonts (#7085) (#7117)

* fix: social plugin fonts on Windows (squidfunk #7085)

* fix: managed to edit in material instead of src

* added resource mgmt for ByteIO, comments

* formatted comment

* Fix for Social plugin crashes when font autoloading is disabled (#7118)
This commit is contained in:
Alexander Voss 2024-04-29 10:04:43 +02:00 committed by GitHub
parent ff49d74024
commit e90871f210
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 26 deletions

View File

@ -46,7 +46,7 @@ from io import BytesIO
from mkdocs.commands.build import DuplicateFilter from mkdocs.commands.build import DuplicateFilter
from mkdocs.exceptions import PluginError from mkdocs.exceptions import PluginError
from mkdocs.plugins import BasePlugin from mkdocs.plugins import BasePlugin
from mkdocs.utils import copy_file from mkdocs.utils import write_file
from shutil import copyfile from shutil import copyfile
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
@ -444,11 +444,17 @@ class SocialPlugin(BasePlugin[SocialConfig]):
svg2png(bytestring = data, write_to = file, scale = 10) svg2png(bytestring = data, write_to = file, scale = 10)
return Image.open(file) return Image.open(file)
# Retrieve font # Retrieve font either from the card layout option or from the Material
# font defintion. If no font is defined for Material or font is False
# then choose a default.
def _load_font(self, config): def _load_font(self, config):
name = self.config.cards_layout_options.get("font_family") name = self.config.cards_layout_options.get("font_family")
if not name: if not name:
name = config.theme.get("font", {}).get("text", "Roboto") material_name = config.theme.get("font", False)
if material_name is False:
name = "Roboto"
else:
name = material_name.get("text", "Roboto")
# Resolve relevant fonts # Resolve relevant fonts
font = {} font = {}
@ -522,19 +528,18 @@ class SocialPlugin(BasePlugin[SocialConfig]):
with requests.get(match) as res: with requests.get(match) as res:
res.raise_for_status() res.raise_for_status()
# Create a temporary file to download the font # Extract font family name and style using the content in the
with NamedTemporaryFile() as temp: # response via ByteIO to avoid writing a temp file. Done to fix
temp.write(res.content) # problems with passing a NamedTemporaryFile to
temp.flush() # ImageFont.truetype() on Windows, see https://t.ly/LiF_k
with BytesIO(res.content) as fontdata:
# Extract font family name and style font = ImageFont.truetype(fontdata)
font = ImageFont.truetype(temp.name)
name, style = font.getname() name, style = font.getname()
name = " ".join([name.replace(family, ""), style]).strip() name = " ".join([name.replace(family, ""), style]).strip()
# Move fonts to cache directory
target = os.path.join(path, family, f"{name}.ttf") target = os.path.join(path, family, f"{name}.ttf")
copy_file(temp.name, target)
# write file to cache
write_file(res.content, target)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Data # Data

View File

@ -46,7 +46,7 @@ from io import BytesIO
from mkdocs.commands.build import DuplicateFilter from mkdocs.commands.build import DuplicateFilter
from mkdocs.exceptions import PluginError from mkdocs.exceptions import PluginError
from mkdocs.plugins import BasePlugin from mkdocs.plugins import BasePlugin
from mkdocs.utils import copy_file from mkdocs.utils import write_file
from shutil import copyfile from shutil import copyfile
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
@ -444,11 +444,17 @@ class SocialPlugin(BasePlugin[SocialConfig]):
svg2png(bytestring = data, write_to = file, scale = 10) svg2png(bytestring = data, write_to = file, scale = 10)
return Image.open(file) return Image.open(file)
# Retrieve font # Retrieve font either from the card layout option or from the Material
# font defintion. If no font is defined for Material or font is False
# then choose a default.
def _load_font(self, config): def _load_font(self, config):
name = self.config.cards_layout_options.get("font_family") name = self.config.cards_layout_options.get("font_family")
if not name: if not name:
name = config.theme.get("font", {}).get("text", "Roboto") material_name = config.theme.get("font", False)
if material_name is False:
name = "Roboto"
else:
name = material_name.get("text", "Roboto")
# Resolve relevant fonts # Resolve relevant fonts
font = {} font = {}
@ -522,19 +528,18 @@ class SocialPlugin(BasePlugin[SocialConfig]):
with requests.get(match) as res: with requests.get(match) as res:
res.raise_for_status() res.raise_for_status()
# Create a temporary file to download the font # Extract font family name and style using the content in the
with NamedTemporaryFile() as temp: # response via ByteIO to avoid writing a temp file. Done to fix
temp.write(res.content) # problems with passing a NamedTemporaryFile to
temp.flush() # ImageFont.truetype() on Windows, see https://t.ly/LiF_k
with BytesIO(res.content) as fontdata:
# Extract font family name and style font = ImageFont.truetype(fontdata)
font = ImageFont.truetype(temp.name)
name, style = font.getname() name, style = font.getname()
name = " ".join([name.replace(family, ""), style]).strip() name = " ".join([name.replace(family, ""), style]).strip()
# Move fonts to cache directory
target = os.path.join(path, family, f"{name}.ttf") target = os.path.join(path, family, f"{name}.ttf")
copy_file(temp.name, target)
# write file to cache
write_file(res.content, target)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Data # Data