1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial |
3 | |
4 | use std::collections::HashMap; |
5 | use std::path::PathBuf; |
6 | |
7 | use super::JsComponentDefinition; |
8 | use super::JsDiagnostic; |
9 | use itertools::Itertools; |
10 | use slint_interpreter::ComponentCompiler; |
11 | |
12 | /// ComponentCompiler is the entry point to the Slint interpreter that can be used |
13 | /// to load .slint files or compile them on-the-fly from a string. |
14 | #[napi (js_name = "ComponentCompiler" )] |
15 | pub struct JsComponentCompiler { |
16 | internal: ComponentCompiler, |
17 | } |
18 | |
19 | #[napi ] |
20 | impl JsComponentCompiler { |
21 | /// Returns a new ComponentCompiler. |
22 | #[napi (constructor)] |
23 | pub fn new() -> Self { |
24 | let mut compiler = ComponentCompiler::default(); |
25 | let include_paths = match std::env::var_os("SLINT_INCLUDE_PATH" ) { |
26 | Some(paths) => { |
27 | std::env::split_paths(&paths).filter(|path| !path.as_os_str().is_empty()).collect() |
28 | } |
29 | None => vec![], |
30 | }; |
31 | let library_paths = match std::env::var_os("SLINT_LIBRARY_PATH" ) { |
32 | Some(paths) => std::env::split_paths(&paths) |
33 | .filter_map(|entry| { |
34 | entry |
35 | .to_str() |
36 | .unwrap_or_default() |
37 | .split('=' ) |
38 | .collect_tuple() |
39 | .map(|(k, v)| (k.into(), v.into())) |
40 | }) |
41 | .collect(), |
42 | None => std::collections::HashMap::new(), |
43 | }; |
44 | |
45 | compiler.set_include_paths(include_paths); |
46 | compiler.set_library_paths(library_paths); |
47 | Self { internal: compiler } |
48 | } |
49 | |
50 | #[napi (setter)] |
51 | pub fn set_include_paths(&mut self, include_paths: Vec<String>) { |
52 | self.internal.set_include_paths(include_paths.iter().map(|p| PathBuf::from(p)).collect()); |
53 | } |
54 | |
55 | #[napi (getter)] |
56 | pub fn include_paths(&self) -> Vec<String> { |
57 | self.internal |
58 | .include_paths() |
59 | .iter() |
60 | .map(|p| p.to_str().unwrap_or_default().to_string()) |
61 | .collect() |
62 | } |
63 | |
64 | #[napi (setter)] |
65 | pub fn set_library_paths(&mut self, paths: HashMap<String, String>) { |
66 | let mut library_paths = HashMap::new(); |
67 | for (key, path) in paths { |
68 | library_paths.insert(key, PathBuf::from(path)); |
69 | } |
70 | |
71 | self.internal.set_library_paths(library_paths); |
72 | } |
73 | |
74 | #[napi (getter)] |
75 | pub fn library_paths(&self) -> HashMap<String, String> { |
76 | let mut library_paths = HashMap::new(); |
77 | |
78 | for (key, path) in self.internal.library_paths() { |
79 | library_paths.insert(key.clone(), path.to_str().unwrap_or_default().to_string()); |
80 | } |
81 | |
82 | library_paths |
83 | } |
84 | |
85 | #[napi (setter)] |
86 | pub fn set_style(&mut self, style: String) { |
87 | self.internal.set_style(style); |
88 | } |
89 | |
90 | #[napi (getter)] |
91 | pub fn style(&self) -> Option<String> { |
92 | self.internal.style().cloned() |
93 | } |
94 | |
95 | // todo: set_file_loader |
96 | |
97 | #[napi (getter)] |
98 | pub fn diagnostics(&self) -> Vec<JsDiagnostic> { |
99 | self.internal.diagnostics().iter().map(|d| JsDiagnostic::from(d.clone())).collect() |
100 | } |
101 | |
102 | /// Compile a .slint file into a ComponentDefinition |
103 | /// |
104 | /// Returns the compiled `ComponentDefinition` if there were no errors. |
105 | #[napi ] |
106 | pub fn build_from_path(&mut self, path: String) -> Option<JsComponentDefinition> { |
107 | spin_on::spin_on(self.internal.build_from_path(PathBuf::from(path))).map(|d| d.into()) |
108 | } |
109 | |
110 | /// Compile some .slint code into a ComponentDefinition |
111 | #[napi ] |
112 | pub fn build_from_source( |
113 | &mut self, |
114 | source_code: String, |
115 | path: String, |
116 | ) -> Option<JsComponentDefinition> { |
117 | spin_on::spin_on(self.internal.build_from_source(source_code, PathBuf::from(path))) |
118 | .map(|d| d.into()) |
119 | } |
120 | } |
121 | |