1#[cfg(any(
9 feature = "syntax-rust",
10 feature = "syntax-python",
11 feature = "syntax-javascript",
12 feature = "syntax-typescript",
13 feature = "syntax-go",
14 feature = "syntax-bash",
15 feature = "syntax-json",
16 feature = "syntax-toml",
17 feature = "syntax-c",
18 feature = "syntax-cpp",
19 feature = "syntax-java",
20 feature = "syntax-ruby",
21 feature = "syntax-css",
22 feature = "syntax-html",
23 feature = "syntax-yaml",
24))]
25use crate::style::Color;
26use crate::style::{Style, Theme};
27
28#[cfg(any(
33 feature = "syntax-rust",
34 feature = "syntax-python",
35 feature = "syntax-javascript",
36 feature = "syntax-typescript",
37 feature = "syntax-go",
38 feature = "syntax-bash",
39 feature = "syntax-json",
40 feature = "syntax-toml",
41 feature = "syntax-c",
42 feature = "syntax-cpp",
43 feature = "syntax-java",
44 feature = "syntax-ruby",
45 feature = "syntax-css",
46 feature = "syntax-html",
47 feature = "syntax-yaml",
48))]
49const HIGHLIGHT_NAMES: &[&str] = &[
50 "attribute",
51 "comment",
52 "constant",
53 "constant.builtin",
54 "constructor",
55 "embedded",
56 "function",
57 "function.builtin",
58 "function.macro",
59 "keyword",
60 "module",
61 "number",
62 "operator",
63 "property",
64 "property.builtin",
65 "punctuation",
66 "punctuation.bracket",
67 "punctuation.delimiter",
68 "punctuation.special",
69 "string",
70 "string.special",
71 "tag",
72 "type",
73 "type.builtin",
74 "variable",
75 "variable.builtin",
76 "variable.parameter",
77];
78
79#[cfg(any(
80 feature = "syntax-rust",
81 feature = "syntax-python",
82 feature = "syntax-javascript",
83 feature = "syntax-typescript",
84 feature = "syntax-go",
85 feature = "syntax-bash",
86 feature = "syntax-json",
87 feature = "syntax-toml",
88 feature = "syntax-c",
89 feature = "syntax-cpp",
90 feature = "syntax-java",
91 feature = "syntax-ruby",
92 feature = "syntax-css",
93 feature = "syntax-html",
94 feature = "syntax-yaml",
95))]
96use std::sync::OnceLock;
97
98#[cfg(any(
99 feature = "syntax-rust",
100 feature = "syntax-python",
101 feature = "syntax-javascript",
102 feature = "syntax-typescript",
103 feature = "syntax-go",
104 feature = "syntax-bash",
105 feature = "syntax-json",
106 feature = "syntax-toml",
107 feature = "syntax-c",
108 feature = "syntax-cpp",
109 feature = "syntax-java",
110 feature = "syntax-ruby",
111 feature = "syntax-css",
112 feature = "syntax-html",
113 feature = "syntax-yaml",
114))]
115use tree_sitter_highlight::HighlightConfiguration;
116
117#[cfg(any(
120 feature = "syntax-rust",
121 feature = "syntax-python",
122 feature = "syntax-javascript",
123 feature = "syntax-typescript",
124 feature = "syntax-go",
125 feature = "syntax-bash",
126 feature = "syntax-json",
127 feature = "syntax-toml",
128 feature = "syntax-c",
129 feature = "syntax-cpp",
130 feature = "syntax-java",
131 feature = "syntax-ruby",
132 feature = "syntax-css",
133 feature = "syntax-html",
134 feature = "syntax-yaml",
135))]
136fn get_config(lang: &str) -> Option<&'static HighlightConfiguration> {
137 match lang {
138 #[cfg(feature = "syntax-rust")]
139 "rust" | "rs" => {
140 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
141 Some(CFG.get_or_init(|| {
142 let mut c = HighlightConfiguration::new(
143 tree_sitter_rust::LANGUAGE.into(),
144 "rust",
145 tree_sitter_rust::HIGHLIGHTS_QUERY,
146 tree_sitter_rust::INJECTIONS_QUERY,
147 "",
148 )
149 .expect("valid rust highlight config");
150 c.configure(HIGHLIGHT_NAMES);
151 c
152 }))
153 }
154
155 #[cfg(feature = "syntax-python")]
156 "python" | "py" => {
157 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
158 Some(CFG.get_or_init(|| {
159 let mut c = HighlightConfiguration::new(
160 tree_sitter_python::LANGUAGE.into(),
161 "python",
162 tree_sitter_python::HIGHLIGHTS_QUERY,
163 "",
164 "",
165 )
166 .expect("valid python highlight config");
167 c.configure(HIGHLIGHT_NAMES);
168 c
169 }))
170 }
171
172 #[cfg(feature = "syntax-javascript")]
173 "javascript" | "js" | "jsx" => {
174 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
175 Some(CFG.get_or_init(|| {
176 let mut c = HighlightConfiguration::new(
177 tree_sitter_javascript::LANGUAGE.into(),
178 "javascript",
179 tree_sitter_javascript::HIGHLIGHT_QUERY,
180 tree_sitter_javascript::INJECTIONS_QUERY,
181 tree_sitter_javascript::LOCALS_QUERY,
182 )
183 .expect("valid javascript highlight config");
184 c.configure(HIGHLIGHT_NAMES);
185 c
186 }))
187 }
188
189 #[cfg(feature = "syntax-go")]
190 "go" | "golang" => {
191 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
192 Some(CFG.get_or_init(|| {
193 let mut c = HighlightConfiguration::new(
194 tree_sitter_go::LANGUAGE.into(),
195 "go",
196 tree_sitter_go::HIGHLIGHTS_QUERY,
197 "",
198 "",
199 )
200 .expect("valid go highlight config");
201 c.configure(HIGHLIGHT_NAMES);
202 c
203 }))
204 }
205
206 #[cfg(feature = "syntax-bash")]
207 "bash" | "sh" | "shell" | "zsh" => {
208 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
209 Some(CFG.get_or_init(|| {
210 let mut c = HighlightConfiguration::new(
211 tree_sitter_bash::LANGUAGE.into(),
212 "bash",
213 tree_sitter_bash::HIGHLIGHT_QUERY,
214 "",
215 "",
216 )
217 .expect("valid bash highlight config");
218 c.configure(HIGHLIGHT_NAMES);
219 c
220 }))
221 }
222
223 #[cfg(feature = "syntax-json")]
224 "json" | "jsonc" => {
225 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
226 Some(CFG.get_or_init(|| {
227 let mut c = HighlightConfiguration::new(
228 tree_sitter_json::LANGUAGE.into(),
229 "json",
230 tree_sitter_json::HIGHLIGHTS_QUERY,
231 "",
232 "",
233 )
234 .expect("valid json highlight config");
235 c.configure(HIGHLIGHT_NAMES);
236 c
237 }))
238 }
239
240 #[cfg(feature = "syntax-toml")]
241 "toml" => {
242 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
243 Some(CFG.get_or_init(|| {
244 let mut c = HighlightConfiguration::new(
245 tree_sitter_toml_ng::LANGUAGE.into(),
246 "toml",
247 tree_sitter_toml_ng::HIGHLIGHTS_QUERY,
248 "",
249 "",
250 )
251 .expect("valid toml highlight config");
252 c.configure(HIGHLIGHT_NAMES);
253 c
254 }))
255 }
256
257 #[cfg(feature = "syntax-c")]
258 "c" | "h" => {
259 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
260 Some(CFG.get_or_init(|| {
261 let mut c = HighlightConfiguration::new(
262 tree_sitter_c::LANGUAGE.into(),
263 "c",
264 tree_sitter_c::HIGHLIGHT_QUERY,
265 "",
266 "",
267 )
268 .expect("valid c highlight config");
269 c.configure(HIGHLIGHT_NAMES);
270 c
271 }))
272 }
273
274 #[cfg(feature = "syntax-cpp")]
275 "cpp" | "c++" | "cxx" | "cc" | "hpp" => {
276 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
277 Some(CFG.get_or_init(|| {
278 #[cfg(feature = "syntax-c")]
279 let highlights = {
280 let mut combined = String::with_capacity(
281 tree_sitter_c::HIGHLIGHT_QUERY.len()
282 + tree_sitter_cpp::HIGHLIGHT_QUERY.len()
283 + 1,
284 );
285 combined.push_str(tree_sitter_c::HIGHLIGHT_QUERY);
286 combined.push('\n');
287 combined.push_str(tree_sitter_cpp::HIGHLIGHT_QUERY);
288 combined
289 };
290 #[cfg(not(feature = "syntax-c"))]
291 let highlights = tree_sitter_cpp::HIGHLIGHT_QUERY.to_string();
292
293 let mut c = HighlightConfiguration::new(
294 tree_sitter_cpp::LANGUAGE.into(),
295 "cpp",
296 &highlights,
297 "",
298 "",
299 )
300 .expect("valid cpp highlight config");
301 c.configure(HIGHLIGHT_NAMES);
302 c
303 }))
304 }
305
306 #[cfg(feature = "syntax-typescript")]
307 "typescript" | "ts" => {
308 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
309 Some(CFG.get_or_init(|| {
310 let mut c = HighlightConfiguration::new(
311 tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
312 "typescript",
313 tree_sitter_typescript::HIGHLIGHTS_QUERY,
314 tree_sitter_typescript::LOCALS_QUERY,
315 "",
316 )
317 .expect("valid typescript highlight config");
318 c.configure(HIGHLIGHT_NAMES);
319 c
320 }))
321 }
322
323 #[cfg(feature = "syntax-typescript")]
324 "tsx" => {
325 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
326 Some(CFG.get_or_init(|| {
327 let mut c = HighlightConfiguration::new(
328 tree_sitter_typescript::LANGUAGE_TSX.into(),
329 "tsx",
330 tree_sitter_typescript::HIGHLIGHTS_QUERY,
331 tree_sitter_typescript::LOCALS_QUERY,
332 "",
333 )
334 .expect("valid tsx highlight config");
335 c.configure(HIGHLIGHT_NAMES);
336 c
337 }))
338 }
339
340 #[cfg(feature = "syntax-java")]
341 "java" => {
342 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
343 Some(CFG.get_or_init(|| {
344 let mut c = HighlightConfiguration::new(
345 tree_sitter_java::LANGUAGE.into(),
346 "java",
347 tree_sitter_java::HIGHLIGHTS_QUERY,
348 "",
349 "",
350 )
351 .expect("valid java highlight config");
352 c.configure(HIGHLIGHT_NAMES);
353 c
354 }))
355 }
356
357 #[cfg(feature = "syntax-ruby")]
358 "ruby" | "rb" => {
359 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
360 Some(CFG.get_or_init(|| {
361 let mut c = HighlightConfiguration::new(
362 tree_sitter_ruby::LANGUAGE.into(),
363 "ruby",
364 tree_sitter_ruby::HIGHLIGHTS_QUERY,
365 tree_sitter_ruby::LOCALS_QUERY,
366 "",
367 )
368 .expect("valid ruby highlight config");
369 c.configure(HIGHLIGHT_NAMES);
370 c
371 }))
372 }
373
374 #[cfg(feature = "syntax-css")]
375 "css" => {
376 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
377 Some(CFG.get_or_init(|| {
378 let mut c = HighlightConfiguration::new(
379 tree_sitter_css::LANGUAGE.into(),
380 "css",
381 tree_sitter_css::HIGHLIGHTS_QUERY,
382 "",
383 "",
384 )
385 .expect("valid css highlight config");
386 c.configure(HIGHLIGHT_NAMES);
387 c
388 }))
389 }
390
391 #[cfg(feature = "syntax-html")]
392 "html" | "htm" => {
393 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
394 Some(CFG.get_or_init(|| {
395 let mut c = HighlightConfiguration::new(
396 tree_sitter_html::LANGUAGE.into(),
397 "html",
398 tree_sitter_html::HIGHLIGHTS_QUERY,
399 tree_sitter_html::INJECTIONS_QUERY,
400 "",
401 )
402 .expect("valid html highlight config");
403 c.configure(HIGHLIGHT_NAMES);
404 c
405 }))
406 }
407
408 #[cfg(feature = "syntax-yaml")]
409 "yaml" | "yml" => {
410 static CFG: OnceLock<HighlightConfiguration> = OnceLock::new();
411 Some(CFG.get_or_init(|| {
412 let mut c = HighlightConfiguration::new(
413 tree_sitter_yaml::LANGUAGE.into(),
414 "yaml",
415 tree_sitter_yaml::HIGHLIGHTS_QUERY,
416 "",
417 "",
418 )
419 .expect("valid yaml highlight config");
420 c.configure(HIGHLIGHT_NAMES);
421 c
422 }))
423 }
424
425 _ => None,
426 }
427}
428
429#[cfg(any(
434 feature = "syntax-rust",
435 feature = "syntax-python",
436 feature = "syntax-javascript",
437 feature = "syntax-typescript",
438 feature = "syntax-go",
439 feature = "syntax-bash",
440 feature = "syntax-json",
441 feature = "syntax-toml",
442 feature = "syntax-c",
443 feature = "syntax-cpp",
444 feature = "syntax-java",
445 feature = "syntax-ruby",
446 feature = "syntax-css",
447 feature = "syntax-html",
448 feature = "syntax-yaml",
449))]
450fn highlight_name_to_style(name: &str, theme: &Theme) -> Style {
451 let dark = theme.is_dark;
452 match name {
453 "keyword" => Style::new().fg(if dark {
454 Color::Rgb(198, 120, 221)
455 } else {
456 Color::Rgb(166, 38, 164)
457 }),
458 "string" | "string.special" => Style::new().fg(if dark {
459 Color::Rgb(152, 195, 121)
460 } else {
461 Color::Rgb(80, 161, 79)
462 }),
463 "comment" => Style::new().fg(theme.text_dim).italic(),
464 "number" | "constant" | "constant.builtin" => Style::new().fg(if dark {
465 Color::Rgb(209, 154, 102)
466 } else {
467 Color::Rgb(152, 104, 1)
468 }),
469 "function" | "function.builtin" => Style::new().fg(if dark {
470 Color::Rgb(97, 175, 239)
471 } else {
472 Color::Rgb(64, 120, 242)
473 }),
474 "function.macro" => Style::new().fg(if dark {
475 Color::Rgb(86, 182, 194)
476 } else {
477 Color::Rgb(1, 132, 188)
478 }),
479 "type" | "type.builtin" | "constructor" => Style::new().fg(if dark {
480 Color::Rgb(229, 192, 123)
481 } else {
482 Color::Rgb(152, 104, 1)
483 }),
484 "variable.builtin" => Style::new().fg(if dark {
485 Color::Rgb(224, 108, 117)
486 } else {
487 Color::Rgb(166, 38, 164)
488 }),
489 "property" | "property.builtin" => Style::new().fg(if dark {
490 Color::Rgb(97, 175, 239)
491 } else {
492 Color::Rgb(64, 120, 242)
493 }),
494 "tag" => Style::new().fg(if dark {
495 Color::Rgb(224, 108, 117)
496 } else {
497 Color::Rgb(166, 38, 164)
498 }),
499 "attribute" => Style::new().fg(if dark {
500 Color::Rgb(209, 154, 102)
501 } else {
502 Color::Rgb(152, 104, 1)
503 }),
504 "module" | "embedded" | "operator" | "variable" | "variable.parameter" => {
505 Style::new().fg(theme.text)
506 }
507 "punctuation" | "punctuation.bracket" | "punctuation.delimiter" | "punctuation.special" => {
508 Style::new().fg(theme.text_dim)
509 }
510 _ => Style::new().fg(theme.text),
511 }
512}
513
514#[allow(unused_variables)]
531pub fn highlight_code(code: &str, lang: &str, theme: &Theme) -> Option<Vec<Vec<(String, Style)>>> {
532 #[cfg(any(
533 feature = "syntax-rust",
534 feature = "syntax-python",
535 feature = "syntax-javascript",
536 feature = "syntax-typescript",
537 feature = "syntax-go",
538 feature = "syntax-bash",
539 feature = "syntax-json",
540 feature = "syntax-toml",
541 feature = "syntax-c",
542 feature = "syntax-cpp",
543 feature = "syntax-java",
544 feature = "syntax-ruby",
545 feature = "syntax-css",
546 feature = "syntax-html",
547 feature = "syntax-yaml",
548 ))]
549 {
550 use tree_sitter_highlight::{HighlightEvent, Highlighter};
551
552 let config = get_config(lang)?;
553 let mut highlighter = Highlighter::new();
554 let highlights = highlighter
555 .highlight(config, code.as_bytes(), None, |_| None)
556 .ok()?;
557
558 let default_style = Style::new().fg(theme.text);
559 let mut result: Vec<Vec<(String, Style)>> = Vec::new();
560 let mut current_line: Vec<(String, Style)> = Vec::new();
561 let mut style_stack: Vec<Style> = vec![default_style];
562
563 for event in highlights {
564 match event.ok()? {
565 HighlightEvent::Source { start, end } => {
566 let text = &code[start..end];
567 let style = *style_stack.last().unwrap_or(&default_style);
568 for (i, part) in text.split('\n').enumerate() {
570 if i > 0 {
571 result.push(std::mem::take(&mut current_line));
572 }
573 if !part.is_empty() {
574 current_line.push((part.to_string(), style));
575 }
576 }
577 }
578 HighlightEvent::HighlightStart(highlight) => {
579 let name = HIGHLIGHT_NAMES.get(highlight.0).copied().unwrap_or("");
580 let style = highlight_name_to_style(name, theme);
581 style_stack.push(style);
582 }
583 HighlightEvent::HighlightEnd => {
584 style_stack.pop();
585 }
586 }
587 }
588
589 if !current_line.is_empty() {
590 result.push(current_line);
591 }
592
593 Some(result)
594 }
595
596 #[cfg(not(any(
597 feature = "syntax-rust",
598 feature = "syntax-python",
599 feature = "syntax-javascript",
600 feature = "syntax-typescript",
601 feature = "syntax-go",
602 feature = "syntax-bash",
603 feature = "syntax-json",
604 feature = "syntax-toml",
605 feature = "syntax-c",
606 feature = "syntax-cpp",
607 feature = "syntax-java",
608 feature = "syntax-ruby",
609 feature = "syntax-css",
610 feature = "syntax-html",
611 feature = "syntax-yaml",
612 )))]
613 {
614 None
615 }
616}
617
618#[allow(unused_variables)]
623pub fn is_language_supported(lang: &str) -> bool {
624 #[cfg(any(
625 feature = "syntax-rust",
626 feature = "syntax-python",
627 feature = "syntax-javascript",
628 feature = "syntax-typescript",
629 feature = "syntax-go",
630 feature = "syntax-bash",
631 feature = "syntax-json",
632 feature = "syntax-toml",
633 feature = "syntax-c",
634 feature = "syntax-cpp",
635 feature = "syntax-java",
636 feature = "syntax-ruby",
637 feature = "syntax-css",
638 feature = "syntax-html",
639 feature = "syntax-yaml",
640 ))]
641 {
642 get_config(lang).is_some()
643 }
644 #[cfg(not(any(
645 feature = "syntax-rust",
646 feature = "syntax-python",
647 feature = "syntax-javascript",
648 feature = "syntax-typescript",
649 feature = "syntax-go",
650 feature = "syntax-bash",
651 feature = "syntax-json",
652 feature = "syntax-toml",
653 feature = "syntax-c",
654 feature = "syntax-cpp",
655 feature = "syntax-java",
656 feature = "syntax-ruby",
657 feature = "syntax-css",
658 feature = "syntax-html",
659 feature = "syntax-yaml",
660 )))]
661 {
662 false
663 }
664}
665
666#[cfg(test)]
667mod tests {
668 use super::*;
669 use crate::style::Theme;
670
671 #[test]
672 fn highlight_returns_none_for_unknown_lang() {
673 let theme = Theme::dark();
674 assert!(highlight_code("let x = 1;", "brainfuck", &theme).is_none());
675 }
676
677 #[test]
678 fn is_language_supported_unknown() {
679 assert!(!is_language_supported("haskell"));
680 }
681
682 #[cfg(feature = "syntax-rust")]
683 #[test]
684 fn highlight_rust_basic() {
685 let theme = Theme::dark();
686 let result = highlight_code("let x = 1;", "rust", &theme);
687 assert!(result.is_some());
688 let lines = result.unwrap();
689 assert_eq!(lines.len(), 1);
690 let flat: String = lines[0].iter().map(|(t, _)| t.as_str()).collect();
692 assert!(flat.contains("let"));
693 assert!(flat.contains("1"));
694 }
695
696 #[cfg(feature = "syntax-rust")]
697 #[test]
698 fn highlight_rust_multiline() {
699 let theme = Theme::dark();
700 let code = "fn main() {\n println!(\"hello\");\n}";
701 let result = highlight_code(code, "rust", &theme).unwrap();
702 assert_eq!(result.len(), 3);
703 }
704
705 #[cfg(feature = "syntax-rust")]
706 #[test]
707 fn highlight_rust_rs_alias() {
708 let theme = Theme::dark();
709 assert!(highlight_code("let x = 1;", "rs", &theme).is_some());
710 }
711
712 #[cfg(feature = "syntax-python")]
713 #[test]
714 fn highlight_python_basic() {
715 let theme = Theme::dark();
716 let result = highlight_code("def foo():\n return 42", "python", &theme);
717 assert!(result.is_some());
718 let lines = result.unwrap();
719 assert_eq!(lines.len(), 2);
720 }
721
722 #[cfg(feature = "syntax-javascript")]
723 #[test]
724 fn highlight_javascript_basic() {
725 let theme = Theme::dark();
726 let result = highlight_code("const x = () => 42;", "js", &theme);
727 assert!(result.is_some());
728 }
729
730 #[cfg(feature = "syntax-bash")]
731 #[test]
732 fn highlight_bash_basic() {
733 let theme = Theme::dark();
734 let result = highlight_code("echo \"hello\"", "sh", &theme);
735 assert!(result.is_some());
736 }
737
738 #[cfg(feature = "syntax-json")]
739 #[test]
740 fn highlight_json_basic() {
741 let theme = Theme::dark();
742 let result = highlight_code("{\"key\": 42}", "json", &theme);
743 assert!(result.is_some());
744 }
745
746 #[cfg(feature = "syntax-toml")]
747 #[test]
748 fn highlight_toml_basic() {
749 let theme = Theme::dark();
750 let result = highlight_code("[package]\nname = \"slt\"", "toml", &theme);
751 assert!(result.is_some());
752 }
753
754 #[cfg(feature = "syntax-go")]
755 #[test]
756 fn highlight_go_basic() {
757 let theme = Theme::dark();
758 let result = highlight_code("package main\nfunc main() {}", "go", &theme);
759 assert!(result.is_some());
760 }
761
762 #[cfg(feature = "syntax-rust")]
763 #[test]
764 fn highlight_light_theme_differs() {
765 let dark = Theme::dark();
766 let light = Theme::light();
767 let dark_result = highlight_code("let x = 1;", "rust", &dark).unwrap();
768 let light_result = highlight_code("let x = 1;", "rust", &light).unwrap();
769 let dark_styles: Vec<Style> = dark_result[0].iter().map(|(_, s)| *s).collect();
771 let light_styles: Vec<Style> = light_result[0].iter().map(|(_, s)| *s).collect();
772 assert_ne!(dark_styles, light_styles);
773 }
774
775 #[cfg(feature = "syntax-rust")]
776 #[test]
777 fn highlight_incomplete_code_does_not_panic() {
778 let theme = Theme::dark();
779 let result = highlight_code("fn main( {", "rust", &theme);
780 assert!(result.is_some());
781 }
782
783 #[cfg(feature = "syntax-c")]
784 #[test]
785 fn highlight_c_basic() {
786 let theme = Theme::dark();
787 assert!(
788 highlight_code("#include <stdio.h>\nint main() { return 0; }", "c", &theme).is_some()
789 );
790 }
791
792 #[cfg(feature = "syntax-cpp")]
793 #[test]
794 fn highlight_cpp_basic() {
795 let theme = Theme::dark();
796 assert!(highlight_code("class Foo { public: void bar(); };", "cpp", &theme).is_some());
797 }
798
799 #[cfg(feature = "syntax-typescript")]
800 #[test]
801 fn highlight_typescript_basic() {
802 let theme = Theme::dark();
803 assert!(highlight_code("const x: number = 42;", "ts", &theme).is_some());
804 }
805
806 #[cfg(feature = "syntax-typescript")]
807 #[test]
808 fn highlight_tsx_basic() {
809 let theme = Theme::dark();
810 assert!(highlight_code("const App = () => <div>hello</div>;", "tsx", &theme).is_some());
811 }
812
813 #[cfg(feature = "syntax-java")]
814 #[test]
815 fn highlight_java_basic() {
816 let theme = Theme::dark();
817 assert!(highlight_code(
818 "public class Main { public static void main(String[] args) {} }",
819 "java",
820 &theme
821 )
822 .is_some());
823 }
824
825 #[cfg(feature = "syntax-ruby")]
826 #[test]
827 fn highlight_ruby_basic() {
828 let theme = Theme::dark();
829 assert!(highlight_code("def hello\n puts 'world'\nend", "ruby", &theme).is_some());
830 }
831
832 #[cfg(feature = "syntax-css")]
833 #[test]
834 fn highlight_css_basic() {
835 let theme = Theme::dark();
836 assert!(highlight_code("body { color: red; }", "css", &theme).is_some());
837 }
838
839 #[cfg(feature = "syntax-html")]
840 #[test]
841 fn highlight_html_basic() {
842 let theme = Theme::dark();
843 assert!(highlight_code("<div class=\"test\">hello</div>", "html", &theme).is_some());
844 }
845
846 #[cfg(feature = "syntax-yaml")]
847 #[test]
848 fn highlight_yaml_basic() {
849 let theme = Theme::dark();
850 assert!(highlight_code("name: slt\nversion: 0.14", "yaml", &theme).is_some());
851 }
852}