Skip to content

Commit 9004849

Browse files
uncenternotriddle
andcommitted
Use embedded Font Awesome SVG icons
Co-authored-by: Michael Howell <[email protected]>
1 parent 9096012 commit 9004849

17 files changed

+171
-2752
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ clap = { version = "4.3.12", features = ["cargo", "wrap_help"] }
2626
clap_complete = "4.3.2"
2727
once_cell = "1.17.1"
2828
env_logger = "0.11.1"
29+
font-awesome-as-a-crate = "0.3.0"
2930
handlebars = "6.0"
3031
log = "0.4.17"
3132
memchr = "2.5.0"

src/renderer/html_handlebars/hbs_renderer.rs

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ impl HtmlHandlebars {
218218
let rendered = fix_code_blocks(&rendered);
219219
let rendered = add_playground_pre(&rendered, playground_config, edition);
220220
let rendered = hide_lines(&rendered, code_config);
221+
let rendered = convert_fontawesome(&rendered);
221222

222223
rendered
223224
}
@@ -258,41 +259,7 @@ impl HtmlHandlebars {
258259
write_file(destination, "ayu-highlight.css", &theme.ayu_highlight_css)?;
259260
write_file(destination, "highlight.js", &theme.highlight_js)?;
260261
write_file(destination, "clipboard.min.js", &theme.clipboard_js)?;
261-
write_file(
262-
destination,
263-
"FontAwesome/css/font-awesome.css",
264-
theme::FONT_AWESOME,
265-
)?;
266-
write_file(
267-
destination,
268-
"FontAwesome/fonts/fontawesome-webfont.eot",
269-
theme::FONT_AWESOME_EOT,
270-
)?;
271-
write_file(
272-
destination,
273-
"FontAwesome/fonts/fontawesome-webfont.svg",
274-
theme::FONT_AWESOME_SVG,
275-
)?;
276-
write_file(
277-
destination,
278-
"FontAwesome/fonts/fontawesome-webfont.ttf",
279-
theme::FONT_AWESOME_TTF,
280-
)?;
281-
write_file(
282-
destination,
283-
"FontAwesome/fonts/fontawesome-webfont.woff",
284-
theme::FONT_AWESOME_WOFF,
285-
)?;
286-
write_file(
287-
destination,
288-
"FontAwesome/fonts/fontawesome-webfont.woff2",
289-
theme::FONT_AWESOME_WOFF2,
290-
)?;
291-
write_file(
292-
destination,
293-
"FontAwesome/fonts/FontAwesome.ttf",
294-
theme::FONT_AWESOME_TTF,
295-
)?;
262+
296263
// Don't copy the stock fonts if the user has specified their own fonts to use.
297264
if html_config.copy_fonts && theme.fonts_css.is_none() {
298265
write_file(destination, "fonts/fonts.css", theme::fonts::CSS)?;
@@ -379,6 +346,7 @@ impl HtmlHandlebars {
379346
handlebars.register_helper("next", Box::new(helpers::navigation::next));
380347
// TODO: remove theme_option in 0.5, it is not needed.
381348
handlebars.register_helper("theme_option", Box::new(helpers::theme::theme_option));
349+
handlebars.register_helper("fa", Box::new(helpers::fontawesome::fa_helper));
382350
}
383351

384352
/// Copy across any additional CSS and JavaScript files which the book
@@ -754,9 +722,19 @@ fn make_data(
754722

755723
let git_repository_icon = match html_config.git_repository_icon {
756724
Some(ref git_repository_icon) => git_repository_icon,
757-
None => "fa-github",
725+
None => "fab-github",
726+
};
727+
let git_repository_icon_class = match git_repository_icon.split('-').next() {
728+
Some("fa") => "regular",
729+
Some("fas") => "solid",
730+
Some("fab") => "brands",
731+
_ => "regular",
758732
};
759733
data.insert("git_repository_icon".to_owned(), json!(git_repository_icon));
734+
data.insert(
735+
"git_repository_icon_class".to_owned(),
736+
json!(git_repository_icon_class),
737+
);
760738

761739
let mut chapters = vec![];
762740

@@ -855,6 +833,54 @@ fn insert_link_into_header(
855833
)
856834
}
857835

836+
// Convert fontawesome `<i>` tags to inline SVG
837+
fn convert_fontawesome(html: &str) -> String {
838+
use font_awesome_as_a_crate as fa;
839+
840+
let regex = Regex::new(r##"<i([^>]+)class="([^"]+)"([^>]*)></i>"##).unwrap();
841+
regex
842+
.replace_all(html, |caps: &Captures<'_>| {
843+
let text = &caps[0];
844+
let before = &caps[1];
845+
let classes = &caps[2];
846+
let after = &caps[3];
847+
848+
let mut icon = String::new();
849+
let mut type_ = fa::Type::Regular;
850+
let mut other_classes = String::new();
851+
852+
for class in classes.split(" ") {
853+
if let Some(class) = class.strip_prefix("fa-") {
854+
icon = class.to_owned();
855+
} else if class == "fa" {
856+
type_ = fa::Type::Regular;
857+
} else if class == "fas" {
858+
type_ = fa::Type::Solid;
859+
} else if class == "fab" {
860+
type_ = fa::Type::Brands;
861+
} else {
862+
other_classes += " ";
863+
other_classes += class;
864+
}
865+
}
866+
867+
if icon.is_empty() {
868+
text.to_owned()
869+
} else if let Ok(svg) = fa::svg(type_, &icon) {
870+
format!(
871+
r#"<span{before}class="fa-svg{other_classes}"{after}>{svg}</span>"#,
872+
before = before,
873+
other_classes = other_classes,
874+
after = after,
875+
svg = svg
876+
)
877+
} else {
878+
text.to_owned()
879+
}
880+
})
881+
.into_owned()
882+
}
883+
858884
// The rust book uses annotations for rustdoc to test code snippets,
859885
// like the following:
860886
// ```rust,should_panic
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use font_awesome_as_a_crate as fa;
2+
use handlebars::{
3+
Context, Handlebars, Helper, Output, RenderContext, RenderError, RenderErrorReason,
4+
};
5+
use log::trace;
6+
use std::str::FromStr;
7+
8+
pub fn fa_helper(
9+
h: &Helper<'_>,
10+
_r: &Handlebars<'_>,
11+
_ctx: &Context,
12+
_rc: &mut RenderContext<'_, '_>,
13+
out: &mut dyn Output,
14+
) -> Result<(), RenderError> {
15+
trace!("fa_helper (handlebars helper)");
16+
17+
let type_ = h
18+
.param(0)
19+
.and_then(|v| v.value().as_str())
20+
.and_then(|v| fa::Type::from_str(v).ok())
21+
.ok_or_else(|| {
22+
RenderErrorReason::Other(
23+
"Param 0 with String type is required for fontawesome helper.".to_owned(),
24+
)
25+
})?;
26+
27+
let name = h.param(1).and_then(|v| v.value().as_str()).ok_or_else(|| {
28+
RenderErrorReason::Other(
29+
"Param 1 with String type is required for fontawesome helper.".to_owned(),
30+
)
31+
})?;
32+
33+
trace!("fa_helper: {} {}", type_, name);
34+
35+
let name = name
36+
.strip_prefix("fa-")
37+
.or_else(|| name.strip_prefix("fab-"))
38+
.or_else(|| name.strip_prefix("fas-"))
39+
.unwrap_or(name);
40+
41+
if let Some(id) = h.param(2).and_then(|v| v.value().as_str()) {
42+
out.write(&format!("<span class=\"fa-svg\" id=\"{}\">", id))?;
43+
} else {
44+
out.write("<span class=\"fa-svg\">")?;
45+
}
46+
out.write(
47+
fa::svg(type_, name)
48+
.map_err(|_| RenderErrorReason::Other(format!("Missing font {}", name)))?,
49+
)?;
50+
out.write("</span>")?;
51+
52+
Ok(())
53+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod fontawesome;
12
pub mod navigation;
23
pub mod theme;
34
pub mod toc;

src/theme/FontAwesome/css/font-awesome.min.css

Lines changed: 0 additions & 4 deletions
This file was deleted.
-132 KB
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)