You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pollen/pollen/scribblings/typography.scrbl

130 lines
4.5 KiB
Racket

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#lang scribble/manual
@(require scribble/eval pollen/decode pollen/setup txexpr (for-label pollen/unstable/typography txexpr racket (except-in pollen #%module-begin)))
@(define my-eval (make-base-eval))
@(my-eval `(require pollen pollen/unstable/typography))
@(require "mb-tools.rkt")
@title{Typography}
@defmodule[pollen/unstable/typography]
Quick & dirty utilities. I use them, but I haven't tested them with enough edge cases to feel like they deserve to live outside @racket[unstable]. I welcome improvements.
@defproc[
(smart-quotes
[xexpr (or/c string? txexpr?)]
[#:apostophe apostrophe-str string? ""]
[#:single-open single-open-str string? ""]
[#:single-close single-close-str string? ""]
[#:double-open double-open-str string? ""]
[#:double-close double-close-str string? ""])
(or/c string? txexpr?)]{
Convert straight quotes in @racket[xexpr] to curly. By default, American English curly quotes are used. The optional keyword arguments can be used to set different quotes suited to other languages or script systems.
@examples[#:eval my-eval
(define tricky-string
"\"Why,\" she could've asked, \"are we in Oahu watching 'Mame'?\"")
(display tricky-string)
(display (smart-quotes tricky-string))
(display (smart-quotes tricky-string
#:double-open "«" #:double-close "»"
#:single-open "" #:single-close ""))
(display (smart-quotes tricky-string
#:double-open "" #:double-close ""
#:single-open "" #:single-close ""))
]
}
@defproc[
(smart-dashes
[str string?])
string?]
In @racket[_str], convert three hyphens to an em dash, and two hyphens to an en dash, and remove surrounding spaces.
@examples[#:eval my-eval
(define tricky-string "I had a few --- OK, like 6--8 --- thin mints.")
(display tricky-string)
(display (smart-dashes tricky-string))
(code:comment @#,t{Monospaced font not great for showing dashes, but you get the idea})
]
@defproc[
(smart-ellipses
[str string?])
string?]
In @racket[_str], convert three periods to an ellipsis.
@examples[#:eval my-eval
(define tricky-string "I had a few ... OK, like 6--8 ... thin mints.")
(display tricky-string)
(display (smart-ellipses tricky-string))
]
@defproc[
(wrap-hanging-quotes
[tx txexpr?]
[#:single-preprend single-preprender txexpr-tag? 'squo]
[#:double-preprend double-preprender txexpr-tag? 'dquo]
)
txexpr?]
Find single or double quote marks at the beginning of @racket[_tx] and wrap them in an X-expression with the tag @racket[_single-preprender] or @racket[_double-preprender], respectively. The default values are @racket['squo] and @racket['dquo].
@examples[#:eval my-eval
(wrap-hanging-quotes '(p "No quote to hang."))
(wrap-hanging-quotes '(p "“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 @racket['squo] and @racket['dquo] tags, which provide hooks that let you do the actual hanging via CSS, like so (actual measurement can be refined to taste):
@verbatim{squo {margin-left: -0.25em;}
dquo {margin-left: -0.50em;}
}
Be warned: there are many edge cases this function does not handle well.
@examples[#:eval my-eval
(code:comment @#,t{Argh: this edge case is not handled properly})
(wrap-hanging-quotes '(p "" (em "What?") "We need to hang quotes?”"))
]
@defproc[
(whitespace?
[v any/c])
boolean?]
A predicate that returns @racket[#t] for any stringlike @racket[_v] that's entirely whitespace, but also the empty string, as well as lists and vectors that are made only of @racket[whitespace?] members. Following the @racket[regexp-match] convention, @racket[whitespace?] does not return @racket[#t] for a nonbreaking space. If you prefer that behavior, use @racket[whitespace/nbsp?].
@examples[#:eval my-eval
(whitespace? "\n\n ")
(whitespace? (string->symbol "\n\n "))
(whitespace? "")
(whitespace? '("" " " "\n\n\n" " \n"))
(define nonbreaking-space (format "~a" #\u00A0))
(whitespace? nonbreaking-space)
]
@defproc[
(whitespace/nbsp?
[v any/c])
boolean?]
Like @racket[whitespace?], but also returns @racket[#t] for nonbreaking spaces.
@examples[#:eval my-eval
(whitespace/nbsp? "\n\n ")
(whitespace/nbsp? (string->symbol "\n\n "))
(whitespace/nbsp? "")
(whitespace/nbsp? '("" " " "\n\n\n" " \n"))
(define nonbreaking-space (format "~a" #\u00A0))
(whitespace/nbsp? nonbreaking-space)
]