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)]
394mod tests {
395 use super::*;
396
397 #[test]
400 #[cfg(feature = "material-icons")]
401 fn material_icons_cover_all_roles() {
402 for role in IconRole::ALL {
403 let svg = bundled_icon_svg(IconSet::Material, role);
404 assert!(svg.is_some(), "Material icons missing SVG for {:?}", role);
405 let bytes = svg.unwrap();
406 let content = std::str::from_utf8(bytes).expect("SVG should be valid UTF-8");
407 assert!(
408 content.contains("<svg"),
409 "Material {:?} does not contain <svg tag",
410 role
411 );
412 }
413 }
414
415 #[test]
416 #[cfg(feature = "material-icons")]
417 fn material_icons_total_size_under_200kb() {
418 let total: usize = IconRole::ALL
419 .iter()
420 .filter_map(|role| bundled_icon_svg(IconSet::Material, *role))
421 .map(|svg| svg.len())
422 .sum();
423 assert!(
424 total < 400 * 1024,
425 "Material icons total size {} bytes exceeds 400KB budget",
426 total
427 );
428 }
429
430 #[test]
433 #[cfg(feature = "lucide-icons")]
434 fn lucide_icons_cover_all_roles() {
435 for role in IconRole::ALL {
436 let svg = bundled_icon_svg(IconSet::Lucide, role);
437 assert!(svg.is_some(), "Lucide icons missing SVG for {:?}", role);
438 let bytes = svg.unwrap();
439 let content = std::str::from_utf8(bytes).expect("SVG should be valid UTF-8");
440 assert!(
441 content.contains("<svg"),
442 "Lucide {:?} does not contain <svg tag",
443 role
444 );
445 }
446 }
447
448 #[test]
449 #[cfg(feature = "lucide-icons")]
450 fn lucide_icons_total_size_under_100kb() {
451 let total: usize = IconRole::ALL
452 .iter()
453 .filter_map(|role| bundled_icon_svg(IconSet::Lucide, *role))
454 .map(|svg| svg.len())
455 .sum();
456 assert!(
457 total < 200 * 1024,
458 "Lucide icons total size {} bytes exceeds 200KB budget",
459 total
460 );
461 }
462
463 #[test]
466 fn non_bundled_sets_return_none() {
467 assert!(
468 bundled_icon_svg(IconSet::SfSymbols, IconRole::ActionCopy).is_none(),
469 "SfSymbols should not be a bundled set"
470 );
471 assert!(
472 bundled_icon_svg(IconSet::Freedesktop, IconRole::ActionCopy).is_none(),
473 "Freedesktop should not be a bundled set"
474 );
475 assert!(
476 bundled_icon_svg(IconSet::SegoeIcons, IconRole::ActionCopy).is_none(),
477 "SegoeIcons should not be a bundled set"
478 );
479 }
480
481 #[test]
484 #[cfg(feature = "lucide-icons")]
485 fn lucide_by_name_covers_gpui_icons() {
486 let names = [
487 "a-large-small",
488 "arrow-down",
489 "arrow-left",
490 "arrow-right",
491 "arrow-up",
492 "asterisk",
493 "bell",
494 "book-open",
495 "bot",
496 "building-2",
497 "calendar",
498 "case-sensitive",
499 "chart-pie",
500 "check",
501 "chevron-down",
502 "chevron-left",
503 "chevron-right",
504 "chevrons-up-down",
505 "chevron-up",
506 "circle-check",
507 "circle-user",
508 "circle-x",
509 "close",
510 "copy",
511 "dash",
512 "delete",
513 "ellipsis",
514 "ellipsis-vertical",
515 "external-link",
516 "eye",
517 "eye-off",
518 "file",
519 "folder",
520 "folder-closed",
521 "folder-open",
522 "frame",
523 "gallery-vertical-end",
524 "github",
525 "globe",
526 "heart",
527 "heart-off",
528 "inbox",
529 "info",
530 "inspect",
531 "layout-dashboard",
532 "loader",
533 "loader-circle",
534 "map",
535 "maximize",
536 "menu",
537 "minimize",
538 "minus",
539 "moon",
540 "palette",
541 "panel-bottom",
542 "panel-bottom-open",
543 "panel-left",
544 "panel-left-close",
545 "panel-left-open",
546 "panel-right",
547 "panel-right-close",
548 "panel-right-open",
549 "plus",
550 "redo",
551 "redo-2",
552 "replace",
553 "resize-corner",
554 "search",
555 "settings",
556 "settings-2",
557 "sort-ascending",
558 "sort-descending",
559 "square-terminal",
560 "star",
561 "star-off",
562 "sun",
563 "thumbs-down",
564 "thumbs-up",
565 "triangle-alert",
566 "undo",
567 "undo-2",
568 "user",
569 "window-close",
570 "window-maximize",
571 "window-minimize",
572 "window-restore",
573 ];
574 for name in names {
575 let svg = bundled_icon_by_name(IconSet::Lucide, name);
576 assert!(svg.is_some(), "Lucide by-name missing: {}", name);
577 let bytes = svg.unwrap();
578 let content = std::str::from_utf8(bytes).expect("SVG should be valid UTF-8");
579 assert!(
580 content.contains("<svg"),
581 "Lucide {} does not contain <svg tag",
582 name
583 );
584 }
585 }
586
587 #[test]
588 #[cfg(feature = "material-icons")]
589 fn material_by_name_covers_gpui_icons() {
590 let names = [
591 "font_size",
592 "arrow_downward",
593 "arrow_back",
594 "arrow_forward",
595 "arrow_upward",
596 "emergency",
597 "notifications",
598 "menu_book",
599 "smart_toy",
600 "apartment",
601 "calendar_today",
602 "match_case",
603 "pie_chart",
604 "check",
605 "expand_more",
606 "chevron_left",
607 "chevron_right",
608 "unfold_more",
609 "expand_less",
610 "check_circle",
611 "account_circle",
612 "cancel",
613 "close",
614 "content_copy",
615 "remove",
616 "delete",
617 "more_horiz",
618 "more_vert",
619 "open_in_new",
620 "visibility",
621 "visibility_off",
622 "description",
623 "folder",
624 "folder_open",
625 "crop_free",
626 "view_carousel",
627 "code",
628 "language",
629 "favorite",
630 "heart_broken",
631 "inbox",
632 "info",
633 "developer_mode",
634 "dashboard",
635 "progress_activity",
636 "autorenew",
637 "map",
638 "open_in_full",
639 "menu",
640 "minimize",
641 "dark_mode",
642 "palette",
643 "dock_to_bottom",
644 "web_asset",
645 "side_navigation",
646 "left_panel_close",
647 "left_panel_open",
648 "right_panel_close",
649 "right_panel_open",
650 "add",
651 "redo",
652 "find_replace",
653 "drag_indicator",
654 "search",
655 "settings",
656 "tune",
657 "terminal",
658 "star",
659 "star_border",
660 "light_mode",
661 "thumb_down",
662 "thumb_up",
663 "warning",
664 "undo",
665 "person",
666 "close_fullscreen",
667 ];
668 for name in names {
669 let svg = bundled_icon_by_name(IconSet::Material, name);
670 assert!(svg.is_some(), "Material by-name missing: {}", name);
671 let bytes = svg.unwrap();
672 let content = std::str::from_utf8(bytes).expect("SVG should be valid UTF-8");
673 assert!(
674 content.contains("<svg"),
675 "Material {} does not contain <svg tag",
676 name
677 );
678 }
679 }
680
681 #[test]
682 fn by_name_non_bundled_sets_return_none() {
683 assert!(bundled_icon_by_name(IconSet::SfSymbols, "check").is_none());
684 assert!(bundled_icon_by_name(IconSet::Freedesktop, "check").is_none());
685 assert!(bundled_icon_by_name(IconSet::SegoeIcons, "check").is_none());
686 }
687
688 #[test]
689 fn by_name_unknown_name_returns_none() {
690 assert!(bundled_icon_by_name(IconSet::Lucide, "nonexistent-icon-xyz").is_none());
691 assert!(bundled_icon_by_name(IconSet::Material, "nonexistent_icon_xyz").is_none());
692 }
693}