1use super::icons::{IconRole, IconSet};
8
9#[must_use = "this returns SVG bytes; it does not render the icon"]
29#[allow(unreachable_patterns, unused_variables)]
30pub fn bundled_icon_svg(set: IconSet, role: IconRole) -> Option<&'static [u8]> {
31 match set {
32 #[cfg(feature = "material-icons")]
33 IconSet::Material => material_svg(role),
34
35 #[cfg(feature = "lucide-icons")]
36 IconSet::Lucide => lucide_svg(role),
37
38 _ => None,
39 }
40}
41
42#[cfg(feature = "material-icons")]
43#[allow(unreachable_patterns)]
44fn material_svg(role: IconRole) -> Option<&'static [u8]> {
45 Some(match role {
46 IconRole::DialogWarning => include_bytes!("../../icons/material/warning.svg"),
48 IconRole::DialogError => include_bytes!("../../icons/material/error.svg"),
49 IconRole::DialogInfo => include_bytes!("../../icons/material/info.svg"),
50 IconRole::DialogQuestion => include_bytes!("../../icons/material/help.svg"),
51 IconRole::DialogSuccess => include_bytes!("../../icons/material/check_circle.svg"),
52 IconRole::Shield => include_bytes!("../../icons/material/shield.svg"),
53
54 IconRole::WindowClose => include_bytes!("../../icons/material/close.svg"),
56 IconRole::WindowMinimize => include_bytes!("../../icons/material/minimize.svg"),
57 IconRole::WindowMaximize => include_bytes!("../../icons/material/open_in_full.svg"),
58 IconRole::WindowRestore => include_bytes!("../../icons/material/close_fullscreen.svg"),
59
60 IconRole::ActionSave => include_bytes!("../../icons/material/save.svg"),
62 IconRole::ActionDelete => include_bytes!("../../icons/material/delete.svg"),
63 IconRole::ActionCopy => include_bytes!("../../icons/material/content_copy.svg"),
64 IconRole::ActionPaste => include_bytes!("../../icons/material/content_paste.svg"),
65 IconRole::ActionCut => include_bytes!("../../icons/material/content_cut.svg"),
66 IconRole::ActionUndo => include_bytes!("../../icons/material/undo.svg"),
67 IconRole::ActionRedo => include_bytes!("../../icons/material/redo.svg"),
68 IconRole::ActionSearch => include_bytes!("../../icons/material/search.svg"),
69 IconRole::ActionSettings => include_bytes!("../../icons/material/settings.svg"),
70 IconRole::ActionEdit => include_bytes!("../../icons/material/edit.svg"),
71 IconRole::ActionAdd => include_bytes!("../../icons/material/add.svg"),
72 IconRole::ActionRemove => include_bytes!("../../icons/material/remove.svg"),
73 IconRole::ActionRefresh => include_bytes!("../../icons/material/refresh.svg"),
74 IconRole::ActionPrint => include_bytes!("../../icons/material/print.svg"),
75
76 IconRole::NavBack => include_bytes!("../../icons/material/arrow_back.svg"),
78 IconRole::NavForward => include_bytes!("../../icons/material/arrow_forward.svg"),
79 IconRole::NavUp => include_bytes!("../../icons/material/arrow_upward.svg"),
80 IconRole::NavDown => include_bytes!("../../icons/material/arrow_downward.svg"),
81 IconRole::NavHome => include_bytes!("../../icons/material/home.svg"),
82 IconRole::NavMenu => include_bytes!("../../icons/material/menu.svg"),
83
84 IconRole::FileGeneric => include_bytes!("../../icons/material/description.svg"),
86 IconRole::FolderClosed => include_bytes!("../../icons/material/folder.svg"),
87 IconRole::FolderOpen => include_bytes!("../../icons/material/folder_open.svg"),
88 IconRole::TrashEmpty => include_bytes!("../../icons/material/delete.svg"),
89 IconRole::TrashFull => include_bytes!("../../icons/material/delete.svg"), IconRole::StatusBusy => include_bytes!("../../icons/material/progress_activity.svg"),
93 IconRole::StatusCheck => include_bytes!("../../icons/material/check.svg"),
94 IconRole::StatusError => include_bytes!("../../icons/material/error.svg"), IconRole::UserAccount => include_bytes!("../../icons/material/person.svg"),
98 IconRole::Notification => include_bytes!("../../icons/material/notifications.svg"),
99 IconRole::Help => include_bytes!("../../icons/material/help.svg"), IconRole::Lock => include_bytes!("../../icons/material/lock.svg"),
101
102 _ => return None, })
104}
105
106#[cfg(feature = "lucide-icons")]
107#[allow(unreachable_patterns)]
108fn lucide_svg(role: IconRole) -> Option<&'static [u8]> {
109 Some(match role {
110 IconRole::DialogWarning => include_bytes!("../../icons/lucide/triangle-alert.svg"),
112 IconRole::DialogError => include_bytes!("../../icons/lucide/circle-x.svg"),
113 IconRole::DialogInfo => include_bytes!("../../icons/lucide/info.svg"),
114 IconRole::DialogQuestion => include_bytes!("../../icons/lucide/circle-question-mark.svg"),
115 IconRole::DialogSuccess => include_bytes!("../../icons/lucide/circle-check.svg"),
116 IconRole::Shield => include_bytes!("../../icons/lucide/shield.svg"),
117
118 IconRole::WindowClose => include_bytes!("../../icons/lucide/x.svg"),
120 IconRole::WindowMinimize => include_bytes!("../../icons/lucide/minimize.svg"),
121 IconRole::WindowMaximize => include_bytes!("../../icons/lucide/maximize.svg"),
122 IconRole::WindowRestore => include_bytes!("../../icons/lucide/minimize-2.svg"),
123
124 IconRole::ActionSave => include_bytes!("../../icons/lucide/save.svg"),
126 IconRole::ActionDelete => include_bytes!("../../icons/lucide/trash-2.svg"),
127 IconRole::ActionCopy => include_bytes!("../../icons/lucide/copy.svg"),
128 IconRole::ActionPaste => include_bytes!("../../icons/lucide/clipboard-paste.svg"),
129 IconRole::ActionCut => include_bytes!("../../icons/lucide/scissors.svg"),
130 IconRole::ActionUndo => include_bytes!("../../icons/lucide/undo-2.svg"),
131 IconRole::ActionRedo => include_bytes!("../../icons/lucide/redo-2.svg"),
132 IconRole::ActionSearch => include_bytes!("../../icons/lucide/search.svg"),
133 IconRole::ActionSettings => include_bytes!("../../icons/lucide/settings.svg"),
134 IconRole::ActionEdit => include_bytes!("../../icons/lucide/pencil.svg"),
135 IconRole::ActionAdd => include_bytes!("../../icons/lucide/plus.svg"),
136 IconRole::ActionRemove => include_bytes!("../../icons/lucide/minus.svg"),
137 IconRole::ActionRefresh => include_bytes!("../../icons/lucide/refresh-cw.svg"),
138 IconRole::ActionPrint => include_bytes!("../../icons/lucide/printer.svg"),
139
140 IconRole::NavBack => include_bytes!("../../icons/lucide/chevron-left.svg"),
142 IconRole::NavForward => include_bytes!("../../icons/lucide/chevron-right.svg"),
143 IconRole::NavUp => include_bytes!("../../icons/lucide/chevron-up.svg"),
144 IconRole::NavDown => include_bytes!("../../icons/lucide/chevron-down.svg"),
145 IconRole::NavHome => include_bytes!("../../icons/lucide/house.svg"),
146 IconRole::NavMenu => include_bytes!("../../icons/lucide/menu.svg"),
147
148 IconRole::FileGeneric => include_bytes!("../../icons/lucide/file.svg"),
150 IconRole::FolderClosed => include_bytes!("../../icons/lucide/folder-closed.svg"),
151 IconRole::FolderOpen => include_bytes!("../../icons/lucide/folder-open.svg"),
152 IconRole::TrashEmpty => include_bytes!("../../icons/lucide/trash-2.svg"),
153 IconRole::TrashFull => include_bytes!("../../icons/lucide/trash-2.svg"), IconRole::StatusBusy => include_bytes!("../../icons/lucide/loader.svg"),
157 IconRole::StatusCheck => include_bytes!("../../icons/lucide/check.svg"),
158 IconRole::StatusError => include_bytes!("../../icons/lucide/circle-x.svg"), IconRole::UserAccount => include_bytes!("../../icons/lucide/user.svg"),
162 IconRole::Notification => include_bytes!("../../icons/lucide/bell.svg"),
163 IconRole::Help => include_bytes!("../../icons/lucide/circle-question-mark.svg"), IconRole::Lock => include_bytes!("../../icons/lucide/lock.svg"),
165
166 _ => return None, })
168}
169
170#[must_use = "this returns SVG bytes; it does not render the icon"]
189#[allow(unreachable_patterns, unused_variables)]
190pub fn bundled_icon_by_name(set: IconSet, name: &str) -> Option<&'static [u8]> {
191 match set {
192 #[cfg(feature = "material-icons")]
193 IconSet::Material => material_svg_by_name(name),
194
195 #[cfg(feature = "lucide-icons")]
196 IconSet::Lucide => lucide_svg_by_name(name),
197
198 _ => None,
199 }
200}
201
202#[cfg(feature = "lucide-icons")]
203#[allow(unreachable_patterns)]
204fn lucide_svg_by_name(name: &str) -> Option<&'static [u8]> {
205 Some(match name {
206 "a-large-small" => include_bytes!("../../icons/lucide/a-large-small.svg"),
207 "arrow-down" => include_bytes!("../../icons/lucide/arrow-down.svg"),
208 "arrow-left" => include_bytes!("../../icons/lucide/arrow-left.svg"),
209 "arrow-right" => include_bytes!("../../icons/lucide/arrow-right.svg"),
210 "arrow-up" => include_bytes!("../../icons/lucide/arrow-up.svg"),
211 "asterisk" => include_bytes!("../../icons/lucide/asterisk.svg"),
212 "bell" => include_bytes!("../../icons/lucide/bell.svg"),
213 "book-open" => include_bytes!("../../icons/lucide/book-open.svg"),
214 "bot" => include_bytes!("../../icons/lucide/bot.svg"),
215 "building-2" => include_bytes!("../../icons/lucide/building-2.svg"),
216 "calendar" => include_bytes!("../../icons/lucide/calendar.svg"),
217 "case-sensitive" => include_bytes!("../../icons/lucide/case-sensitive.svg"),
218 "chart-pie" => include_bytes!("../../icons/lucide/chart-pie.svg"),
219 "check" => include_bytes!("../../icons/lucide/check.svg"),
220 "chevron-down" => include_bytes!("../../icons/lucide/chevron-down.svg"),
221 "chevron-left" => include_bytes!("../../icons/lucide/chevron-left.svg"),
222 "chevron-right" => include_bytes!("../../icons/lucide/chevron-right.svg"),
223 "chevrons-up-down" => include_bytes!("../../icons/lucide/chevrons-up-down.svg"),
224 "chevron-up" => include_bytes!("../../icons/lucide/chevron-up.svg"),
225 "circle-check" => include_bytes!("../../icons/lucide/circle-check.svg"),
226 "circle-question-mark" => include_bytes!("../../icons/lucide/circle-question-mark.svg"),
227 "circle-user" => include_bytes!("../../icons/lucide/circle-user.svg"),
228 "circle-x" => include_bytes!("../../icons/lucide/circle-x.svg"),
229 "clipboard-paste" => include_bytes!("../../icons/lucide/clipboard-paste.svg"),
230 "close" => include_bytes!("../../icons/lucide/close.svg"),
231 "copy" => include_bytes!("../../icons/lucide/copy.svg"),
232 "dash" => include_bytes!("../../icons/lucide/dash.svg"),
233 "delete" => include_bytes!("../../icons/lucide/delete.svg"),
234 "ellipsis" => include_bytes!("../../icons/lucide/ellipsis.svg"),
235 "ellipsis-vertical" => include_bytes!("../../icons/lucide/ellipsis-vertical.svg"),
236 "external-link" => include_bytes!("../../icons/lucide/external-link.svg"),
237 "eye" => include_bytes!("../../icons/lucide/eye.svg"),
238 "eye-off" => include_bytes!("../../icons/lucide/eye-off.svg"),
239 "file" => include_bytes!("../../icons/lucide/file.svg"),
240 "folder" => include_bytes!("../../icons/lucide/folder.svg"),
241 "folder-closed" => include_bytes!("../../icons/lucide/folder-closed.svg"),
242 "folder-open" => include_bytes!("../../icons/lucide/folder-open.svg"),
243 "frame" => include_bytes!("../../icons/lucide/frame.svg"),
244 "gallery-vertical-end" => include_bytes!("../../icons/lucide/gallery-vertical-end.svg"),
245 "github" => include_bytes!("../../icons/lucide/github.svg"),
246 "globe" => include_bytes!("../../icons/lucide/globe.svg"),
247 "heart" => include_bytes!("../../icons/lucide/heart.svg"),
248 "heart-off" => include_bytes!("../../icons/lucide/heart-off.svg"),
249 "house" => include_bytes!("../../icons/lucide/house.svg"),
250 "inbox" => include_bytes!("../../icons/lucide/inbox.svg"),
251 "info" => include_bytes!("../../icons/lucide/info.svg"),
252 "inspect" => include_bytes!("../../icons/lucide/inspect.svg"),
253 "layout-dashboard" => include_bytes!("../../icons/lucide/layout-dashboard.svg"),
254 "loader" => include_bytes!("../../icons/lucide/loader.svg"),
255 "loader-circle" => include_bytes!("../../icons/lucide/loader-circle.svg"),
256 "lock" => include_bytes!("../../icons/lucide/lock.svg"),
257 "map" => include_bytes!("../../icons/lucide/map.svg"),
258 "maximize" => include_bytes!("../../icons/lucide/maximize.svg"),
259 "menu" => include_bytes!("../../icons/lucide/menu.svg"),
260 "minimize" => include_bytes!("../../icons/lucide/minimize.svg"),
261 "minimize-2" => include_bytes!("../../icons/lucide/minimize-2.svg"),
262 "minus" => include_bytes!("../../icons/lucide/minus.svg"),
263 "moon" => include_bytes!("../../icons/lucide/moon.svg"),
264 "palette" => include_bytes!("../../icons/lucide/palette.svg"),
265 "panel-bottom" => include_bytes!("../../icons/lucide/panel-bottom.svg"),
266 "panel-bottom-open" => include_bytes!("../../icons/lucide/panel-bottom-open.svg"),
267 "panel-left" => include_bytes!("../../icons/lucide/panel-left.svg"),
268 "panel-left-close" => include_bytes!("../../icons/lucide/panel-left-close.svg"),
269 "panel-left-open" => include_bytes!("../../icons/lucide/panel-left-open.svg"),
270 "panel-right" => include_bytes!("../../icons/lucide/panel-right.svg"),
271 "panel-right-close" => include_bytes!("../../icons/lucide/panel-right-close.svg"),
272 "panel-right-open" => include_bytes!("../../icons/lucide/panel-right-open.svg"),
273 "pencil" => include_bytes!("../../icons/lucide/pencil.svg"),
274 "plus" => include_bytes!("../../icons/lucide/plus.svg"),
275 "printer" => include_bytes!("../../icons/lucide/printer.svg"),
276 "redo" => include_bytes!("../../icons/lucide/redo.svg"),
277 "redo-2" => include_bytes!("../../icons/lucide/redo-2.svg"),
278 "refresh-cw" => include_bytes!("../../icons/lucide/refresh-cw.svg"),
279 "replace" => include_bytes!("../../icons/lucide/replace.svg"),
280 "resize-corner" => include_bytes!("../../icons/lucide/resize-corner.svg"),
281 "save" => include_bytes!("../../icons/lucide/save.svg"),
282 "scissors" => include_bytes!("../../icons/lucide/scissors.svg"),
283 "search" => include_bytes!("../../icons/lucide/search.svg"),
284 "settings" => include_bytes!("../../icons/lucide/settings.svg"),
285 "settings-2" => include_bytes!("../../icons/lucide/settings-2.svg"),
286 "shield" => include_bytes!("../../icons/lucide/shield.svg"),
287 "sort-ascending" => include_bytes!("../../icons/lucide/sort-ascending.svg"),
288 "sort-descending" => include_bytes!("../../icons/lucide/sort-descending.svg"),
289 "square-terminal" => include_bytes!("../../icons/lucide/square-terminal.svg"),
290 "star" => include_bytes!("../../icons/lucide/star.svg"),
291 "star-off" => include_bytes!("../../icons/lucide/star-off.svg"),
292 "sun" => include_bytes!("../../icons/lucide/sun.svg"),
293 "thumbs-down" => include_bytes!("../../icons/lucide/thumbs-down.svg"),
294 "thumbs-up" => include_bytes!("../../icons/lucide/thumbs-up.svg"),
295 "trash-2" => include_bytes!("../../icons/lucide/trash-2.svg"),
296 "triangle-alert" => include_bytes!("../../icons/lucide/triangle-alert.svg"),
297 "undo" => include_bytes!("../../icons/lucide/undo.svg"),
298 "undo-2" => include_bytes!("../../icons/lucide/undo-2.svg"),
299 "user" => include_bytes!("../../icons/lucide/user.svg"),
300 "window-close" => include_bytes!("../../icons/lucide/window-close.svg"),
301 "window-maximize" => include_bytes!("../../icons/lucide/window-maximize.svg"),
302 "window-minimize" => include_bytes!("../../icons/lucide/window-minimize.svg"),
303 "window-restore" => include_bytes!("../../icons/lucide/window-restore.svg"),
304 "x" => include_bytes!("../../icons/lucide/x.svg"),
305 _ => return None,
306 })
307}
308
309#[cfg(feature = "material-icons")]
310#[allow(unreachable_patterns)]
311fn material_svg_by_name(name: &str) -> Option<&'static [u8]> {
312 Some(match name {
313 "account_circle" => include_bytes!("../../icons/material/account_circle.svg"),
314 "add" => include_bytes!("../../icons/material/add.svg"),
315 "apartment" => include_bytes!("../../icons/material/apartment.svg"),
316 "arrow_back" => include_bytes!("../../icons/material/arrow_back.svg"),
317 "arrow_downward" => include_bytes!("../../icons/material/arrow_downward.svg"),
318 "arrow_forward" => include_bytes!("../../icons/material/arrow_forward.svg"),
319 "arrow_upward" => include_bytes!("../../icons/material/arrow_upward.svg"),
320 "autorenew" => include_bytes!("../../icons/material/autorenew.svg"),
321 "calendar_today" => include_bytes!("../../icons/material/calendar_today.svg"),
322 "cancel" => include_bytes!("../../icons/material/cancel.svg"),
323 "check" => include_bytes!("../../icons/material/check.svg"),
324 "check_circle" => include_bytes!("../../icons/material/check_circle.svg"),
325 "chevron_left" => include_bytes!("../../icons/material/chevron_left.svg"),
326 "chevron_right" => include_bytes!("../../icons/material/chevron_right.svg"),
327 "close" => include_bytes!("../../icons/material/close.svg"),
328 "close_fullscreen" => include_bytes!("../../icons/material/close_fullscreen.svg"),
329 "code" => include_bytes!("../../icons/material/code.svg"),
330 "content_copy" => include_bytes!("../../icons/material/content_copy.svg"),
331 "crop_free" => include_bytes!("../../icons/material/crop_free.svg"),
332 "dark_mode" => include_bytes!("../../icons/material/dark_mode.svg"),
333 "dashboard" => include_bytes!("../../icons/material/dashboard.svg"),
334 "delete" => include_bytes!("../../icons/material/delete.svg"),
335 "description" => include_bytes!("../../icons/material/description.svg"),
336 "developer_mode" => include_bytes!("../../icons/material/developer_mode.svg"),
337 "dock_to_bottom" => include_bytes!("../../icons/material/dock_to_bottom.svg"),
338 "drag_indicator" => include_bytes!("../../icons/material/drag_indicator.svg"),
339 "emergency" => include_bytes!("../../icons/material/emergency.svg"),
340 "expand_less" => include_bytes!("../../icons/material/expand_less.svg"),
341 "expand_more" => include_bytes!("../../icons/material/expand_more.svg"),
342 "favorite" => include_bytes!("../../icons/material/favorite.svg"),
343 "find_replace" => include_bytes!("../../icons/material/find_replace.svg"),
344 "folder" => include_bytes!("../../icons/material/folder.svg"),
345 "folder_open" => include_bytes!("../../icons/material/folder_open.svg"),
346 "font_size" => include_bytes!("../../icons/material/font_size.svg"),
347 "heart_broken" => include_bytes!("../../icons/material/heart_broken.svg"),
348 "inbox" => include_bytes!("../../icons/material/inbox.svg"),
349 "info" => include_bytes!("../../icons/material/info.svg"),
350 "language" => include_bytes!("../../icons/material/language.svg"),
351 "left_panel_close" => include_bytes!("../../icons/material/left_panel_close.svg"),
352 "left_panel_open" => include_bytes!("../../icons/material/left_panel_open.svg"),
353 "light_mode" => include_bytes!("../../icons/material/light_mode.svg"),
354 "map" => include_bytes!("../../icons/material/map.svg"),
355 "match_case" => include_bytes!("../../icons/material/match_case.svg"),
356 "menu" => include_bytes!("../../icons/material/menu.svg"),
357 "menu_book" => include_bytes!("../../icons/material/menu_book.svg"),
358 "minimize" => include_bytes!("../../icons/material/minimize.svg"),
359 "more_horiz" => include_bytes!("../../icons/material/more_horiz.svg"),
360 "more_vert" => include_bytes!("../../icons/material/more_vert.svg"),
361 "notifications" => include_bytes!("../../icons/material/notifications.svg"),
362 "open_in_full" => include_bytes!("../../icons/material/open_in_full.svg"),
363 "open_in_new" => include_bytes!("../../icons/material/open_in_new.svg"),
364 "palette" => include_bytes!("../../icons/material/palette.svg"),
365 "person" => include_bytes!("../../icons/material/person.svg"),
366 "pie_chart" => include_bytes!("../../icons/material/pie_chart.svg"),
367 "progress_activity" => include_bytes!("../../icons/material/progress_activity.svg"),
368 "redo" => include_bytes!("../../icons/material/redo.svg"),
369 "remove" => include_bytes!("../../icons/material/remove.svg"),
370 "right_panel_close" => include_bytes!("../../icons/material/right_panel_close.svg"),
371 "right_panel_open" => include_bytes!("../../icons/material/right_panel_open.svg"),
372 "search" => include_bytes!("../../icons/material/search.svg"),
373 "settings" => include_bytes!("../../icons/material/settings.svg"),
374 "side_navigation" => include_bytes!("../../icons/material/side_navigation.svg"),
375 "smart_toy" => include_bytes!("../../icons/material/smart_toy.svg"),
376 "star" => include_bytes!("../../icons/material/star.svg"),
377 "star_border" => include_bytes!("../../icons/material/star_border.svg"),
378 "terminal" => include_bytes!("../../icons/material/terminal.svg"),
379 "thumb_down" => include_bytes!("../../icons/material/thumb_down.svg"),
380 "thumb_up" => include_bytes!("../../icons/material/thumb_up.svg"),
381 "tune" => include_bytes!("../../icons/material/tune.svg"),
382 "undo" => include_bytes!("../../icons/material/undo.svg"),
383 "unfold_more" => include_bytes!("../../icons/material/unfold_more.svg"),
384 "view_carousel" => include_bytes!("../../icons/material/view_carousel.svg"),
385 "visibility" => include_bytes!("../../icons/material/visibility.svg"),
386 "visibility_off" => include_bytes!("../../icons/material/visibility_off.svg"),
387 "warning" => include_bytes!("../../icons/material/warning.svg"),
388 "web_asset" => include_bytes!("../../icons/material/web_asset.svg"),
389 _ => return None,
390 })
391}
392
393#[cfg(test)]
394#[allow(clippy::unwrap_used, clippy::expect_used)]
395mod tests {
396 use super::*;
397
398 #[test]
401 #[cfg(feature = "material-icons")]
402 fn material_icons_cover_all_roles() {
403 for role in IconRole::ALL {
404 let svg = bundled_icon_svg(IconSet::Material, role);
405 assert!(svg.is_some(), "Material icons missing SVG for {:?}", role);
406 let bytes = svg.unwrap();
407 let content = std::str::from_utf8(bytes).expect("SVG should be valid UTF-8");
408 assert!(
409 content.contains("<svg"),
410 "Material {:?} does not contain <svg tag",
411 role
412 );
413 }
414 }
415
416 #[test]
417 #[cfg(feature = "material-icons")]
418 fn material_icons_total_size_under_200kb() {
419 let total: usize = IconRole::ALL
420 .iter()
421 .filter_map(|role| bundled_icon_svg(IconSet::Material, *role))
422 .map(|svg| svg.len())
423 .sum();
424 assert!(
425 total < 400 * 1024,
426 "Material icons total size {} bytes exceeds 400KB budget",
427 total
428 );
429 }
430
431 #[test]
434 #[cfg(feature = "lucide-icons")]
435 fn lucide_icons_cover_all_roles() {
436 for role in IconRole::ALL {
437 let svg = bundled_icon_svg(IconSet::Lucide, role);
438 assert!(svg.is_some(), "Lucide icons missing SVG for {:?}", role);
439 let bytes = svg.unwrap();
440 let content = std::str::from_utf8(bytes).expect("SVG should be valid UTF-8");
441 assert!(
442 content.contains("<svg"),
443 "Lucide {:?} does not contain <svg tag",
444 role
445 );
446 }
447 }
448
449 #[test]
450 #[cfg(feature = "lucide-icons")]
451 fn lucide_icons_total_size_under_100kb() {
452 let total: usize = IconRole::ALL
453 .iter()
454 .filter_map(|role| bundled_icon_svg(IconSet::Lucide, *role))
455 .map(|svg| svg.len())
456 .sum();
457 assert!(
458 total < 200 * 1024,
459 "Lucide icons total size {} bytes exceeds 200KB budget",
460 total
461 );
462 }
463
464 #[test]
467 fn non_bundled_sets_return_none() {
468 assert!(
469 bundled_icon_svg(IconSet::SfSymbols, IconRole::ActionCopy).is_none(),
470 "SfSymbols should not be a bundled set"
471 );
472 assert!(
473 bundled_icon_svg(IconSet::Freedesktop, IconRole::ActionCopy).is_none(),
474 "Freedesktop should not be a bundled set"
475 );
476 assert!(
477 bundled_icon_svg(IconSet::SegoeIcons, IconRole::ActionCopy).is_none(),
478 "SegoeIcons should not be a bundled set"
479 );
480 }
481
482 #[test]
485 #[cfg(feature = "lucide-icons")]
486 fn lucide_by_name_covers_gpui_icons() {
487 let names = [
488 "a-large-small",
489 "arrow-down",
490 "arrow-left",
491 "arrow-right",
492 "arrow-up",
493 "asterisk",
494 "bell",
495 "book-open",
496 "bot",
497 "building-2",
498 "calendar",
499 "case-sensitive",
500 "chart-pie",
501 "check",
502 "chevron-down",
503 "chevron-left",
504 "chevron-right",
505 "chevrons-up-down",
506 "chevron-up",
507 "circle-check",
508 "circle-user",
509 "circle-x",
510 "close",
511 "copy",
512 "dash",
513 "delete",
514 "ellipsis",
515 "ellipsis-vertical",
516 "external-link",
517 "eye",
518 "eye-off",
519 "file",
520 "folder",
521 "folder-closed",
522 "folder-open",
523 "frame",
524 "gallery-vertical-end",
525 "github",
526 "globe",
527 "heart",
528 "heart-off",
529 "inbox",
530 "info",
531 "inspect",
532 "layout-dashboard",
533 "loader",
534 "loader-circle",
535 "map",
536 "maximize",
537 "menu",
538 "minimize",
539 "minus",
540 "moon",
541 "palette",
542 "panel-bottom",
543 "panel-bottom-open",
544 "panel-left",
545 "panel-left-close",
546 "panel-left-open",
547 "panel-right",
548 "panel-right-close",
549 "panel-right-open",
550 "plus",
551 "redo",
552 "redo-2",
553 "replace",
554 "resize-corner",
555 "search",
556 "settings",
557 "settings-2",
558 "sort-ascending",
559 "sort-descending",
560 "square-terminal",
561 "star",
562 "star-off",
563 "sun",
564 "thumbs-down",
565 "thumbs-up",
566 "triangle-alert",
567 "undo",
568 "undo-2",
569 "user",
570 "window-close",
571 "window-maximize",
572 "window-minimize",
573 "window-restore",
574 ];
575 for name in names {
576 let svg = bundled_icon_by_name(IconSet::Lucide, name);
577 assert!(svg.is_some(), "Lucide by-name missing: {}", name);
578 let bytes = svg.unwrap();
579 let content = std::str::from_utf8(bytes).expect("SVG should be valid UTF-8");
580 assert!(
581 content.contains("<svg"),
582 "Lucide {} does not contain <svg tag",
583 name
584 );
585 }
586 }
587
588 #[test]
589 #[cfg(feature = "material-icons")]
590 fn material_by_name_covers_gpui_icons() {
591 let names = [
592 "font_size",
593 "arrow_downward",
594 "arrow_back",
595 "arrow_forward",
596 "arrow_upward",
597 "emergency",
598 "notifications",
599 "menu_book",
600 "smart_toy",
601 "apartment",
602 "calendar_today",
603 "match_case",
604 "pie_chart",
605 "check",
606 "expand_more",
607 "chevron_left",
608 "chevron_right",
609 "unfold_more",
610 "expand_less",
611 "check_circle",
612 "account_circle",
613 "cancel",
614 "close",
615 "content_copy",
616 "remove",
617 "delete",
618 "more_horiz",
619 "more_vert",
620 "open_in_new",
621 "visibility",
622 "visibility_off",
623 "description",
624 "folder",
625 "folder_open",
626 "crop_free",
627 "view_carousel",
628 "code",
629 "language",
630 "favorite",
631 "heart_broken",
632 "inbox",
633 "info",
634 "developer_mode",
635 "dashboard",
636 "progress_activity",
637 "autorenew",
638 "map",
639 "open_in_full",
640 "menu",
641 "minimize",
642 "dark_mode",
643 "palette",
644 "dock_to_bottom",
645 "web_asset",
646 "side_navigation",
647 "left_panel_close",
648 "left_panel_open",
649 "right_panel_close",
650 "right_panel_open",
651 "add",
652 "redo",
653 "find_replace",
654 "drag_indicator",
655 "search",
656 "settings",
657 "tune",
658 "terminal",
659 "star",
660 "star_border",
661 "light_mode",
662 "thumb_down",
663 "thumb_up",
664 "warning",
665 "undo",
666 "person",
667 "close_fullscreen",
668 ];
669 for name in names {
670 let svg = bundled_icon_by_name(IconSet::Material, name);
671 assert!(svg.is_some(), "Material by-name missing: {}", name);
672 let bytes = svg.unwrap();
673 let content = std::str::from_utf8(bytes).expect("SVG should be valid UTF-8");
674 assert!(
675 content.contains("<svg"),
676 "Material {} does not contain <svg tag",
677 name
678 );
679 }
680 }
681
682 #[test]
683 fn by_name_non_bundled_sets_return_none() {
684 assert!(bundled_icon_by_name(IconSet::SfSymbols, "check").is_none());
685 assert!(bundled_icon_by_name(IconSet::Freedesktop, "check").is_none());
686 assert!(bundled_icon_by_name(IconSet::SegoeIcons, "check").is_none());
687 }
688
689 #[test]
690 fn by_name_unknown_name_returns_none() {
691 assert!(bundled_icon_by_name(IconSet::Lucide, "nonexistent-icon-xyz").is_none());
692 assert!(bundled_icon_by_name(IconSet::Material, "nonexistent_icon_xyz").is_none());
693 }
694}