diff --git a/etc/shared.conf b/etc/shared.conf index ec31a26..1a38980 100644 --- a/etc/shared.conf +++ b/etc/shared.conf @@ -97,6 +97,10 @@ open-message-link-window.close-after-select = yes # Some examples follows, order matters! +# footnotes + +color-regexp = "[⁰¹²³⁴⁵⁶⁷⁸⁹]" #f7a805 italic + # http links color-regexp = "http(s)?://[^ ]+" #ff0000 @@ -132,7 +136,7 @@ color-regexp = "The poll has expired" #ff00ff bold # HH:MM -color-regexp = "[012][0-9]:[0123456][0-9]" cyan bold +color-regexp = "[012]?[0-9]:[0123456][0-9]" cyan bold # your username mentioned diff --git a/src/html-utils.lisp b/src/html-utils.lisp index 9d5d0ad..f34d514 100644 --- a/src/html-utils.lisp +++ b/src/html-utils.lisp @@ -152,16 +152,19 @@ Some convenience functions are provided to works with these structures. (incf link-count) (if link (format footnotes-stream - "[~a] ~a~%" - link-count + "~a ~a~%" + (number->superscripts link-count) (attribute-value link)) (format footnotes-stream - "[~a] ~a~%" - link-count + "~a ~a~%" + (number->superscripts link-count) (_ "No address found"))) (descend-children node) (when add-link-footnotes - (format body-stream " [~a] " link-count)))) + (format body-stream + "~a~a " + #\ZERO_WIDTH_SPACE + (number->superscripts link-count))))) ((tag= +tag-break+ node) (let ((*block-tag* nil)) (format body-stream "~%") diff --git a/src/package.lisp b/src/package.lisp index 66b252f..261b0db 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -502,6 +502,7 @@ :display-corrupting-utf8-p :remove-corrupting-utf8-chars :match-words + :number->superscripts :emojip :starting-emoji)) diff --git a/src/text-utils.lisp b/src/text-utils.lisp index 416b904..e09495f 100644 --- a/src/text-utils.lisp +++ b/src/text-utils.lisp @@ -181,8 +181,15 @@ (declare (ignore blanks)) s) -(defun split-words (text) - (cl-ppcre:split "\\p{White_Space}" text)) +(let ((scanner-including-zero-width (cl-ppcre:create-scanner (strcat "(\\p{White_Space})|(" + ;; \\x200B → #\ZERO_WIDTH_SPACE + (string (code-char #x200B)) + ")"))) + (scanner (cl-ppcre:create-scanner "\\p{White_Space}"))) + (defun split-words (text &key (include-zero-width-space nil)) + (if include-zero-width-space + (cl-ppcre:split scanner-including-zero-width text) + (cl-ppcre:split scanner text)))) (defun extract-blanks (text) (remove-if #'string-empty-p (cl-ppcre:split "\\P{White_Space}" text))) @@ -724,7 +731,7 @@ printed in the box column by column; in the example above the results are: (defgeneric lines->uri (object)) (defmethod lines->uri ((object string)) - (a:when-let ((words (split-words object))) + (a:when-let ((words (split-words object :include-zero-width-space t))) (remove-if (lambda (word) (if (< (length word) 4) t @@ -832,3 +839,15 @@ list of string `words' or nil if probe is not in words under predicate (when (not mismatchp) (return-from match-words word-start-count))) (return-from match-words nil)))) + +(a:define-constant +digits-superscripts+ "⁰¹²³⁴⁵⁶⁷⁸⁹" :test #'string=) + +(defun number->superscripts (number &optional (accum "")) + (flet ((concat-digit (index) + (strcat (string (elt +digits-superscripts+ index)) + accum))) + (if (< number 10) + (concat-digit number) + (let ((index (mod number 10)) + (new-number (truncate (/ number 10)))) + (number->superscripts new-number (concat-digit index))))))