Skip to content

Commit b1fd58c

Browse files
GuillaumeGomezsyphar
authored andcommitted
Use font-awesome fonts directly instead of generating our own CSS file
1 parent dc7b89d commit b1fd58c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+184
-321
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ once_cell = { version = "1.4.0", features = ["parking_lot"] }
5454
base64 = "0.22"
5555
strum = { version = "0.26.1", features = ["derive"] }
5656
lol_html = "1.0.0"
57+
font-awesome-as-a-crate = { path = "crates/font-awesome-as-a-crate" }
5758
dashmap = "6.0.0"
5859
string_cache = "0.8.0"
5960
zip = {version = "2.2.0", default-features = false, features = ["bzip2"]}
@@ -135,7 +136,6 @@ anyhow = { version = "1.0.42", features = ["backtrace"] }
135136
grass = { version = "0.13.1", default-features = false }
136137
once_cell = { version = "1.4.0", features = ["parking_lot"] }
137138
syntect = { version = "5.0.0", default-features = false, features = ["parsing", "dump-create", "yaml-load", "regex-onig"] }
138-
font-awesome-as-a-crate = { path = "crates/font-awesome-as-a-crate" }
139139

140140
[[bench]]
141141
name = "compression"

build.rs

Lines changed: 1 addition & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
use anyhow::{Context as _, Error, Result};
2-
use font_awesome_as_a_crate as f_a;
3-
use std::{
4-
env,
5-
path::{Path, PathBuf},
6-
};
2+
use std::{env, path::Path};
73

84
mod tracked {
95
use once_cell::sync::Lazy;
@@ -84,194 +80,11 @@ fn main() -> Result<()> {
8480
write_known_targets(out_dir)?;
8581
compile_syntax(out_dir).context("could not compile syntax files")?;
8682

87-
println!("cargo::rustc-check-cfg=cfg(icons_out_dir)");
88-
println!("cargo:rustc-cfg=icons_out_dir");
89-
90-
let out_css = "static/icons.css";
91-
let out_css = if std::env::var("RUN_IN_DOCKER").is_ok() {
92-
let _ = std::fs::create_dir_all("/srv/docsrs/static");
93-
Path::new("/srv/docsrs/").join(out_css)
94-
} else {
95-
let package_dir = env::var("CARGO_MANIFEST_DIR").context("missing CARGO_MANIFEST_DIR")?;
96-
Path::new(&package_dir).join(out_css)
97-
};
98-
generate_css_icons(out_css, out_dir)?;
99-
10083
// trigger recompilation when a new migration is added
10184
println!("cargo:rerun-if-changed=migrations");
10285
Ok(())
10386
}
10487

105-
fn capitalize(s: &str) -> String {
106-
let mut c = s.chars();
107-
match c.next() {
108-
None => String::new(),
109-
Some(f) => f.to_uppercase().chain(c).collect(),
110-
}
111-
}
112-
113-
fn render_icon(
114-
icon_name: &str,
115-
icon_str: &str,
116-
type_name: String,
117-
code_output: &mut String,
118-
css_output: &mut String,
119-
icon_kind: &str,
120-
) {
121-
let css_class = format!("f-a_{icon_name}_{icon_kind}");
122-
css_output.push_str(&format!(
123-
"\
124-
.{css_class} {{
125-
--svg_{icon_name}_{icon_kind}: url('data:image/svg+xml,{icon_str}');
126-
-webkit-mask: var(--svg_{icon_name}_{icon_kind}) no-repeat center;
127-
mask: var(--svg_{icon_name}_{icon_kind}) no-repeat center;
128-
}}
129-
",
130-
));
131-
let type_name = format!("{type_name}{}", capitalize(icon_kind));
132-
code_output.push_str(&format!(
133-
r#"#[derive(Clone, Copy, Debug, PartialEq, Eq)]
134-
pub struct {type_name};
135-
impl {type_name} {{
136-
pub fn render(&self, fw: bool, spin: bool, extra: &str) -> rinja::filters::Safe<String> {{
137-
render({css_class:?}, fw, spin, extra)
138-
}}
139-
}}
140-
"#,
141-
));
142-
}
143-
144-
fn generate_css_icons(css_path: PathBuf, out_dir: &Path) -> Result<()> {
145-
let mut code_output = r#"pub(crate) mod icons {
146-
fn render(
147-
css_class: &str,
148-
fw: bool,
149-
spin: bool,
150-
extra: &str,
151-
) -> rinja::filters::Safe<String> {
152-
let mut classes = vec!["fa-svg"];
153-
if fw {
154-
classes.push("fa-svg-fw");
155-
}
156-
if spin {
157-
classes.push("fa-svg-spin");
158-
}
159-
if !extra.is_empty() {
160-
classes.push(extra);
161-
}
162-
let icon = format!(
163-
"<span class=\"{css_class} {class}\" aria-hidden=\"true\"></span>",
164-
class = classes.join(" "),
165-
);
166-
167-
rinja::filters::Safe(icon)
168-
}"#
169-
.to_string();
170-
let mut css_output = r#".svg-clipboard {
171-
/* This icon is copied from crates.io */
172-
--svg-clipboard: url('data:image/svg+xml,<svg width="24" height="25" viewBox="0 0 24 25" fill="currentColor" xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard"><path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/><path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/></svg>');
173-
-webkit-mask: var(--svg-clipboard) no-repeat center;
174-
mask: var(--svg-clipboard) no-repeat center;
175-
}"#.to_string();
176-
177-
let brands: &[&dyn f_a::Brands] = &[
178-
&f_a::icons::IconFonticons,
179-
&f_a::icons::IconRust,
180-
&f_a::icons::IconMarkdown,
181-
&f_a::icons::IconGitAlt,
182-
];
183-
let regular: &[&dyn f_a::Regular] = &[
184-
&f_a::icons::IconFileLines,
185-
&f_a::icons::IconFolderOpen,
186-
&f_a::icons::IconFile,
187-
&f_a::icons::IconStar,
188-
];
189-
let solid: &[&dyn f_a::Solid] = &[
190-
&f_a::icons::IconCircleInfo,
191-
&f_a::icons::IconGears,
192-
&f_a::icons::IconTable,
193-
&f_a::icons::IconRoad,
194-
&f_a::icons::IconDownload,
195-
&f_a::icons::IconCubes,
196-
&f_a::icons::IconSquareRss,
197-
&f_a::icons::IconFileLines,
198-
&f_a::icons::IconCheck,
199-
&f_a::icons::IconTriangleExclamation,
200-
&f_a::icons::IconGear,
201-
&f_a::icons::IconX,
202-
&f_a::icons::IconHouse,
203-
&f_a::icons::IconCodeBranch,
204-
&f_a::icons::IconStar,
205-
&f_a::icons::IconCircleExclamation,
206-
&f_a::icons::IconCube,
207-
&f_a::icons::IconChevronLeft,
208-
&f_a::icons::IconChevronRight,
209-
&f_a::icons::IconFolderOpen,
210-
&f_a::icons::IconLock,
211-
&f_a::icons::IconFlag,
212-
&f_a::icons::IconBook,
213-
&f_a::icons::IconMagnifyingGlass,
214-
&f_a::icons::IconLeaf,
215-
&f_a::icons::IconChartLine,
216-
&f_a::icons::IconList,
217-
&f_a::icons::IconUser,
218-
&f_a::icons::IconTrash,
219-
&f_a::icons::IconArrowLeft,
220-
&f_a::icons::IconArrowRight,
221-
&f_a::icons::IconLink,
222-
&f_a::icons::IconScaleUnbalancedFlip,
223-
&f_a::icons::IconSpinner,
224-
];
225-
226-
for icon in brands {
227-
render_icon(
228-
icon.icon_name(),
229-
icon.icon_str(),
230-
format!("{icon:?}"),
231-
&mut code_output,
232-
&mut css_output,
233-
"brands",
234-
);
235-
}
236-
for icon in regular {
237-
render_icon(
238-
icon.icon_name(),
239-
icon.icon_str(),
240-
format!("{icon:?}"),
241-
&mut code_output,
242-
&mut css_output,
243-
"regular",
244-
);
245-
}
246-
for icon in solid {
247-
render_icon(
248-
icon.icon_name(),
249-
icon.icon_str(),
250-
format!("{icon:?}"),
251-
&mut code_output,
252-
&mut css_output,
253-
"solid",
254-
);
255-
}
256-
257-
std::fs::write(&css_path, css_output).map_err(|error| {
258-
Error::msg(format!(
259-
"Failed to write into `{}`: {error:?}",
260-
css_path.display()
261-
))
262-
})?;
263-
264-
code_output.push('}');
265-
let icons_file = out_dir.join("icons.rs");
266-
std::fs::write(&icons_file, code_output).map_err(|error| {
267-
Error::msg(format!(
268-
"Failed to write `{}`: {error:?}",
269-
icons_file.display()
270-
))
271-
})?;
272-
Ok(())
273-
}
274-
27588
fn write_git_version(out_dir: &Path) -> Result<()> {
27689
let maybe_hash = get_git_hash()?;
27790
let git_hash = maybe_hash.as_deref().unwrap_or("???????");

crates/font-awesome-as-a-crate/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ fn write_fontawesome_sprite() {
7878
pub struct {type_name};
7979
impl IconStr for {type_name} {{
8080
fn icon_name(&self) -> &'static str {{ r#\"{icon}\"# }}
81-
fn icon_str(&self) -> &'static str {{ r#\"{data}\"# }}
81+
fn icon_svg(&self) -> &'static str {{ r#\"{data}\"# }}
8282
}}
8383
{kinds}"
8484
)

crates/font-awesome-as-a-crate/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,21 +91,21 @@ pub trait IconStr {
9191
/// Name of the icon, like "triangle-exclamation".
9292
fn icon_name(&self) -> &'static str;
9393
/// The SVG content of the icon.
94-
fn icon_str(&self) -> &'static str;
94+
fn icon_svg(&self) -> &'static str;
9595
}
9696

9797
pub trait Brands: IconStr + Debug {
98-
fn get_type(&self) -> Type {
98+
fn get_type() -> Type {
9999
Type::Brands
100100
}
101101
}
102102
pub trait Regular: IconStr + Debug {
103-
fn get_type(&self) -> Type {
103+
fn get_type() -> Type {
104104
Type::Regular
105105
}
106106
}
107107
pub trait Solid: IconStr + Debug {
108-
fn get_type(&self) -> Type {
108+
fn get_type() -> Type {
109109
Type::Solid
110110
}
111111
}

dockerfiles/Dockerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ COPY assets assets/
6161
COPY .sqlx .sqlx/
6262
COPY migrations migrations/
6363

64-
ENV RUN_IN_DOCKER="1"
6564
RUN cargo build --profile=$PROFILE
6665

6766
######################

src/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ pub use self::registry_api::RegistryApi;
1313
pub use self::storage::{AsyncStorage, Storage};
1414
pub use self::web::{start_background_metrics_webserver, start_web_server};
1515

16-
#[cfg(icons_out_dir)]
17-
include!(concat!(env!("OUT_DIR"), "/icons.rs"));
18-
#[cfg(not(icons_out_dir))]
19-
include!("icons.rs");
16+
pub use font_awesome_as_a_crate::icons;
2017

2118
mod build_queue;
2219
pub mod cdn;

src/web/build_details.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use crate::{
55
error::{AxumNope, AxumResult},
66
extractors::{DbConnection, Path},
77
file::File,
8-
filters, MetaData,
8+
filters,
9+
page::templates::{RenderRegular, RenderSolid},
10+
MetaData,
911
},
1012
AsyncStorage, Config,
1113
};

src/web/builds.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ use crate::{
1010
web::{
1111
error::AxumResult,
1212
extractors::{DbConnection, Path},
13-
filters, match_version, MetaData, ReqVersion,
13+
filters, match_version,
14+
page::templates::{RenderRegular, RenderSolid},
15+
MetaData, ReqVersion,
1416
},
1517
AsyncBuildQueue, Config,
1618
};

src/web/crate_details.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
encode_url_path,
1111
error::{AxumNope, AxumResult},
1212
extractors::{DbConnection, Path},
13-
page::templates::filters,
13+
page::templates::{filters, RenderRegular, RenderSolid},
1414
rustdoc::RustdocHtmlParams,
1515
MatchedRelease, ReqVersion,
1616
},
@@ -1614,7 +1614,7 @@ mod tests {
16141614
.borrow()
16151615
.get("class")
16161616
.unwrap(),
1617-
"f-a_code-branch_solid fa-svg"
1617+
"fa fa-solid fa-code-branch "
16181618
);
16191619

16201620
Ok(())

src/web/csp.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl Csp {
5454
// the MIME type to allow loading favicons.
5555
//
5656
// Images from other HTTPS origins are also temporary allowed until issue #66 is fixed.
57-
result.push_str("; img-src 'self' https: data:");
57+
result.push_str("; img-src 'self' https:");
5858

5959
match content_type {
6060
ContentType::Html => self.render_html(&mut result),
@@ -169,7 +169,7 @@ mod tests {
169169
fn test_csp_other() {
170170
let csp = Csp::new();
171171
assert_eq!(
172-
Some("default-src 'none'; base-uri 'none'; img-src 'self' https: data:".into()),
172+
Some("default-src 'none'; base-uri 'none'; img-src 'self' https:".into()),
173173
csp.render(ContentType::Other)
174174
);
175175
}
@@ -179,7 +179,7 @@ mod tests {
179179
let csp = Csp::new();
180180
assert_eq!(
181181
Some(
182-
"default-src 'none'; base-uri 'none'; img-src 'self' https: data:; \
182+
"default-src 'none'; base-uri 'none'; img-src 'self' https:; \
183183
style-src 'self' 'unsafe-inline'"
184184
.into()
185185
),
@@ -192,7 +192,7 @@ mod tests {
192192
let csp = Csp::new();
193193
assert_eq!(
194194
Some(format!(
195-
"default-src 'none'; base-uri 'none'; img-src 'self' https: data:; \
195+
"default-src 'none'; base-uri 'none'; img-src 'self' https:; \
196196
style-src 'self'; font-src 'self'; connect-src 'self'; script-src 'nonce-{}'",
197197
csp.nonce()
198198
)),

0 commit comments

Comments
 (0)