diff --git a/Cargo.lock b/Cargo.lock index 10fae527..90b8073f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -809,10 +809,10 @@ dependencies = [ "futures-util", "gitignore", "handlebars", - "lazy_static", "log", "memchr", "notify", + "once_cell", "opener", "predicates", "pretty_assertions", @@ -997,6 +997,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" + [[package]] name = "opaque-debug" version = "0.2.3" diff --git a/Cargo.toml b/Cargo.toml index b1c095d3..07b2ed78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,9 +20,9 @@ anyhow = "1.0.28" chrono = "0.4" clap = { version = "3.0", features = ["cargo"] } clap_complete = "3.0" +once_cell = "1" env_logger = "0.9.0" handlebars = "4.0" -lazy_static = "1.0" log = "0.4" memchr = "2.0" opener = "0.5" diff --git a/src/preprocess/index.rs b/src/preprocess/index.rs index d8a4e375..004b7eda 100644 --- a/src/preprocess/index.rs +++ b/src/preprocess/index.rs @@ -4,8 +4,8 @@ use std::path::Path; use super::{Preprocessor, PreprocessorContext}; use crate::book::{Book, BookItem}; use crate::errors::*; -use lazy_static::lazy_static; use log::warn; +use once_cell::sync::Lazy; /// A preprocessor for converting file name `README.md` to `index.md` since /// `README.md` is the de facto index file in markdown-based documentation. @@ -68,9 +68,8 @@ fn warn_readme_name_conflict>(readme_path: P, index_path: P) { } fn is_readme_file>(path: P) -> bool { - lazy_static! { - static ref RE: Regex = Regex::new(r"(?i)^readme$").unwrap(); - } + static RE: Lazy = Lazy::new(|| Regex::new(r"(?i)^readme$").unwrap()); + RE.is_match( path.as_ref() .file_stem() diff --git a/src/preprocess/links.rs b/src/preprocess/links.rs index 81575e86..c2c81f52 100644 --- a/src/preprocess/links.rs +++ b/src/preprocess/links.rs @@ -10,8 +10,8 @@ use std::path::{Path, PathBuf}; use super::{Preprocessor, PreprocessorContext}; use crate::book::{Book, BookItem}; -use lazy_static::lazy_static; use log::{error, warn}; +use once_cell::sync::Lazy; const ESCAPE_CHAR: char = '\\'; const MAX_LINK_NESTED_DEPTH: usize = 10; @@ -410,19 +410,20 @@ impl<'a> Iterator for LinkIter<'a> { fn find_links(contents: &str) -> LinkIter<'_> { // lazily compute following regex // r"\\\{\{#.*\}\}|\{\{#([a-zA-Z0-9]+)\s*([^}]+)\}\}")?; - lazy_static! { - static ref RE: Regex = Regex::new( + static RE: Lazy = Lazy::new(|| { + Regex::new( r"(?x) # insignificant whitespace mode - \\\{\{\#.*\}\} # match escaped link - | # or - \{\{\s* # link opening parens and whitespace - \#([a-zA-Z0-9_]+) # link type - \s+ # separating whitespace - ([^}]+) # link target path and space separated properties - \}\} # link closing parens" + \\\{\{\#.*\}\} # match escaped link + | # or + \{\{\s* # link opening parens and whitespace + \#([a-zA-Z0-9_]+) # link type + \s+ # separating whitespace + ([^}]+) # link target path and space separated properties + \}\} # link closing parens", ) - .unwrap(); - } + .unwrap() + }); + LinkIter(RE.captures_iter(contents)) } diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 9c126feb..710449af 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -14,8 +14,8 @@ use std::path::{Path, PathBuf}; use crate::utils::fs::get_404_output_file; use handlebars::Handlebars; -use lazy_static::lazy_static; use log::{debug, trace, warn}; +use once_cell::sync::Lazy; use regex::{Captures, Regex}; use serde_json::json; @@ -767,9 +767,8 @@ fn make_data( /// Goes through the rendered HTML, making sure all header tags have /// an anchor respectively so people can link to sections directly. fn build_header_links(html: &str) -> String { - lazy_static! { - static ref BUILD_HEADER_LINKS: Regex = Regex::new(r"(.*?)").unwrap(); - } + static BUILD_HEADER_LINKS: Lazy = + Lazy::new(|| Regex::new(r"(.*?)").unwrap()); let mut id_counter = HashMap::new(); @@ -810,10 +809,8 @@ fn insert_link_into_header( // ``` // This function replaces all commas by spaces in the code block classes fn fix_code_blocks(html: &str) -> String { - lazy_static! { - static ref FIX_CODE_BLOCKS: Regex = - Regex::new(r##"]+)class="([^"]+)"([^>]*)>"##).unwrap(); - } + static FIX_CODE_BLOCKS: Lazy = + Lazy::new(|| Regex::new(r##"]+)class="([^"]+)"([^>]*)>"##).unwrap()); FIX_CODE_BLOCKS .replace_all(html, |caps: &Captures<'_>| { @@ -836,10 +833,9 @@ fn add_playground_pre( playground_config: &Playground, edition: Option, ) -> String { - lazy_static! { - static ref ADD_PLAYGROUND_PRE: Regex = - Regex::new(r##"((?s)]?class="([^"]+)".*?>(.*?))"##).unwrap(); - } + static ADD_PLAYGROUND_PRE: Lazy = + Lazy::new(|| Regex::new(r##"((?s)]?class="([^"]+)".*?>(.*?))"##).unwrap()); + ADD_PLAYGROUND_PRE .replace_all(html, |caps: &Captures<'_>| { let text = &caps[1]; @@ -902,9 +898,7 @@ fn add_playground_pre( } fn hide_lines(content: &str) -> String { - lazy_static! { - static ref BORING_LINES_REGEX: Regex = Regex::new(r"^(\s*)#(.?)(.*)$").unwrap(); - } + static BORING_LINES_REGEX: Lazy = Lazy::new(|| Regex::new(r"^(\s*)#(.?)(.*)$").unwrap()); let mut result = String::with_capacity(content.len()); let mut lines = content.lines().peekable(); diff --git a/src/renderer/html_handlebars/search.rs b/src/renderer/html_handlebars/search.rs index f88893a0..a9e2f5ca 100644 --- a/src/renderer/html_handlebars/search.rs +++ b/src/renderer/html_handlebars/search.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, HashSet}; use std::path::Path; use elasticlunr::{Index, IndexBuilder}; +use once_cell::sync::Lazy; use pulldown_cmark::*; use crate::book::{Book, BookItem}; @@ -10,7 +11,6 @@ use crate::config::Search; use crate::errors::*; use crate::theme::searcher; use crate::utils; -use lazy_static::lazy_static; use log::{debug, warn}; use serde::Serialize; @@ -267,21 +267,19 @@ fn write_to_json(index: Index, search_config: &Search, doc_urls: Vec) -> } fn clean_html(html: &str) -> String { - lazy_static! { - static ref AMMONIA: ammonia::Builder<'static> = { - let mut clean_content = HashSet::new(); - clean_content.insert("script"); - clean_content.insert("style"); - let mut builder = ammonia::Builder::new(); - builder - .tags(HashSet::new()) - .tag_attributes(HashMap::new()) - .generic_attributes(HashSet::new()) - .link_rel(None) - .allowed_classes(HashMap::new()) - .clean_content_tags(clean_content); - builder - }; - } + static AMMONIA: Lazy> = Lazy::new(|| { + let mut clean_content = HashSet::new(); + clean_content.insert("script"); + clean_content.insert("style"); + let mut builder = ammonia::Builder::new(); + builder + .tags(HashSet::new()) + .tag_attributes(HashMap::new()) + .generic_attributes(HashSet::new()) + .link_rel(None) + .allowed_classes(HashMap::new()) + .clean_content_tags(clean_content); + builder + }); AMMONIA.clean(html).to_string() } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index ab1a1bcd..9f67deda 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -4,8 +4,8 @@ pub mod fs; mod string; pub(crate) mod toml_ext; use crate::errors::Error; -use lazy_static::lazy_static; use log::error; +use once_cell::sync::Lazy; use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag}; use regex::Regex; @@ -21,9 +21,7 @@ pub use self::string::{ /// Replaces multiple consecutive whitespace characters with a single space character. pub fn collapse_whitespace(text: &str) -> Cow<'_, str> { - lazy_static! { - static ref RE: Regex = Regex::new(r"\s\s+").unwrap(); - } + static RE: Lazy = Lazy::new(|| Regex::new(r"\s\s+").unwrap()); RE.replace_all(text, " ") } @@ -52,9 +50,7 @@ pub fn id_from_content(content: &str) -> String { let mut content = content.to_string(); // Skip any tags or html-encoded stuff - lazy_static! { - static ref HTML: Regex = Regex::new(r"(<.*?>)").unwrap(); - } + static HTML: Lazy = Lazy::new(|| Regex::new(r"(<.*?>)").unwrap()); content = HTML.replace_all(&content, "").into(); const REPL_SUB: &[&str] = &["<", ">", "&", "'", """]; for sub in REPL_SUB { @@ -97,10 +93,9 @@ pub fn unique_id_from_content(content: &str, id_counter: &mut HashMap(event: Event<'a>, path: Option<&Path>) -> Event<'a> { - lazy_static! { - static ref SCHEME_LINK: Regex = Regex::new(r"^[a-z][a-z0-9+.-]*:").unwrap(); - static ref MD_LINK: Regex = Regex::new(r"(?P.*)\.md(?P#.*)?").unwrap(); - } + static SCHEME_LINK: Lazy = Lazy::new(|| Regex::new(r"^[a-z][a-z0-9+.-]*:").unwrap()); + static MD_LINK: Lazy = + Lazy::new(|| Regex::new(r"(?P.*)\.md(?P#.*)?").unwrap()); fn fix<'a>(dest: CowStr<'a>, path: Option<&Path>) -> CowStr<'a> { if dest.starts_with('#') { @@ -153,10 +148,8 @@ fn adjust_links<'a>(event: Event<'a>, path: Option<&Path>) -> Event<'a> { // There are dozens of HTML tags/attributes that contain paths, so // feel free to add more tags if desired; these are the only ones I // care about right now. - lazy_static! { - static ref HTML_LINK: Regex = - Regex::new(r#"(<(?:a|img) [^>]*?(?:src|href)=")([^"]+?)""#).unwrap(); - } + static HTML_LINK: Lazy = + Lazy::new(|| Regex::new(r#"(<(?:a|img) [^>]*?(?:src|href)=")([^"]+?)""#).unwrap()); HTML_LINK .replace_all(&html, |caps: ®ex::Captures<'_>| { diff --git a/src/utils/string.rs b/src/utils/string.rs index bc854347..6dafe260 100644 --- a/src/utils/string.rs +++ b/src/utils/string.rs @@ -1,4 +1,4 @@ -use lazy_static::lazy_static; +use once_cell::sync::Lazy; use regex::Regex; use std::ops::Bound::{Excluded, Included, Unbounded}; use std::ops::RangeBounds; @@ -24,10 +24,10 @@ pub fn take_lines>(s: &str, range: R) -> String { } } -lazy_static! { - static ref ANCHOR_START: Regex = Regex::new(r"ANCHOR:\s*(?P[\w_-]+)").unwrap(); - static ref ANCHOR_END: Regex = Regex::new(r"ANCHOR_END:\s*(?P[\w_-]+)").unwrap(); -} +static ANCHOR_START: Lazy = + Lazy::new(|| Regex::new(r"ANCHOR:\s*(?P[\w_-]+)").unwrap()); +static ANCHOR_END: Lazy = + Lazy::new(|| Regex::new(r"ANCHOR_END:\s*(?P[\w_-]+)").unwrap()); /// Take anchored lines from a string. /// Lines containing anchor are ignored.