Fancypants is a fairly simple set of functions plus an SXSLT ruleset to automagically convert SXML with plain-ASCII strings to typographically enhanced Unicode strings. Ligatures are added and quotes are educated ie, opening quotes are curled to the left while closing quotes are curled the other way. An example piece of SXML:
(sxml-apply-rules '(blockquote "\"The affable Estonian wasn't fired\"," " said the --- strangely afflicted ---" " flying monkey at the office.") (make-fancy-rules) (make-smart-quote-rules))
When rendered, looks like the following:
“The aﬀable Estonian wasn’t ﬁred”, said the — strangely aﬄicted — ﬂying monkey at the oﬃce.
Which looks like this without using fancypants:
"The affable Estonian wasn't fired", said the --- strangely afflicted --- flying monkey at the office.
As you can see, the quotes are curled correctly, the three minuses are converted to real emdashes and the 'fi', 'ffl', 'fl' and 'ff' characters are replaced by ligatures that merge the characters in a nice way.
A word of warning: How the ligatures are displayed depends heavily on the particular font being used and the implementation of the fonts. For example, on a Mac, most MS Corefonts are apparently modified by Apple to support all ligatures, while the basic Corefonts by Microsoft (as found under Windows and many Unix installations) are lacking ligatures in most fonts. Consider this before using Fancypants' ligature capability (the fi and ff ligatures are reasonably safe to use in most cases, though). Testing on a number of platforms is, unfortunately, still a good idea while doing webdevelopment.
There are two rulesets: one for auto-conversion of ligatures and other types of character combinations to Unicode and one for smartening quotes. Both rulesets are generated by functions.
character-mapargument. Please note that the order matters because the replacement algorithm employes a nongreedy search. Place prefixes of other matches after them and there is no problem. The symbols in
exceptionsare the tags to leave alone. (ie, nothing below these is fancified)
quotesdefines the strategy of how to translate quotes to smart quotes. See the documentation for
all-quotesfor more info on the structure of this argument. Please note that here, the order doesn't matter because the replacement algorithm uses simple regexes. The symbols in
exceptionsare the tags to leave alone. (ie, under these nothing has its quotes changes)
(head script pre code kbd samp @)
make-fancy-rules. Contains mappings for 'ffi', 'ffl', 'ff', 'fi', 'fl' and 'ft'. The mapping for 'st' is intentionally left out because this ligature is too elaborate to use in body copy. You could easily define a ruleset for eg headings that does include the 'st' ligature (it's Unicode character fb06).
make-smart-quotes. Remove any you don't want to have handled.The structure of an entry in this list is:
(pre match post how counts?).
preis the part of the string that's before the quote to match,
postis the string that is after the match. These are all regexes, or
howis one of:
counts?is a boolean describing whether the quote should influence the nesting of subsequent quotes or not. (ie, "isn't" => #f, since the ' is not a quote which matches a preceding quote or which is matched by a subsequent quote). Note that you (currently) can't use brackets in these regexes, since that messes up the expected structure of the result of
These functions are used internally by Fancypants, but they are probably useful enough to export, so here they are.
character-mapalist to their Unicode character within
sxml. Translates only the strings in the
quotesargument, and skips all tag names in the
Copyright (c) 2006-2009, Peter Bex (email@example.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.