15.2 Typography
(require pollen/unstable/typography) | package: pollen |
Quick & dirty utilities. I use them, but I haven’t tested them with enough edge cases to feel like they deserve to live outside unstable. I welcome improvements.
procedure
(smart-quotes xexpr [ #:apostophe apostrophe-str #:single-open single-open-str #:single-close single-close-str #:double-open double-open-str #:double-close double-close-str]) → (or/c string? txexpr?) xexpr : (or/c string? txexpr?) apostrophe-str : string? = "’" single-open-str : string? = "‘" single-close-str : string? = "’" double-open-str : string? = "“" double-close-str : string? = "”"
> (define tricky-string "\"Why,\" she could've asked, \"are we in O‘ahu watching 'Mame'?\"") > (display tricky-string) "Why," she could've asked, "are we in O‘ahu watching 'Mame'?"
> (display (smart-quotes tricky-string)) “Why,” she could’ve asked, “are we in O‘ahu watching ‘Mame’?”
> (display (smart-quotes tricky-string #:double-open "«" #:double-close "»" #:single-open "‹" #:single-close "›")) «Why,» she could’ve asked, «are we in O‘ahu watching ‹Mame›?»
> (display (smart-quotes tricky-string #:double-open "„" #:double-close "”" #:single-open "‚" #:single-close "’")) „Why,” she could’ve asked, „are we in O‘ahu watching ‚Mame’?”
procedure
(smart-dashes str) → string?
str : string?
> (define tricky-string "I had a few --- OK, like 6--8 --- thin mints.") > (display tricky-string) I had a few --- OK, like 6--8 --- thin mints.
> (display (smart-dashes tricky-string)) I had a few—OK, like 6–8—thin mints.
; Monospaced font not great for showing dashes, but you get the idea
procedure
(smart-ellipses str) → string?
str : string?
> (define tricky-string "I had a few ... OK, like 6--8 ... thin mints.") > (display tricky-string) I had a few ... OK, like 6--8 ... thin mints.
> (display (smart-ellipses tricky-string)) I had a few … OK, like 6--8 … thin mints.
procedure
(wrap-hanging-quotes tx [ #:single-preprend single-preprender #:double-preprend double-preprender]) → txexpr? tx : txexpr? single-preprender : txexpr-tag? = 'squo double-preprender : txexpr-tag? = 'dquo
> (wrap-hanging-quotes '(p "No quote to hang.")) '(p "No quote to hang.")
> (wrap-hanging-quotes '(p "“What? We need to hang quotes?”")) '(p (dquo "“" "What? We need to hang quotes?”"))
In pro typography, quotation marks at the beginning of a line or paragraph are often shifted into the margin slightly to make them appear more optically aligned with the left edge of the text. With a reflowable layout model like HTML, you don’t know where your line breaks will be.
This function will simply insert the 'squo and 'dquo tags, which provide hooks that let you do the actual hanging via CSS, like so (actual measurement can be refined to taste):
squo {margin-left: -0.25em;} |
dquo {margin-left: -0.50em;} |
Be warned: there are many edge cases this function does not handle well.
; Argh: this edge case is not handled properly > (wrap-hanging-quotes '(p "“" (em "What?") "We need to hang quotes?”")) '(p "“" (em "What?") "We need to hang quotes?”")
procedure
(whitespace? v) → boolean?
v : any/c
> (whitespace? "\n\n ") #t
> (whitespace? (string->symbol "\n\n ")) #t
> (whitespace? "") #t
> (whitespace? '("" " " "\n\n\n" " \n")) #t
> (define nonbreaking-space (format "~a" #\u00A0)) > (whitespace? nonbreaking-space) #f
procedure
(whitespace/nbsp? v) → boolean?
v : any/c
> (whitespace/nbsp? "\n\n ") #t
> (whitespace/nbsp? (string->symbol "\n\n ")) #t
> (whitespace/nbsp? "") #t
> (whitespace/nbsp? '("" " " "\n\n\n" " \n")) #t
> (define nonbreaking-space (format "~a" #\u00A0)) > (whitespace/nbsp? nonbreaking-space) #t