From e5f302647a91cfb44dcfcf0e1592e40db3fe4bc1 Mon Sep 17 00:00:00 2001
From: Vincent Prouillet
Date: Tue, 19 Dec 2023 13:22:40 +0100
Subject: [PATCH 01/25] Next version
---
CHANGELOG.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d917e4a9b2..44bd027a19 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog
+## 0.19.0 (unreleased)
+
+
## 0.18.0 (2023-12-18)
- Fix LFI in `zola serve`
From a586a5af55b0a49cae9dfb05dfba7141a9aa3cdc Mon Sep 17 00:00:00 2001
From: Morgan Creekmore
Date: Fri, 5 Jan 2024 05:16:38 -0600
Subject: [PATCH 02/25] Add option to include date in search index (#2401)
---
components/config/src/config/search.rs | 3 ++
components/search/src/lib.rs | 40 +++++++++++++++++--
.../getting-started/configuration.md | 2 +
3 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/components/config/src/config/search.rs b/components/config/src/config/search.rs
index 6f64cc20e3..3ce6878cd2 100644
--- a/components/config/src/config/search.rs
+++ b/components/config/src/config/search.rs
@@ -22,6 +22,8 @@ pub struct Search {
/// Includes the description in the search index. When the site becomes too large, you can switch
/// to that instead. `false` by default
pub include_description: bool,
+ /// Include the RFC3339 datetime of the page in the search index. `false` by default.
+ pub include_date: bool,
/// Include the path of the page in the search index. `false` by default.
pub include_path: bool,
/// Foramt of the search index to be produced. Javascript by default
@@ -35,6 +37,7 @@ impl Default for Search {
include_content: true,
include_description: false,
include_path: false,
+ include_date: false,
truncate_content_length: None,
index_format: Default::default(),
}
diff --git a/components/search/src/lib.rs b/components/search/src/lib.rs
index 073eb09307..51d25579d2 100644
--- a/components/search/src/lib.rs
+++ b/components/search/src/lib.rs
@@ -3,6 +3,8 @@ use std::collections::{HashMap, HashSet};
use libs::ammonia;
use libs::elasticlunr::{lang, Index, IndexBuilder};
use libs::once_cell::sync::Lazy;
+use libs::time::format_description::well_known::Rfc3339;
+use libs::time::OffsetDateTime;
use config::{Config, Search};
use content::{Library, Section};
@@ -35,6 +37,10 @@ fn build_fields(search_config: &Search, mut index: IndexBuilder) -> IndexBuilder
index = index.add_field("description");
}
+ if search_config.include_date {
+ index = index.add_field("date")
+ }
+
if search_config.include_path {
index = index.add_field_with_tokenizer("path", Box::new(path_tokenizer));
}
@@ -57,6 +63,7 @@ fn fill_index(
search_config: &Search,
title: &Option,
description: &Option,
+ datetime: &Option,
path: &str,
content: &str,
) -> Vec {
@@ -70,6 +77,14 @@ fn fill_index(
row.push(description.clone().unwrap_or_default());
}
+ if search_config.include_date {
+ if let Some(date) = datetime {
+ if let Ok(d) = date.format(&Rfc3339) {
+ row.push(d);
+ }
+ }
+ }
+
if search_config.include_path {
row.push(path.to_string());
}
@@ -133,6 +148,7 @@ fn add_section_to_index(
search_config,
§ion.meta.title,
§ion.meta.description,
+ &None,
§ion.path,
§ion.content,
),
@@ -151,6 +167,7 @@ fn add_section_to_index(
search_config,
&page.meta.title,
&page.meta.description,
+ &page.meta.datetime,
&page.path,
&page.content,
),
@@ -192,7 +209,7 @@ mod tests {
let path = "/a/page/".to_string();
let content = "Some content".to_string();
- let res = fill_index(&config.search, &title, &description, &path, &content);
+ let res = fill_index(&config.search, &title, &description, &None, &path, &content);
assert_eq!(res.len(), 2);
assert_eq!(res[0], title.unwrap());
assert_eq!(res[1], content);
@@ -207,7 +224,7 @@ mod tests {
let path = "/a/page/".to_string();
let content = "Some content".to_string();
- let res = fill_index(&config.search, &title, &description, &path, &content);
+ let res = fill_index(&config.search, &title, &description, &None, &path, &content);
assert_eq!(res.len(), 3);
assert_eq!(res[0], title.unwrap());
assert_eq!(res[1], description.unwrap());
@@ -223,9 +240,26 @@ mod tests {
let path = "/a/page/".to_string();
let content = "Some content".to_string();
- let res = fill_index(&config.search, &title, &description, &path, &content);
+ let res = fill_index(&config.search, &title, &description, &None, &path, &content);
assert_eq!(res.len(), 2);
assert_eq!(res[0], title.unwrap());
assert_eq!(res[1], content[..5]);
}
+
+ #[test]
+ fn can_fill_index_date() {
+ let mut config = Config::default();
+ config.search.include_date = true;
+ let title = Some("A title".to_string());
+ let description = Some("A description".to_string());
+ let path = "/a/page/".to_string();
+ let content = "Some content".to_string();
+ let datetime = Some(OffsetDateTime::parse("2023-01-31T00:00:00Z", &Rfc3339).unwrap());
+
+ let res = fill_index(&config.search, &title, &description, &datetime, &path, &content);
+ assert_eq!(res.len(), 3);
+ assert_eq!(res[0], title.unwrap());
+ assert_eq!(res[1], "2023-01-31T00:00:00Z");
+ assert_eq!(res[2], content);
+ }
}
diff --git a/docs/content/documentation/getting-started/configuration.md b/docs/content/documentation/getting-started/configuration.md
index fbf4c01f55..d8ec482d5d 100644
--- a/docs/content/documentation/getting-started/configuration.md
+++ b/docs/content/documentation/getting-started/configuration.md
@@ -169,6 +169,8 @@ paths_keep_dates = false
include_title = true
# Whether to include the description of the page/section in the index
include_description = false
+# Whether to include the RFC3339 datetime of the page in the search index
+include_date = false
# Whether to include the path of the page/section in the index
include_path = false
# Whether to include the rendered content of the page/section in the index
From 682447ee73fb858be3b9fbb73ff0a372b9e4af58 Mon Sep 17 00:00:00 2001
From: Clar Fon <15850505+clarfonthey@users.noreply.github.com>
Date: Sun, 7 Jan 2024 14:23:36 -0500
Subject: [PATCH 03/25] Match `` in addition to ``
(#2397)
* Match without spaces
* Add tests for new handling, with a note on pulldown-cmark bug
---
components/markdown/src/markdown.rs | 42 +++++++++++++++++++++++++++--
1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/components/markdown/src/markdown.rs b/components/markdown/src/markdown.rs
index a6cb3beca6..4d30b2ac92 100644
--- a/components/markdown/src/markdown.rs
+++ b/components/markdown/src/markdown.rs
@@ -10,7 +10,7 @@ use utils::net::is_external_link;
use crate::context::RenderContext;
use errors::{Context, Error, Result};
use libs::pulldown_cmark::escape::escape_html;
-use libs::regex::Regex;
+use libs::regex::{Regex, RegexBuilder};
use utils::site::resolve_internal_link;
use utils::slugs::slugify_anchors;
use utils::table_of_contents::{make_table_of_contents, Heading};
@@ -24,6 +24,15 @@ const CONTINUE_READING: &str = "";
const ANCHOR_LINK_TEMPLATE: &str = "anchor-link.html";
static EMOJI_REPLACER: Lazy = Lazy::new(EmojiReplacer::new);
+/// Set as a regex to help match some extra cases. This way, spaces and case don't matter.
+static MORE_DIVIDER_RE: Lazy = Lazy::new(|| {
+ RegexBuilder::new(r#""#)
+ .case_insensitive(true)
+ .dot_matches_new_line(true)
+ .build()
+ .unwrap()
+});
+
/// Although there exists [a list of registered URI schemes][uri-schemes], a link may use arbitrary,
/// private schemes. This regex checks if the given string starts with something that just looks
/// like a scheme, i.e., a case-insensitive identifier followed by a colon.
@@ -485,7 +494,7 @@ pub fn markdown_to_html(
});
}
Event::Html(text) => {
- if text.contains("") {
+ if !has_summary && MORE_DIVIDER_RE.is_match(&text) {
has_summary = true;
events.push(Event::Html(CONTINUE_READING.into()));
continue;
@@ -600,6 +609,8 @@ pub fn markdown_to_html(
#[cfg(test)]
mod tests {
+ use config::Config;
+
use super::*;
#[test]
@@ -644,4 +655,31 @@ mod tests {
assert!(!is_colocated_asset_link(link));
}
}
+
+ #[test]
+ // Tests for summary being split out
+ fn test_summary_split() {
+ let top = "Here's a compelling summary.";
+ let top_rendered = format!("{top}
");
+ let bottom = "Here's the compelling conclusion.";
+ let bottom_rendered = format!("{bottom}
");
+ // FIXME: would add a test that includes newlines, but due to the way pulldown-cmark parses HTML nodes, these are passed as separate HTML events. see: https://github.com/raphlinus/pulldown-cmark/issues/803
+ let mores =
+ ["", "", "", "", ""];
+ let config = Config::default();
+ let context = RenderContext::from_config(&config);
+ for more in mores {
+ let content = format!("{top}\n\n{more}\n\n{bottom}");
+ let rendered = markdown_to_html(&content, &context, vec![]).unwrap();
+ assert!(rendered.summary_len.is_some(), "no summary when splitting on {more}");
+ let summary_len = rendered.summary_len.unwrap();
+ let summary = &rendered.body[..summary_len].trim();
+ let body = &rendered.body[summary_len..].trim();
+ let continue_reading = &body[..CONTINUE_READING.len()];
+ let body = &body[CONTINUE_READING.len()..].trim();
+ assert_eq!(summary, &top_rendered);
+ assert_eq!(continue_reading, CONTINUE_READING);
+ assert_eq!(body, &bottom_rendered);
+ }
+ }
}
From 42ea1b49d1e340b083ba2ca12b7ba940bb91793f Mon Sep 17 00:00:00 2001
From: Stan Rozenraukh
Date: Sun, 7 Jan 2024 14:37:33 -0500
Subject: [PATCH 04/25] fix(serve): content can be served from output_path
(#2398)
This fixes a bug introduced in https://github.com/getzola/zola/pull/2258
The issue arose when `output_path` was relative. The request being
served would be canonicalized and this would be a string. So, for
example, if you were serving content from `public` the code
[right after](https://github.com/getzola/zola/blob/38199c125501e9ff0e700e96adaca72cc3f25d2b/src/cmd/serve.rs#L144-L147)
the canonicalization checking if
`root.starts_with(original_root)` would always return `false` since
an absolute path, `/some/path/to/content` would never start with a
string like `public`.
---
src/cmd/serve.rs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs
index 2f2f718e3e..dce008e1fa 100644
--- a/src/cmd/serve.rs
+++ b/src/cmd/serve.rs
@@ -461,9 +461,9 @@ pub fn serve(
let ws_address = format!("{}:{}", interface, ws_port.unwrap());
let output_path = site.output_path.clone();
- // output path is going to need to be moved later on, so clone it for the
- // http closure to avoid contention.
- let static_root = output_path.clone();
+ // static_root needs to be canonicalized because we do the same for the http server.
+ let static_root = std::fs::canonicalize(&output_path).unwrap();
+
let broadcaster = {
thread::spawn(move || {
let addr = address.parse().unwrap();
From 8b602b2fde11534643a5aa1cb5c0c474f0f49301 Mon Sep 17 00:00:00 2001
From: Clar Fon <15850505+clarfonthey@users.noreply.github.com>
Date: Sun, 7 Jan 2024 15:14:21 -0500
Subject: [PATCH 05/25] Allow IPv6 serve, default `base_url` to listen
interface instead of 127.0.0.1 (#2395)
* Parse interface as IpAddr, allow IPv6.
* Default base_url to socket address, instead of 127.0.0.1
---
src/cli.rs | 7 ++++---
src/cmd/serve.rs | 41 ++++++++++++++++++++++-------------------
src/main.rs | 4 ++--
3 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/src/cli.rs b/src/cli.rs
index b55dc18a5e..1329edff4d 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -1,3 +1,4 @@
+use std::net::IpAddr;
use std::path::PathBuf;
use clap::{Parser, Subcommand};
@@ -54,7 +55,7 @@ pub enum Command {
Serve {
/// Interface to bind on
#[clap(short = 'i', long, default_value = "127.0.0.1")]
- interface: String,
+ interface: IpAddr,
/// Which port to use
#[clap(short = 'p', long, default_value_t = 1111)]
@@ -70,8 +71,8 @@ pub enum Command {
force: bool,
/// Changes the base_url
- #[clap(short = 'u', long, default_value = "127.0.0.1")]
- base_url: String,
+ #[clap(short = 'u', long)]
+ base_url: Option,
/// Include drafts when loading the site
#[clap(long)]
diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs
index dce008e1fa..d13b945942 100644
--- a/src/cmd/serve.rs
+++ b/src/cmd/serve.rs
@@ -24,7 +24,7 @@
use std::cell::Cell;
use std::fs::read_dir;
use std::future::IntoFuture;
-use std::net::{SocketAddrV4, TcpListener};
+use std::net::{IpAddr, SocketAddr, TcpListener};
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
use std::sync::mpsc::channel;
use std::sync::Mutex;
@@ -321,20 +321,29 @@ fn rebuild_done_handling(broadcaster: &Sender, res: Result<()>, reload_path: &st
#[allow(clippy::too_many_arguments)]
fn create_new_site(
root_dir: &Path,
- interface: &str,
+ interface: IpAddr,
interface_port: u16,
output_dir: Option<&Path>,
force: bool,
- base_url: &str,
+ base_url: Option<&str>,
config_file: &Path,
include_drafts: bool,
- no_port_append: bool,
+ mut no_port_append: bool,
ws_port: Option,
-) -> Result<(Site, String)> {
+) -> Result<(Site, SocketAddr)> {
SITE_CONTENT.write().unwrap().clear();
let mut site = Site::new(root_dir, config_file)?;
- let address = format!("{}:{}", interface, interface_port);
+ let address = SocketAddr::new(interface, interface_port);
+
+ // if no base URL provided, use socket address
+ let base_url = base_url.map_or_else(
+ || {
+ no_port_append = true;
+ address.to_string()
+ },
+ |u| u.to_string(),
+ );
let base_url = if base_url == "/" {
String::from("/")
@@ -381,11 +390,11 @@ fn create_new_site(
#[allow(clippy::too_many_arguments)]
pub fn serve(
root_dir: &Path,
- interface: &str,
+ interface: IpAddr,
interface_port: u16,
output_dir: Option<&Path>,
force: bool,
- base_url: &str,
+ base_url: Option<&str>,
config_file: &Path,
open: bool,
include_drafts: bool,
@@ -394,7 +403,7 @@ pub fn serve(
utc_offset: UtcOffset,
) -> Result<()> {
let start = Instant::now();
- let (mut site, address) = create_new_site(
+ let (mut site, bind_address) = create_new_site(
root_dir,
interface,
interface_port,
@@ -409,12 +418,8 @@ pub fn serve(
messages::report_elapsed_time(start);
// Stop right there if we can't bind to the address
- let bind_address: SocketAddrV4 = match address.parse() {
- Ok(a) => a,
- Err(_) => return Err(anyhow!("Invalid address: {}.", address)),
- };
if (TcpListener::bind(bind_address)).is_err() {
- return Err(anyhow!("Cannot start server on address {}.", address));
+ return Err(anyhow!("Cannot start server on address {}.", bind_address));
}
let config_path = PathBuf::from(config_file);
@@ -466,8 +471,6 @@ pub fn serve(
let broadcaster = {
thread::spawn(move || {
- let addr = address.parse().unwrap();
-
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
@@ -484,11 +487,11 @@ pub fn serve(
}
});
- let server = Server::bind(&addr).serve(make_service);
+ let server = Server::bind(&bind_address).serve(make_service);
- println!("Web server is available at http://{}\n", &address);
+ println!("Web server is available at http://{}\n", bind_address);
if open {
- if let Err(err) = open::that(format!("http://{}", &address)) {
+ if let Err(err) = open::that(format!("http://{}", bind_address)) {
eprintln!("Failed to open URL in your browser: {}", err);
}
}
diff --git a/src/main.rs b/src/main.rs
index 59bc80df5c..48e95b9693 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -102,11 +102,11 @@ fn main() {
console::info("Building site...");
if let Err(e) = cmd::serve(
&root_dir,
- &interface,
+ interface,
port,
output_dir.as_deref(),
force,
- &base_url,
+ base_url.as_deref(),
&config_file,
open,
drafts,
From a6bd2b90131545bcef38c16379d9550296f10dcd Mon Sep 17 00:00:00 2001
From: Clar Fon <15850505+clarfonthey@users.noreply.github.com>
Date: Thu, 18 Jan 2024 04:07:59 -0500
Subject: [PATCH 06/25] Refactor: create_directory responsibly (#2407)
* Remove ensure_directory_exists since it's identical to create_directory, and misleading
* Don't create directories unless needed; rely on create_dir_all instead of manually iterating over components
---
components/imageproc/src/processor.rs | 4 +--
components/site/src/lib.rs | 39 +++++++--------------------
components/site/src/sass.rs | 4 +--
components/utils/src/fs.rs | 8 ------
4 files changed, 14 insertions(+), 41 deletions(-)
diff --git a/components/imageproc/src/processor.rs b/components/imageproc/src/processor.rs
index 4ef9869698..63346663a6 100644
--- a/components/imageproc/src/processor.rs
+++ b/components/imageproc/src/processor.rs
@@ -177,7 +177,7 @@ impl Processor {
/// Run the enqueued image operations
pub fn do_process(&mut self) -> Result<()> {
if !self.img_ops.is_empty() {
- ufs::ensure_directory_exists(&self.output_dir)?;
+ ufs::create_directory(&self.output_dir)?;
}
self.img_ops
@@ -197,7 +197,7 @@ impl Processor {
return Ok(());
}
- ufs::ensure_directory_exists(&self.output_dir)?;
+ ufs::create_directory(&self.output_dir)?;
let output_paths: HashSet<_> = self
.img_ops
.iter()
diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs
index 91af546168..ab38ddc8e4 100644
--- a/components/site/src/lib.rs
+++ b/components/site/src/lib.rs
@@ -23,7 +23,6 @@ use std::time::Instant;
use templates::{load_tera, render_redirect_template};
use utils::fs::{
clean_site_output_folder, copy_directory, copy_file_if_needed, create_directory, create_file,
- ensure_directory_exists,
};
use utils::net::{get_available_port, is_external_link};
use utils::templates::{render_template, ShortcodeDefinition};
@@ -639,7 +638,6 @@ impl Site {
create_dirs: bool,
) -> Result {
let write_dirs = self.build_mode == BuildMode::Disk || create_dirs;
- ensure_directory_exists(&self.output_path)?;
let mut site_path = RelativePathBuf::new();
let mut current_path = self.output_path.to_path_buf();
@@ -647,10 +645,6 @@ impl Site {
for component in components {
current_path.push(component);
site_path.push(component);
-
- if !current_path.exists() && write_dirs {
- create_directory(¤t_path)?;
- }
}
if write_dirs {
@@ -788,9 +782,13 @@ impl Site {
}
pub fn render_themes_css(&self) -> Result<()> {
- ensure_directory_exists(&self.static_path)?;
+ let themes = &self.config.markdown.highlight_themes_css;
+
+ if !themes.is_empty() {
+ create_directory(&self.static_path)?;
+ }
- for t in &self.config.markdown.highlight_themes_css {
+ for t in themes {
let p = self.static_path.join(&t.filename);
if !p.exists() {
let content = &self.config.markdown.export_theme_css(&t.theme)?;
@@ -818,7 +816,7 @@ impl Site {
}
pub fn build_search_index(&self) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
+ create_directory(&self.output_path)?;
// TODO: add those to the SITE_CONTENT map
// index first
@@ -857,7 +855,6 @@ impl Site {
/// Renders all the aliases for each page/section: a magic HTML template that redirects to
/// the canonical one
pub fn render_aliases(&self) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
let library = self.library.read().unwrap();
for (_, page) in &library.pages {
for alias in &page.meta.aliases {
@@ -874,7 +871,6 @@ impl Site {
/// Renders 404.html
pub fn render_404(&self) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
let mut context = Context::new();
context.insert("config", &self.config.serialize(&self.config.default_language));
context.insert("lang", &self.config.default_language);
@@ -886,7 +882,6 @@ impl Site {
/// Renders robots.txt
pub fn render_robots(&self) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
let mut context = Context::new();
context.insert("config", &self.config.serialize(&self.config.default_language));
let content = render_template("robots.txt", &self.tera, context, &self.config.theme)?;
@@ -911,8 +906,6 @@ impl Site {
return Ok(());
}
- ensure_directory_exists(&self.output_path)?;
-
let mut components = Vec::new();
if taxonomy.lang != self.config.default_language {
components.push(taxonomy.lang.as_ref());
@@ -977,8 +970,6 @@ impl Site {
/// What it says on the tin
pub fn render_sitemap(&self) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
-
let library = self.library.read().unwrap();
let all_sitemap_entries =
{ sitemap::find_entries(&library, &self.taxonomies[..], &self.config) };
@@ -1032,8 +1023,6 @@ impl Site {
lang: &str,
additional_context_fn: impl Fn(Context) -> Context,
) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
-
let feed = match feed::render_feed(self, all_pages, lang, base_path, additional_context_fn)?
{
Some(v) => v,
@@ -1060,7 +1049,6 @@ impl Site {
/// Renders a single section
pub fn render_section(&self, section: &Section, render_pages: bool) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
let mut output_path = self.output_path.clone();
let mut components: Vec<&str> = Vec::new();
let create_directories = self.build_mode == BuildMode::Disk || !section.assets.is_empty();
@@ -1068,19 +1056,15 @@ impl Site {
if section.lang != self.config.default_language {
components.push(§ion.lang);
output_path.push(§ion.lang);
-
- if !output_path.exists() && create_directories {
- create_directory(&output_path)?;
- }
}
for component in §ion.file.components {
components.push(component);
output_path.push(component);
+ }
- if !output_path.exists() && create_directories {
- create_directory(&output_path)?;
- }
+ if create_directories {
+ create_directory(&output_path)?;
}
if section.meta.generate_feed {
@@ -1166,7 +1150,6 @@ impl Site {
/// Renders all pages that do not belong to any sections
pub fn render_orphan_pages(&self) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
let library = self.library.read().unwrap();
for page in library.get_all_orphan_pages() {
self.render_page(page)?;
@@ -1181,8 +1164,6 @@ impl Site {
components: Vec<&'a str>,
paginator: &'a Paginator,
) -> Result<()> {
- ensure_directory_exists(&self.output_path)?;
-
let index_components = components.clone();
paginator
diff --git a/components/site/src/sass.rs b/components/site/src/sass.rs
index 87f5c7dd8c..a5fddedf0b 100644
--- a/components/site/src/sass.rs
+++ b/components/site/src/sass.rs
@@ -7,10 +7,10 @@ use libs::walkdir::{DirEntry, WalkDir};
use crate::anyhow;
use errors::{bail, Result};
-use utils::fs::{create_file, ensure_directory_exists};
+use utils::fs::{create_directory, create_file};
pub fn compile_sass(base_path: &Path, output_path: &Path) -> Result<()> {
- ensure_directory_exists(output_path)?;
+ create_directory(output_path)?;
let sass_path = {
let mut sass_path = PathBuf::from(base_path);
diff --git a/components/utils/src/fs.rs b/components/utils/src/fs.rs
index 1d3dbdfa5c..e1a1a5f29a 100644
--- a/components/utils/src/fs.rs
+++ b/components/utils/src/fs.rs
@@ -27,14 +27,6 @@ pub fn create_file(path: &Path, content: &str) -> Result<()> {
Ok(())
}
-/// Create a directory at the given path if it doesn't exist already
-pub fn ensure_directory_exists(path: &Path) -> Result<()> {
- if !path.exists() {
- create_directory(path)?;
- }
- Ok(())
-}
-
/// Very similar to `create_dir` from the std except it checks if the folder
/// exists before creating it
pub fn create_directory(path: &Path) -> Result<()> {
From 012284516b37512a7d87c834041220df8205c354 Mon Sep 17 00:00:00 2001
From: Clar Fon <15850505+clarfonthey@users.noreply.github.com>
Date: Mon, 22 Jan 2024 06:57:42 -0500
Subject: [PATCH 07/25] Refactor: copy_assets instead of copy_asset (#2418)
---
components/site/src/lib.rs | 39 +++++++++++++++-----------------------
1 file changed, 15 insertions(+), 24 deletions(-)
diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs
index ab38ddc8e4..dce82d812f 100644
--- a/components/site/src/lib.rs
+++ b/components/site/src/lib.rs
@@ -676,8 +676,19 @@ impl Site {
Ok(current_path)
}
- fn copy_asset(&self, src: &Path, dest: &Path) -> Result<()> {
- copy_file_if_needed(src, dest, self.config.hard_link_static)
+ fn copy_assets(&self, parent: &Path, assets: &[impl AsRef], dest: &Path) -> Result<()> {
+ for asset in assets {
+ let asset_path = asset.as_ref();
+ copy_file_if_needed(
+ asset_path,
+ &dest.join(
+ asset_path.strip_prefix(parent).expect("Couldn't get filename from page asset"),
+ ),
+ self.config.hard_link_static,
+ )?;
+ }
+
+ Ok(())
}
/// Renders a single content page
@@ -689,17 +700,7 @@ impl Site {
self.write_content(&components, "index.html", content, !page.assets.is_empty())?;
// Copy any asset we found previously into the same directory as the index.html
- for asset in &page.assets {
- let asset_path = asset.as_path();
- self.copy_asset(
- asset_path,
- ¤t_path.join(
- asset_path
- .strip_prefix(page.file.path.parent().unwrap())
- .expect("Couldn't get filename from page asset"),
- ),
- )?;
- }
+ self.copy_assets(page.file.path.parent().unwrap(), &page.assets, ¤t_path)?;
Ok(())
}
@@ -1082,17 +1083,7 @@ impl Site {
}
// Copy any asset we found previously into the same directory as the index.html
- for asset in §ion.assets {
- let asset_path = asset.as_path();
- self.copy_asset(
- asset_path,
- &output_path.join(
- asset_path
- .strip_prefix(section.file.path.parent().unwrap())
- .expect("Failed to get asset filename for section"),
- ),
- )?;
- }
+ self.copy_assets(§ion.file.path.parent().unwrap(), §ion.assets, &output_path)?;
if render_pages {
section
From 0098877056322d5c8cc0672bdf41876dc39c2503 Mon Sep 17 00:00:00 2001
From: Andrew Langmeier
Date: Sun, 4 Feb 2024 14:59:30 -0500
Subject: [PATCH 08/25] Allow ignoring files when link checking (#2264)
* Allow ignoring files when link checking
* cargo fmt
* Fix tests
* Remove mystery duplicate function..?
* Add in some mysterious missing code..?
* Simple tests for link checker file globs in config
* cargo fmt
* Remove comment
* convert expect to error propagation
* Address comments
* cargo fmt
---
components/config/src/config/link_checker.rs | 18 ++-
components/config/src/config/mod.rs | 110 ++++++++++++-------
components/site/src/link_checking.rs | 10 +-
components/utils/src/globs.rs | 20 ++++
components/utils/src/lib.rs | 1 +
5 files changed, 117 insertions(+), 42 deletions(-)
create mode 100644 components/utils/src/globs.rs
diff --git a/components/config/src/config/link_checker.rs b/components/config/src/config/link_checker.rs
index 8501287981..7668c71b1f 100644
--- a/components/config/src/config/link_checker.rs
+++ b/components/config/src/config/link_checker.rs
@@ -1,5 +1,9 @@
+use libs::globset::GlobSet;
use serde::{Deserialize, Serialize};
+use errors::Result;
+use utils::globs::build_ignore_glob_set;
+
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum LinkCheckerLevel {
#[serde(rename = "error")]
@@ -14,7 +18,7 @@ impl Default for LinkCheckerLevel {
}
}
-#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
+#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct LinkChecker {
/// Skip link checking for these URL prefixes
@@ -25,4 +29,16 @@ pub struct LinkChecker {
pub internal_level: LinkCheckerLevel,
/// Emit either "error" or "warn" for broken external links (including anchor links).
pub external_level: LinkCheckerLevel,
+ /// A list of file glob patterns to skip link checking on
+ pub ignored_files: Vec,
+ #[serde(skip_serializing, skip_deserializing)] // not a typo, 2 are needed
+ pub ignored_files_globset: Option,
+}
+
+impl LinkChecker {
+ pub fn resolve_globset(&mut self) -> Result<()> {
+ let glob_set = build_ignore_glob_set(&self.ignored_files, "files")?;
+ self.ignored_files_globset = Some(glob_set);
+ Ok(())
+ }
}
diff --git a/components/config/src/config/mod.rs b/components/config/src/config/mod.rs
index a79542e85e..f2a40675ae 100644
--- a/components/config/src/config/mod.rs
+++ b/components/config/src/config/mod.rs
@@ -8,13 +8,14 @@ pub mod taxonomies;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
-use libs::globset::{Glob, GlobSet, GlobSetBuilder};
+use libs::globset::GlobSet;
use libs::toml::Value as Toml;
use serde::{Deserialize, Serialize};
use crate::theme::Theme;
use errors::{anyhow, bail, Result};
use utils::fs::read_file;
+use utils::globs::build_ignore_glob_set;
use utils::slugs::slugify_paths;
// We want a default base url for tests
@@ -28,18 +29,6 @@ pub enum Mode {
Check,
}
-fn build_ignore_glob_set(ignore: &Vec, name: &str) -> Result {
- let mut glob_set_builder = GlobSetBuilder::new();
- for pat in ignore {
- let glob = match Glob::new(pat) {
- Ok(g) => g,
- Err(e) => bail!("Invalid ignored_{} glob pattern: {}, error = {}", name, pat, e),
- };
- glob_set_builder.add(glob);
- }
- Ok(glob_set_builder.build().unwrap_or_else(|_| panic!("Bad ignored_{} in config file.", name)))
-}
-
#[derive(Clone, Debug, Deserialize)]
#[serde(default)]
pub struct Config {
@@ -150,21 +139,13 @@ impl Config {
config.add_default_language()?;
config.slugify_taxonomies();
+ config.link_checker.resolve_globset()?;
- if !config.ignored_content.is_empty() {
- // Convert the file glob strings into a compiled glob set matcher. We want to do this once,
- // at program initialization, rather than for every page, for example. We arrange for the
- // globset matcher to always exist (even though it has to be an inside an Option at the
- // moment because of the TOML serializer); if the glob set is empty the `is_match` function
- // of the globber always returns false.
- let glob_set = build_ignore_glob_set(&config.ignored_content, "content")?;
- config.ignored_content_globset = Some(glob_set);
- }
+ let content_glob_set = build_ignore_glob_set(&config.ignored_content, "content")?;
+ config.ignored_content_globset = Some(content_glob_set);
- if !config.ignored_static.is_empty() {
- let glob_set = build_ignore_glob_set(&config.ignored_static, "static")?;
- config.ignored_static_globset = Some(glob_set);
- }
+ let static_glob_set = build_ignore_glob_set(&config.ignored_static, "static")?;
+ config.ignored_static_globset = Some(static_glob_set);
Ok(config)
}
@@ -652,45 +633,41 @@ title = "A title"
}
#[test]
- fn missing_ignored_content_results_in_empty_vector_and_empty_globset() {
+ fn missing_ignored_content_results_in_empty_vector() {
let config_str = r#"
title = "My site"
base_url = "example.com"
"#;
let config = Config::parse(config_str).unwrap();
- let v = config.ignored_content;
- assert_eq!(v.len(), 0);
- assert!(config.ignored_content_globset.is_none());
+ assert_eq!(config.ignored_content.len(), 0);
}
#[test]
- fn missing_ignored_static_results_in_empty_vector_and_empty_globset() {
+ fn empty_ignored_content_results_in_empty_vector() {
let config_str = r#"
title = "My site"
base_url = "example.com"
+ignored_content = []
"#;
+
let config = Config::parse(config_str).unwrap();
- let v = config.ignored_static;
- assert_eq!(v.len(), 0);
- assert!(config.ignored_static_globset.is_none());
+ assert_eq!(config.ignored_content.len(), 0);
}
#[test]
- fn empty_ignored_content_results_in_empty_vector_and_empty_globset() {
+ fn missing_ignored_static_results_in_empty_vector() {
let config_str = r#"
title = "My site"
base_url = "example.com"
-ignored_content = []
"#;
let config = Config::parse(config_str).unwrap();
- assert_eq!(config.ignored_content.len(), 0);
- assert!(config.ignored_content_globset.is_none());
+ assert_eq!(config.ignored_static.len(), 0);
}
#[test]
- fn empty_ignored_static_results_in_empty_vector_and_empty_globset() {
+ fn empty_ignored_static_results_in_empty_vector() {
let config_str = r#"
title = "My site"
base_url = "example.com"
@@ -699,7 +676,30 @@ ignored_static = []
let config = Config::parse(config_str).unwrap();
assert_eq!(config.ignored_static.len(), 0);
- assert!(config.ignored_static_globset.is_none());
+ }
+
+ #[test]
+ fn missing_link_checker_ignored_files_results_in_empty_vector() {
+ let config_str = r#"
+title = "My site"
+base_url = "example.com"
+ "#;
+
+ let config = Config::parse(config_str).unwrap();
+ assert_eq!(config.link_checker.ignored_files.len(), 0);
+ }
+
+ #[test]
+ fn empty_link_checker_ignored_files_results_in_empty_vector() {
+ let config_str = r#"
+title = "My site"
+base_url = "example.com"
+[link_checker]
+ignored_files = []
+ "#;
+
+ let config = Config::parse(config_str).unwrap();
+ assert_eq!(config.link_checker.ignored_files.len(), 0);
}
#[test]
@@ -760,6 +760,36 @@ ignored_static = ["*.{graphml,iso}", "*.py?", "**/{target,temp_folder}"]
assert!(g.is_match("content/poetry/zen.py2"));
}
+ #[test]
+ fn non_empty_link_checker_ignored_pages_results_in_vector_of_patterns_and_configured_globset() {
+ let config_str = r#"
+title = "My site"
+base_url = "example.com"
+[link_checker]
+ignored_files = ["*.{graphml,iso}", "*.py?", "**/{target,temp_folder}"]
+ "#;
+
+ let config = Config::parse(config_str).unwrap();
+ let v = config.link_checker.ignored_files;
+ assert_eq!(v, vec!["*.{graphml,iso}", "*.py?", "**/{target,temp_folder}"]);
+
+ let g = config.link_checker.ignored_files_globset.unwrap();
+ assert_eq!(g.len(), 3);
+ assert!(g.is_match("foo.graphml"));
+ assert!(g.is_match("foo/bar/foo.graphml"));
+ assert!(g.is_match("foo.iso"));
+ assert!(!g.is_match("foo.png"));
+ assert!(g.is_match("foo.py2"));
+ assert!(g.is_match("foo.py3"));
+ assert!(!g.is_match("foo.py"));
+ assert!(g.is_match("foo/bar/target"));
+ assert!(g.is_match("foo/bar/baz/temp_folder"));
+ assert!(g.is_match("foo/bar/baz/temp_folder/target"));
+ assert!(g.is_match("temp_folder"));
+ assert!(g.is_match("my/isos/foo.iso"));
+ assert!(g.is_match("content/poetry/zen.py2"));
+ }
+
#[test]
fn link_checker_skip_anchor_prefixes() {
let config_str = r#"
diff --git a/components/site/src/link_checking.rs b/components/site/src/link_checking.rs
index b5c1ed2186..1bb1a66941 100644
--- a/components/site/src/link_checking.rs
+++ b/components/site/src/link_checking.rs
@@ -3,6 +3,7 @@ use std::path::{Path, PathBuf};
use std::{cmp, collections::HashMap, collections::HashSet, iter::FromIterator, thread};
use config::LinkCheckerLevel;
+use libs::globset::GlobSet;
use libs::rayon::prelude::*;
use crate::Site;
@@ -105,6 +106,10 @@ fn should_skip_by_prefix(link: &str, skip_prefixes: &[String]) -> bool {
skip_prefixes.iter().any(|prefix| link.starts_with(prefix))
}
+fn should_skip_by_file(file_path: &Path, glob_set: &GlobSet) -> bool {
+ glob_set.is_match(file_path)
+}
+
fn get_link_domain(link: &str) -> Result {
return match Url::parse(link) {
Ok(url) => match url.host_str().map(String::from) {
@@ -150,9 +155,12 @@ pub fn check_external_links(site: &Site) -> Vec {
let mut invalid_url_links: u32 = 0;
// First we look at all the external links, skip those the user wants to skip and record
// the ones that have invalid URLs
+ let ignored_files_globset = site.config.link_checker.ignored_files_globset.as_ref().unwrap();
for (file_path, links) in external_links {
for link in links {
- if should_skip_by_prefix(link, &site.config.link_checker.skip_prefixes) {
+ if should_skip_by_prefix(link, &site.config.link_checker.skip_prefixes)
+ || should_skip_by_file(file_path, ignored_files_globset)
+ {
skipped_link_count += 1;
} else {
match get_link_domain(link) {
diff --git a/components/utils/src/globs.rs b/components/utils/src/globs.rs
new file mode 100644
index 0000000000..2377964b17
--- /dev/null
+++ b/components/utils/src/globs.rs
@@ -0,0 +1,20 @@
+use libs::globset::{Glob, GlobSet, GlobSetBuilder};
+
+use errors::{bail, Result};
+
+pub fn build_ignore_glob_set(ignore: &Vec, name: &str) -> Result {
+ // Convert the file glob strings into a compiled glob set matcher. We want to do this once,
+ // at program initialization, rather than for every page, for example. We arrange for the
+ // globset matcher to always exist (even though it has to be inside an Option at the
+ // moment because of the TOML serializer); if the glob set is empty the `is_match` function
+ // of the globber always returns false.
+ let mut glob_set_builder = GlobSetBuilder::new();
+ for pat in ignore {
+ let glob = match Glob::new(pat) {
+ Ok(g) => g,
+ Err(e) => bail!("Invalid ignored_{} glob pattern: {}, error = {}", name, pat, e),
+ };
+ glob_set_builder.add(glob);
+ }
+ Ok(glob_set_builder.build()?)
+}
diff --git a/components/utils/src/lib.rs b/components/utils/src/lib.rs
index 3b2ab6022d..619636b8f7 100644
--- a/components/utils/src/lib.rs
+++ b/components/utils/src/lib.rs
@@ -1,6 +1,7 @@
pub mod anchors;
pub mod de;
pub mod fs;
+pub mod globs;
pub mod net;
pub mod site;
pub mod slugs;
From 73e06bd4cf0712d2f36675334c29594cb2fb9b34 Mon Sep 17 00:00:00 2001
From: SumDonkuS
Date: Sun, 4 Feb 2024 14:39:18 -0700
Subject: [PATCH 09/25] Issue 2359 get section by lang (#2410)
* adding optional `lang` arugment to `get_section` global function
* Add handling of default language passed in `lang` argument of `get_section`
* Remove clones for path. Change "?" to an explicit check for error
* lint changes
* Clean up error handling for add_lang_to_path call
* fix format
* Add optional parameter "lang" to get_page template function. Add check for language available in config.
* Modify helper function name from calculate_path to get_path_with_lang. Modify documentation for get_section and get_page to include equivalent calls without using lang argument to demostrate how lang argument effects pathing.
---
components/site/src/tpls.rs | 17 +-
.../templates/src/global_fns/content.rs | 274 ++++++++++++++++--
.../documentation/templates/overview.md | 24 ++
3 files changed, 290 insertions(+), 25 deletions(-)
diff --git a/components/site/src/tpls.rs b/components/site/src/tpls.rs
index d1e2eacd5a..c51d0de175 100644
--- a/components/site/src/tpls.rs
+++ b/components/site/src/tpls.rs
@@ -1,5 +1,6 @@
use crate::Site;
use libs::tera::Result as TeraResult;
+use std::sync::Arc;
use templates::{filters, global_fns};
/// Adds global fns that are to be available to shortcodes while rendering markdown
@@ -74,13 +75,25 @@ pub fn register_early_global_fns(site: &mut Site) -> TeraResult<()> {
/// Functions filled once we have parsed all the pages/sections only, so not available in shortcodes
pub fn register_tera_global_fns(site: &mut Site) {
+ let language_list: Arc> =
+ Arc::new(site.config.languages.keys().map(|s| s.to_string()).collect());
site.tera.register_function(
"get_page",
- global_fns::GetPage::new(site.base_path.clone(), site.library.clone()),
+ global_fns::GetPage::new(
+ site.base_path.clone(),
+ &site.config.default_language,
+ Arc::clone(&language_list),
+ site.library.clone(),
+ ),
);
site.tera.register_function(
"get_section",
- global_fns::GetSection::new(site.base_path.clone(), site.library.clone()),
+ global_fns::GetSection::new(
+ site.base_path.clone(),
+ &site.config.default_language,
+ Arc::clone(&language_list),
+ site.library.clone(),
+ ),
);
site.tera.register_function(
"get_taxonomy",
diff --git a/components/templates/src/global_fns/content.rs b/components/templates/src/global_fns/content.rs
index 84c155fd71..17183bb639 100644
--- a/components/templates/src/global_fns/content.rs
+++ b/components/templates/src/global_fns/content.rs
@@ -1,5 +1,6 @@
use content::{Library, Taxonomy, TaxonomyTerm};
use libs::tera::{from_value, to_value, Function as TeraFn, Result, Value};
+use std::borrow::Cow;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{Arc, RwLock};
@@ -71,14 +72,60 @@ impl TeraFn for GetTaxonomyUrl {
}
}
+fn add_lang_to_path<'a>(path: &str, lang: &str) -> Result> {
+ match path.rfind('.') {
+ Some(period_offset) => {
+ let prefix = path.get(0..period_offset);
+ let suffix = path.get(period_offset..);
+ if prefix.is_none() || suffix.is_none() {
+ Err(format!("Error adding language code to {}", path).into())
+ } else {
+ Ok(Cow::Owned(format!("{}.{}{}", prefix.unwrap(), lang, suffix.unwrap())))
+ }
+ }
+ None => Ok(Cow::Owned(format!("{}.{}", path, lang))),
+ }
+}
+
+fn get_path_with_lang<'a>(
+ path: &'a String,
+ lang: &Option,
+ default_lang: &str,
+ supported_languages: &[String],
+) -> Result> {
+ if supported_languages.contains(&default_lang.to_string()) {
+ lang.as_ref().map_or_else(
+ || Ok(Cow::Borrowed(path)),
+ |lang_code| match default_lang == lang_code {
+ true => Ok(Cow::Borrowed(path)),
+ false => add_lang_to_path(path, lang_code),
+ },
+ )
+ } else {
+ Err(format!("Unsupported language {}", default_lang).into())
+ }
+}
+
#[derive(Debug)]
pub struct GetPage {
base_path: PathBuf,
+ default_lang: String,
+ supported_languages: Arc>,
library: Arc>,
}
impl GetPage {
- pub fn new(base_path: PathBuf, library: Arc>) -> Self {
- Self { base_path: base_path.join("content"), library }
+ pub fn new(
+ base_path: PathBuf,
+ default_lang: &str,
+ supported_languages: Arc>,
+ library: Arc>,
+ ) -> Self {
+ Self {
+ base_path: base_path.join("content"),
+ default_lang: default_lang.to_string(),
+ supported_languages,
+ library,
+ }
}
}
impl TeraFn for GetPage {
@@ -88,23 +135,50 @@ impl TeraFn for GetPage {
args.get("path"),
"`get_page` requires a `path` argument with a string value"
);
- let full_path = self.base_path.join(&path);
- let library = self.library.read().unwrap();
- match library.pages.get(&full_path) {
- Some(p) => Ok(to_value(p.serialize(&library)).unwrap()),
- None => Err(format!("Page `{}` not found.", path).into()),
- }
+
+ let lang =
+ optional_arg!(String, args.get("lang"), "`get_section`: `lang` must be a string");
+
+ get_path_with_lang(&path, &lang, &self.default_lang, &self.supported_languages).and_then(
+ |path_with_lang| {
+ let full_path = self.base_path.join(path_with_lang.as_ref());
+ let library = self.library.read().unwrap();
+
+ match library.pages.get(&full_path) {
+ Some(p) => Ok(to_value(p.serialize(&library)).unwrap()),
+ None => match lang {
+ Some(lang_code) => {
+ Err(format!("Page `{}` not found for language `{}`.", path, lang_code)
+ .into())
+ }
+ None => Err(format!("Page `{}` not found.", path).into()),
+ },
+ }
+ },
+ )
}
}
#[derive(Debug)]
pub struct GetSection {
base_path: PathBuf,
+ default_lang: String,
+ supported_languages: Arc>,
library: Arc>,
}
impl GetSection {
- pub fn new(base_path: PathBuf, library: Arc>) -> Self {
- Self { base_path: base_path.join("content"), library }
+ pub fn new(
+ base_path: PathBuf,
+ default_lang: &str,
+ supported_languages: Arc>,
+ library: Arc>,
+ ) -> Self {
+ Self {
+ base_path: base_path.join("content"),
+ default_lang: default_lang.to_string(),
+ supported_languages,
+ library,
+ }
}
}
impl TeraFn for GetSection {
@@ -119,19 +193,32 @@ impl TeraFn for GetSection {
.get("metadata_only")
.map_or(false, |c| from_value::(c.clone()).unwrap_or(false));
- let full_path = self.base_path.join(&path);
- let library = self.library.read().unwrap();
-
- match library.sections.get(&full_path) {
- Some(s) => {
- if metadata_only {
- Ok(to_value(s.serialize_basic(&library)).unwrap())
- } else {
- Ok(to_value(s.serialize(&library)).unwrap())
+ let lang =
+ optional_arg!(String, args.get("lang"), "`get_section`: `lang` must be a string");
+
+ get_path_with_lang(&path, &lang, self.default_lang.as_str(), &self.supported_languages)
+ .and_then(|path_with_lang| {
+ let full_path = self.base_path.join(path_with_lang.as_ref());
+ let library = self.library.read().unwrap();
+
+ match library.sections.get(&full_path) {
+ Some(s) => {
+ if metadata_only {
+ Ok(to_value(s.serialize_basic(&library)).unwrap())
+ } else {
+ Ok(to_value(s.serialize(&library)).unwrap())
+ }
+ }
+ None => match lang {
+ Some(lang_code) => Err(format!(
+ "Section `{}` not found for language `{}`.",
+ path, lang_code
+ )
+ .into()),
+ None => Err(format!("Section `{}` not found.", path).into()),
+ },
}
- }
- None => Err(format!("Section `{}` not found.", path).into()),
- }
+ })
}
}
@@ -273,7 +360,148 @@ impl TeraFn for GetTaxonomyTerm {
mod tests {
use super::*;
use config::{Config, TaxonomyConfig};
- use content::TaxonomyTerm;
+ use content::{FileInfo, Library, Page, Section, SortBy, TaxonomyTerm};
+ use std::path::Path;
+ use std::sync::{Arc, RwLock};
+
+ fn create_page(title: &str, file_path: &str, lang: &str) -> Page {
+ let mut page = Page { lang: lang.to_owned(), ..Page::default() };
+ page.file = FileInfo::new_page(
+ Path::new(format!("/test/base/path/{}", file_path).as_str()),
+ &PathBuf::new(),
+ );
+ page.meta.title = Some(title.to_string());
+ page.meta.weight = Some(1);
+ page.file.find_language("en", &["fr"]).unwrap();
+ page
+ }
+
+ #[test]
+ fn can_get_page() {
+ let mut library = Library::default();
+ let pages = vec![
+ ("Homepage", "content/homepage.md", "en"),
+ ("Page D'Accueil", "content/homepage.fr.md", "fr"),
+ ("Blog", "content/blog.md", "en"),
+ ("Wiki", "content/wiki.md", "en"),
+ ("Wiki", "content/wiki.fr.md", "fr"),
+ ("Recipes", "content/wiki/recipes.md", "en"),
+ ("Recettes", "content/wiki/recipes.fr.md", "fr"),
+ ("Programming", "content/wiki/programming.md", "en"),
+ ("La Programmation", "content/wiki/programming.fr.md", "fr"),
+ ("Novels", "content/novels.md", "en"),
+ ("Des Romans", "content/novels.fr.md", "fr"),
+ ];
+ for (t, f, l) in pages.clone() {
+ library.insert_page(create_page(t, f, l));
+ }
+ let base_path = "/test/base/path".into();
+ let lang_list = vec!["en".to_string(), "fr".to_string()];
+
+ let static_fn =
+ GetPage::new(base_path, "en", Arc::new(lang_list), Arc::new(RwLock::new(library)));
+
+ // Find with lang argument
+ let mut args = HashMap::new();
+ args.insert("path".to_string(), to_value("wiki/recipes.md").unwrap());
+ args.insert("lang".to_string(), to_value("fr").unwrap());
+ let res = static_fn.call(&args).unwrap();
+ let res_obj = res.as_object().unwrap();
+ assert_eq!(res_obj["title"], to_value("Recettes").unwrap());
+
+ // Find with lang in path for legacy support
+ args = HashMap::new();
+ args.insert("path".to_string(), to_value("wiki/recipes.fr.md").unwrap());
+ let res = static_fn.call(&args).unwrap();
+ let res_obj = res.as_object().unwrap();
+ assert_eq!(res_obj["title"], to_value("Recettes").unwrap());
+
+ // Find with default lang
+ args = HashMap::new();
+ args.insert("path".to_string(), to_value("wiki/recipes.md").unwrap());
+ let res = static_fn.call(&args).unwrap();
+ let res_obj = res.as_object().unwrap();
+ assert_eq!(res_obj["title"], to_value("Recipes").unwrap());
+
+ // Find with default lang when default lang passed
+ args = HashMap::new();
+ args.insert("path".to_string(), to_value("wiki/recipes.md").unwrap());
+ args.insert("lang".to_string(), to_value("en").unwrap());
+ let res = static_fn.call(&args).unwrap();
+ let res_obj = res.as_object().unwrap();
+ assert_eq!(res_obj["title"], to_value("Recipes").unwrap());
+ }
+
+ fn create_section(title: &str, file_path: &str, lang: &str) -> Section {
+ let mut section = Section { lang: lang.to_owned(), ..Section::default() };
+ section.file = FileInfo::new_section(
+ Path::new(format!("/test/base/path/{}", file_path).as_str()),
+ &PathBuf::new(),
+ );
+ section.meta.title = Some(title.to_string());
+ section.meta.weight = 1;
+ section.meta.transparent = false;
+ section.meta.sort_by = SortBy::None;
+ section.meta.page_template = Some("new_page.html".to_owned());
+ section.file.find_language("en", &["fr"]).unwrap();
+ section
+ }
+
+ #[test]
+ fn can_get_section() {
+ let mut library = Library::default();
+ let sections = vec![
+ ("Homepage", "content/_index.md", "en"),
+ ("Page D'Accueil", "content/_index.fr.md", "fr"),
+ ("Blog", "content/blog/_index.md", "en"),
+ ("Wiki", "content/wiki/_index.md", "en"),
+ ("Wiki", "content/wiki/_index.fr.md", "fr"),
+ ("Recipes", "content/wiki/recipes/_index.md", "en"),
+ ("Recettes", "content/wiki/recipes/_index.fr.md", "fr"),
+ ("Programming", "content/wiki/programming/_index.md", "en"),
+ ("La Programmation", "content/wiki/programming/_index.fr.md", "fr"),
+ ("Novels", "content/novels/_index.md", "en"),
+ ("Des Romans", "content/novels/_index.fr.md", "fr"),
+ ];
+ for (t, f, l) in sections.clone() {
+ library.insert_section(create_section(t, f, l));
+ }
+ let base_path = "/test/base/path".into();
+ let lang_list = vec!["en".to_string(), "fr".to_string()];
+
+ let static_fn =
+ GetSection::new(base_path, "en", Arc::new(lang_list), Arc::new(RwLock::new(library)));
+
+ // Find with lang argument
+ let mut args = HashMap::new();
+ args.insert("path".to_string(), to_value("wiki/recipes/_index.md").unwrap());
+ args.insert("lang".to_string(), to_value("fr").unwrap());
+ let res = static_fn.call(&args).unwrap();
+ let res_obj = res.as_object().unwrap();
+ assert_eq!(res_obj["title"], to_value("Recettes").unwrap());
+
+ // Find with lang in path for legacy support
+ args = HashMap::new();
+ args.insert("path".to_string(), to_value("wiki/recipes/_index.fr.md").unwrap());
+ let res = static_fn.call(&args).unwrap();
+ let res_obj = res.as_object().unwrap();
+ assert_eq!(res_obj["title"], to_value("Recettes").unwrap());
+
+ // Find with default lang
+ args = HashMap::new();
+ args.insert("path".to_string(), to_value("wiki/recipes/_index.md").unwrap());
+ let res = static_fn.call(&args).unwrap();
+ let res_obj = res.as_object().unwrap();
+ assert_eq!(res_obj["title"], to_value("Recipes").unwrap());
+
+ // Find with default lang when default lang passed
+ args = HashMap::new();
+ args.insert("path".to_string(), to_value("wiki/recipes/_index.md").unwrap());
+ args.insert("lang".to_string(), to_value("en").unwrap());
+ let res = static_fn.call(&args).unwrap();
+ let res_obj = res.as_object().unwrap();
+ assert_eq!(res_obj["title"], to_value("Recipes").unwrap());
+ }
#[test]
fn can_get_taxonomy() {
diff --git a/docs/content/documentation/templates/overview.md b/docs/content/documentation/templates/overview.md
index b5f1a50947..c94cf86b93 100644
--- a/docs/content/documentation/templates/overview.md
+++ b/docs/content/documentation/templates/overview.md
@@ -141,6 +141,18 @@ Takes a path to an `.md` file and returns the associated page. The base path is
{% set page = get_page(path="blog/page2.md") %}
```
+If selecting a specific language for the page, you can pass `lang` with the language code to the function:
+
+```jinja2
+{% set page = get_page(path="blog/page2.md", lang="fr") %}
+
+{# If "fr" is the default language, this is equivalent to #}
+{% set page = get_page(path="blog/page2.md") %}
+
+{# If "fr" is not the default language, this is equivalent to #}
+{% set page = get_page(path="blog/page2.fr.md") %}
+```
+
### `get_section`
Takes a path to an `_index.md` file and returns the associated section. The base path is the `content` directory.
@@ -154,6 +166,18 @@ If you only need the metadata of the section, you can pass `metadata_only=true`
{% set section = get_section(path="blog/_index.md", metadata_only=true) %}
```
+If selecting a specific language for the section, you can pass `lang` with the language code to the function:
+
+```jinja2
+{% set section = get_section(path="blog/_index.md", lang="fr") %}
+
+{# If "fr" is the default language, this is equivalent to #}
+{% set section = get_section(path="blog/_index.md") %}
+
+{# If "fr" is not the default language, this is equivalent to #}
+{% set section = get_section(path="blog/_index.fr.md") %}
+```
+
### `get_taxonomy_url`
Gets the permalink for the taxonomy item found.
From 42fc576388c5cc2d460de54ca6838d927272c5fe Mon Sep 17 00:00:00 2001
From: Timon Van Overveldt
Date: Sun, 18 Feb 2024 12:57:17 -0800
Subject: [PATCH 10/25] Update pulldown_cmark dep to v0.10, and add
pulldown_cmark_escape dep. (#2432)
The pulldown_cmark escaping functionality is now shipped in a separate
pulldown_cmark_escape crate
(https://crates.io/crates/pulldown-cmark-escape), starting with v0.10.0.
The markdown.rs module has to be adapted to a few API changes in
pulldown_cmark, and we have to introduce explicit handling of
alt
text to ensure it continues to be properly escaped.
There are also a few other behavior changes that are caught by the
tests, but these actually seem to be desired, so I've updated the insta
snapshot files for those tests to incorporate those changes.
Specifically, one footnote-parsing case seems to be handled better now,
and pulldown-cmark's `push_html` now doesn't escape quotes in text nodes
anymore (see https://github.com/pulldown-cmark/pulldown-cmark/pull/836).
---
CHANGELOG.md | 1 +
Cargo.lock | 23 ++++-
components/libs/Cargo.toml | 3 +-
components/libs/src/lib.rs | 1 +
components/markdown/src/markdown.rs | 88 +++++++++++++------
...wn__all_markdown_features_integration.snap | 6 +-
.../markdown__can_handle_heading_ids-2.snap | 8 +-
.../markdown__can_handle_heading_ids.snap | 6 +-
...des__doesnt_render_ignored_shortcodes.snap | 6 +-
9 files changed, 94 insertions(+), 48 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44bd027a19..7edc406a2e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
## 0.19.0 (unreleased)
+- Updates the pulldown-cmark dependency to v0.10.0. This improves footnote handling, and may also introduce some minor behavior changes such as reducing the amount of unnecessary HTML-escaping of text content.
## 0.18.0 (2023-12-18)
diff --git a/Cargo.lock b/Cargo.lock
index 26050e06e7..0d90eea7c0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1736,7 +1736,8 @@ dependencies = [
"num-format",
"once_cell",
"percent-encoding",
- "pulldown-cmark",
+ "pulldown-cmark 0.10.0",
+ "pulldown-cmark-escape",
"quickxml_to_serde",
"rayon",
"regex",
@@ -2775,6 +2776,24 @@ dependencies = [
"unicase",
]
+[[package]]
+name = "pulldown-cmark"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dce76ce678ffc8e5675b22aa1405de0b7037e2fdf8913fea40d1926c6fe1e6e7"
+dependencies = [
+ "bitflags 2.4.1",
+ "memchr",
+ "pulldown-cmark-escape",
+ "unicase",
+]
+
+[[package]]
+name = "pulldown-cmark-escape"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5d8f9aa0e3cbcfaf8bf00300004ee3b72f74770f9cbac93f6928771f613276b"
+
[[package]]
name = "pure-rust-locales"
version = "0.7.0"
@@ -3341,7 +3360,7 @@ dependencies = [
"cargo_metadata",
"error-chain",
"glob",
- "pulldown-cmark",
+ "pulldown-cmark 0.9.3",
"tempfile",
"walkdir",
]
diff --git a/components/libs/Cargo.toml b/components/libs/Cargo.toml
index 5f551ea663..9f6abf1d58 100644
--- a/components/libs/Cargo.toml
+++ b/components/libs/Cargo.toml
@@ -21,7 +21,8 @@ nom-bibtex = "0.5"
num-format = "0.4"
once_cell = "1"
percent-encoding = "2"
-pulldown-cmark = { version = "0.9", default-features = false, features = ["simd"] }
+pulldown-cmark = { version = "0.10", default-features = false, features = ["html", "simd"] }
+pulldown-cmark-escape = { version = "0.10", default-features = false }
quickxml_to_serde = "0.5"
rayon = "1"
regex = "1"
diff --git a/components/libs/src/lib.rs b/components/libs/src/lib.rs
index d0772dc0a4..3992c2ed29 100644
--- a/components/libs/src/lib.rs
+++ b/components/libs/src/lib.rs
@@ -23,6 +23,7 @@ pub use num_format;
pub use once_cell;
pub use percent_encoding;
pub use pulldown_cmark;
+pub use pulldown_cmark_escape;
pub use quickxml_to_serde;
pub use rayon;
pub use regex;
diff --git a/components/markdown/src/markdown.rs b/components/markdown/src/markdown.rs
index 4d30b2ac92..40c94afac5 100644
--- a/components/markdown/src/markdown.rs
+++ b/components/markdown/src/markdown.rs
@@ -4,19 +4,20 @@ use errors::bail;
use libs::gh_emoji::Replacer as EmojiReplacer;
use libs::once_cell::sync::Lazy;
use libs::pulldown_cmark as cmark;
+use libs::pulldown_cmark_escape as cmark_escape;
use libs::tera;
use utils::net::is_external_link;
use crate::context::RenderContext;
use errors::{Context, Error, Result};
-use libs::pulldown_cmark::escape::escape_html;
+use libs::pulldown_cmark_escape::escape_html;
use libs::regex::{Regex, RegexBuilder};
use utils::site::resolve_internal_link;
use utils::slugs::slugify_anchors;
use utils::table_of_contents::{make_table_of_contents, Heading};
use utils::types::InsertAnchor;
-use self::cmark::{Event, LinkType, Options, Parser, Tag};
+use self::cmark::{Event, LinkType, Options, Parser, Tag, TagEnd};
use crate::codeblock::{CodeBlock, FenceSettings};
use crate::shortcode::{Shortcode, SHORTCODE_PLACEHOLDER};
@@ -220,15 +221,15 @@ fn get_heading_refs(events: &[Event]) -> Vec {
for (i, event) in events.iter().enumerate() {
match event {
- Event::Start(Tag::Heading(level, anchor, classes)) => {
+ Event::Start(Tag::Heading { level, id, classes, .. }) => {
heading_refs.push(HeadingRef::new(
i,
*level as u32,
- anchor.map(|a| a.to_owned()),
+ id.clone().map(|a| a.to_string()),
&classes.iter().map(|x| x.to_string()).collect::>(),
));
}
- Event::End(Tag::Heading(_, _, _)) => {
+ Event::End(TagEnd::Heading { .. }) => {
heading_refs.last_mut().expect("Heading end before start?").end_idx = i;
}
_ => (),
@@ -254,6 +255,10 @@ pub fn markdown_to_html(
let mut error = None;
let mut code_block: Option = None;
+ // Indicates whether we're in the middle of parsing a text node which will be placed in an HTML
+ // attribute, and which hence has to be escaped using escape_html rather than push_html's
+ // default HTML body escaping for text nodes.
+ let mut inside_attribute = false;
let mut headings: Vec = vec![];
let mut internal_links = Vec::new();
@@ -294,12 +299,19 @@ pub fn markdown_to_html(
// we have some text before the shortcode, push that first
if $range.start != sc_span.start {
- let content = $text[($range.start - orig_range_start)
- ..(sc_span.start - orig_range_start)]
- .to_string()
- .into();
+ let content: cmark::CowStr<'_> =
+ $text[($range.start - orig_range_start)
+ ..(sc_span.start - orig_range_start)]
+ .to_string()
+ .into();
events.push(if $is_text {
- Event::Text(content)
+ if inside_attribute {
+ let mut buffer = "".to_string();
+ escape_html(&mut buffer, content.as_ref()).unwrap();
+ Event::Html(buffer.into())
+ } else {
+ Event::Text(content)
+ }
} else {
Event::Html(content)
});
@@ -370,7 +382,13 @@ pub fn markdown_to_html(
};
if !contains_shortcode(text.as_ref()) {
- events.push(Event::Text(text));
+ if inside_attribute {
+ let mut buffer = "".to_string();
+ escape_html(&mut buffer, text.as_ref()).unwrap();
+ events.push(Event::Html(buffer.into()));
+ } else {
+ events.push(Event::Text(text));
+ }
continue;
}
@@ -386,7 +404,7 @@ pub fn markdown_to_html(
code_block = Some(block);
events.push(Event::Html(begin.into()));
}
- Event::End(Tag::CodeBlock(_)) => {
+ Event::End(TagEnd::CodeBlock { .. }) => {
if let Some(ref mut code_block) = code_block {
let html = code_block.highlight(&accumulated_block);
events.push(Event::Html(html.into()));
@@ -397,44 +415,53 @@ pub fn markdown_to_html(
code_block = None;
events.push(Event::Html("\n".into()));
}
- Event::Start(Tag::Image(link_type, src, title)) => {
- let link = if is_colocated_asset_link(&src) {
- let link = format!("{}{}", context.current_page_permalink, &*src);
+ Event::Start(Tag::Image { link_type, dest_url, title, id }) => {
+ let link = if is_colocated_asset_link(&dest_url) {
+ let link = format!("{}{}", context.current_page_permalink, &*dest_url);
link.into()
} else {
- src
+ dest_url
};
events.push(if lazy_async_image {
let mut img_before_alt: String = "
events.push(if lazy_async_image {
+ Event::End(TagEnd::Image) => events.push(if lazy_async_image {
Event::Html("\" loading=\"lazy\" decoding=\"async\" />".into())
} else {
event
}),
- Event::Start(Tag::Link(link_type, link, title)) if link.is_empty() => {
+ Event::Start(Tag::Link { link_type, dest_url, title, id })
+ if dest_url.is_empty() =>
+ {
error = Some(Error::msg("There is a link that is missing a URL"));
- events.push(Event::Start(Tag::Link(link_type, "#".into(), title)));
+ events.push(Event::Start(Tag::Link {
+ link_type,
+ dest_url: "#".into(),
+ title,
+ id,
+ }));
}
- Event::Start(Tag::Link(link_type, link, title)) => {
+ Event::Start(Tag::Link { link_type, dest_url, title, id }) => {
let fixed_link = match fix_link(
link_type,
- &link,
+ &dest_url,
context,
&mut internal_links,
&mut external_links,
@@ -448,12 +475,12 @@ pub fn markdown_to_html(
};
events.push(
- if is_external_link(&link)
+ if is_external_link(&dest_url)
&& context.config.markdown.has_external_link_tweaks()
{
let mut escaped = String::new();
// write_str can fail but here there are no reasons it should (afaik?)
- cmark::escape::escape_href(&mut escaped, &link)
+ cmark_escape::escape_href(&mut escaped, &dest_url)
.expect("Could not write to buffer");
Event::Html(
context
@@ -463,7 +490,12 @@ pub fn markdown_to_html(
.into(),
)
} else {
- Event::Start(Tag::Link(link_type, fixed_link.into(), title))
+ Event::Start(Tag::Link {
+ link_type,
+ dest_url: fixed_link.into(),
+ title,
+ id,
+ })
},
)
}
@@ -485,7 +517,7 @@ pub fn markdown_to_html(
events.push(event);
}
- Event::End(Tag::Paragraph) => {
+ Event::End(TagEnd::Paragraph) => {
events.push(if stop_next_end_p {
stop_next_end_p = false;
Event::Html("".into())
diff --git a/components/markdown/tests/snapshots/markdown__all_markdown_features_integration.snap b/components/markdown/tests/snapshots/markdown__all_markdown_features_integration.snap
index 72aedc4c21..9e95d41805 100644
--- a/components/markdown/tests/snapshots/markdown__all_markdown_features_integration.snap
+++ b/components/markdown/tests/snapshots/markdown__all_markdown_features_integration.snap
@@ -1,8 +1,6 @@
---
-source: components/rendering/tests/markdown.rs
-assertion_line: 358
+source: components/markdown/tests/markdown.rs
expression: body
-
---
h1 Heading
@@ -83,7 +81,7 @@ line 1 of code
line 2 of code
line 3 of code
-Block code "fences"
+Block code "fences"
Sample text here...
Syntax highlighting
diff --git a/components/markdown/tests/snapshots/markdown__can_handle_heading_ids-2.snap b/components/markdown/tests/snapshots/markdown__can_handle_heading_ids-2.snap
index d2847a8e94..e9fabcc4fa 100644
--- a/components/markdown/tests/snapshots/markdown__can_handle_heading_ids-2.snap
+++ b/components/markdown/tests/snapshots/markdown__can_handle_heading_ids-2.snap
@@ -1,12 +1,10 @@
---
-source: components/rendering/tests/markdown.rs
-assertion_line: 84
+source: components/markdown/tests/markdown.rs
expression: body
-
---
Hello
Hello
-L'écologie et vous
+L'écologie et vous
Hello
Hello
Hello
@@ -22,6 +20,6 @@ expression: body
text there
+Classes
diff --git a/components/markdown/tests/snapshots/markdown__can_handle_heading_ids.snap b/components/markdown/tests/snapshots/markdown__can_handle_heading_ids.snap
index 87cce483ae..663be5947f 100644
--- a/components/markdown/tests/snapshots/markdown__can_handle_heading_ids.snap
+++ b/components/markdown/tests/snapshots/markdown__can_handle_heading_ids.snap
@@ -1,8 +1,6 @@
---
-source: components/rendering/tests/markdown.rs
-assertion_line: 79
+source: components/markdown/tests/markdown.rs
expression: body
-
---
Hello
Hello
@@ -22,6 +20,6 @@ expression: body
text there
+Classes
diff --git a/components/markdown/tests/snapshots/shortcodes__doesnt_render_ignored_shortcodes.snap b/components/markdown/tests/snapshots/shortcodes__doesnt_render_ignored_shortcodes.snap
index 64d9bfbabe..15c94e4678 100644
--- a/components/markdown/tests/snapshots/shortcodes__doesnt_render_ignored_shortcodes.snap
+++ b/components/markdown/tests/snapshots/shortcodes__doesnt_render_ignored_shortcodes.snap
@@ -1,8 +1,6 @@
---
-source: components/rendering/tests/shortcodes.rs
-assertion_line: 104
+source: components/markdown/tests/shortcodes.rs
expression: body
-
---
-{{ youtube(id="w7Ft2ymGmfc") }}
+{{ youtube(id="w7Ft2ymGmfc") }}
From 472b1f574c662ae3d9a890f5ece0b53e30380cdb Mon Sep 17 00:00:00 2001
From: Clar Fon <15850505+clarfonthey@users.noreply.github.com>
Date: Thu, 29 Feb 2024 07:46:29 -0500
Subject: [PATCH 11/25] Add MIME type to get_image_metadata (#2409)
---
components/imageproc/src/meta.rs | 4 +++-
components/imageproc/tests/resize_image.rs | 23 +++++++++++++++----
components/templates/src/global_fns/images.rs | 8 +++++++
.../documentation/templates/overview.md | 2 +-
4 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/components/imageproc/src/meta.rs b/components/imageproc/src/meta.rs
index a619e97d28..8ee83c335f 100644
--- a/components/imageproc/src/meta.rs
+++ b/components/imageproc/src/meta.rs
@@ -37,11 +37,12 @@ pub struct ImageMetaResponse {
pub width: u32,
pub height: u32,
pub format: Option<&'static str>,
+ pub mime: Option<&'static str>,
}
impl ImageMetaResponse {
pub fn new_svg(width: u32, height: u32) -> Self {
- Self { width, height, format: Some("svg") }
+ Self { width, height, format: Some("svg"), mime: Some("text/svg+xml") }
}
}
@@ -51,6 +52,7 @@ impl From for ImageMetaResponse {
width: im.size.0,
height: im.size.1,
format: im.format.and_then(|f| f.extensions_str().first()).copied(),
+ mime: im.format.map(|f| f.to_mime_type()),
}
}
}
diff --git a/components/imageproc/tests/resize_image.rs b/components/imageproc/tests/resize_image.rs
index 7715687f8e..c52ff9321e 100644
--- a/components/imageproc/tests/resize_image.rs
+++ b/components/imageproc/tests/resize_image.rs
@@ -136,7 +136,12 @@ fn resize_image_webp_jpg() {
fn read_image_metadata_jpg() {
assert_eq!(
image_meta_test("jpg.jpg"),
- ImageMetaResponse { width: 300, height: 380, format: Some("jpg") }
+ ImageMetaResponse {
+ width: 300,
+ height: 380,
+ format: Some("jpg"),
+ mime: Some("image/jpeg")
+ }
);
}
@@ -144,7 +149,7 @@ fn read_image_metadata_jpg() {
fn read_image_metadata_png() {
assert_eq!(
image_meta_test("png.png"),
- ImageMetaResponse { width: 300, height: 380, format: Some("png") }
+ ImageMetaResponse { width: 300, height: 380, format: Some("png"), mime: Some("image/png") }
);
}
@@ -152,7 +157,12 @@ fn read_image_metadata_png() {
fn read_image_metadata_svg() {
assert_eq!(
image_meta_test("svg.svg"),
- ImageMetaResponse { width: 300, height: 300, format: Some("svg") }
+ ImageMetaResponse {
+ width: 300,
+ height: 300,
+ format: Some("svg"),
+ mime: Some("text/svg+xml")
+ }
);
}
@@ -160,7 +170,12 @@ fn read_image_metadata_svg() {
fn read_image_metadata_webp() {
assert_eq!(
image_meta_test("webp.webp"),
- ImageMetaResponse { width: 300, height: 380, format: Some("webp") }
+ ImageMetaResponse {
+ width: 300,
+ height: 380,
+ format: Some("webp"),
+ mime: Some("image/webp")
+ }
);
}
diff --git a/components/templates/src/global_fns/images.rs b/components/templates/src/global_fns/images.rs
index 641e26391c..2ac74b0ebb 100644
--- a/components/templates/src/global_fns/images.rs
+++ b/components/templates/src/global_fns/images.rs
@@ -269,6 +269,8 @@ mod tests {
let data = static_fn.call(&args).unwrap().as_object().unwrap().clone();
assert_eq!(data["height"], to_value(380).unwrap());
assert_eq!(data["width"], to_value(300).unwrap());
+ assert_eq!(data["format"], to_value("jpg").unwrap());
+ assert_eq!(data["mime"], to_value("image/jpeg").unwrap());
// 2. a call to something in `static` with an absolute path is handled currently the same as the above
let mut args = HashMap::new();
@@ -276,6 +278,8 @@ mod tests {
let data = static_fn.call(&args).unwrap().as_object().unwrap().clone();
assert_eq!(data["height"], to_value(380).unwrap());
assert_eq!(data["width"], to_value(300).unwrap());
+ assert_eq!(data["format"], to_value("jpg").unwrap());
+ assert_eq!(data["mime"], to_value("image/jpeg").unwrap());
// 3. a call to something in `content` with a relative path
let mut args = HashMap::new();
@@ -283,6 +287,8 @@ mod tests {
let data = static_fn.call(&args).unwrap().as_object().unwrap().clone();
assert_eq!(data["height"], to_value(380).unwrap());
assert_eq!(data["width"], to_value(300).unwrap());
+ assert_eq!(data["format"], to_value("jpg").unwrap());
+ assert_eq!(data["mime"], to_value("image/jpeg").unwrap());
// 4. a call to something in `content` with a @/ path corresponds to
let mut args = HashMap::new();
@@ -290,5 +296,7 @@ mod tests {
let data = static_fn.call(&args).unwrap().as_object().unwrap().clone();
assert_eq!(data["height"], to_value(380).unwrap());
assert_eq!(data["width"], to_value(300).unwrap());
+ assert_eq!(data["format"], to_value("jpg").unwrap());
+ assert_eq!(data["mime"], to_value("image/jpeg").unwrap());
}
}
diff --git a/docs/content/documentation/templates/overview.md b/docs/content/documentation/templates/overview.md
index c94cf86b93..49a7d1f886 100644
--- a/docs/content/documentation/templates/overview.md
+++ b/docs/content/documentation/templates/overview.md
@@ -305,7 +305,7 @@ It can take the following arguments:
- `path`: mandatory, see [File Searching Logic](@/documentation/templates/overview.md#file-searching-logic) for details
- `allow_missing`: optional, `true` or `false`, defaults to `false`. Whether a missing file should raise an error or not.
-The method returns a map containing `width`, `height` and `format` (the lowercased value as string).
+The method returns a map containing `width`, `height`, `format`, and `mime`. The `format` returned is the most common file extension for the file format, which may not match the one used for the image.
```jinja2
{% set meta = get_image_metadata(path="...") %}
From 4bf67afd875b99d2bad6fe252d6fb6e44f52b313 Mon Sep 17 00:00:00 2001
From: James Williams
Date: Fri, 1 Mar 2024 02:17:45 -0800
Subject: [PATCH 12/25] Fix --base-url improper path and protocol handling
using `zola serve` (#2311)
* Fix --base-url improper path and protocol handling.
* Fix formatting.
---
src/cmd/serve.rs | 140 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 113 insertions(+), 27 deletions(-)
diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs
index d13b945942..27c9b057bb 100644
--- a/src/cmd/serve.rs
+++ b/src/cmd/serve.rs
@@ -92,16 +92,34 @@ fn set_serve_error(msg: &'static str, e: errors::Error) {
}
}
-async fn handle_request(req: Request, mut root: PathBuf) -> Result> {
+async fn handle_request(
+ req: Request,
+ mut root: PathBuf,
+ base_path: String,
+) -> Result> {
+ let path_str = req.uri().path();
+ if !path_str.starts_with(&base_path) {
+ return Ok(not_found());
+ }
+
+ let trimmed_path = &path_str[base_path.len() - 1..];
+
let original_root = root.clone();
let mut path = RelativePathBuf::new();
// https://zola.discourse.group/t/percent-encoding-for-slugs/736
- let decoded = match percent_encoding::percent_decode_str(req.uri().path()).decode_utf8() {
+ let decoded = match percent_encoding::percent_decode_str(trimmed_path).decode_utf8() {
Ok(d) => d,
Err(_) => return Ok(not_found()),
};
- for c in decoded.split('/') {
+ let decoded_path = if base_path != "/" && decoded.starts_with(&base_path) {
+ // Remove the base_path from the request path before processing
+ decoded[base_path.len()..].to_string()
+ } else {
+ decoded.to_string()
+ };
+
+ for c in decoded_path.split('/') {
path.push(c);
}
@@ -318,6 +336,39 @@ fn rebuild_done_handling(broadcaster: &Sender, res: Result<()>, reload_path: &st
}
}
+fn construct_url(base_url: &str, no_port_append: bool, interface_port: u16) -> String {
+ if base_url == "/" {
+ return String::from("/");
+ }
+
+ let (protocol, stripped_url) = match base_url {
+ url if url.starts_with("http://") => ("http://", &url[7..]),
+ url if url.starts_with("https://") => ("https://", &url[8..]),
+ url => ("http://", url),
+ };
+
+ let (domain, path) = {
+ let parts: Vec<&str> = stripped_url.splitn(2, '/').collect();
+ if parts.len() > 1 {
+ (parts[0], format!("/{}", parts[1]))
+ } else {
+ (parts[0], String::new())
+ }
+ };
+
+ let full_address = if no_port_append {
+ format!("{}{}{}", protocol, domain, path)
+ } else {
+ format!("{}{}:{}{}", protocol, domain, interface_port, path)
+ };
+
+ if full_address.ends_with('/') {
+ full_address
+ } else {
+ format!("{}/", full_address)
+ }
+}
+
#[allow(clippy::too_many_arguments)]
fn create_new_site(
root_dir: &Path,
@@ -330,7 +381,7 @@ fn create_new_site(
include_drafts: bool,
mut no_port_append: bool,
ws_port: Option,
-) -> Result<(Site, SocketAddr)> {
+) -> Result<(Site, SocketAddr, String)> {
SITE_CONTENT.write().unwrap().clear();
let mut site = Site::new(root_dir, config_file)?;
@@ -345,24 +396,10 @@ fn create_new_site(
|u| u.to_string(),
);
- let base_url = if base_url == "/" {
- String::from("/")
- } else {
- let base_address = if no_port_append {
- base_url.to_string()
- } else {
- format!("{}:{}", base_url, interface_port)
- };
-
- if site.config.base_url.ends_with('/') {
- format!("http://{}/", base_address)
- } else {
- format!("http://{}", base_address)
- }
- };
+ let constructed_base_url = construct_url(&base_url, no_port_append, interface_port);
site.enable_serve_mode();
- site.set_base_url(base_url);
+ site.set_base_url(constructed_base_url.clone());
if let Some(output_dir) = output_dir {
if !force && output_dir.exists() {
return Err(Error::msg(format!(
@@ -384,7 +421,7 @@ fn create_new_site(
messages::notify_site_size(&site);
messages::warn_about_ignored_pages(&site);
site.build()?;
- Ok((site, address))
+ Ok((site, address, constructed_base_url))
}
#[allow(clippy::too_many_arguments)]
@@ -403,7 +440,7 @@ pub fn serve(
utc_offset: UtcOffset,
) -> Result<()> {
let start = Instant::now();
- let (mut site, bind_address) = create_new_site(
+ let (mut site, bind_address, constructed_base_url) = create_new_site(
root_dir,
interface,
interface_port,
@@ -415,6 +452,11 @@ pub fn serve(
no_port_append,
None,
)?;
+ let base_path = match constructed_base_url.splitn(4, '/').nth(3) {
+ Some(path) => format!("/{}", path),
+ None => "/".to_string(),
+ };
+
messages::report_elapsed_time(start);
// Stop right there if we can't bind to the address
@@ -479,19 +521,27 @@ pub fn serve(
rt.block_on(async {
let make_service = make_service_fn(move |_| {
let static_root = static_root.clone();
+ let base_path = base_path.clone();
async {
Ok::<_, hyper::Error>(service_fn(move |req| {
- response_error_injector(handle_request(req, static_root.clone()))
+ response_error_injector(handle_request(
+ req,
+ static_root.clone(),
+ base_path.clone(),
+ ))
}))
}
});
let server = Server::bind(&bind_address).serve(make_service);
- println!("Web server is available at http://{}\n", bind_address);
+ println!(
+ "Web server is available at {} (bound to {})\n",
+ &constructed_base_url, &bind_address
+ );
if open {
- if let Err(err) = open::that(format!("http://{}", bind_address)) {
+ if let Err(err) = open::that(format!("{}", &constructed_base_url)) {
eprintln!("Failed to open URL in your browser: {}", err);
}
}
@@ -618,7 +668,7 @@ pub fn serve(
no_port_append,
ws_port,
) {
- Ok((s, _)) => {
+ Ok((s, _, _)) => {
clear_serve_error();
rebuild_done_handling(&broadcaster, Ok(()), "/x.js");
@@ -801,7 +851,7 @@ fn is_folder_empty(dir: &Path) -> bool {
mod tests {
use std::path::{Path, PathBuf};
- use super::{detect_change_kind, is_temp_file, ChangeKind};
+ use super::{construct_url, detect_change_kind, is_temp_file, ChangeKind};
#[test]
fn can_recognize_temp_files() {
@@ -893,4 +943,40 @@ mod tests {
let config_filename = Path::new("config.toml");
assert_eq!(expected, detect_change_kind(pwd, path, config_filename));
}
+
+ #[test]
+ fn test_construct_url_base_url_is_slash() {
+ let result = construct_url("/", false, 8080);
+ assert_eq!(result, "/");
+ }
+
+ #[test]
+ fn test_construct_url_http_protocol() {
+ let result = construct_url("http://example.com", false, 8080);
+ assert_eq!(result, "http://example.com:8080/");
+ }
+
+ #[test]
+ fn test_construct_url_https_protocol() {
+ let result = construct_url("https://example.com", false, 8080);
+ assert_eq!(result, "https://example.com:8080/");
+ }
+
+ #[test]
+ fn test_construct_url_no_protocol() {
+ let result = construct_url("example.com", false, 8080);
+ assert_eq!(result, "http://example.com:8080/");
+ }
+
+ #[test]
+ fn test_construct_url_no_port_append() {
+ let result = construct_url("https://example.com", true, 8080);
+ assert_eq!(result, "https://example.com/");
+ }
+
+ #[test]
+ fn test_construct_url_trailing_slash() {
+ let result = construct_url("http://example.com/", false, 8080);
+ assert_eq!(result, "http://example.com:8080/");
+ }
}
From 7a12e622bec6f021d33c70ca55b2f42e7105429a Mon Sep 17 00:00:00 2001
From: William Ouwehand
Date: Thu, 21 Mar 2024 23:23:22 +0100
Subject: [PATCH 13/25] Fix section transparency serialization (#2462)
Fixes passing section.transparency for
https://github.com/getzola/zola/issues/1840
---
components/content/src/ser.rs | 2 ++
docs/content/documentation/templates/pages-sections.md | 2 ++
2 files changed, 4 insertions(+)
diff --git a/components/content/src/ser.rs b/components/content/src/ser.rs
index 18e175f11d..607d361dee 100644
--- a/components/content/src/ser.rs
+++ b/components/content/src/ser.rs
@@ -161,6 +161,7 @@ pub struct SerializingSection<'a> {
translations: Vec>,
backlinks: Vec>,
generate_feed: bool,
+ transparent: bool,
}
#[derive(Debug)]
@@ -220,6 +221,7 @@ impl<'a> SerializingSection<'a> {
assets: §ion.serialized_assets,
lang: §ion.lang,
generate_feed: section.meta.generate_feed,
+ transparent: section.meta.transparent,
pages,
subsections,
translations,
diff --git a/docs/content/documentation/templates/pages-sections.md b/docs/content/documentation/templates/pages-sections.md
index 1b1b15ad8b..5d0d466d3e 100644
--- a/docs/content/documentation/templates/pages-sections.md
+++ b/docs/content/documentation/templates/pages-sections.md
@@ -109,6 +109,8 @@ translations: Array;
backlinks: Array<{permalink: String, title: String?}>;
// Whether this section generates a feed or not. Taken from the front-matter if set
generate_feed: bool;
+// Whether this section is transparent. Taken from the front-matter if set
+transparent: bool;
```
## Table of contents
From 866eb0c40541cca4eea0edf033f7a8a1f224ff00 Mon Sep 17 00:00:00 2001
From: Tanishq
Date: Wed, 3 Apr 2024 15:55:49 +0530
Subject: [PATCH 14/25] Fix resizing for images with EXIF orientation (#2468)
* Fix resizing for images with EXIF orientation
* Added test for asymmetric resize for exif images
---------
Co-authored-by: Tanishq
---
components/imageproc/src/processor.rs | 5 ++---
components/imageproc/tests/resize_image.rs | 22 ++++++++++++++++++++++
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/components/imageproc/src/processor.rs b/components/imageproc/src/processor.rs
index 63346663a6..2c6a17b725 100644
--- a/components/imageproc/src/processor.rs
+++ b/components/imageproc/src/processor.rs
@@ -38,7 +38,8 @@ impl ImageOp {
return Ok(());
}
- let mut img = image::open(&self.input_path)?;
+ let img = image::open(&self.input_path)?;
+ let mut img = fix_orientation(&img, &self.input_path).unwrap_or(img);
let img = match self.instr.crop_instruction {
Some((x, y, w, h)) => img.crop(x, y, w, h),
@@ -49,8 +50,6 @@ impl ImageOp {
None => img,
};
- let img = fix_orientation(&img, &self.input_path).unwrap_or(img);
-
let f = File::create(&self.output_path)?;
let mut buffered_f = BufWriter::new(f);
diff --git a/components/imageproc/tests/resize_image.rs b/components/imageproc/tests/resize_image.rs
index c52ff9321e..41114abf50 100644
--- a/components/imageproc/tests/resize_image.rs
+++ b/components/imageproc/tests/resize_image.rs
@@ -248,3 +248,25 @@ fn check_img(img: DynamicImage) -> bool {
// bottom right is white
&& img.get_pixel(15, 15).channels() == [255, 255, 255, 255]
}
+
+#[test]
+fn asymmetric_resize_with_exif_orientations() {
+ // No exif metadata
+ image_op_test("exif_0.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+ // 1: Horizontal (normal)
+ image_op_test("exif_1.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+ // 2: Mirror horizontal
+ image_op_test("exif_2.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+ // 3: Rotate 180
+ image_op_test("exif_3.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+ // 4: Mirror vertical
+ image_op_test("exif_4.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+ // 5: Mirror horizontal and rotate 270 CW
+ image_op_test("exif_5.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+ // 6: Rotate 90 CW
+ image_op_test("exif_6.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+ // 7: Mirror horizontal and rotate 90 CW
+ image_op_test("exif_7.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+ // 8: Rotate 270 CW
+ image_op_test("exif_8.jpg", "scale", Some(16), Some(32), "auto", "jpg", 16, 32, 16, 16);
+}
From 7bf429b400266a75eb78025b211aa50a3def7f7a Mon Sep 17 00:00:00 2001
From: Tanishq
Date: Fri, 5 Apr 2024 20:48:30 +0530
Subject: [PATCH 15/25] Fix link check report inconsistency (#2472)
* Fix link check report inconsistency
* Fix formatting issue
---------
Co-authored-by: Tanishq
---
components/site/src/link_checking.rs | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/components/site/src/link_checking.rs b/components/site/src/link_checking.rs
index 1bb1a66941..c7e4678195 100644
--- a/components/site/src/link_checking.rs
+++ b/components/site/src/link_checking.rs
@@ -178,13 +178,15 @@ pub fn check_external_links(site: &Site) -> Vec {
}
}
+ // Get unique links count from Vec by creating a temporary HashSet.
+ let unique_links_count = HashSet::<&str>::from_iter(
+ checked_links.iter().map(|link_def| link_def.external_link.as_str()),
+ )
+ .len();
+
println!(
"Checking {} external link(s). Skipping {} external link(s).{}",
- // Get unique links count from Vec by creating a temporary HashSet.
- HashSet::<&str>::from_iter(
- checked_links.iter().map(|link_def| link_def.external_link.as_str())
- )
- .len(),
+ unique_links_count,
skipped_link_count,
if invalid_url_links == 0 {
"".to_string()
@@ -272,7 +274,7 @@ pub fn check_external_links(site: &Site) -> Vec {
println!(
"> Checked {} external link(s): {} error(s) found.",
- checked_links.len(),
+ unique_links_count,
errors.len()
);
From 20f00bad300b9d19e2ca596632ca20bd46067e2f Mon Sep 17 00:00:00 2001
From: Clar Fon <15850505+clarfonthey@users.noreply.github.com>
Date: Tue, 23 Apr 2024 15:57:30 -0400
Subject: [PATCH 16/25] Refactor: remove even more unnecessary create_directory
(#2428)
---
components/site/src/lib.rs | 42 ++++++++++++--------------------------
components/utils/src/fs.rs | 22 ++++++++++----------
2 files changed, 24 insertions(+), 40 deletions(-)
diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs
index dce82d812f..b906885131 100644
--- a/components/site/src/lib.rs
+++ b/components/site/src/lib.rs
@@ -635,10 +635,7 @@ impl Site {
components: &[&str],
filename: &str,
content: String,
- create_dirs: bool,
) -> Result {
- let write_dirs = self.build_mode == BuildMode::Disk || create_dirs;
-
let mut site_path = RelativePathBuf::new();
let mut current_path = self.output_path.to_path_buf();
@@ -647,10 +644,6 @@ impl Site {
site_path.push(component);
}
- if write_dirs {
- create_directory(¤t_path)?;
- }
-
let final_content = if !filename.ends_with("html") || !self.config.minify_html {
content
} else {
@@ -696,8 +689,7 @@ impl Site {
let output = page.render_html(&self.tera, &self.config, &self.library.read().unwrap())?;
let content = self.inject_livereload(output);
let components: Vec<&str> = page.path.split('/').collect();
- let current_path =
- self.write_content(&components, "index.html", content, !page.assets.is_empty())?;
+ let current_path = self.write_content(&components, "index.html", content)?;
// Copy any asset we found previously into the same directory as the index.html
self.copy_assets(page.file.path.parent().unwrap(), &page.assets, ¤t_path)?;
@@ -849,7 +841,7 @@ impl Site {
None => "index.html",
};
let content = render_redirect_template(permalink, &self.tera)?;
- self.write_content(&split, page_name, content, false)?;
+ self.write_content(&split, page_name, content)?;
Ok(())
}
@@ -877,7 +869,7 @@ impl Site {
context.insert("lang", &self.config.default_language);
let output = render_template("404.html", &self.tera, context, &self.config.theme)?;
let content = self.inject_livereload(output);
- self.write_content(&[], "404.html", content, false)?;
+ self.write_content(&[], "404.html", content)?;
Ok(())
}
@@ -886,7 +878,7 @@ impl Site {
let mut context = Context::new();
context.insert("config", &self.config.serialize(&self.config.default_language));
let content = render_template("robots.txt", &self.tera, context, &self.config.theme)?;
- self.write_content(&[], "robots.txt", content, false)?;
+ self.write_content(&[], "robots.txt", content)?;
Ok(())
}
@@ -917,7 +909,7 @@ impl Site {
let list_output =
taxonomy.render_all_terms(&self.tera, &self.config, &self.library.read().unwrap())?;
let content = self.inject_livereload(list_output);
- self.write_content(&components, "index.html", content, false)?;
+ self.write_content(&components, "index.html", content)?;
let library = self.library.read().unwrap();
taxonomy
@@ -942,7 +934,7 @@ impl Site {
let single_output =
taxonomy.render_term(item, &self.tera, &self.config, &library)?;
let content = self.inject_livereload(single_output);
- self.write_content(&comp, "index.html", content, false)?;
+ self.write_content(&comp, "index.html", content)?;
}
if taxonomy.kind.feed {
@@ -981,7 +973,7 @@ impl Site {
let mut context = Context::new();
context.insert("entries", &all_sitemap_entries);
let sitemap = render_template("sitemap.xml", &self.tera, context, &self.config.theme)?;
- self.write_content(&[], "sitemap.xml", sitemap, false)?;
+ self.write_content(&[], "sitemap.xml", sitemap)?;
return Ok(());
}
@@ -994,7 +986,7 @@ impl Site {
context.insert("entries", &chunk);
let sitemap = render_template("sitemap.xml", &self.tera, context, &self.config.theme)?;
let file_name = format!("sitemap{}.xml", i + 1);
- self.write_content(&[], &file_name, sitemap, false)?;
+ self.write_content(&[], &file_name, sitemap)?;
let mut sitemap_url = self.config.make_permalink(&file_name);
sitemap_url.pop(); // Remove trailing slash
sitemap_index.push(sitemap_url);
@@ -1009,7 +1001,7 @@ impl Site {
main_context,
&self.config.theme,
)?;
- self.write_content(&[], "sitemap.xml", sitemap, false)?;
+ self.write_content(&[], "sitemap.xml", sitemap)?;
Ok(())
}
@@ -1040,10 +1032,9 @@ impl Site {
&components.iter().map(|x| x.as_ref()).collect::>(),
feed_filename,
feed,
- false,
)?;
} else {
- self.write_content(&[], feed_filename, feed, false)?;
+ self.write_content(&[], feed_filename, feed)?;
}
Ok(())
}
@@ -1052,7 +1043,6 @@ impl Site {
pub fn render_section(&self, section: &Section, render_pages: bool) -> Result<()> {
let mut output_path = self.output_path.clone();
let mut components: Vec<&str> = Vec::new();
- let create_directories = self.build_mode == BuildMode::Disk || !section.assets.is_empty();
if section.lang != self.config.default_language {
components.push(§ion.lang);
@@ -1064,10 +1054,6 @@ impl Site {
output_path.push(component);
}
- if create_directories {
- create_directory(&output_path)?;
- }
-
if section.meta.generate_feed {
let library = &self.library.read().unwrap();
let pages = section.pages.iter().map(|k| library.pages.get(k).unwrap()).collect();
@@ -1107,7 +1093,6 @@ impl Site {
&components,
"index.html",
render_redirect_template(&permalink, &self.tera)?,
- create_directories,
)?;
return Ok(());
@@ -1122,7 +1107,7 @@ impl Site {
let output =
section.render_html(&self.tera, &self.config, &self.library.read().unwrap())?;
let content = self.inject_livereload(output);
- self.write_content(&components, "index.html", content, false)?;
+ self.write_content(&components, "index.html", content)?;
}
Ok(())
@@ -1174,14 +1159,13 @@ impl Site {
let content = self.inject_livereload(output);
if pager.index > 1 {
- self.write_content(&pager_components, "index.html", content, false)?;
+ self.write_content(&pager_components, "index.html", content)?;
} else {
- self.write_content(&index_components, "index.html", content, false)?;
+ self.write_content(&index_components, "index.html", content)?;
self.write_content(
&pager_components,
"index.html",
render_redirect_template(&paginator.permalink, &self.tera)?,
- false,
)?;
}
diff --git a/components/utils/src/fs.rs b/components/utils/src/fs.rs
index e1a1a5f29a..2b1557068a 100644
--- a/components/utils/src/fs.rs
+++ b/components/utils/src/fs.rs
@@ -19,8 +19,17 @@ pub fn is_path_in_directory(parent: &Path, path: &Path) -> Result {
Ok(canonical_path.starts_with(canonical_parent))
}
+/// Creates the parent of a directory, if needed.
+fn create_parent(path: &Path) -> Result<()> {
+ if let Some(parent) = path.parent() {
+ create_directory(parent)?;
+ }
+ Ok(())
+}
+
/// Create a file with the content given
pub fn create_file(path: &Path, content: &str) -> Result<()> {
+ create_parent(path)?;
let mut file =
File::create(path).with_context(|| format!("Failed to create file {}", path.display()))?;
file.write_all(content.as_bytes())?;
@@ -58,12 +67,7 @@ pub fn copy_file(src: &Path, dest: &Path, base_path: &Path, hard_link: bool) ->
let relative_path = src.strip_prefix(base_path).unwrap();
let target_path = dest.join(relative_path);
- if let Some(parent_directory) = target_path.parent() {
- create_dir_all(parent_directory).with_context(|| {
- format!("Failed to create directory {}", parent_directory.display())
- })?;
- }
-
+ create_parent(&target_path)?;
copy_file_if_needed(src, &target_path, hard_link)
}
@@ -72,11 +76,7 @@ pub fn copy_file(src: &Path, dest: &Path, base_path: &Path, hard_link: bool) ->
/// 2. Its modification timestamp is identical to that of the src file.
/// 3. Its filesize is identical to that of the src file.
pub fn copy_file_if_needed(src: &Path, dest: &Path, hard_link: bool) -> Result<()> {
- if let Some(parent_directory) = dest.parent() {
- create_dir_all(parent_directory).with_context(|| {
- format!("Failed to create directory {}", parent_directory.display())
- })?;
- }
+ create_parent(&dest)?;
if hard_link {
if dest.exists() {
From 3423b8a6bd02cce1cdeaf623b9016a2d0877a509 Mon Sep 17 00:00:00 2001
From: James Williams
Date: Fri, 3 May 2024 11:09:37 -0700
Subject: [PATCH 17/25] Restore trailing slash behaviour in serve command
(#2482)
* Restore trailing slash behaviour in serve command.
* Restore guard in case where base_url is just a slash.
---
src/cmd/serve.rs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs
index 27c9b057bb..d3aa01f660 100644
--- a/src/cmd/serve.rs
+++ b/src/cmd/serve.rs
@@ -396,7 +396,11 @@ fn create_new_site(
|u| u.to_string(),
);
- let constructed_base_url = construct_url(&base_url, no_port_append, interface_port);
+ let mut constructed_base_url = construct_url(&base_url, no_port_append, interface_port);
+
+ if !site.config.base_url.ends_with("/") && constructed_base_url != "/" {
+ constructed_base_url.truncate(constructed_base_url.len() - 1);
+ }
site.enable_serve_mode();
site.set_base_url(constructed_base_url.clone());
From b76d37cc1b2f28572903b849d6dd312d15d18cfa Mon Sep 17 00:00:00 2001
From: Eugene Lomov
Date: Thu, 9 May 2024 16:45:47 +0300
Subject: [PATCH 18/25] Implemented bottom footnotes with backreferences
(#2480)
* Implemented bottom footnotes with backreferences
Fixes #1285
* Added bottom_footnotes option to configuration.md
* Renamed fix_github_style_footnotes()
* Added tests for convert_footnotes_to_github_style()
* Changed test to plain html instead of Vec
* Added integration test for footnotes
* Applied suggested changes
---
components/config/src/config/markup.rs | 3 +
components/markdown/src/markdown.rs | 264 +++++++++++++++++-
...down__markdown__tests__def_before_use.snap | 10 +
...down__tests__footnote_inside_footnote.snap | 13 +
...kdown__markdown__tests__multiple_refs.snap | 10 +
...rkdown__markdown__tests__no_footnotes.snap | 6 +
..._markdown__tests__reordered_footnotes.snap | 13 +
...own__markdown__tests__single_footnote.snap | 10 +
components/markdown/tests/markdown.rs | 37 +++
.../markdown__github_style_footnotes.snap | 36 +++
.../getting-started/configuration.md | 3 +
11 files changed, 403 insertions(+), 2 deletions(-)
create mode 100644 components/markdown/src/snapshots/markdown__markdown__tests__def_before_use.snap
create mode 100644 components/markdown/src/snapshots/markdown__markdown__tests__footnote_inside_footnote.snap
create mode 100644 components/markdown/src/snapshots/markdown__markdown__tests__multiple_refs.snap
create mode 100644 components/markdown/src/snapshots/markdown__markdown__tests__no_footnotes.snap
create mode 100644 components/markdown/src/snapshots/markdown__markdown__tests__reordered_footnotes.snap
create mode 100644 components/markdown/src/snapshots/markdown__markdown__tests__single_footnote.snap
create mode 100644 components/markdown/tests/snapshots/markdown__github_style_footnotes.snap
diff --git a/components/config/src/config/markup.rs b/components/config/src/config/markup.rs
index b1ac7fa22f..580a665ae6 100644
--- a/components/config/src/config/markup.rs
+++ b/components/config/src/config/markup.rs
@@ -43,6 +43,8 @@ pub struct Markdown {
pub external_links_no_referrer: bool,
/// Whether smart punctuation is enabled (changing quotes, dashes, dots etc in their typographic form)
pub smart_punctuation: bool,
+ /// Whether footnotes are rendered at the bottom in the style of GitHub.
+ pub bottom_footnotes: bool,
/// A list of directories to search for additional `.sublime-syntax` and `.tmTheme` files in.
pub extra_syntaxes_and_themes: Vec,
/// The compiled extra syntaxes into a syntax set
@@ -203,6 +205,7 @@ impl Default for Markdown {
external_links_no_follow: false,
external_links_no_referrer: false,
smart_punctuation: false,
+ bottom_footnotes: false,
extra_syntaxes_and_themes: vec![],
extra_syntax_set: None,
extra_theme_set: Arc::new(None),
diff --git a/components/markdown/src/markdown.rs b/components/markdown/src/markdown.rs
index 40c94afac5..a8565176c8 100644
--- a/components/markdown/src/markdown.rs
+++ b/components/markdown/src/markdown.rs
@@ -1,5 +1,7 @@
+use std::collections::HashMap;
use std::fmt::Write;
+use crate::markdown::cmark::CowStr;
use errors::bail;
use libs::gh_emoji::Replacer as EmojiReplacer;
use libs::once_cell::sync::Lazy;
@@ -239,6 +241,158 @@ fn get_heading_refs(events: &[Event]) -> Vec {
heading_refs
}
+fn convert_footnotes_to_github_style(old_events: &mut Vec) {
+ let events = std::mem::take(old_events);
+ // step 1: We need to extract footnotes from the event stream and tweak footnote references
+
+ // footnotes bodies are stored in a stack of vectors, because it is possible to have footnotes
+ // inside footnotes
+ let mut footnote_bodies_stack = Vec::new();
+ let mut footnotes = Vec::new();
+ // this will allow to create a multiple back references
+ let mut footnote_numbers = HashMap::new();
+ let filtered_events = events.into_iter().filter_map(|event| {
+ match event {
+ // New footnote definition is pushed to the stack
+ Event::Start(Tag::FootnoteDefinition(_)) => {
+ footnote_bodies_stack.push(vec![event]);
+ None
+ }
+ // The topmost footnote definition is popped from the stack
+ Event::End(TagEnd::FootnoteDefinition) => {
+ // unwrap will never fail, because Tag::FootnoteDefinition always comes before
+ // TagEnd::FootnoteDefinition
+ let mut footnote_body = footnote_bodies_stack.pop().unwrap();
+ footnote_body.push(event);
+ footnotes.push(footnote_body);
+ None
+ }
+ Event::FootnoteReference(name) => {
+ // n will be a unique index of the footnote
+ let n = footnote_numbers.len() + 1;
+ // nr is a number of references to this footnote
+ let (n, nr) = footnote_numbers.entry(name.clone()).or_insert((n, 0usize));
+ *nr += 1;
+ let reference = Event::Html(format!(r##""##).into());
+
+ if footnote_bodies_stack.is_empty() {
+ // we are in the main text, just output the reference
+ Some(reference)
+ } else {
+ // we are inside other footnote, we have to push that reference into that
+ // footnote
+ footnote_bodies_stack.last_mut().unwrap().push(reference);
+ None
+ }
+ }
+ _ if !footnote_bodies_stack.is_empty() => {
+ footnote_bodies_stack.last_mut().unwrap().push(event);
+ None
+ }
+ _ => Some(event),
+ }
+ }
+ );
+
+ old_events.extend(filtered_events);
+
+ if footnotes.is_empty() {
+ return;
+ }
+
+ old_events.push(Event::Html("
\n");
+ }
+ Event::Html(end.into())
+ }
+ Event::End(TagEnd::FootnoteDefinition) => Event::Html("\n".into()),
+ Event::FootnoteReference(_) => unreachable!("converted to HTML earlier"),
+ f => f,
+ })
+ });
+
+ old_events.extend(footnotes);
+ old_events.push(Event::Html("\n".into()));
+}
+
pub fn markdown_to_html(
content: &str,
context: &RenderContext,
@@ -623,6 +777,10 @@ pub fn markdown_to_html(
insert_many(&mut events, anchors_to_insert);
}
+ if context.config.markdown.bottom_footnotes {
+ convert_footnotes_to_github_style(&mut events);
+ }
+
cmark::html::push_html(&mut html, events.into_iter());
}
@@ -641,11 +799,11 @@ pub fn markdown_to_html(
#[cfg(test)]
mod tests {
+ use super::*;
use config::Config;
+ use insta::assert_snapshot;
- use super::*;
#[test]
-
fn insert_many_works() {
let mut v = vec![1, 2, 3, 4, 5];
insert_many(&mut v, vec![(0, 0), (2, -1), (5, 6)]);
@@ -714,4 +872,106 @@ mod tests {
assert_eq!(body, &bottom_rendered);
}
}
+
+ #[test]
+ fn no_footnotes() {
+ let mut opts = Options::empty();
+ opts.insert(Options::ENABLE_TABLES);
+ opts.insert(Options::ENABLE_FOOTNOTES);
+ opts.insert(Options::ENABLE_STRIKETHROUGH);
+ opts.insert(Options::ENABLE_TASKLISTS);
+ opts.insert(Options::ENABLE_HEADING_ATTRIBUTES);
+
+ let content = "Some text *without* footnotes.\n\nOnly ~~fancy~~ formatting.";
+ let mut events: Vec<_> = Parser::new_ext(&content, opts).collect();
+ convert_footnotes_to_github_style(&mut events);
+ let mut html = String::new();
+ cmark::html::push_html(&mut html, events.into_iter());
+ assert_snapshot!(html);
+ }
+
+ #[test]
+ fn single_footnote() {
+ let mut opts = Options::empty();
+ opts.insert(Options::ENABLE_TABLES);
+ opts.insert(Options::ENABLE_FOOTNOTES);
+ opts.insert(Options::ENABLE_STRIKETHROUGH);
+ opts.insert(Options::ENABLE_TASKLISTS);
+ opts.insert(Options::ENABLE_HEADING_ATTRIBUTES);
+
+ let content = "This text has a footnote[^1]\n [^1]:But it is meaningless.";
+ let mut events: Vec<_> = Parser::new_ext(&content, opts).collect();
+ convert_footnotes_to_github_style(&mut events);
+ let mut html = String::new();
+ cmark::html::push_html(&mut html, events.into_iter());
+ assert_snapshot!(html);
+ }
+
+ #[test]
+ fn reordered_footnotes() {
+ let mut opts = Options::empty();
+ opts.insert(Options::ENABLE_TABLES);
+ opts.insert(Options::ENABLE_FOOTNOTES);
+ opts.insert(Options::ENABLE_STRIKETHROUGH);
+ opts.insert(Options::ENABLE_TASKLISTS);
+ opts.insert(Options::ENABLE_HEADING_ATTRIBUTES);
+
+ let content = "This text has two[^2] footnotes[^1]\n[^1]: not sorted.\n[^2]: But they are";
+ let mut events: Vec<_> = Parser::new_ext(&content, opts).collect();
+ convert_footnotes_to_github_style(&mut events);
+ let mut html = String::new();
+ cmark::html::push_html(&mut html, events.into_iter());
+ assert_snapshot!(html);
+ }
+
+ #[test]
+ fn def_before_use() {
+ let mut opts = Options::empty();
+ opts.insert(Options::ENABLE_TABLES);
+ opts.insert(Options::ENABLE_FOOTNOTES);
+ opts.insert(Options::ENABLE_STRIKETHROUGH);
+ opts.insert(Options::ENABLE_TASKLISTS);
+ opts.insert(Options::ENABLE_HEADING_ATTRIBUTES);
+
+ let content = "[^1]:It's before the reference.\n\n There is footnote definition?[^1]";
+ let mut events: Vec<_> = Parser::new_ext(&content, opts).collect();
+ convert_footnotes_to_github_style(&mut events);
+ let mut html = String::new();
+ cmark::html::push_html(&mut html, events.into_iter());
+ assert_snapshot!(html);
+ }
+
+ #[test]
+ fn multiple_refs() {
+ let mut opts = Options::empty();
+ opts.insert(Options::ENABLE_TABLES);
+ opts.insert(Options::ENABLE_FOOTNOTES);
+ opts.insert(Options::ENABLE_STRIKETHROUGH);
+ opts.insert(Options::ENABLE_TASKLISTS);
+ opts.insert(Options::ENABLE_HEADING_ATTRIBUTES);
+
+ let content = "This text has two[^1] identical footnotes[^1]\n[^1]: So one is present.\n[^2]: But another in not.";
+ let mut events: Vec<_> = Parser::new_ext(&content, opts).collect();
+ convert_footnotes_to_github_style(&mut events);
+ let mut html = String::new();
+ cmark::html::push_html(&mut html, events.into_iter());
+ assert_snapshot!(html);
+ }
+
+ #[test]
+ fn footnote_inside_footnote() {
+ let mut opts = Options::empty();
+ opts.insert(Options::ENABLE_TABLES);
+ opts.insert(Options::ENABLE_FOOTNOTES);
+ opts.insert(Options::ENABLE_STRIKETHROUGH);
+ opts.insert(Options::ENABLE_TASKLISTS);
+ opts.insert(Options::ENABLE_HEADING_ATTRIBUTES);
+
+ let content = "This text has a footnote[^1]\n[^1]: But the footnote has another footnote[^2].\n[^2]: That's it.";
+ let mut events: Vec<_> = Parser::new_ext(&content, opts).collect();
+ convert_footnotes_to_github_style(&mut events);
+ let mut html = String::new();
+ cmark::html::push_html(&mut html, events.into_iter());
+ assert_snapshot!(html);
+ }
}
diff --git a/components/markdown/src/snapshots/markdown__markdown__tests__def_before_use.snap b/components/markdown/src/snapshots/markdown__markdown__tests__def_before_use.snap
new file mode 100644
index 0000000000..57e3a922ad
--- /dev/null
+++ b/components/markdown/src/snapshots/markdown__markdown__tests__def_before_use.snap
@@ -0,0 +1,10 @@
+---
+source: components/markdown/src/markdown.rs
+expression: html
+---
+There is footnote definition?
+
diff --git a/components/markdown/src/snapshots/markdown__markdown__tests__footnote_inside_footnote.snap b/components/markdown/src/snapshots/markdown__markdown__tests__footnote_inside_footnote.snap
new file mode 100644
index 0000000000..6b5e28d476
--- /dev/null
+++ b/components/markdown/src/snapshots/markdown__markdown__tests__footnote_inside_footnote.snap
@@ -0,0 +1,13 @@
+---
+source: components/markdown/src/markdown.rs
+expression: html
+---
+This text has a footnote
+
diff --git a/components/markdown/src/snapshots/markdown__markdown__tests__multiple_refs.snap b/components/markdown/src/snapshots/markdown__markdown__tests__multiple_refs.snap
new file mode 100644
index 0000000000..1f7eaff186
--- /dev/null
+++ b/components/markdown/src/snapshots/markdown__markdown__tests__multiple_refs.snap
@@ -0,0 +1,10 @@
+---
+source: components/markdown/src/markdown.rs
+expression: html
+---
+This text has two identical footnotes
+
diff --git a/components/markdown/src/snapshots/markdown__markdown__tests__no_footnotes.snap b/components/markdown/src/snapshots/markdown__markdown__tests__no_footnotes.snap
new file mode 100644
index 0000000000..f9cc7730d8
--- /dev/null
+++ b/components/markdown/src/snapshots/markdown__markdown__tests__no_footnotes.snap
@@ -0,0 +1,6 @@
+---
+source: components/markdown/src/markdown.rs
+expression: html
+---
+Some text without footnotes.
+Only fancy formatting.
diff --git a/components/markdown/src/snapshots/markdown__markdown__tests__reordered_footnotes.snap b/components/markdown/src/snapshots/markdown__markdown__tests__reordered_footnotes.snap
new file mode 100644
index 0000000000..865a344e5c
--- /dev/null
+++ b/components/markdown/src/snapshots/markdown__markdown__tests__reordered_footnotes.snap
@@ -0,0 +1,13 @@
+---
+source: components/markdown/src/markdown.rs
+expression: html
+---
+This text has two footnotes
+
diff --git a/components/markdown/src/snapshots/markdown__markdown__tests__single_footnote.snap b/components/markdown/src/snapshots/markdown__markdown__tests__single_footnote.snap
new file mode 100644
index 0000000000..34a7f2d3e6
--- /dev/null
+++ b/components/markdown/src/snapshots/markdown__markdown__tests__single_footnote.snap
@@ -0,0 +1,10 @@
+---
+source: components/markdown/src/markdown.rs
+expression: html
+---
+This text has a footnote
+
diff --git a/components/markdown/tests/markdown.rs b/components/markdown/tests/markdown.rs
index a12246837b..e8cdcd42c2 100644
--- a/components/markdown/tests/markdown.rs
+++ b/components/markdown/tests/markdown.rs
@@ -355,3 +355,40 @@ and multiple paragraphs.
.body;
insta::assert_snapshot!(body);
}
+
+#[test]
+fn github_style_footnotes() {
+ let mut config = Config::default_for_test();
+ config.markdown.bottom_footnotes = true;
+
+ let markdown = r#"This text has a footnote[^1]
+
+[^1]:But it is meaningless.
+
+This text has two[^3] footnotes[^2].
+
+[^2]: not sorted.
+[^3]: But they are
+
+[^4]:It's before the reference.
+
+There is footnote definition?[^4]
+
+This text has two[^5] identical footnotes[^5]
+[^5]: So one is present.
+[^6]: But another in not.
+
+This text has a footnote[^7]
+
+[^7]: But the footnote has another footnote[^8].
+
+[^8]: That's it.
+
+Footnotes can also be referenced with identifiers[^first].
+
+[^first]: Like this: `[^first]`.
+"#;
+
+ let body = common::render_with_config(&markdown, config).unwrap().body;
+ insta::assert_snapshot!(body);
+}
diff --git a/components/markdown/tests/snapshots/markdown__github_style_footnotes.snap b/components/markdown/tests/snapshots/markdown__github_style_footnotes.snap
new file mode 100644
index 0000000000..de55e63fb7
--- /dev/null
+++ b/components/markdown/tests/snapshots/markdown__github_style_footnotes.snap
@@ -0,0 +1,36 @@
+---
+source: components/markdown/tests/markdown.rs
+expression: body
+---
+This text has a footnote
+This text has two footnotes.
+There is footnote definition?
+This text has two identical footnotes
+This text has a footnote
+Footnotes can also be referenced with identifiers.
+
diff --git a/docs/content/documentation/getting-started/configuration.md b/docs/content/documentation/getting-started/configuration.md
index d8ec482d5d..dce920ce8d 100644
--- a/docs/content/documentation/getting-started/configuration.md
+++ b/docs/content/documentation/getting-started/configuration.md
@@ -135,6 +135,9 @@ smart_punctuation = false
# For example, `![xx](...)` is ok but `![*x*x](...)` isn’t ok
lazy_async_image = false
+# Whether footnotes are rendered in the GitHub-style (at the bottom, with back references) or plain (in the place, where they are defined)
+bottom_footnotes = false
+
# Configuration of the link checker.
[link_checker]
# Skip link checking for external URLs that start with these prefixes
From b3d5349d3b82063efe60fd752b26d61553611ec1 Mon Sep 17 00:00:00 2001
From: Vincent Prouillet
Date: Thu, 9 May 2024 23:24:56 +0200
Subject: [PATCH 19/25] Update deps
---
Cargo.lock | 1818 ++++++++++++++++---------
components/imageproc/src/processor.rs | 8 +-
components/libs/Cargo.toml | 12 +-
3 files changed, 1200 insertions(+), 638 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 0d90eea7c0..293d58133a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -19,23 +19,23 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
-version = "0.7.7"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd"
+checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
dependencies = [
- "getrandom 0.2.11",
+ "getrandom 0.2.15",
"once_cell",
"version_check",
]
[[package]]
name = "ahash"
-version = "0.8.6"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if 1.0.0",
- "getrandom 0.2.11",
+ "getrandom 0.2.15",
"once_cell",
"version_check",
"zerocopy",
@@ -52,18 +52,24 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "1.1.2"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
+[[package]]
+name = "aligned-vec"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
+
[[package]]
name = "ammonia"
-version = "3.3.0"
+version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e6d1c7838db705c9b756557ee27c384ce695a1c51a6fe528784cb1c6840170"
+checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459"
dependencies = [
"html5ever",
"maplit",
@@ -89,47 +95,48 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.5"
+version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
+ "is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
-version = "1.0.4"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.2"
+version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
@@ -143,9 +150,26 @@ checksum = "70033777eb8b5124a81a1889416543dddef2de240019b674c81285a2635a7e1e"
[[package]]
name = "anyhow"
-version = "1.0.75"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
+checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
+
+[[package]]
+name = "arbitrary"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
+
+[[package]]
+name = "arg_enum_proc_macro"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.61",
+]
[[package]]
name = "arrayvec"
@@ -169,22 +193,45 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi 0.1.19",
+ "hermit-abi",
"libc",
"winapi 0.3.9",
]
[[package]]
name = "autocfg"
-version = "1.1.0"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+
+[[package]]
+name = "av1-grain"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf"
+dependencies = [
+ "anyhow",
+ "arrayvec",
+ "log",
+ "nom",
+ "num-rational",
+ "v_frame",
+]
+
+[[package]]
+name = "avif-serialize"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2"
+dependencies = [
+ "arrayvec",
+]
[[package]]
name = "backtrace"
-version = "0.3.69"
+version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [
"addr2line",
"cc",
@@ -197,9 +244,24 @@ dependencies = [
[[package]]
name = "base64"
-version = "0.21.5"
+version = "0.21.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
+[[package]]
+name = "base64"
+version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "base64-simd"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5"
+dependencies = [
+ "simd-abstraction",
+]
[[package]]
name = "bincode"
@@ -224,9 +286,27 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.4.1"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
+
+[[package]]
+name = "bitstream-io"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "7c12d1856e42f0d817a835fe55853957c85c8c8a470114029143d3f12671446e"
+
+[[package]]
+name = "bitvec"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
[[package]]
name = "block-buffer"
@@ -260,9 +340,9 @@ dependencies = [
[[package]]
name = "bstr"
-version = "1.8.0"
+version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
+checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
dependencies = [
"memchr",
"serde",
@@ -274,11 +354,17 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7"
+[[package]]
+name = "built"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41bfbdb21256b87a8b5e80fab81a8eed158178e812fd7ba451907518b2742f16"
+
[[package]]
name = "bumpalo"
-version = "3.14.0"
+version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "byte-tools"
@@ -286,17 +372,39 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
+[[package]]
+name = "bytecheck"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
+dependencies = [
+ "bytecheck_derive",
+ "ptr_meta",
+ "simdutf8",
+]
+
+[[package]]
+name = "bytecheck_derive"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
[[package]]
name = "bytecount"
-version = "0.6.7"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205"
+checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
[[package]]
name = "bytemuck"
-version = "1.14.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
+checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
[[package]]
name = "byteorder"
@@ -304,6 +412,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+[[package]]
+name = "byteorder-lite"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
+
[[package]]
name = "bytes"
version = "0.4.12"
@@ -316,9 +430,9 @@ dependencies = [
[[package]]
name = "bytes"
-version = "1.5.0"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
+checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]]
name = "camino"
@@ -331,9 +445,9 @@ dependencies = [
[[package]]
name = "cargo-platform"
-version = "0.1.5"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff"
+checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc"
dependencies = [
"serde",
]
@@ -353,12 +467,13 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.83"
+version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
dependencies = [
"jobserver",
"libc",
+ "once_cell",
]
[[package]]
@@ -370,6 +485,16 @@ dependencies = [
"smallvec",
]
+[[package]]
+name = "cfg-expr"
+version = "0.15.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
+dependencies = [
+ "smallvec",
+ "target-lexicon",
+]
+
[[package]]
name = "cfg-if"
version = "0.1.10"
@@ -382,24 +507,30 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+[[package]]
+name = "cfg_aliases"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+
[[package]]
name = "chrono"
-version = "0.4.31"
+version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"pure-rust-locales",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.5",
]
[[package]]
name = "chrono-tz"
-version = "0.8.4"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e23185c0e21df6ed832a12e2bda87c7d1def6842881fb634a8511ced741b0d76"
+checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e"
dependencies = [
"chrono",
"chrono-tz-build",
@@ -429,40 +560,40 @@ dependencies = [
"clap_lex 0.2.4",
"indexmap 1.9.3",
"once_cell",
- "strsim",
+ "strsim 0.10.0",
"termcolor",
"textwrap",
]
[[package]]
name = "clap"
-version = "4.4.11"
+version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
- "clap_derive 4.4.7",
+ "clap_derive 4.5.4",
]
[[package]]
name = "clap_builder"
-version = "4.4.11"
+version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstream",
"anstyle",
- "clap_lex 0.6.0",
- "strsim",
+ "clap_lex 0.7.0",
+ "strsim 0.11.1",
]
[[package]]
name = "clap_complete"
-version = "4.4.4"
+version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae"
+checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e"
dependencies = [
- "clap 4.4.11",
+ "clap 4.5.4",
]
[[package]]
@@ -471,7 +602,7 @@ version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
dependencies = [
- "heck",
+ "heck 0.4.1",
"proc-macro-error",
"proc-macro2",
"quote",
@@ -480,14 +611,14 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.4.7"
+version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [
- "heck",
+ "heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
]
[[package]]
@@ -501,9 +632,9 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "codemap"
@@ -519,9 +650,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "colorchoice"
-version = "1.0.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "colored"
@@ -553,14 +684,34 @@ dependencies = [
[[package]]
name = "console"
-version = "0.15.7"
+version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
+checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
- "windows-sys 0.45.0",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "const-str"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21077772762a1002bb421c3af42ac1725fa56066bfc53d9a55bb79905df2aaf3"
+dependencies = [
+ "const-str-proc-macro",
+]
+
+[[package]]
+name = "const-str-proc-macro"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e1e0fdd2e5d3041e530e1b21158aeeef8b5d0e306bc5c1e3d6cf0930d10e25a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
]
[[package]]
@@ -578,12 +729,6 @@ dependencies = [
"utils",
]
-[[package]]
-name = "convert_case"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
-
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -602,9 +747,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cpufeatures"
-version = "0.2.11"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
@@ -620,44 +765,37 @@ dependencies = [
[[package]]
name = "crc32fast"
-version = "1.3.2"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crossbeam-deque"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
- "cfg-if 1.0.0",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
-version = "0.9.16"
+version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
- "autocfg",
- "cfg-if 1.0.0",
"crossbeam-utils",
- "memoffset",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.17"
+version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
-dependencies = [
- "cfg-if 1.0.0",
-]
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "crunchy"
@@ -676,14 +814,35 @@ dependencies = [
]
[[package]]
-name = "css-minify"
-version = "0.3.1"
+name = "cssparser"
+version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "874c6e2d19f8d4a285083b11a3241bfbe01ac3ed85f26e1e6b34888d960552bd"
+checksum = "9be934d936a0fbed5bcdc01042b770de1398bf79d0e192f49fa7faea0e99281e"
dependencies = [
- "derive_more",
- "indexmap 1.9.3",
- "nom",
+ "cssparser-macros",
+ "dtoa-short",
+ "itoa",
+ "phf 0.11.2",
+ "smallvec",
+]
+
+[[package]]
+name = "cssparser-color"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "556c099a61d85989d7af52b692e35a8d68a57e7df8c6d07563dc0778b3960c9f"
+dependencies = [
+ "cssparser",
+]
+
+[[package]]
+name = "cssparser-macros"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
+dependencies = [
+ "quote",
+ "syn 2.0.61",
]
[[package]]
@@ -709,41 +868,56 @@ dependencies = [
[[package]]
name = "ctrlc"
-version = "3.4.1"
+version = "3.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
+checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345"
dependencies = [
"nix",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
]
[[package]]
-name = "deranged"
-version = "0.3.10"
+name = "dashmap"
+version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc"
+checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
- "powerfmt",
+ "cfg-if 1.0.0",
+ "hashbrown 0.14.5",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
]
[[package]]
-name = "derive_more"
-version = "0.99.17"
+name = "data-encoding"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
+
+[[package]]
+name = "data-url"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193"
dependencies = [
- "convert_case",
- "proc-macro2",
- "quote",
- "rustc_version",
- "syn 1.0.109",
+ "matches",
+]
+
+[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
]
[[package]]
name = "deunicode"
-version = "1.4.2"
+version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ae2a35373c5c74340b79ae6780b498b2b183915ec5dacf263aac5a099bf485a"
+checksum = "322ef0094744e63628e6f0eb2295517f79276a5b342a4c2ff3042566ca181d4e"
[[package]]
name = "digest"
@@ -772,7 +946,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
]
[[package]]
@@ -781,11 +955,26 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+[[package]]
+name = "dtoa"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653"
+
+[[package]]
+name = "dtoa-short"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74"
+dependencies = [
+ "dtoa",
+]
+
[[package]]
name = "either"
-version = "1.9.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
[[package]]
name = "elasticlunr-rs"
@@ -875,9 +1064,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
[[package]]
name = "encoding_rs"
-version = "0.8.33"
+version = "0.8.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
+checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
dependencies = [
"cfg-if 1.0.0",
]
@@ -903,9 +1092,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
-version = "0.3.8"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
@@ -929,9 +1118,9 @@ dependencies = [
[[package]]
name = "exr"
-version = "1.71.0"
+version = "1.72.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8"
+checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4"
dependencies = [
"bit_field",
"flume",
@@ -951,15 +1140,15 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fastrand"
-version = "2.0.1"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
[[package]]
name = "fdeflate"
-version = "0.3.1"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868"
+checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"
dependencies = [
"simd-adler32",
]
@@ -972,15 +1161,15 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if 1.0.0",
"libc",
- "redox_syscall",
+ "redox_syscall 0.4.1",
"windows-sys 0.52.0",
]
[[package]]
name = "flate2"
-version = "1.0.28"
+version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
+checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -1060,6 +1249,12 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+[[package]]
+name = "funty"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
+
[[package]]
name = "futf"
version = "0.1.5"
@@ -1072,42 +1267,42 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.29"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
-version = "0.3.29"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-io"
-version = "0.3.29"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-sink"
-version = "0.3.29"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
-version = "0.3.29"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
-version = "0.3.29"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-core",
"futures-io",
@@ -1159,9 +1354,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.11"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if 1.0.0",
"libc",
@@ -1180,9 +1375,9 @@ dependencies = [
[[package]]
name = "gif"
-version = "0.12.0"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
+checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"
dependencies = [
"color_quant",
"weezl",
@@ -1206,11 +1401,11 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
dependencies = [
- "aho-corasick 1.1.2",
+ "aho-corasick 1.1.3",
"bstr",
"log",
"regex-automata",
- "regex-syntax 0.8.2",
+ "regex-syntax",
]
[[package]]
@@ -1226,40 +1421,40 @@ dependencies = [
[[package]]
name = "grass"
-version = "0.13.1"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7746cd9bf09f9bb7d98638774a70642000356f543898d9a352cd043f82744528"
+checksum = "b89786a806d5b192cf4e573f9831c847a455a142d000c922bdfc1e5edad14303"
dependencies = [
"grass_compiler",
]
[[package]]
name = "grass_compiler"
-version = "0.13.0"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "187adfc0b34289c7f8f3819453ce9da3177c3d73f40ac74bb17faba578813d45"
+checksum = "7cf7d155dd7cef20195016d01005033a5521aad307033f0f8e8bf0a02f5f7554"
dependencies = [
"codemap",
- "indexmap 1.9.3",
+ "indexmap 2.2.6",
"lasso",
"once_cell",
- "phf 0.10.1",
+ "phf 0.11.2",
"rand 0.8.5",
]
[[package]]
name = "h2"
-version = "0.3.22"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
+checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [
- "bytes 1.5.0",
+ "bytes 1.6.0",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
- "indexmap 2.1.0",
+ "indexmap 2.2.6",
"slab",
"tokio",
"tokio-util",
@@ -1268,33 +1463,38 @@ dependencies = [
[[package]]
name = "half"
-version = "2.2.1"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0"
+checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
+ "cfg-if 1.0.0",
"crunchy",
]
[[package]]
name = "hashbrown"
-version = "0.11.2"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
- "ahash 0.7.7",
+ "ahash 0.7.8",
]
[[package]]
name = "hashbrown"
-version = "0.12.3"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
+dependencies = [
+ "ahash 0.8.11",
+ "bumpalo",
+]
[[package]]
name = "hashbrown"
-version = "0.14.3"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "heck"
@@ -1302,6 +1502,12 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
[[package]]
name = "hermit-abi"
version = "0.1.19"
@@ -1311,33 +1517,27 @@ dependencies = [
"libc",
]
-[[package]]
-name = "hermit-abi"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
-
[[package]]
name = "html5ever"
-version = "0.26.0"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
+checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4"
dependencies = [
"log",
"mac",
"markup5ever",
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.61",
]
[[package]]
name = "http"
-version = "0.2.11"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
dependencies = [
- "bytes 1.5.0",
+ "bytes 1.6.0",
"fnv",
"itoa",
]
@@ -1348,7 +1548,7 @@ version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
- "bytes 1.5.0",
+ "bytes 1.6.0",
"http",
"pin-project-lite",
]
@@ -1382,11 +1582,11 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
-version = "0.14.27"
+version = "0.14.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
+checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
dependencies = [
- "bytes 1.5.0",
+ "bytes 1.6.0",
"futures-channel",
"futures-core",
"futures-util",
@@ -1397,7 +1597,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
- "socket2 0.4.10",
+ "socket2",
"tokio",
"tower-service",
"tracing",
@@ -1424,7 +1624,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
- "bytes 1.5.0",
+ "bytes 1.6.0",
"hyper",
"native-tls",
"tokio",
@@ -1433,9 +1633,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
-version = "0.1.58"
+version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -1466,9 +1666,9 @@ dependencies = [
[[package]]
name = "ignore"
-version = "0.4.21"
+version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060"
+checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1"
dependencies = [
"crossbeam-deque",
"globset",
@@ -1482,21 +1682,35 @@ dependencies = [
[[package]]
name = "image"
-version = "0.24.7"
+version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711"
+checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"exr",
"gif",
- "jpeg-decoder",
- "num-rational",
+ "image-webp",
"num-traits",
"png",
"qoi",
+ "ravif",
+ "rayon",
+ "rgb",
"tiff",
+ "zune-core",
+ "zune-jpeg",
+]
+
+[[package]]
+name = "image-webp"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d730b085583c4d789dfd07fdcf185be59501666a90c97c40162b37e4fdad272d"
+dependencies = [
+ "byteorder-lite",
+ "thiserror",
]
[[package]]
@@ -1512,6 +1726,12 @@ dependencies = [
"utils",
]
+[[package]]
+name = "imgref"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126"
+
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -1524,12 +1744,12 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.1.0"
+version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"equivalent",
- "hashbrown 0.14.3",
+ "hashbrown 0.14.5",
]
[[package]]
@@ -1554,15 +1774,25 @@ dependencies = [
[[package]]
name = "insta"
-version = "1.34.0"
+version = "1.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc"
+checksum = "3eab73f58e59ca6526037208f0e98851159ec1633cf17b6cd2e1f2c3fd5d53cc"
dependencies = [
- "console 0.15.7",
+ "console 0.15.8",
"lazy_static",
"linked-hash-map",
"similar",
- "yaml-rust",
+]
+
+[[package]]
+name = "interpolate_name"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.61",
]
[[package]]
@@ -1599,11 +1829,35 @@ dependencies = [
"once_cell",
]
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itoa"
-version = "1.0.10"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jieba-rs"
@@ -1613,7 +1867,7 @@ checksum = "93f0c1347cd3ac8d7c6e3a2dc33ac496d365cf09fc0831aa61111e1a6738983e"
dependencies = [
"cedarwood",
"fxhash",
- "hashbrown 0.14.3",
+ "hashbrown 0.14.5",
"lazy_static",
"phf 0.11.2",
"phf_codegen 0.11.2",
@@ -1622,27 +1876,24 @@ dependencies = [
[[package]]
name = "jobserver"
-version = "0.1.27"
+version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
+checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
-dependencies = [
- "rayon",
-]
+checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
[[package]]
name = "js-sys"
-version = "0.3.66"
+version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
@@ -1668,11 +1919,11 @@ dependencies = [
[[package]]
name = "lasso"
-version = "0.6.0"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aeb7b21a526375c5ca55f1a6dfd4e1fad9fa4edd750f530252a718a44b2608f0"
+checksum = "4644821e1c3d7a560fe13d842d13f587c07348a1a05d3a797152d41c90c56df2"
dependencies = [
- "hashbrown 0.11.2",
+ "hashbrown 0.13.2",
]
[[package]]
@@ -1704,9 +1955,20 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.151"
+version = "0.2.154"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
+checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
+
+[[package]]
+name = "libfuzzer-sys"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
+dependencies = [
+ "arbitrary",
+ "cc",
+ "once_cell",
+]
[[package]]
name = "libm"
@@ -1718,10 +1980,10 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
name = "libs"
version = "0.1.0"
dependencies = [
- "ahash 0.8.6",
+ "ahash 0.8.11",
"ammonia",
"atty",
- "base64",
+ "base64 0.22.1",
"csv",
"elasticlunr-rs",
"filetime",
@@ -1736,7 +1998,7 @@ dependencies = [
"num-format",
"once_cell",
"percent-encoding",
- "pulldown-cmark 0.10.0",
+ "pulldown-cmark 0.10.3",
"pulldown-cmark-escape",
"quickxml_to_serde",
"rayon",
@@ -1752,7 +2014,7 @@ dependencies = [
"tera",
"termcolor",
"time",
- "toml 0.8.8",
+ "toml 0.8.12",
"unic-langid",
"unicode-segmentation",
"url",
@@ -1762,14 +2024,39 @@ dependencies = [
[[package]]
name = "libwebp-sys"
-version = "0.9.4"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e0df0a0f9444d52aee6335cd724d21a2ee3285f646291799a72be518ec8ee3c"
+checksum = "829b6b604f31ed6d2bccbac841fe0788de93dbd87e4eb1ba2c4adfe8c012a838"
dependencies = [
"cc",
"glob",
]
+[[package]]
+name = "lightningcss"
+version = "1.0.0-alpha.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bd5bed3814fb631bfc1e24c2be6f7e86a9837c660909acab79a38374dcb8798"
+dependencies = [
+ "ahash 0.8.11",
+ "bitflags 2.5.0",
+ "const-str",
+ "cssparser",
+ "cssparser-color",
+ "dashmap",
+ "data-encoding",
+ "getrandom 0.2.15",
+ "itertools 0.10.5",
+ "lazy_static",
+ "parcel_selectors",
+ "parcel_sourcemap",
+ "paste",
+ "pathdiff",
+ "rayon",
+ "serde",
+ "smallvec",
+]
+
[[package]]
name = "lindera"
version = "0.14.0"
@@ -1929,12 +2216,9 @@ dependencies = [
[[package]]
name = "line-wrap"
-version = "0.1.1"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
-dependencies = [
- "safemem",
-]
+checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e"
[[package]]
name = "link_checker"
@@ -1955,15 +2239,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lock_api"
-version = "0.4.11"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
@@ -1971,9 +2255,18 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.20"
+version = "0.4.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+
+[[package]]
+name = "loop9"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062"
+dependencies = [
+ "imgref",
+]
[[package]]
name = "lzma-rs"
@@ -2014,33 +2307,40 @@ dependencies = [
[[package]]
name = "markup5ever"
-version = "0.11.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
+checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45"
dependencies = [
"log",
- "phf 0.10.1",
- "phf_codegen 0.10.0",
+ "phf 0.11.2",
+ "phf_codegen 0.11.2",
"string_cache",
"string_cache_codegen",
"tendril",
]
[[package]]
-name = "memchr"
-version = "2.6.4"
+name = "matches"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
-name = "memoffset"
-version = "0.9.0"
+name = "maybe-rayon"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
+checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519"
dependencies = [
- "autocfg",
+ "cfg-if 1.0.0",
+ "rayon",
]
+[[package]]
+name = "memchr"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+
[[package]]
name = "mime"
version = "0.3.17"
@@ -2068,23 +2368,40 @@ dependencies = [
[[package]]
name = "minify-html"
-version = "0.11.1"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc4d9147754a49e80557df835eb59e743eab1bf75410a134f55dc4b9dbb692ad"
+checksum = "1cd4517942a8e7425c990b14977f86a63e4996eed7b15cfcca1540126ac5ff25"
dependencies = [
"aho-corasick 0.7.20",
- "css-minify",
"lazy_static",
+ "lightningcss",
"memchr",
+ "minify-html-common",
"minify-js",
+ "once_cell",
+ "rustc-hash",
+]
+
+[[package]]
+name = "minify-html-common"
+version = "0.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "697a6b40dffdc5de10c0cbd709dc2bc2039cea9dab8aaa636eb9a49d6b411780"
+dependencies = [
+ "aho-corasick 0.7.20",
+ "itertools 0.12.1",
+ "lazy_static",
+ "memchr",
"rustc-hash",
+ "serde",
+ "serde_json",
]
[[package]]
name = "minify-js"
-version = "0.4.3"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c300f90ba1138b5c5daf5d9441dc9bdc67b808aac22cf638362a2647bc213be4"
+checksum = "22d6c512a82abddbbc13b70609cb2beff01be2c7afff534d6e5e1c85e438fc8b"
dependencies = [
"lazy_static",
"parse-js",
@@ -2098,9 +2415,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
-version = "0.7.1"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
"simd-adler32",
@@ -2127,9 +2444,9 @@ dependencies = [
[[package]]
name = "mio"
-version = "0.8.10"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
@@ -2215,18 +2532,19 @@ dependencies = [
[[package]]
name = "new_debug_unreachable"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "nix"
-version = "0.27.1"
+version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
+checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.5.0",
"cfg-if 1.0.0",
+ "cfg_aliases",
"libc",
]
@@ -2254,9 +2572,9 @@ dependencies = [
[[package]]
name = "nom-tracable"
-version = "0.9.0"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "160767ce1eed2cdadc2256015a6dc51d9632226ea02e0f0ce4590b904e1d80e2"
+checksum = "6a39d3ec4e5bc9816ca540bd6b1e4885c0275536eb3293d317d984bb17f9a294"
dependencies = [
"nom",
"nom-tracable-macros",
@@ -2265,9 +2583,9 @@ dependencies = [
[[package]]
name = "nom-tracable-macros"
-version = "0.9.0"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7ac681ea0c3d468b003bdebe3a65d1632e340302452f95c3ffadf515704c48d"
+checksum = "c9c68f5316254dae193b3ce083f6caf19ae1a58471e6585e89f0796b9e5bdf4a"
dependencies = [
"quote",
"syn 1.0.109",
@@ -2284,6 +2602,12 @@ dependencies = [
"nom",
]
+[[package]]
+name = "noop_proc_macro"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
+
[[package]]
name = "notify"
version = "4.0.17"
@@ -2302,6 +2626,33 @@ dependencies = [
"winapi 0.3.9",
]
+[[package]]
+name = "num-bigint"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
+name = "num-derive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.61",
+]
+
[[package]]
name = "num-format"
version = "0.4.4"
@@ -2314,58 +2665,47 @@ dependencies = [
[[package]]
name = "num-integer"
-version = "0.1.45"
+version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
- "autocfg",
"num-traits",
]
[[package]]
name = "num-rational"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
+checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
- "autocfg",
+ "num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
-version = "0.2.17"
+version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
-[[package]]
-name = "num_cpus"
-version = "1.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
-dependencies = [
- "hermit-abi 0.3.3",
- "libc",
-]
-
[[package]]
name = "num_threads"
-version = "0.1.6"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
dependencies = [
"libc",
]
[[package]]
name = "object"
-version = "0.32.1"
+version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
@@ -2406,9 +2746,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "open"
-version = "5.0.1"
+version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90878fb664448b54c4e592455ad02831e23a3f7e157374a8b95654731aac7349"
+checksum = "449f0ff855d85ddbf1edd5b646d65249ead3f5e422aaa86b7d2d0b049b103e32"
dependencies = [
"is-wsl",
"libc",
@@ -2417,11 +2757,11 @@ dependencies = [
[[package]]
name = "openssl"
-version = "0.10.61"
+version = "0.10.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45"
+checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.5.0",
"cfg-if 1.0.0",
"foreign-types",
"libc",
@@ -2438,7 +2778,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
]
[[package]]
@@ -2449,9 +2789,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
-version = "0.9.97"
+version = "0.9.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b"
+checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
dependencies = [
"cc",
"libc",
@@ -2465,11 +2805,47 @@ version = "6.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
+[[package]]
+name = "outref"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4"
+
+[[package]]
+name = "parcel_selectors"
+version = "0.26.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05d74befe2d076330d9a58bf9ca2da424568724ab278adf15fb5718253133887"
+dependencies = [
+ "bitflags 2.5.0",
+ "cssparser",
+ "fxhash",
+ "log",
+ "phf 0.10.1",
+ "phf_codegen 0.10.0",
+ "precomputed-hash",
+ "smallvec",
+]
+
+[[package]]
+name = "parcel_sourcemap"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "485b74d7218068b2b7c0e3ff12fbc61ae11d57cb5d8224f525bd304c6be05bbb"
+dependencies = [
+ "base64-simd",
+ "data-url",
+ "rkyv",
+ "serde",
+ "serde_json",
+ "vlq",
+]
+
[[package]]
name = "parking_lot"
-version = "0.12.1"
+version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -2477,37 +2853,45 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.9"
+version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if 1.0.0",
"libc",
- "redox_syscall",
+ "redox_syscall 0.5.1",
"smallvec",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.5",
]
[[package]]
name = "parse-js"
-version = "0.10.3"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30534759e6ad87aa144c396544747e1c25b1020bd133356fd758c8facec764e5"
+checksum = "9ec3b11d443640ec35165ee8f6f0559f1c6f41878d70330fe9187012b5935f02"
dependencies = [
"aho-corasick 0.7.20",
+ "bumpalo",
+ "hashbrown 0.13.2",
"lazy_static",
"memchr",
]
[[package]]
name = "parse-zoneinfo"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
+checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
dependencies = [
"regex",
]
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
[[package]]
name = "path-slash"
version = "0.2.1"
@@ -2528,9 +2912,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pest"
-version = "2.7.5"
+version = "2.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5"
+checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8"
dependencies = [
"memchr",
"thiserror",
@@ -2539,9 +2923,9 @@ dependencies = [
[[package]]
name = "pest_derive"
-version = "2.7.5"
+version = "2.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2"
+checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459"
dependencies = [
"pest",
"pest_generator",
@@ -2549,22 +2933,22 @@ dependencies = [
[[package]]
name = "pest_generator"
-version = "2.7.5"
+version = "2.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227"
+checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
]
[[package]]
name = "pest_meta"
-version = "2.7.5"
+version = "2.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6"
+checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd"
dependencies = [
"once_cell",
"pest",
@@ -2577,9 +2961,7 @@ version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
dependencies = [
- "phf_macros",
"phf_shared 0.10.0",
- "proc-macro-hack",
]
[[package]]
@@ -2588,6 +2970,7 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
+ "phf_macros",
"phf_shared 0.11.2",
]
@@ -2633,16 +3016,15 @@ dependencies = [
[[package]]
name = "phf_macros"
-version = "0.10.0"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0"
+checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
dependencies = [
- "phf_generator 0.10.0",
- "phf_shared 0.10.0",
- "proc-macro-hack",
+ "phf_generator 0.11.2",
+ "phf_shared 0.11.2",
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.61",
]
[[package]]
@@ -2665,9 +3047,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
-version = "0.2.13"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
@@ -2677,18 +3059,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.27"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "plist"
-version = "1.6.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
+checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9"
dependencies = [
- "base64",
- "indexmap 2.1.0",
+ "base64 0.21.7",
+ "indexmap 2.2.6",
"line-wrap",
"quick-xml 0.31.0",
"serde",
@@ -2697,9 +3079,9 @@ dependencies = [
[[package]]
name = "png"
-version = "0.17.10"
+version = "0.17.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64"
+checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"
dependencies = [
"bitflags 1.3.2",
"crc32fast",
@@ -2751,38 +3133,71 @@ dependencies = [
]
[[package]]
-name = "proc-macro-hack"
-version = "0.5.20+deprecated"
+name = "proc-macro2"
+version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
+checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
+dependencies = [
+ "unicode-ident",
+]
[[package]]
-name = "proc-macro2"
-version = "1.0.70"
+name = "profiling"
+version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
+checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
dependencies = [
- "unicode-ident",
+ "profiling-procmacros",
+]
+
+[[package]]
+name = "profiling-procmacros"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
+dependencies = [
+ "quote",
+ "syn 2.0.61",
+]
+
+[[package]]
+name = "ptr_meta"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
+dependencies = [
+ "ptr_meta_derive",
+]
+
+[[package]]
+name = "ptr_meta_derive"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
]
[[package]]
name = "pulldown-cmark"
-version = "0.9.3"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
+checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.5.0",
"memchr",
"unicase",
]
[[package]]
name = "pulldown-cmark"
-version = "0.10.0"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dce76ce678ffc8e5675b22aa1405de0b7037e2fdf8913fea40d1926c6fe1e6e7"
+checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.5.0",
"memchr",
"pulldown-cmark-escape",
"unicase",
@@ -2790,15 +3205,15 @@ dependencies = [
[[package]]
name = "pulldown-cmark-escape"
-version = "0.10.0"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5d8f9aa0e3cbcfaf8bf00300004ee3b72f74770f9cbac93f6928771f613276b"
+checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3"
[[package]]
name = "pure-rust-locales"
-version = "0.7.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed02a829e62dc2715ceb8afb4f80e298148e1345749ceb369540fe0eb3368432"
+checksum = "1190fd18ae6ce9e137184f207593877e70f39b015040156b1e05081cdfe3733a"
[[package]]
name = "qoi"
@@ -2835,11 +3250,12 @@ dependencies = [
[[package]]
name = "quickxml_to_serde"
-version = "0.5.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26f35112b35480fd72f63444289083eeedbd61d13907c82c4309f0ccda35e244"
+checksum = "286b05c7a00b356ff6ac5218e10d628e0a3be02e777d067ca7286d353c3c407e"
dependencies = [
"minidom",
+ "regex",
"serde",
"serde_derive",
"serde_json",
@@ -2847,13 +3263,19 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.33"
+version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
+[[package]]
+name = "radium"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+
[[package]]
name = "rand"
version = "0.7.3"
@@ -2913,7 +3335,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
- "getrandom 0.2.11",
+ "getrandom 0.2.15",
]
[[package]]
@@ -2925,11 +3347,61 @@ dependencies = [
"rand_core 0.5.1",
]
+[[package]]
+name = "rav1e"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9"
+dependencies = [
+ "arbitrary",
+ "arg_enum_proc_macro",
+ "arrayvec",
+ "av1-grain",
+ "bitstream-io",
+ "built",
+ "cfg-if 1.0.0",
+ "interpolate_name",
+ "itertools 0.12.1",
+ "libc",
+ "libfuzzer-sys",
+ "log",
+ "maybe-rayon",
+ "new_debug_unreachable",
+ "noop_proc_macro",
+ "num-derive",
+ "num-traits",
+ "once_cell",
+ "paste",
+ "profiling",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
+ "simd_helpers",
+ "system-deps",
+ "thiserror",
+ "v_frame",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "ravif"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc13288f5ab39e6d7c9d501759712e6969fcc9734220846fc9ed26cae2cc4234"
+dependencies = [
+ "avif-serialize",
+ "imgref",
+ "loop9",
+ "quick-error",
+ "rav1e",
+ "rayon",
+ "rgb",
+]
+
[[package]]
name = "rayon"
-version = "1.8.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
@@ -2937,9 +3409,9 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.12.0"
+version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
@@ -2954,55 +3426,67 @@ dependencies = [
"bitflags 1.3.2",
]
+[[package]]
+name = "redox_syscall"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
+dependencies = [
+ "bitflags 2.5.0",
+]
+
[[package]]
name = "regex"
-version = "1.10.2"
+version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
+checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
- "aho-corasick 1.1.2",
+ "aho-corasick 1.1.3",
"memchr",
"regex-automata",
- "regex-syntax 0.8.2",
+ "regex-syntax",
]
[[package]]
name = "regex-automata"
-version = "0.4.3"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
- "aho-corasick 1.1.2",
+ "aho-corasick 1.1.3",
"memchr",
- "regex-syntax 0.8.2",
+ "regex-syntax",
]
[[package]]
name = "regex-syntax"
-version = "0.7.5"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
-name = "regex-syntax"
-version = "0.8.2"
+name = "relative-path"
+version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
[[package]]
-name = "relative-path"
-version = "1.9.0"
+name = "rend"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c707298afce11da2efef2f600116fa93ffa7a032b5d7b628aa17711ec81383ca"
+checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
+dependencies = [
+ "bytecheck",
+]
[[package]]
name = "reqwest"
-version = "0.11.22"
+version = "0.11.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
+checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
dependencies = [
- "base64",
- "bytes 1.5.0",
+ "base64 0.21.7",
+ "bytes 1.6.0",
"encoding_rs",
"futures-core",
"futures-util",
@@ -3025,6 +3509,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
+ "sync_wrapper",
"system-configuration",
"tokio",
"tokio-native-tls",
@@ -3038,18 +3523,57 @@ dependencies = [
"winreg",
]
+[[package]]
+name = "rgb"
+version = "0.8.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8"
+dependencies = [
+ "bytemuck",
+]
+
[[package]]
name = "ring"
-version = "0.17.7"
+version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
+checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
- "getrandom 0.2.11",
+ "cfg-if 1.0.0",
+ "getrandom 0.2.15",
"libc",
"spin",
"untrusted",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rkyv"
+version = "0.7.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0"
+dependencies = [
+ "bitvec",
+ "bytecheck",
+ "bytes 1.6.0",
+ "hashbrown 0.12.3",
+ "ptr_meta",
+ "rend",
+ "rkyv_derive",
+ "seahash",
+ "tinyvec",
+ "uuid",
+]
+
+[[package]]
+name = "rkyv_derive"
+version = "0.7.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
]
[[package]]
@@ -3073,9 +3597,9 @@ dependencies = [
[[package]]
name = "rustc-demangle"
-version = "0.1.23"
+version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
@@ -3083,22 +3607,13 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-[[package]]
-name = "rustc_version"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
-dependencies = [
- "semver",
-]
-
[[package]]
name = "rustix"
-version = "0.38.28"
+version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.5.0",
"errno",
"libc",
"linux-raw-sys",
@@ -3107,9 +3622,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.21.10"
+version = "0.21.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
+checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
dependencies = [
"log",
"ring",
@@ -3123,7 +3638,7 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
dependencies = [
- "base64",
+ "base64 0.21.7",
]
[[package]]
@@ -3138,15 +3653,9 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
-
-[[package]]
-name = "safemem"
-version = "0.3.3"
+version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
@@ -3159,11 +3668,11 @@ dependencies = [
[[package]]
name = "schannel"
-version = "0.1.22"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
+checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
dependencies = [
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -3182,6 +3691,12 @@ dependencies = [
"untrusted",
]
+[[package]]
+name = "seahash"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
+
[[package]]
name = "search"
version = "0.1.0"
@@ -3194,11 +3709,11 @@ dependencies = [
[[package]]
name = "security-framework"
-version = "2.9.2"
+version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
+checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.5.0",
"core-foundation",
"core-foundation-sys",
"libc",
@@ -3207,9 +3722,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.9.1"
+version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
+checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7"
dependencies = [
"core-foundation-sys",
"libc",
@@ -3217,40 +3732,40 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.20"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
dependencies = [
"serde",
]
[[package]]
name = "serde"
-version = "1.0.193"
+version = "1.0.201"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
+checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.193"
+version = "1.0.201"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
+checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
]
[[package]]
name = "serde_json"
-version = "1.0.108"
+version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
+checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.6",
"itoa",
"ryu",
"serde",
@@ -3258,9 +3773,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "0.6.4"
+version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80"
+checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
dependencies = [
"serde",
]
@@ -3279,11 +3794,11 @@ dependencies = [
[[package]]
name = "serde_yaml"
-version = "0.9.27"
+version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c"
+checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.6",
"itoa",
"ryu",
"serde",
@@ -3313,17 +3828,41 @@ dependencies = [
"digest 0.10.7",
]
+[[package]]
+name = "simd-abstraction"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987"
+dependencies = [
+ "outref",
+]
+
[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
+[[package]]
+name = "simd_helpers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6"
+dependencies = [
+ "quote",
+]
+
+[[package]]
+name = "simdutf8"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
+
[[package]]
name = "similar"
-version = "2.3.0"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597"
+checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640"
[[package]]
name = "siphasher"
@@ -3360,7 +3899,7 @@ dependencies = [
"cargo_metadata",
"error-chain",
"glob",
- "pulldown-cmark 0.9.3",
+ "pulldown-cmark 0.9.6",
"tempfile",
"walkdir",
]
@@ -3386,28 +3925,18 @@ dependencies = [
[[package]]
name = "smallvec"
-version = "1.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
-
-[[package]]
-name = "socket2"
-version = "0.4.10"
+version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
-dependencies = [
- "libc",
- "winapi 0.3.9",
-]
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
-version = "0.5.5"
+version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
+checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -3451,6 +3980,12 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
[[package]]
name = "svg_metadata"
version = "0.5.0"
@@ -3477,20 +4012,26 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.41"
+version = "2.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
+checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
+[[package]]
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
[[package]]
name = "syntect"
-version = "5.1.0"
+version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91"
+checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
dependencies = [
"bincode",
"bitflags 1.3.2",
@@ -3499,8 +4040,9 @@ dependencies = [
"once_cell",
"onig",
"plist",
- "regex-syntax 0.7.5",
+ "regex-syntax",
"serde",
+ "serde_derive",
"serde_json",
"thiserror",
"walkdir",
@@ -3528,6 +4070,25 @@ dependencies = [
"libc",
]
+[[package]]
+name = "system-deps"
+version = "6.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
+dependencies = [
+ "cfg-expr",
+ "heck 0.5.0",
+ "pkg-config",
+ "toml 0.8.12",
+ "version-compare",
+]
+
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
[[package]]
name = "tar"
version = "0.4.40"
@@ -3539,17 +4100,22 @@ dependencies = [
"xattr",
]
+[[package]]
+name = "target-lexicon"
+version = "0.12.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
+
[[package]]
name = "tempfile"
-version = "3.8.1"
+version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
"cfg-if 1.0.0",
"fastrand",
- "redox_syscall",
"rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -3602,9 +4168,9 @@ dependencies = [
[[package]]
name = "termcolor"
-version = "1.4.0"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
@@ -3627,7 +4193,7 @@ dependencies = [
"cfg-if 1.0.0",
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
]
[[package]]
@@ -3638,41 +4204,41 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
"test-case-core",
]
[[package]]
name = "textwrap"
-version = "0.16.0"
+version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
+checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
[[package]]
name = "thiserror"
-version = "1.0.51"
+version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
+checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.51"
+version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
+checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
]
[[package]]
name = "tiff"
-version = "0.9.0"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211"
+checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e"
dependencies = [
"flate2",
"jpeg-decoder",
@@ -3681,13 +4247,14 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.30"
+version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
+checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"libc",
+ "num-conv",
"num_threads",
"powerfmt",
"serde",
@@ -3703,10 +4270,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
-version = "0.2.15"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
+checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
+ "num-conv",
"time-core",
]
@@ -3736,17 +4304,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.35.0"
+version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c"
+checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
dependencies = [
"backtrace",
- "bytes 1.5.0",
+ "bytes 1.6.0",
"libc",
- "mio 0.8.10",
- "num_cpus",
+ "mio 0.8.11",
"pin-project-lite",
- "socket2 0.5.5",
+ "socket2",
"windows-sys 0.48.0",
]
@@ -3772,16 +4339,15 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.10"
+version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
+checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
dependencies = [
- "bytes 1.5.0",
+ "bytes 1.6.0",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
- "tracing",
]
[[package]]
@@ -3795,9 +4361,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.8.8"
+version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
+checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
dependencies = [
"serde",
"serde_spanned",
@@ -3816,11 +4382,11 @@ dependencies = [
[[package]]
name = "toml_edit"
-version = "0.21.0"
+version = "0.22.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
+checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.6",
"serde",
"serde_spanned",
"toml_datetime",
@@ -3949,9 +4515,9 @@ dependencies = [
[[package]]
name = "unicode-bidi"
-version = "0.3.14"
+version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
@@ -3961,24 +4527,24 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
-version = "0.1.22"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
-version = "1.10.1"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "unsafe-libyaml"
-version = "0.2.10"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
name = "untrusted"
@@ -4019,23 +4585,52 @@ dependencies = [
"tempfile",
]
+[[package]]
+name = "uuid"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
+
+[[package]]
+name = "v_frame"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b"
+dependencies = [
+ "aligned-vec",
+ "num-traits",
+ "wasm-bindgen",
+]
+
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+[[package]]
+name = "version-compare"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
+
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+[[package]]
+name = "vlq"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65dd7eed29412da847b0f78bcec0ac98588165988a8cfe41d4ea1d429f8ccfff"
+
[[package]]
name = "walkdir"
-version = "2.4.0"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
@@ -4064,9 +4659,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.89"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@@ -4074,24 +4669,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.89"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.39"
+version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
+checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@@ -4101,9 +4696,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.89"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -4111,28 +4706,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.89"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.89"
+version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "web-sys"
-version = "0.3.66"
+version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f"
+checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -4140,9 +4735,9 @@ dependencies = [
[[package]]
name = "webp"
-version = "0.2.6"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bb5d8e7814e92297b0e1c773ce43d290bef6c17452dafd9fc49e5edb5beba71"
+checksum = "8f53152f51fb5af0c08484c33d16cca96175881d1f3dec068c23b31a158c2d99"
dependencies = [
"image",
"libwebp-sys",
@@ -4150,15 +4745,15 @@ dependencies = [
[[package]]
name = "webpki-roots"
-version = "0.25.3"
+version = "0.25.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
+checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
[[package]]
name = "weezl"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
+checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
[[package]]
name = "winapi"
@@ -4190,11 +4785,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
-version = "0.1.6"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
+checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
- "winapi 0.3.9",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -4205,20 +4800,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
-version = "0.51.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.45.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
- "windows-targets 0.42.2",
+ "windows-targets 0.52.5",
]
[[package]]
@@ -4236,22 +4822,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets 0.52.0",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets 0.52.5",
]
[[package]]
@@ -4271,25 +4842,20 @@ dependencies = [
[[package]]
name = "windows-targets"
-version = "0.52.0"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
- "windows_aarch64_gnullvm 0.52.0",
- "windows_aarch64_msvc 0.52.0",
- "windows_i686_gnu 0.52.0",
- "windows_i686_msvc 0.52.0",
- "windows_x86_64_gnu 0.52.0",
- "windows_x86_64_gnullvm 0.52.0",
- "windows_x86_64_msvc 0.52.0",
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
]
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
-
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
@@ -4298,15 +4864,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.42.2"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
@@ -4316,15 +4876,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.42.2"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
@@ -4334,15 +4888,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
-version = "0.52.0"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
-name = "windows_i686_msvc"
-version = "0.42.2"
+name = "windows_i686_gnullvm"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
@@ -4352,15 +4906,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.42.2"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
@@ -4370,15 +4918,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.42.2"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -4388,15 +4930,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.42.2"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
@@ -4406,15 +4942,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.52.0"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "winnow"
-version = "0.5.28"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2"
+checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
dependencies = [
"memchr",
]
@@ -4466,11 +5002,20 @@ dependencies = [
"winapi-build",
]
+[[package]]
+name = "wyz"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
+dependencies = [
+ "tap",
+]
+
[[package]]
name = "xattr"
-version = "1.1.3"
+version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7dae5072fe1f8db8f8d29059189ac175196e410e40ba42d5d4684ae2f750995"
+checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
dependencies = [
"libc",
"linux-raw-sys",
@@ -4485,9 +5030,9 @@ checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
[[package]]
name = "yada"
-version = "0.5.0"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6d12cb7a57bbf2ab670ed9545bae3648048547f9039279a89ce000208e585c1"
+checksum = "aed111bd9e48a802518765906cbdadf0b45afb72b9c81ab049a3b86252adffdd"
[[package]]
name = "yaml-rust"
@@ -4500,29 +5045,29 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.7.31"
+version = "0.7.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d"
+checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.7.31"
+version = "0.7.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
+checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.41",
+ "syn 2.0.61",
]
[[package]]
name = "zola"
version = "0.18.0"
dependencies = [
- "clap 4.4.11",
+ "clap 4.5.4",
"clap_complete",
"console 0.1.0",
"ctrlc",
@@ -4543,6 +5088,12 @@ dependencies = [
"ws",
]
+[[package]]
+name = "zune-core"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
+
[[package]]
name = "zune-inflate"
version = "0.2.54"
@@ -4551,3 +5102,12 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
dependencies = [
"simd-adler32",
]
+
+[[package]]
+name = "zune-jpeg"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448"
+dependencies = [
+ "zune-core",
+]
diff --git a/components/imageproc/src/processor.rs b/components/imageproc/src/processor.rs
index 2c6a17b725..678e84a1f5 100644
--- a/components/imageproc/src/processor.rs
+++ b/components/imageproc/src/processor.rs
@@ -7,10 +7,11 @@ use config::Config;
use errors::{anyhow, Context, Result};
use libs::ahash::{HashMap, HashSet};
use libs::image::imageops::FilterType;
-use libs::image::{EncodableLayout, ImageOutputFormat};
+use libs::image::{EncodableLayout, ImageFormat};
use libs::rayon::prelude::*;
use libs::{image, webp};
use serde::{Deserialize, Serialize};
+use libs::image::codecs::jpeg::JpegEncoder;
use utils::fs as ufs;
use crate::format::Format;
@@ -55,10 +56,11 @@ impl ImageOp {
match self.format {
Format::Png => {
- img.write_to(&mut buffered_f, ImageOutputFormat::Png)?;
+ img.write_to(&mut buffered_f, ImageFormat::Png)?;
}
Format::Jpeg(q) => {
- img.write_to(&mut buffered_f, ImageOutputFormat::Jpeg(q))?;
+ let mut encoder = JpegEncoder::new_with_quality(&mut buffered_f, q);
+ encoder.encode_image(&img)?;
}
Format::WebP(q) => {
let encoder = webp::Encoder::from_image(&img)
diff --git a/components/libs/Cargo.toml b/components/libs/Cargo.toml
index 9f6abf1d58..7c23ff3127 100644
--- a/components/libs/Cargo.toml
+++ b/components/libs/Cargo.toml
@@ -5,25 +5,25 @@ edition = "2021"
[dependencies]
ahash = "0.8"
-ammonia = "3"
+ammonia = "4"
atty = "0.2.11"
-base64 = "0.21"
+base64 = "0.22"
csv = "1"
elasticlunr-rs = { version = "3.0.2", features = ["da", "no", "de", "du", "es", "fi", "fr", "hu", "it", "pt", "ro", "ru", "sv", "tr"] }
filetime = "0.2"
gh-emoji = "1"
glob = "0.3"
globset = "0.4"
-image = "0.24"
+image = "0.25"
lexical-sort = "0.3"
-minify-html = "0.11"
+minify-html = "0.15"
nom-bibtex = "0.5"
num-format = "0.4"
once_cell = "1"
percent-encoding = "2"
pulldown-cmark = { version = "0.10", default-features = false, features = ["html", "simd"] }
pulldown-cmark-escape = { version = "0.10", default-features = false }
-quickxml_to_serde = "0.5"
+quickxml_to_serde = "0.6"
rayon = "1"
regex = "1"
relative-path = "1"
@@ -43,7 +43,7 @@ unic-langid = "0.9"
unicode-segmentation = "1.2"
url = "2"
walkdir = "2"
-webp = "0.2"
+webp = "0.3"
[features]
From eccc642a0001f07002a6cd93a8a2ab75d544e9ed Mon Sep 17 00:00:00 2001
From: Vincent Prouillet
Date: Thu, 9 May 2024 23:26:18 +0200
Subject: [PATCH 20/25] Update changelog
---
CHANGELOG.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7edc406a2e..b53c298784 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@
## 0.19.0 (unreleased)
- Updates the pulldown-cmark dependency to v0.10.0. This improves footnote handling, and may also introduce some minor behavior changes such as reducing the amount of unnecessary HTML-escaping of text content.
+- Add bottom footnotes with backreference option
+- Fix link check report inconsistency
+- Fix resizing for images with EXIF orientation
+- Add MIME type to get_image_metadata
## 0.18.0 (2023-12-18)
From 731e6c05ad6a0e97b90cfd83dcd8a802df1a1932 Mon Sep 17 00:00:00 2001
From: Vincent Prouillet
Date: Sun, 12 May 2024 21:19:35 +0200
Subject: [PATCH 21/25] Update msrv
---
azure-pipelines.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 0221c7169f..2ac2cae6d2 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -21,7 +21,7 @@ stages:
rustup_toolchain: stable
linux-pinned:
imageName: 'ubuntu-20.04'
- rustup_toolchain: 1.71.1
+ rustup_toolchain: 1.74.0
pool:
vmImage: $(imageName)
steps:
From 83d144d1414df961339005e243c529e498bdd626 Mon Sep 17 00:00:00 2001
From: Vincent Prouillet
Date: Sun, 12 May 2024 22:11:13 +0200
Subject: [PATCH 22/25] update tests
---
components/site/src/minify.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/site/src/minify.rs b/components/site/src/minify.rs
index 8f3862b902..7c613299e9 100644
--- a/components/site/src/minify.rs
+++ b/components/site/src/minify.rs
@@ -108,7 +108,7 @@ mod tests {
"#;
- let expected = r#"Example blog post
FOO BAR"#;
+ let expected = r#"Example blog post
FOO BAR"#;
let res = html(input.to_owned()).unwrap();
assert_eq!(res, expected);
}
@@ -135,7 +135,7 @@ mod tests {
"#;
- let expected = r#"Example blog post
FOO BAR"#;
+ let expected = r#"Example blog post
FOO BAR"#;
let res = html(input.to_owned()).unwrap();
assert_eq!(res, expected);
}
From cebeb3a90e5cc2f9560075471fc69ad89c9af3e7 Mon Sep 17 00:00:00 2001
From: Vincent Prouillet
Date: Mon, 13 May 2024 10:20:22 +0200
Subject: [PATCH 23/25] cargo fmt
---
components/imageproc/src/processor.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/imageproc/src/processor.rs b/components/imageproc/src/processor.rs
index 678e84a1f5..577aeb1f3e 100644
--- a/components/imageproc/src/processor.rs
+++ b/components/imageproc/src/processor.rs
@@ -6,12 +6,12 @@ use std::path::{Path, PathBuf};
use config::Config;
use errors::{anyhow, Context, Result};
use libs::ahash::{HashMap, HashSet};
+use libs::image::codecs::jpeg::JpegEncoder;
use libs::image::imageops::FilterType;
use libs::image::{EncodableLayout, ImageFormat};
use libs::rayon::prelude::*;
use libs::{image, webp};
use serde::{Deserialize, Serialize};
-use libs::image::codecs::jpeg::JpegEncoder;
use utils::fs as ufs;
use crate::format::Format;
From 8842da7523ba45dce32f6dd2bfc2d066c2ecb641 Mon Sep 17 00:00:00 2001
From: Luca Versari
Date: Wed, 1 May 2024 10:37:58 +0200
Subject: [PATCH 24/25] Add JPEG XL support to image processing.
As discussed in #2421.
---
Cargo.lock | 115 ++++++++++++++++++
components/imageproc/src/format.rs | 10 +-
components/imageproc/src/meta.rs | 31 ++++-
components/imageproc/src/processor.rs | 53 +++++++-
components/imageproc/tests/resize_image.rs | 10 ++
components/imageproc/tests/test_imgs/jxl.jxl | Bin 0 -> 21972 bytes
components/libs/Cargo.toml | 1 +
components/libs/src/lib.rs | 1 +
.../content/image-processing/index.md | 1 +
9 files changed, 210 insertions(+), 12 deletions(-)
create mode 100644 components/imageproc/tests/test_imgs/jxl.jxl
diff --git a/Cargo.lock b/Cargo.lock
index 293d58133a..4c5e73796a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -636,6 +636,15 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+[[package]]
+name = "cmake"
+version = "0.1.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "codemap"
version = "0.1.3"
@@ -876,6 +885,41 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "darling"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim 0.10.0",
+ "syn 2.0.61",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 2.0.61",
+]
+
[[package]]
name = "dashmap"
version = "5.5.3"
@@ -913,6 +957,37 @@ dependencies = [
"powerfmt",
]
+[[package]]
+name = "derive_builder"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7"
+dependencies = [
+ "derive_builder_macro",
+]
+
+[[package]]
+name = "derive_builder_core"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.61",
+]
+
+[[package]]
+name = "derive_builder_macro"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b"
+dependencies = [
+ "derive_builder_core",
+ "syn 2.0.61",
+]
+
[[package]]
name = "deunicode"
version = "1.4.4"
@@ -1654,6 +1729,12 @@ dependencies = [
"cc",
]
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
[[package]]
name = "idna"
version = "0.5.0"
@@ -1889,6 +1970,39 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
+[[package]]
+name = "jpegxl-rs"
+version = "0.10.3+libjxl-0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e697c7532d4a244d91306a19c63763769366fbc61e75d5a08cc602923e478a7a"
+dependencies = [
+ "byteorder",
+ "derive_builder",
+ "half",
+ "image",
+ "jpegxl-sys",
+ "thiserror",
+]
+
+[[package]]
+name = "jpegxl-src"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7808dc25b79f6ff27137f91b1b7659eb27f570d401ff464d03fd336041fc5c68"
+dependencies = [
+ "cmake",
+]
+
+[[package]]
+name = "jpegxl-sys"
+version = "0.10.3+libjxl-0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8262d19ed55829441dc2a2b1315c8f15e040139443fc1dbc48551890020a5c2"
+dependencies = [
+ "jpegxl-src",
+ "pkg-config",
+]
+
[[package]]
name = "js-sys"
version = "0.3.69"
@@ -1992,6 +2106,7 @@ dependencies = [
"globset",
"grass",
"image",
+ "jpegxl-rs",
"lexical-sort",
"minify-html",
"nom-bibtex",
diff --git a/components/imageproc/src/format.rs b/components/imageproc/src/format.rs
index d7c992eab8..ea49d73756 100644
--- a/components/imageproc/src/format.rs
+++ b/components/imageproc/src/format.rs
@@ -6,12 +6,14 @@ const DEFAULT_Q_JPG: u8 = 75;
/// Thumbnail image format
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Format {
- /// JPEG, The `u8` argument is JPEG quality (in percent).
+ /// JPEG, The `u8` argument is JPEG quality (1..100).
Jpeg(u8),
/// PNG
Png,
- /// WebP, The `u8` argument is WebP quality (in percent), None meaning lossless.
+ /// WebP, The `u8` argument is WebP quality (1..100), None meaning lossless.
WebP(Option),
+ /// JPEG XL, The `u8` argument is quality (1..100), None meaning lossless.
+ JXL(Option),
}
impl Format {
@@ -32,6 +34,7 @@ impl Format {
"jpeg" | "jpg" => Ok(Jpeg(jpg_quality)),
"png" => Ok(Png),
"webp" => Ok(WebP(quality)),
+ "jxl" => Ok(JXL(quality)),
_ => Err(anyhow!("Invalid image format: {}", format)),
}
}
@@ -44,6 +47,7 @@ impl Format {
Png => "png",
Jpeg(_) => "jpg",
WebP(_) => "webp",
+ JXL(_) => "jxl",
}
}
}
@@ -58,6 +62,8 @@ impl Hash for Format {
Jpeg(q) => 1001 + q as u16,
WebP(None) => 2000,
WebP(Some(q)) => 2001 + q as u16,
+ JXL(None) => 3000,
+ JXL(Some(q)) => 3001 + q as u16,
};
hasher.write_u16(q);
diff --git a/components/imageproc/src/meta.rs b/components/imageproc/src/meta.rs
index 8ee83c335f..1ba38897c1 100644
--- a/components/imageproc/src/meta.rs
+++ b/components/imageproc/src/meta.rs
@@ -1,6 +1,7 @@
use errors::{anyhow, Context, Result};
use libs::image::io::Reader as ImgReader;
-use libs::image::{ImageFormat, ImageResult};
+use libs::image::ImageFormat;
+use libs::jpegxl_rs::decoder_builder;
use libs::svg_metadata::Metadata as SvgMetadata;
use serde::Serialize;
use std::ffi::OsStr;
@@ -15,12 +16,23 @@ pub struct ImageMeta {
}
impl ImageMeta {
- pub fn read(path: &Path) -> ImageResult {
- let reader = ImgReader::open(path).and_then(ImgReader::with_guessed_format)?;
- let format = reader.format();
- let size = reader.into_dimensions()?;
+ pub fn read(path: &Path) -> Result {
+ if path.extension().is_some_and(|ext| ext == "jxl") {
+ Self::read_jxl(path)
+ } else {
+ let reader = ImgReader::open(path).and_then(ImgReader::with_guessed_format)?;
+ let format = reader.format();
+ let size = reader.into_dimensions()?;
- Ok(Self { size, format })
+ Ok(Self { size, format })
+ }
+ }
+
+ fn read_jxl(path: &Path) -> Result {
+ let input = std::fs::read(path)?;
+ let decoder = decoder_builder().build()?;
+ let (meta, _) = decoder.decode(&input)?;
+ Ok(ImageMeta { size: (meta.width, meta.height), format: None })
}
pub fn is_lossy(&self) -> bool {
@@ -44,6 +56,9 @@ impl ImageMetaResponse {
pub fn new_svg(width: u32, height: u32) -> Self {
Self { width, height, format: Some("svg"), mime: Some("text/svg+xml") }
}
+ pub fn new_jxl(width: u32, height: u32) -> Self {
+ Self { width, height, format: Some("jxl"), mime: Some("image/jxl") }
+ }
}
impl From for ImageMetaResponse {
@@ -75,6 +90,10 @@ pub fn read_image_metadata>(path: P) -> Result
// this is not a typo, this returns the correct values for width and height.
.map(|(h, w)| ImageMetaResponse::new_svg(w as u32, h as u32))
}
+ "jxl" => {
+ let meta = ImageMeta::read(path)?;
+ Ok(ImageMetaResponse::new_jxl(meta.size.0, meta.size.1))
+ }
_ => ImageMeta::read(path).map(ImageMetaResponse::from).with_context(err_context),
}
}
diff --git a/components/imageproc/src/processor.rs b/components/imageproc/src/processor.rs
index 577aeb1f3e..72f8a42615 100644
--- a/components/imageproc/src/processor.rs
+++ b/components/imageproc/src/processor.rs
@@ -4,13 +4,16 @@ use std::io::{BufWriter, Write};
use std::path::{Path, PathBuf};
use config::Config;
-use errors::{anyhow, Context, Result};
+use errors::{anyhow, bail, Context, Result};
use libs::ahash::{HashMap, HashSet};
use libs::image::codecs::jpeg::JpegEncoder;
use libs::image::imageops::FilterType;
-use libs::image::{EncodableLayout, ImageFormat};
+use libs::image::{ColorType, EncodableLayout, ImageFormat};
+use libs::jpegxl_rs::decoder_builder;
+use libs::jpegxl_rs::encode::EncoderFrame;
+use libs::jpegxl_rs::image::ToDynamic;
use libs::rayon::prelude::*;
-use libs::{image, webp};
+use libs::{image, jpegxl_rs, webp};
use serde::{Deserialize, Serialize};
use utils::fs as ufs;
@@ -39,7 +42,15 @@ impl ImageOp {
return Ok(());
}
- let img = image::open(&self.input_path)?;
+ let img = if self.input_path.extension().is_some_and(|ext| ext == "jxl") {
+ let input = std::fs::read(&self.input_path)?;
+ let decoder = decoder_builder().build()?;
+ decoder
+ .decode_to_image(&input)?
+ .context("jxl image could not be represented in an Image")?
+ } else {
+ image::open(&self.input_path)?
+ };
let mut img = fix_orientation(&img, &self.input_path).unwrap_or(img);
let img = match self.instr.crop_instruction {
@@ -71,6 +82,40 @@ impl ImageOp {
};
buffered_f.write_all(memory.as_bytes())?;
}
+ Format::JXL(q) => {
+ let mut encoder = jpegxl_rs::encoder_builder();
+ if let Some(q) = q {
+ if q == 100 {
+ encoder.uses_original_profile(true);
+ encoder.lossless(true);
+ } else {
+ encoder.set_jpeg_quality(q as f32);
+ }
+ } else {
+ encoder.uses_original_profile(true);
+ encoder.lossless(true);
+ }
+ let frame = EncoderFrame::new(img.as_bytes());
+ let frame = match img.color() {
+ ColorType::L8 => frame.num_channels(1),
+ ColorType::La8 => {
+ encoder.has_alpha(true);
+ frame.num_channels(2)
+ }
+ ColorType::Rgb8 => frame.num_channels(3),
+ ColorType::Rgba8 => {
+ encoder.has_alpha(true);
+ frame.num_channels(4)
+ }
+ _ => {
+ bail!("Unsupported pixel type {:?}", img.color());
+ }
+ };
+ let mut encoder = encoder.build()?;
+ buffered_f.write_all(
+ &encoder.encode_frame::(&frame, img.width(), img.height())?.data,
+ )?;
+ }
}
Ok(())
diff --git a/components/imageproc/tests/resize_image.rs b/components/imageproc/tests/resize_image.rs
index 41114abf50..40e32732e1 100644
--- a/components/imageproc/tests/resize_image.rs
+++ b/components/imageproc/tests/resize_image.rs
@@ -132,6 +132,16 @@ fn resize_image_webp_jpg() {
image_op_test("webp.webp", "scale", Some(150), Some(150), "auto", "jpg", 150, 150, 300, 380);
}
+#[test]
+fn resize_image_png_jxl() {
+ image_op_test("png.png", "scale", Some(150), Some(150), "jxl", "jxl", 150, 150, 300, 380);
+}
+
+#[test]
+fn resize_image_jxl_png() {
+ image_op_test("jxl.jxl", "scale", Some(150), Some(150), "png", "png", 150, 150, 300, 380);
+}
+
#[test]
fn read_image_metadata_jpg() {
assert_eq!(
diff --git a/components/imageproc/tests/test_imgs/jxl.jxl b/components/imageproc/tests/test_imgs/jxl.jxl
new file mode 100644
index 0000000000000000000000000000000000000000..a5e3db1de35224a54f7f1cd3ffe582a217bb6e03
GIT binary patch
literal 21972
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
Date: Thu, 16 May 2024 14:41:07 +0200
Subject: [PATCH 25/25] Rename JXL -> JpegXl
---
components/imageproc/src/format.rs | 10 +++++-----
components/imageproc/src/processor.rs | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/components/imageproc/src/format.rs b/components/imageproc/src/format.rs
index ea49d73756..f0f6bb69a0 100644
--- a/components/imageproc/src/format.rs
+++ b/components/imageproc/src/format.rs
@@ -13,7 +13,7 @@ pub enum Format {
/// WebP, The `u8` argument is WebP quality (1..100), None meaning lossless.
WebP(Option),
/// JPEG XL, The `u8` argument is quality (1..100), None meaning lossless.
- JXL(Option),
+ JpegXL(Option),
}
impl Format {
@@ -34,7 +34,7 @@ impl Format {
"jpeg" | "jpg" => Ok(Jpeg(jpg_quality)),
"png" => Ok(Png),
"webp" => Ok(WebP(quality)),
- "jxl" => Ok(JXL(quality)),
+ "jxl" => Ok(JpegXL(quality)),
_ => Err(anyhow!("Invalid image format: {}", format)),
}
}
@@ -47,7 +47,7 @@ impl Format {
Png => "png",
Jpeg(_) => "jpg",
WebP(_) => "webp",
- JXL(_) => "jxl",
+ JpegXL(_) => "jxl",
}
}
}
@@ -62,8 +62,8 @@ impl Hash for Format {
Jpeg(q) => 1001 + q as u16,
WebP(None) => 2000,
WebP(Some(q)) => 2001 + q as u16,
- JXL(None) => 3000,
- JXL(Some(q)) => 3001 + q as u16,
+ JpegXL(None) => 3000,
+ JpegXL(Some(q)) => 3001 + q as u16,
};
hasher.write_u16(q);
diff --git a/components/imageproc/src/processor.rs b/components/imageproc/src/processor.rs
index 72f8a42615..48e661127a 100644
--- a/components/imageproc/src/processor.rs
+++ b/components/imageproc/src/processor.rs
@@ -82,7 +82,7 @@ impl ImageOp {
};
buffered_f.write_all(memory.as_bytes())?;
}
- Format::JXL(q) => {
+ Format::JpegXL(q) => {
let mut encoder = jpegxl_rs::encoder_builder();
if let Some(q) = q {
if q == 100 {