it crashes past ~60 images
This commit is contained in:
parent
9bca7045cc
commit
d9fae875f4
6 changed files with 128 additions and 84 deletions
|
@ -4,6 +4,7 @@ use comrak::nodes::{AstNode, NodeValue};
|
||||||
use comrak::{format_html, parse_document, Arena, ComrakOptions, ListStyleType, Options};
|
use comrak::{format_html, parse_document, Arena, ComrakOptions, ListStyleType, Options};
|
||||||
use lol_html::html_content::ContentType;
|
use lol_html::html_content::ContentType;
|
||||||
use lol_html::{element, rewrite_str, HtmlRewriter, RewriteStrSettings, Settings};
|
use lol_html::{element, rewrite_str, HtmlRewriter, RewriteStrSettings, Settings};
|
||||||
|
use mime_guess::mime;
|
||||||
use ramhorns::Content;
|
use ramhorns::Content;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -162,10 +163,15 @@ fn custom_img_size(html: &str) -> String {
|
||||||
rewrite_str(
|
rewrite_str(
|
||||||
html,
|
html,
|
||||||
RewriteStrSettings {
|
RewriteStrSettings {
|
||||||
element_content_handlers: vec![element!("img[alt]", |el| {
|
element_content_handlers: vec![element!("img[alt], svg", |el| {
|
||||||
let alt = el.get_attribute("alt").unwrap();
|
let alt = el.get_attribute("alt").unwrap_or_default();
|
||||||
let possible_piece = alt.split('|').collect::<Vec<&str>>();
|
let possible_piece = alt.split('|').collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
if el.tag_name() == *"svg" {
|
||||||
|
el.remove_attribute("width");
|
||||||
|
el.remove_attribute("height");
|
||||||
|
}
|
||||||
|
|
||||||
if possible_piece.len() > 1 {
|
if possible_piece.len() > 1 {
|
||||||
let data = possible_piece.last().unwrap().trim();
|
let data = possible_piece.last().unwrap().trim();
|
||||||
|
|
||||||
|
@ -255,7 +261,7 @@ fn fix_images_and_integration(
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
if let Ok(file_contents) = fs::read(&img_path) {
|
if let Ok(mut file_contents) = fs::read(&img_path) {
|
||||||
let mime = mime_guess::from_path(&img_path).first_or_octet_stream();
|
let mime = mime_guess::from_path(&img_path).first_or_octet_stream();
|
||||||
if recursive && mime == "text/markdown" {
|
if recursive && mime == "text/markdown" {
|
||||||
let file_str = String::from_utf8_lossy(&file_contents).into_owned();
|
let file_str = String::from_utf8_lossy(&file_contents).into_owned();
|
||||||
|
@ -286,6 +292,16 @@ fn fix_images_and_integration(
|
||||||
|
|
||||||
// Store the metadata for later merging
|
// Store the metadata for later merging
|
||||||
additional_metadata.push(data.metadata);
|
additional_metadata.push(data.metadata);
|
||||||
|
} else if mime == mime::IMAGE_SVG {
|
||||||
|
let alt = el.get_attribute("alt").unwrap_or_default();
|
||||||
|
file_contents.drain(0..3);
|
||||||
|
el.replace(
|
||||||
|
&format!(
|
||||||
|
"<svg alt='{alt}'{}",
|
||||||
|
String::from_utf8(file_contents).unwrap()
|
||||||
|
),
|
||||||
|
ContentType::Html,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
let image = general_purpose::STANDARD.encode(&file_contents);
|
let image = general_purpose::STANDARD.encode(&file_contents);
|
||||||
el.set_attribute("src", &format!("data:{mime};base64,{image}"))
|
el.set_attribute("src", &format!("data:{mime};base64,{image}"))
|
||||||
|
|
|
@ -58,7 +58,8 @@ main {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Images */
|
/* Images */
|
||||||
img {
|
img,
|
||||||
|
svg {
|
||||||
max-width: var(--max-width);
|
max-width: var(--max-width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,8 @@ aside a {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Image */
|
/* Image */
|
||||||
main img {
|
main img,
|
||||||
|
main svg {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,8 @@ main a.anchor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Images */
|
/* Images */
|
||||||
main img {
|
main img,
|
||||||
|
main svg {
|
||||||
display: block;
|
display: block;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
@ -249,6 +250,7 @@ table:not(.hljs-ln) tr th:last-child {
|
||||||
|
|
||||||
/* Prevent figures from splitting accross pages */
|
/* Prevent figures from splitting accross pages */
|
||||||
article *:has(img),
|
article *:has(img),
|
||||||
|
article *:has(svg),
|
||||||
table:not(.hljs-ln),
|
table:not(.hljs-ln),
|
||||||
table:not(.hljs-ln) > * {
|
table:not(.hljs-ln) > * {
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
|
|
|
@ -83,7 +83,7 @@ header nav a:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add links */
|
/* Add links */
|
||||||
a:not(:where([href^="#"], [href^="/"])):not(:has(img))::after {
|
a:not(:where([href^="#"], [href^="/"])):not(:has(img)):not(:has(svg))::after {
|
||||||
content: " (" attr(href) ")";
|
content: " (" attr(href) ")";
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
|
@ -96,7 +96,8 @@ header nav a:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
img {
|
img,
|
||||||
|
svg {
|
||||||
filter: brightness(0.8) contrast(1.2);
|
filter: brightness(0.8) contrast(1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,6 @@ const Mode = {
|
||||||
Dark: 2,
|
Dark: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the svg color theme based on the mode
|
|
||||||
* @param {Mode} mode
|
|
||||||
*/
|
|
||||||
const svgChangeTheme = (mode) => {
|
|
||||||
for (const item of document.getElementsByTagName("img")) {
|
|
||||||
if (!item.src.startsWith("data:image/svg+xml;base64,")) {
|
|
||||||
// Exclude image who aren't SVG and base64 encoded
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert to grayscale
|
* Convert to grayscale
|
||||||
* @param {{r: number, g: number, b: number}} color
|
* @param {{r: number, g: number, b: number}} color
|
||||||
|
@ -30,8 +19,8 @@ const svgChangeTheme = (mode) => {
|
||||||
*/
|
*/
|
||||||
const extractColors = (image) => {
|
const extractColors = (image) => {
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
canvas.width = image.naturalWidth;
|
canvas.width = image.naturalWidth || image.width;
|
||||||
canvas.height = image.naturalHeight;
|
canvas.height = image.naturalHeight || image.height;
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
ctx.drawImage(image, 0, 0);
|
ctx.drawImage(image, 0, 0);
|
||||||
|
|
||||||
|
@ -57,9 +46,44 @@ const svgChangeTheme = (mode) => {
|
||||||
return colors;
|
return colors;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract colors
|
/**
|
||||||
const colors = extractColors(item);
|
* Change the color theme based on the mode
|
||||||
|
* @param {Mode} mode
|
||||||
|
*/
|
||||||
|
const changeTheme = (mode) => {
|
||||||
|
for (const item of document.getElementsByTagName("svg")) {
|
||||||
|
const image = document.createElement("img");
|
||||||
|
image.src = `data:image/svg+xml;base64,${btoa(
|
||||||
|
new XMLSerializer().serializeToString(item)
|
||||||
|
)}`;
|
||||||
|
|
||||||
|
image.width = item.viewBox.baseVal.width;
|
||||||
|
image.height = item.viewBox.baseVal.height;
|
||||||
|
|
||||||
|
image.onload = () => {
|
||||||
|
applyFilter(mode, item, extractColors(image));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// SVG embedded in images as base64
|
||||||
|
for (const item of document.getElementsByTagName("img")) {
|
||||||
|
if (!item.src.startsWith("data:image/svg+xml;base64,")) {
|
||||||
|
// Exclude image who aren't SVG and base64 encoded
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyFilter(mode, item, extractColors(item));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the filter based on the selected mode
|
||||||
|
* @param {Mode} mode Current theme
|
||||||
|
* @param {HTMLImageElement | SVGSVGElement} item Element
|
||||||
|
* @param {{r: number, g: number, b: number}} colors Array of the colors of the element
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const applyFilter = (mode, item, colors) => {
|
||||||
// Calculate the average grayscale value
|
// Calculate the average grayscale value
|
||||||
const grayscaleValues = colors.map(colorToGrayscale);
|
const grayscaleValues = colors.map(colorToGrayscale);
|
||||||
const totalGrayscale = grayscaleValues.reduce((acc, val) => acc + val, 0);
|
const totalGrayscale = grayscaleValues.reduce((acc, val) => acc + val, 0);
|
||||||
|
@ -72,26 +96,25 @@ const svgChangeTheme = (mode) => {
|
||||||
|
|
||||||
if (averageGrayscale < treshold && mode === Mode.Dark) {
|
if (averageGrayscale < treshold && mode === Mode.Dark) {
|
||||||
item.style = style + dim + " invert(1);";
|
item.style = style + dim + " invert(1);";
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (averageGrayscale > treshold && mode === Mode.Light) {
|
if (averageGrayscale > treshold && mode === Mode.Light) {
|
||||||
item.style = style + "invert(1);";
|
item.style = style + "invert(1);";
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === Mode.Dark) {
|
if (mode === Mode.Dark) {
|
||||||
item.style = style + `${dim};`;
|
item.style = style + `${dim};`;
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.style = "";
|
item.style = "";
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener("load", () => {
|
window.addEventListener("load", () => {
|
||||||
// Fix SVG images
|
// Fix SVG images
|
||||||
svgChangeTheme(
|
changeTheme(
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
? Mode.Dark
|
? Mode.Dark
|
||||||
: Mode.Light
|
: Mode.Light
|
||||||
|
@ -101,5 +124,5 @@ window.addEventListener("load", () => {
|
||||||
window
|
window
|
||||||
.matchMedia("(prefers-color-scheme: dark)")
|
.matchMedia("(prefers-color-scheme: dark)")
|
||||||
.addEventListener("change", (event) =>
|
.addEventListener("change", (event) =>
|
||||||
svgChangeTheme(event.matches ? Mode.Dark : Mode.Light)
|
changeTheme(event.matches ? Mode.Dark : Mode.Light)
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue