Fold serialized vCards’ lines to ~70 characters

The spec recommends splitting at 75 octets, but
that’s hard. We assume that 70 characters is
more-or-less 75 octets (even though with
UTF-8 chars this might be passed).
This commit is contained in:
Jaidyn Ann 2024-02-20 15:24:28 -06:00
parent 612dde9533
commit c8890a1d22

View File

@ -84,9 +84,7 @@
;; description, but unfortunately Im coming up empty! =w=, ;; description, but unfortunately Im coming up empty! =w=,
(define (write-vcard vcard-alist #!optional (port (current-output-port))) (define (write-vcard vcard-alist #!optional (port (current-output-port)))
(for-each (lambda (element) (for-each (lambda (element)
(write-string (serialize-vcard-element element) #f port) (write-folded-line (serialize-vcard-element element)))
(write-char #\return port)
(write-char #\newline port))
vcard-alist)) vcard-alist))
@ -185,7 +183,7 @@
;;; ~ Property-value parsers ~ ;;; ~ Property-value parsers/serializers ~
;; List of all properties with semicoloned-structured strings. ;; List of all properties with semicoloned-structured strings.
(define vcard-semicoloned-properties (define vcard-semicoloned-properties
@ -328,16 +326,37 @@
;; Reader-thunk. Read a “logical” folded-line, where a line beginning with a ;; Reader-thunk. Read a “logical” folded-line, where a line beginning with a
;; space is a continuation of the previous line — like with vcards. ;; space is a continuation of the previous line — like with vcards.
(define (read-folded-line #!optional (limit 100) (port (current-input-port))) ;; LIMIT is the maximum amount of characters it will read before giving up
(if (not (eof-object? (peek-char port))) ;; on finding a newline.
(let [(line (read-line port limit))] ;; It will default to (current-input-port) as the PORT.
(if (or (eq? (peek-char port) #\space) (define (read-folded-line #!optional (limit #f) (port (current-input-port)))
(eq? (peek-char port) #\tab)) (let [(port (or port (current-input-port)))]
(string-concatenate (if (not (eof-object? (peek-char port)))
(list line (let [(line (read-line port limit))]
(string-drop (read-folded-line limit port) 1))) (if (or (eq? (peek-char port) #\space)
line)) (eq? (peek-char port) #\tab))
"")) (string-concatenate
(list line
(string-drop (read-folded-line limit port) 1)))
line))
"")))
;; Write a line to a port as a “logical” folded-line string, in the style of
;; vCard and vCalendar. If the line is too long (passed FOLD-LENGTH [70]), it
;; will be written as several lines of FOLD-LENGTH, with each such line
;; prepended by the CREASE-CHAR (#\tab).
;; It will default to (current-output-port), if PORT is #f or unspecified.
(define (write-folded-line string #!optional
(port (current-output-port))
(fold-length 70)
(crease-char #\tab))
(write-string
(string-concatenate
(list (string-join (string-split-by-lengths string fold-length)
(list->string (list #\return #\newline crease-char)))
(list->string '(#\return #\newline))))
#f (or port (current-output-port))))
;; Split a STRING into strings of a size of (at most) LENGTH signs. ;; Split a STRING into strings of a size of (at most) LENGTH signs.