git.iko.soy/typeable/pandoc
on master help sign in
Correctly implement capitalisation.

Using `map toUpper` to capitalise text is wrong, as e.g. “Straße” should be converted to “STRASSE”, which is 1 character longer. This commit adds a `capitalize` function and replaces 2 identical implementations in different modules (`toCaps` and `capitalize`) with it.

commitec88d47f23d6761cf2120f76e45ca23cdc478e6c authorArtyom Kazak <yom@artyom.me> dateSun 3 Aug 2014, 16:48 (12 years ago) parent842c705
5 files changed+42−15
src/Text/Pandoc/Shared.hs+13 src/Text/Pandoc/Writers/FB2.hs+3−8 src/Text/Pandoc/Writers/Markdown.hs+3−7 tests/Tests/Writers/Plain.hs+21 tests/test-pandoc.hs+2
src/Text/Pandoc/Shared.hs+13
@@ -59,6 +59,7 @@ module Text.Pandoc.Shared (
5959 normalizeBlocks,
6060 removeFormatting,
6161 stringify,
62+ capitalize,
6263 compactify,
6364 compactify',
6465 compactify'DL,
@@ -122,6 +123,7 @@ import qualified Data.ByteString.Char8 as B8
122123import Text.Pandoc.Compat.Monoid
123124import Data.ByteString.Base64 (decodeLenient)
124125import Data.Sequence (ViewR(..), ViewL(..), viewl, viewr)
126+import qualified Data.Text as T (toUpper, pack, unpack)
125127
126128#ifdef EMBED_DATA_FILES
127129import Text.Pandoc.Data (dataFiles)
@@ -527,6 +529,17 @@ stringify = query go . walk deNote
527529 deNote (Note _) = Str ""
528530 deNote x = x
529531
532+-- | Bring all regular text in a pandoc structure to uppercase.
533+--
534+-- This function correctly handles cases where a lowercase character doesn't
535+-- match to a single uppercase character – e.g. “Straße” would be converted
536+-- to “STRASSE”, not “STRAßE”.
537+capitalize :: Walkable Inline a => a -> a
538+capitalize = walk go
539+ where go :: Inline -> Inline
540+ go (Str s) = Str (T.unpack $ T.toUpper $ T.pack s)
541+ go x = x
542+
530543-- | Change final list item from @Para@ to @Plain@ if the list contains
531544-- no other @Para@ blocks.
532545compactify :: [[Block]] -- ^ List of list items (each a list of blocks)
src/Text/Pandoc/Writers/FB2.hs+3−8
@@ -28,7 +28,7 @@ module Text.Pandoc.Writers.FB2 (writeFB2) where
2828import Control.Monad.State (StateT, evalStateT, get, modify)
2929import Control.Monad.State (liftM, liftM2, liftIO)
3030import Data.ByteString.Base64 (encode)
31−import Data.Char (toUpper, toLower, isSpace, isAscii, isControl)
31+import Data.Char (toLower, isSpace, isAscii, isControl)
3232import Data.List (intersperse, intercalate, isPrefixOf)
3333import Data.Either (lefts, rights)
3434import Network.Browser (browse, request, setAllowRedirects, setOutHandler)
@@ -44,8 +44,7 @@ import qualified Text.XML.Light.Cursor as XC
4444
4545import Text.Pandoc.Definition
4646import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def)
47−import Text.Pandoc.Shared (orderedListMarkers, isHeaderBlock)
48−import Text.Pandoc.Walk
47+import Text.Pandoc.Shared (orderedListMarkers, isHeaderBlock, capitalize)
4948
5049-- | Data to be written at the end of the document:
5150-- (foot)notes, URLs, references, images.
@@ -421,10 +420,6 @@ indent = indentBlock
421420 indentLines ins = let lns = split isLineBreak ins :: [[Inline]]
422421 in intercalate [LineBreak] $ map ((Str spacer):) lns
423422
424−capitalize :: Inline -> Inline
425−capitalize (Str xs) = Str $ map toUpper xs
426−capitalize x = x
427−
428423-- | Convert a Pandoc's Inline element to FictionBook XML representation.
429424toXml :: Inline -> FBM [Content]
430425toXml (Str s) = return [txt s]
@@ -434,7 +429,7 @@ toXml (Strong ss) = list `liftM` wrap "strong" ss
434429toXml (Strikeout ss) = list `liftM` wrap "strikethrough" ss
435430toXml (Superscript ss) = list `liftM` wrap "sup" ss
436431toXml (Subscript ss) = list `liftM` wrap "sub" ss
437−toXml (SmallCaps ss) = cMapM toXml $ walk capitalize ss
432+toXml (SmallCaps ss) = cMapM toXml $ capitalize ss
438433toXml (Quoted SingleQuote ss) = do -- FIXME: should be language-specific
439434 inner <- cMapM toXml ss
440435 return $ [txt "‘"] ++ inner ++ [txt "’"]
src/Text/Pandoc/Writers/Markdown.hs+3−7
@@ -39,7 +39,7 @@ import Text.Pandoc.Writers.Shared
3939import Text.Pandoc.Options
4040import Text.Pandoc.Parsing hiding (blankline, blanklines, char, space)
4141import Data.List ( group, isPrefixOf, find, intersperse, transpose, sortBy )
42−import Data.Char ( isSpace, isPunctuation, toUpper )
42+import Data.Char ( isSpace, isPunctuation )
4343import Data.Ord ( comparing )
4444import Text.Pandoc.Pretty
4545import Control.Monad.State
@@ -672,10 +672,6 @@ escapeSpaces (Str s) = Str $ substitute " " "\\ " s
672672escapeSpaces Space = Str "\\ "
673673escapeSpaces x = x
674674
675−toCaps :: Inline -> Inline
676−toCaps (Str s) = Str (map toUpper s)
677−toCaps x = x
678−
679675-- | Convert Pandoc inline element to markdown.
680676inlineToMarkdown :: WriterOptions -> Inline -> State WriterState Doc
681677inlineToMarkdown opts (Span attrs ils) = do
@@ -693,7 +689,7 @@ inlineToMarkdown opts (Emph lst) = do
693689inlineToMarkdown opts (Strong lst) = do
694690 plain <- gets stPlain
695691 if plain
696− then inlineListToMarkdown opts $ walk toCaps lst
692+ then inlineListToMarkdown opts $ capitalize lst
697693 else do
698694 contents <- inlineListToMarkdown opts lst
699695 return $ "**" <> contents <> "**"
@@ -716,7 +712,7 @@ inlineToMarkdown opts (Subscript lst) = do
716712inlineToMarkdown opts (SmallCaps lst) = do
717713 plain <- gets stPlain
718714 if plain
719− then inlineListToMarkdown opts $ walk toCaps lst
715+ then inlineListToMarkdown opts $ capitalize lst
720716 else do
721717 contents <- inlineListToMarkdown opts lst
722718 return $ tagWithAttrs "span"
tests/Tests/Writers/Plain.hsnew file+21
@@ -0,0 +1,21 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Tests.Writers.Plain (tests) where
3+
4+import Test.Framework
5+import Text.Pandoc.Builder
6+import Text.Pandoc
7+import Tests.Helpers
8+import Tests.Arbitrary()
9+
10+
11+infix 4 =:
12+(=:) :: (ToString a, ToPandoc a)
13+ => String -> (a, String) -> Test
14+(=:) = test (writePlain def . toPandoc)
15+
16+
17+tests :: [Test]
18+tests = [ "strongly emphasized text to uppercase"
19+ =: strong "Straße"
20+ =?> "STRASSE"
21+ ]
tests/test-pandoc.hs+2
@@ -17,6 +17,7 @@ import qualified Tests.Writers.HTML
1717import qualified Tests.Writers.Docbook
1818import qualified Tests.Writers.Native
1919import qualified Tests.Writers.Markdown
20+import qualified Tests.Writers.Plain
2021import qualified Tests.Writers.AsciiDoc
2122import qualified Tests.Shared
2223import qualified Tests.Walk
@@ -33,6 +34,7 @@ tests = [ testGroup "Old" Tests.Old.tests
3334 , testGroup "HTML" Tests.Writers.HTML.tests
3435 , testGroup "Docbook" Tests.Writers.Docbook.tests
3536 , testGroup "Markdown" Tests.Writers.Markdown.tests
37+ , testGroup "Plain" Tests.Writers.Plain.tests
3638 , testGroup "AsciiDoc" Tests.Writers.AsciiDoc.tests
3739 ]
3840 , testGroup "Readers"