diff --git a/guide/src/format/mdbook.md b/guide/src/format/mdbook.md index 62e89843..f653f9dd 100644 --- a/guide/src/format/mdbook.md +++ b/guide/src/format/mdbook.md @@ -274,3 +274,18 @@ contents (sidebar) by including a `\{{#title ...}}` near the top of the page. ```hbs \{{#title My Title}} ``` + +## Font-Awesome icons + +mdBook includes a copy of [Font Awesome Free's](https://fontawesome.com) +MIT-licensed SVG files. It emulates the `` syntax, but converts +the results to inline SVG. Only the regular, solid, and brands icons are +included; paid features like the light icons are not. + +For example, given this HTML syntax: + +```hbs +The result looks like this: +``` + +The result looks like this: diff --git a/guide/src/format/theme/index-hbs.md b/guide/src/format/theme/index-hbs.md index e5331dcc..d85ff59b 100644 --- a/guide/src/format/theme/index-hbs.md +++ b/guide/src/format/theme/index-hbs.md @@ -99,3 +99,25 @@ Of course the inner html can be changed to your liking. *If you would like other properties or helpers exposed, please [create a new issue](https://github.com/rust-lang/mdBook/issues)* + +### 3. fa + +mdBook includes a copy of [Font Awesome Free's](https://fontawesome.com) +MIT-licensed SVG files. It accepts three positional arguments: + +1. Type: one of "solid", "regular", and "brands" (light and duotone are not + currently supported) +2. Icon: anything chosen from the + [free icon set](https://fontawesome.com/icons?d=gallery&m=free) +3. ID (optional): if included, an HTML ID attribute will be added to the + icon's wrapping `` tag + +For example, this handlebars syntax will become this HTML: + +```handlebars +{{fa "solid" "print" "print-button"}} +``` + +```html + +``` diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 352a95b7..83d7541b 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -200,6 +200,7 @@ impl HtmlHandlebars { let rendered = build_header_links(&rendered); let rendered = fix_code_blocks(&rendered); let rendered = add_playground_pre(&rendered, playground_config, edition); + let rendered = convert_fontawesome(&rendered); rendered } @@ -767,6 +768,54 @@ fn insert_link_into_header( ) } +// Convert fontawesome `` tags to inline SVG +fn convert_fontawesome(html: &str) -> String { + use font_awesome_as_a_crate as fa; + + let regex = Regex::new(r##"]+)class="([^"]+)"([^>]*)>"##).unwrap(); + regex + .replace_all(html, |caps: &Captures<'_>| { + let text = &caps[0]; + let before = &caps[1]; + let classes = &caps[2]; + let after = &caps[3]; + + let mut icon = String::new(); + let mut type_ = fa::Type::Regular; + let mut other_classes = String::new(); + + for class in classes.split(" ") { + if class.starts_with("fa-") { + icon = class[3..].to_owned(); + } else if class == "fa" { + type_ = fa::Type::Regular; + } else if class == "fas" { + type_ = fa::Type::Solid; + } else if class == "fab" { + type_ = fa::Type::Brands; + } else { + other_classes += " "; + other_classes += class; + } + } + + if icon == "" { + text.to_owned() + } else if let Ok(svg) = fa::svg(type_, &icon) { + format!( + r#"{svg}"#, + before = before, + other_classes = other_classes, + after = after, + svg = svg + ) + } else { + text.to_owned() + } + }) + .into_owned() +} + // The rust book uses annotations for rustdoc to test code snippets, // like the following: // ```rust,should_panic