normalize_languages/
typst.rs1use crate::{Import, Language, LanguageSymbols};
4use tree_sitter::Node;
5
6pub struct Typst;
8
9impl Language for Typst {
10 fn name(&self) -> &'static str {
11 "Typst"
12 }
13 fn extensions(&self) -> &'static [&'static str] {
14 &["typ"]
15 }
16 fn grammar_name(&self) -> &'static str {
17 "typst"
18 }
19
20 fn as_symbols(&self) -> Option<&dyn LanguageSymbols> {
21 Some(self)
22 }
23
24 fn extract_imports(&self, node: &Node, content: &str) -> Vec<Import> {
25 if node.kind() != "import" {
26 return Vec::new();
27 }
28
29 let text = &content[node.byte_range()];
30 vec![Import {
31 module: text.trim().to_string(),
32 names: Vec::new(),
33 alias: None,
34 is_wildcard: text.contains('*'),
35 is_relative: false,
36 line: node.start_position().row + 1,
37 }]
38 }
39
40 fn format_import(&self, import: &Import, names: Option<&[&str]>) -> String {
41 let names_to_use: Vec<&str> = names
43 .map(|n| n.to_vec())
44 .unwrap_or_else(|| import.names.iter().map(|s| s.as_str()).collect());
45 if names_to_use.is_empty() {
46 format!("#import \"{}\"", import.module)
47 } else if import.is_wildcard {
48 format!("#import \"{}\": *", import.module)
49 } else {
50 format!("#import \"{}\": {}", import.module, names_to_use.join(", "))
51 }
52 }
53}
54
55impl LanguageSymbols for Typst {}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use crate::validate_unused_kinds_audit;
61
62 #[test]
63 fn unused_node_kinds_audit() {
64 #[rustfmt::skip]
65 let documented_unused: &[&str] = &[
66 "formula",
68 "return",
70 "lambda",
72 "for", "while",
74 "import",
76 "block",
78 ];
79 validate_unused_kinds_audit(&Typst, documented_unused)
80 .expect("Typst unused node kinds audit failed");
81 }
82}