specfold_core/authoring/
refs.rs1use regex::Regex;
4use serde_json::{Map, Value};
5
6pub fn rewrite_body(text: &str, old: &str, new: &str) -> String {
8 let re = Regex::new(&format!(r"\[\[{}(#[^\]|]*)?(\|[^\]]*)?\]\]", regex::escape(old))).unwrap();
9 re.replace_all(text, |c: ®ex::Captures| {
10 format!("[[{new}{}{}]]", c.get(1).map_or("", |m| m.as_str()), c.get(2).map_or("", |m| m.as_str()))
11 })
12 .into_owned()
13}
14
15pub fn same_path(cited: &str, path: &str) -> bool {
17 let mut t = cited.trim_end_matches('/');
18 while let Some(rest) = t.strip_prefix("../").or_else(|| t.strip_prefix("./")) {
19 t = rest;
20 }
21 t == path
22}
23
24pub fn rewrite_rel(map: &mut Map<String, Value>, old: &str, new: &str) -> bool {
26 let Some(Value::Object(rel)) = map.get_mut("rel") else { return false };
27 let mut changed = false;
28 for v in rel.values_mut() {
29 let Value::Array(items) = v else { continue };
30 for item in items.iter_mut() {
31 let Some(s) = item.as_str() else { continue };
32 let (target, anchor) = s.split_once('#').map(|(t, a)| (t, Some(a))).unwrap_or((s, None));
33 if target == old {
34 *item = Value::String(match anchor {
35 Some(a) => format!("{new}#{a}"),
36 None => new.to_string(),
37 });
38 changed = true;
39 }
40 }
41 }
42 changed
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn rewrites() {
51 let t = "a [[adr:x/1]] b [[adr:x/1#K-1|see]] c [[adr:x/10]]";
52 assert_eq!(rewrite_body(t, "adr:x/1", "adr:y/1"), "a [[adr:y/1]] b [[adr:y/1#K-1|see]] c [[adr:x/10]]");
53 let mut m: Map<String, Value> =
54 serde_json::from_str(r#"{"rel":{"implements":["adr:x/1#A","sot:z/q"]}}"#).unwrap();
55 assert!(rewrite_rel(&mut m, "adr:x/1", "adr:y/1"));
56 assert_eq!(m["rel"]["implements"][0], "adr:y/1#A");
57 }
58}