csskit_highlight/
default_ansi_theme.rs

1pub trait AnsiTheme: Sized {
2	#[cfg(feature = "anstyle")]
3	fn get_anstyle(&self, kind: crate::SemanticKind, modifier: crate::SemanticModifier) -> anstyle::Style;
4
5	#[cfg(feature = "owo-colors")]
6	fn get_owo_style(&self, kind: crate::SemanticKind, modifier: crate::SemanticModifier) -> owo_colors::Style;
7}
8
9pub struct DefaultAnsiTheme;
10
11impl AnsiTheme for DefaultAnsiTheme {
12	#[cfg(feature = "anstyle")]
13	fn get_anstyle(&self, kind: crate::SemanticKind, modifier: crate::SemanticModifier) -> anstyle::Style {
14		use crate::SemanticKind;
15		use anstyle::{AnsiColor, Color, Effects, Style};
16
17		let color = match kind {
18			SemanticKind::None => Color::Ansi(AnsiColor::White),
19			SemanticKind::Id => Color::Ansi256(214.into()),
20			SemanticKind::Tag => Color::Ansi256(203.into()),
21			// Bright green
22			SemanticKind::Class => Color::Ansi256(149.into()),
23			// Salmon/pink
24			SemanticKind::Wildcard => Color::Ansi256(203.into()),
25			// Bright green
26			SemanticKind::Attribute => Color::Ansi256(149.into()),
27			// Cyan
28			SemanticKind::Namespace => Color::Ansi256(81.into()),
29			// White
30			SemanticKind::Combinator => Color::Ansi(AnsiColor::White),
31			// Bright green
32			SemanticKind::PseudoClass => Color::Ansi256(149.into()),
33			// Bright green
34			SemanticKind::PseudoElement => Color::Ansi256(149.into()),
35			// Bright green
36			SemanticKind::LegacyPseudoElement => Color::Ansi256(149.into()),
37			// Bright green
38			SemanticKind::FunctionalPseudoClass => Color::Ansi256(149.into()),
39			// Bright green
40			SemanticKind::FunctionalPseudoElement => Color::Ansi256(149.into()),
41
42			// Rule Elements
43			// Salmon/pink
44			SemanticKind::AtKeyword => Color::Ansi256(203.into()),
45			// Bright green
46			SemanticKind::Prelude => Color::Ansi256(149.into()),
47
48			// Property Declarations
49			// Cyan
50			SemanticKind::Declaration => Color::Ansi256(81.into()),
51			// Cyan
52			SemanticKind::StyleValueKeyword => Color::Ansi256(81.into()),
53			// Purple
54			SemanticKind::StyleValueDimension => Color::Ansi256(141.into()),
55			// Purple
56			SemanticKind::StyleValueNumber => Color::Ansi256(141.into()),
57			// Yellow/Gold for strings
58			SemanticKind::StyleValueString => Color::Ansi256(220.into()),
59			// Blue for URLs
60			SemanticKind::StyleValueUrl => Color::Ansi256(39.into()),
61			// Magenta for colors
62			SemanticKind::StyleValueColor => Color::Ansi256(201.into()),
63			// Cyan for functions
64			SemanticKind::StyleValueFunction => Color::Ansi256(51.into()),
65			// Red for !important
66			SemanticKind::StyleValueImportant => Color::Ansi256(196.into()),
67			SemanticKind::Punctuation => Color::Ansi(AnsiColor::White),
68		};
69
70		let mut effects = Effects::new();
71		if modifier.contains(crate::SemanticModifier::Deprecated) {
72			effects |= Effects::STRIKETHROUGH;
73		}
74		if modifier.contains(crate::SemanticModifier::Experimental) {
75			effects |= Effects::UNDERLINE;
76		}
77		if modifier.contains(crate::SemanticModifier::Unknown) {
78			effects |= Effects::CURLY_UNDERLINE;
79		}
80		Style::new().fg_color(Some(color)).effects(effects)
81	}
82
83	#[cfg(feature = "owo-colors")]
84	fn get_owo_style(&self, kind: crate::SemanticKind, modifier: crate::SemanticModifier) -> owo_colors::Style {
85		use crate::SemanticKind;
86		use owo_colors::{Style, XtermColors};
87
88		// Map semantic kind to owo-colors style (matching anstyle colors)
89		let mut style = match kind {
90			SemanticKind::None => Style::new(),
91			SemanticKind::Id => Style::new().color(XtermColors::UserBrightYellow),
92			SemanticKind::Tag => Style::new().color(XtermColors::UserBrightMagenta),
93			SemanticKind::Class => Style::new().color(XtermColors::UserBrightCyan),
94			SemanticKind::Wildcard => Style::new().color(XtermColors::UserBrightMagenta),
95			SemanticKind::Attribute => Style::new().color(XtermColors::UserBrightGreen),
96			SemanticKind::Namespace => Style::new().color(XtermColors::UserCyan),
97			SemanticKind::Combinator => Style::new(),
98			SemanticKind::PseudoClass => Style::new().color(XtermColors::UserBrightGreen),
99			SemanticKind::PseudoElement => Style::new().color(XtermColors::UserBrightGreen),
100			SemanticKind::LegacyPseudoElement => Style::new().color(XtermColors::UserBrightGreen),
101			SemanticKind::FunctionalPseudoClass => Style::new().color(XtermColors::UserBrightGreen),
102			SemanticKind::FunctionalPseudoElement => Style::new().color(XtermColors::UserBrightGreen),
103
104			// Rule Elements
105			SemanticKind::AtKeyword => Style::new().color(XtermColors::UserBrightMagenta),
106			SemanticKind::Prelude => Style::new().color(XtermColors::UserBrightGreen),
107
108			// Property Declarations
109			SemanticKind::Declaration => Style::new().color(XtermColors::UserCyan),
110			SemanticKind::StyleValueKeyword => Style::new().color(XtermColors::UserCyan),
111			SemanticKind::StyleValueDimension => Style::new().color(XtermColors::UserMagenta),
112			SemanticKind::StyleValueNumber => Style::new().color(XtermColors::UserMagenta),
113			SemanticKind::StyleValueString => Style::new().color(XtermColors::UserYellow),
114			SemanticKind::StyleValueUrl => Style::new().color(XtermColors::UserBlue),
115			SemanticKind::StyleValueColor => Style::new().color(XtermColors::UserBrightMagenta),
116			SemanticKind::StyleValueFunction => Style::new().color(XtermColors::UserCyan),
117			SemanticKind::StyleValueImportant => Style::new().color(XtermColors::UserRed),
118			SemanticKind::Punctuation => Style::new(),
119		};
120
121		// Apply effects based on modifiers
122		if modifier.contains(crate::SemanticModifier::Deprecated) {
123			style = style.strikethrough();
124		}
125		if modifier.contains(crate::SemanticModifier::Experimental) {
126			style = style.underline();
127		}
128		if modifier.contains(crate::SemanticModifier::Unknown) {
129			style = style.underline(); // TODO: owo-colors doesn't have curly underline
130		}
131
132		style
133	}
134}