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