Strip planning line and drawers from section body
section_body() now filters out: - Leading planning line (SCHEDULED/DEADLINE/CLOSED) - Property drawers (:PROPERTIES: ... :END:) - Any other drawers (:LOGBOOK:, etc.) - Leading/trailing blank lines These are displayed separately in the UI.
This commit is contained in:
parent
ff48f9c7ee
commit
f5f2bffce4
|
|
@ -461,11 +461,11 @@ impl OrkState {
|
|||
}
|
||||
|
||||
/// Get section body content (text between headline and first child).
|
||||
/// Strips planning line and properties drawer.
|
||||
pub fn section_body(&self, doc_name: &str, id: &str) -> Option<String> {
|
||||
self.get_doc(doc_name).and_then(|d| {
|
||||
self.find_section(&d.doc, id).map(|s| {
|
||||
// Body is section content minus children
|
||||
// For now, extract from raw content using spans
|
||||
let start = s.headline.span.end.offset;
|
||||
let end = if let Some(first_child) = s.children.first() {
|
||||
first_child.headline.span.start.offset
|
||||
|
|
@ -473,11 +473,59 @@ impl OrkState {
|
|||
s.span.end.offset
|
||||
};
|
||||
|
||||
if start < end && end <= d.content.len() {
|
||||
d.content[start..end].to_string()
|
||||
} else {
|
||||
String::new()
|
||||
if start >= end || end > d.content.len() {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
let raw_body = &d.content[start..end];
|
||||
|
||||
// Strip leading planning line (SCHEDULED/DEADLINE/CLOSED)
|
||||
// and properties drawer (:PROPERTIES: ... :END:)
|
||||
let lines: Vec<&str> = raw_body.lines().collect();
|
||||
let mut result_lines = Vec::new();
|
||||
let mut in_drawer = false;
|
||||
let mut first_line = true;
|
||||
|
||||
for line in lines {
|
||||
let trimmed = line.trim();
|
||||
|
||||
// Skip planning line at the very start
|
||||
if first_line && (trimmed.starts_with("SCHEDULED:") ||
|
||||
trimmed.starts_with("DEADLINE:") ||
|
||||
trimmed.starts_with("CLOSED:")) {
|
||||
first_line = false;
|
||||
continue;
|
||||
}
|
||||
first_line = false;
|
||||
|
||||
// Handle drawer
|
||||
if trimmed.starts_with(":") && trimmed.ends_with(":") && trimmed.len() > 2 {
|
||||
let drawer_name = &trimmed[1..trimmed.len()-1];
|
||||
if drawer_name.chars().all(|c| c.is_ascii_uppercase() || c == '_') {
|
||||
in_drawer = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if in_drawer {
|
||||
if trimmed == ":END:" {
|
||||
in_drawer = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
result_lines.push(line);
|
||||
}
|
||||
|
||||
// Trim leading/trailing empty lines
|
||||
while result_lines.first().map(|l| l.trim().is_empty()).unwrap_or(false) {
|
||||
result_lines.remove(0);
|
||||
}
|
||||
while result_lines.last().map(|l| l.trim().is_empty()).unwrap_or(false) {
|
||||
result_lines.pop();
|
||||
}
|
||||
|
||||
result_lines.join("\n")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue