1use crate::module::ModuleJson;
4use crate::pkg_context::PkgContextInfo;
5use crate::profile::Route;
6
7const DEFAULT_SOURCE_ROOT: &str = "src/main/";
10
11const SOURCE_EXTENSIONS: &[&str] = &[".ets", ".ts", ".js", ".mjs", ".cjs"];
13
14pub(crate) fn strip_source_extension(path: &str) -> &str {
15 SOURCE_EXTENSIONS.iter().find_map(|ext| path.strip_suffix(ext)).unwrap_or(path)
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
22#[non_exhaustive]
23pub struct RecordNames {
24 pub normalized: Option<String>,
28 pub bundled: Option<String>,
32 pub package_listed: bool,
35}
36
37impl RecordNames {
38 pub fn candidates(&self) -> Vec<&str> {
40 let (first, second) = if self.package_listed { (&self.normalized, &self.bundled) } else { (&self.bundled, &self.normalized) };
41 [first, second].into_iter().flatten().map(String::as_str).collect()
42 }
43}
44
45impl ModuleJson {
46 pub fn record_names(&self, src_entry: &str, packages: Option<&PkgContextInfo>) -> RecordNames {
53 let path = src_entry.strip_prefix("./").unwrap_or(src_entry).trim_start_matches('/');
54 let path = strip_source_extension(path);
55 let module = self.module.name.as_deref();
56 let package_name = self.module.package_name.as_deref().or(module);
57 let package = packages.zip(package_name).and_then(|(table, name)| table.get(name));
58 let normalized = package_name.map(|name| match package {
59 Some(p) if p.entry_path.ends_with('/') => format!("&{name}/{}{path}&{}", p.entry_path, p.version),
61 Some(p) => format!("&{name}/{DEFAULT_SOURCE_ROOT}{path}&{}", p.version),
62 None => format!("&{name}/{DEFAULT_SOURCE_ROOT}{path}&"),
63 });
64 let bundled = self.app.bundle_name.as_deref().zip(module).map(|(bundle, module)| format!("{bundle}/{module}/{path}"));
65 RecordNames { normalized, bundled, package_listed: package.is_some() }
66 }
67
68 pub fn route_record_names(&self, route: &Route, packages: Option<&PkgContextInfo>) -> RecordNames {
76 let module = self.module.name.as_deref();
77 let own_package = self.module.package_name.as_deref().or(module);
78 let path = route.record_path(own_package);
79 let listed = packages.zip(route.package_name.as_deref().or(own_package)).and_then(|(table, name)| table.get(name));
80 let from_source = path.as_ref().map(|path| format!("&{path}&{}", listed.map_or("", |package| package.version.as_str())));
81 let normalized = route.ohmurl_record().map(str::to_owned).or(from_source);
82 let is_own = route.package_name.as_deref().is_none_or(|package| Some(package) == own_package);
83 let source = route.page_source_file.as_deref().map(|source| source.trim_start_matches("./").trim_start_matches('/'));
84 let below_root = source.and_then(|source| source.strip_prefix(DEFAULT_SOURCE_ROOT)).filter(|_| is_own);
85 let bundled = self
86 .app
87 .bundle_name
88 .as_deref()
89 .zip(module)
90 .zip(below_root)
91 .map(|((bundle, module), path)| format!("{bundle}/{module}/{}", strip_source_extension(path)));
92 RecordNames { normalized, bundled, package_listed: listed.is_some() || route.ohmurl.is_some() }
94 }
95}