fix: don't backslash-escape quotes inside %"..."%" summary
All checks were successful
Release Binaries / build (amd64, ocaml/opam:ubuntu-22.04-ocaml-5.4, linux/amd64, linux-amd64, , sudo apt install -y upx) (release) Successful in 1m8s
Release Binaries / build (arm64, ocaml/opam:alpine-ocaml-5.4, linux/arm64, linux-arm64, OCAMLPARAM='_,ccopt=-static,cclib=-static', sudo apk add upx zstd-static) (release) Successful in 3m5s

Remind's %"..."%" delimiter treats the content literally, so a
backslash-escaped double quote shows up as a literal backslash in the
rendered message instead of being interpreted. Only escape quotes for
non-summary MSG bodies where the delimiter isn't %"..."%".
This commit is contained in:
2026-07-14 16:28:42 +02:00
parent 89c577a125
commit cd9838adf8

View File

@@ -257,13 +257,13 @@ let add_through b = function
(** Escape special characters in the body of a MSG clause. (** Escape special characters in the body of a MSG clause.
- '%' must become '%%' (literal percent) - '%' must become '%%' (literal percent)
- '[' must become '["["]' (a Remind expression that evaluates to the literal string "[") *) - '[' must become '["["]' (a Remind expression that evaluates to the literal string "[") *)
let escape_msg s = let escape_msg ?(summary = false) s =
let buf = Buffer.create (String.length s) in let buf = Buffer.create (String.length s) in
String.iter String.iter
(function (function
| '\n' -> Buffer.add_string buf "\\n" | '\n' -> Buffer.add_string buf "\\n"
| '\t' -> () | '\t' -> ()
| '"' -> Buffer.add_string buf "\\\"" | '"' -> if summary then Buffer.add_string buf "\"" else Buffer.add_string buf "\\\""
| '%' -> Buffer.add_string buf "%%" | '%' -> Buffer.add_string buf "%%"
| '[' -> Buffer.add_string buf {|["["]|} | '[' -> Buffer.add_string buf {|["["]|}
| c -> Buffer.add_char buf c) | c -> Buffer.add_char buf c)
@@ -272,7 +272,7 @@ let escape_msg s =
let add_msg b ?(alarm = empty_alarm) ?(timed = false) summary = let add_msg b ?(alarm = empty_alarm) ?(timed = false) summary =
let has_alarm = alarm.day_delta <> "" || alarm.time_delta <> "" || alarm.sched <> "" in let has_alarm = alarm.day_delta <> "" || alarm.time_delta <> "" || alarm.sched <> "" in
let body = escape_msg summary in let body = escape_msg summary ~summary:true in
let body = let body =
if has_alarm then if timed then spf "%%\"%s%%\" (%%b %%3)" body else spf "%%\"%s%%\" (%%b)" body else body if has_alarm then if timed then spf "%%\"%s%%\" (%%b %%3)" body else spf "%%\"%s%%\" (%%b)" body else body
in in