add image sizes to emoji
This commit is contained in:
parent
9bf3409197
commit
e44d5babca
|
@ -1,7 +1,8 @@
|
|||
use std::{collections::HashMap, ffi::OsStr, fs::File, io::BufReader, path::Path};
|
||||
|
||||
use anyhow::Context;
|
||||
use log::debug;
|
||||
use image::ImageError;
|
||||
use log::{debug, error, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
|
@ -180,32 +181,43 @@ impl Config {
|
|||
/// Data derived from the config.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ConfigDerivedData {
|
||||
pub pic_sizes: HashMap<String, Option<PicSize>>,
|
||||
pub image_sizes: HashMap<String, Option<ImageSize>>,
|
||||
}
|
||||
|
||||
/// Picture size. This is useful for emitting <img> elements with a specific size to eliminate layout shifting.
|
||||
/// Image size. This is useful for emitting <img> elements with a specific size to eliminate
|
||||
/// layout shifting.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct PicSize {
|
||||
pub struct ImageSize {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl ConfigDerivedData {
|
||||
fn read_pic_size(config: &Config, pic_id: &str) -> Option<PicSize> {
|
||||
let pic_filename = config.pics.get(pic_id)?;
|
||||
let (width, height) = image::io::Reader::new(BufReader::new(
|
||||
File::open(format!("static/pic/{pic_filename}")).ok()?,
|
||||
))
|
||||
.into_dimensions()
|
||||
.ok()?;
|
||||
Some(PicSize { width, height })
|
||||
fn read_image_size(filename: &str) -> Option<ImageSize> {
|
||||
let (width, height) = image::io::Reader::new(BufReader::new(File::open(filename).ok()?))
|
||||
.with_guessed_format()
|
||||
.map_err(ImageError::from)
|
||||
.and_then(|i| i.into_dimensions())
|
||||
// NOTE: Not being able to determine the image size is not the end of the world,
|
||||
// so just warn the user if we couldn't do it.
|
||||
// For example, currently SVG is not supported at all, which causes this to fail.
|
||||
.inspect_err(|e| warn!("cannot read image size of {filename}: {e}"))
|
||||
.ok()?;
|
||||
Some(ImageSize { width, height })
|
||||
}
|
||||
|
||||
pub fn pic_size(&mut self, config: &Config, pic_id: &str) -> Option<PicSize> {
|
||||
if !self.pic_sizes.contains_key(pic_id) {
|
||||
self.pic_sizes
|
||||
.insert(pic_id.to_owned(), Self::read_pic_size(config, pic_id));
|
||||
pub fn image_size(&mut self, filename: &str) -> Option<ImageSize> {
|
||||
if !self.image_sizes.contains_key(filename) {
|
||||
self.image_sizes
|
||||
.insert(filename.to_owned(), Self::read_image_size(filename));
|
||||
}
|
||||
self.pic_sizes.get(pic_id).copied().flatten()
|
||||
self.image_sizes.get(filename).copied().flatten()
|
||||
}
|
||||
|
||||
pub fn pic_size(&mut self, config: &Config, pic_id: &str) -> Option<ImageSize> {
|
||||
config
|
||||
.pics
|
||||
.get(pic_id)
|
||||
.and_then(|pic_filename| self.image_size(&format!("static/pic/{pic_filename}")))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ use pulldown_cmark::escape::{escape_href, escape_html, StrWrite};
|
|||
use pulldown_cmark::{Alignment, CodeBlockKind, Event, LinkType, Tag};
|
||||
use pulldown_cmark::{CowStr, Event::*};
|
||||
|
||||
use crate::config::{Config, ConfigDerivedData, PicSize};
|
||||
use crate::config::{Config, ConfigDerivedData, ImageSize};
|
||||
use crate::html::highlight::highlight;
|
||||
use crate::state::Treehouse;
|
||||
|
||||
|
@ -281,15 +281,13 @@ where
|
|||
|
||||
if let LiterateCodeKind::Output { placeholder_pic_id } = kind {
|
||||
if !placeholder_pic_id.is_empty() {
|
||||
self.write(
|
||||
"<img class=\"placeholder-image\" loading=\"lazy\" src=\"",
|
||||
)?;
|
||||
self.write("<img class=\"placeholder-image\" loading=\"lazy\" src=\"")?;
|
||||
escape_html(
|
||||
&mut self.writer,
|
||||
&self.config.pic_url(placeholder_pic_id),
|
||||
)?;
|
||||
self.write("\"")?;
|
||||
if let Some(PicSize { width, height }) = self
|
||||
if let Some(ImageSize { width, height }) = self
|
||||
.config_derived_data
|
||||
.pic_size(self.config, placeholder_pic_id)
|
||||
{
|
||||
|
@ -552,6 +550,7 @@ where
|
|||
escape_html(&mut self.writer, &branch.attributes.id)?;
|
||||
self.writer.write_str("\">")?;
|
||||
}
|
||||
|
||||
self.writer
|
||||
.write_str("<img data-cast=\"emoji\" title=\":")?;
|
||||
escape_html(&mut self.writer, name)?;
|
||||
|
@ -561,7 +560,18 @@ where
|
|||
escape_html(&mut self.writer, filename)?;
|
||||
self.writer.write_str("\" alt=\"")?;
|
||||
escape_html(&mut self.writer, name)?;
|
||||
if let Some(image_size) = self
|
||||
.config_derived_data
|
||||
.image_size(&format!("static/emoji/{filename}"))
|
||||
{
|
||||
write!(
|
||||
self.writer,
|
||||
"\" width=\"{}\" height=\"{}",
|
||||
image_size.width, image_size.height
|
||||
)?;
|
||||
}
|
||||
self.writer.write_str("\">")?;
|
||||
|
||||
if branch_id.is_some() {
|
||||
self.writer.write_str("</a>")?;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue