aboutsummaryrefslogtreecommitdiff
path: root/modules/calendar-sync.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/calendar-sync.el')
-rw-r--r--modules/calendar-sync.el33
1 files changed, 28 insertions, 5 deletions
diff --git a/modules/calendar-sync.el b/modules/calendar-sync.el
index b9cc57f4..06bee213 100644
--- a/modules/calendar-sync.el
+++ b/modules/calendar-sync.el
@@ -287,6 +287,20 @@ parsed as org headings. Handles multiple levels (e.g. ** becomes --)."
(concat (make-string (length (match-string 1 match)) ?-) " "))
text)))
+(defun calendar-sync--sanitize-org-property-value (text)
+ "Sanitize TEXT for safe inclusion as a single Org property value."
+ (when text
+ (string-trim
+ (replace-regexp-in-string
+ "[[:space:]\n\r]+"
+ " "
+ text))))
+
+(defun calendar-sync--sanitize-org-heading (text)
+ "Sanitize TEXT for safe inclusion as a single Org heading title."
+ (calendar-sync--sanitize-org-property-value
+ (calendar-sync--sanitize-org-body text)))
+
;;; Date Utilities
(defun calendar-sync--add-months (date months)
@@ -1059,7 +1073,8 @@ Cleans text fields (description, location, summary) via `calendar-sync--clean-te
"Convert parsed EVENT plist to org entry string.
Produces property drawer with LOCATION, ORGANIZER, STATUS, URL when present.
Description appears as body text after the drawer."
- (let* ((summary (or (plist-get event :summary) "(No Title)"))
+ (let* ((summary (calendar-sync--sanitize-org-heading
+ (or (plist-get event :summary) "(No Title)")))
(description (plist-get event :description))
(location (plist-get event :location))
(start (plist-get event :start))
@@ -1072,16 +1087,24 @@ Description appears as body text after the drawer."
(props '()))
;; Collect non-nil properties
(when (and location (not (string-empty-p location)))
- (push (format ":LOCATION: %s" location) props))
+ (push (format ":LOCATION: %s"
+ (calendar-sync--sanitize-org-property-value location))
+ props))
(when organizer
(let ((org-name (or (plist-get organizer :cn)
(plist-get organizer :email))))
(when org-name
- (push (format ":ORGANIZER: %s" org-name) props))))
+ (push (format ":ORGANIZER: %s"
+ (calendar-sync--sanitize-org-property-value org-name))
+ props))))
(when (and status (not (string-empty-p status)))
- (push (format ":STATUS: %s" status) props))
+ (push (format ":STATUS: %s"
+ (calendar-sync--sanitize-org-property-value status))
+ props))
(when (and url (not (string-empty-p url)))
- (push (format ":URL: %s" url) props))
+ (push (format ":URL: %s"
+ (calendar-sync--sanitize-org-property-value url))
+ props))
(setq props (nreverse props))
;; Build output
(let ((parts (list timestamp (format "* %s" summary))))