Smart quote parsing: ignore curly quotes.

Previously we tried to match curly quotes as well as straight
quotes, producing Quoted inlines.  But it seems better just to
assume that those who use curly quotes want them passed through
verbatim.

This also fixes an (unintended) bug whereby curly single left
quotes would sometimes be changed to single right quotes.

Closes #10610.
This commit is contained in:
John MacFarlane
2025-02-13 13:58:53 -08:00
parent 0fe6254535
commit c21177b113
5 changed files with 18 additions and 26 deletions
+4 -12
View File
@@ -43,7 +43,6 @@ import Text.Parsec
, notFollowedBy
, try
)
import qualified Data.Text as T
import qualified Text.Pandoc.Builder as B
-- | Parses various ASCII punctuation, quotes, and apostrophe in a smart
@@ -93,13 +92,6 @@ doubleQuoted inlineParser = do
(withQuoteContext InDoubleQuote (manyTill inlineParser doubleQuoteEnd)))
<|> pure (B.str "\8220")
charOrRef :: (Stream s m Char, UpdateSourcePos s Char) => [Char] -> ParsecT s st m Char
charOrRef cs =
oneOf cs <|> try (do t <- characterReference
case T.unpack t of
[c] | c `elem` cs -> return c
_ -> fail "unexpected character reference")
-- | Succeeds if the parser is
--
-- * not within single quoted text;
@@ -116,13 +108,13 @@ singleQuoteStart = do
-- single quote start can't be right after str
guard =<< notAfterString
try $ do
charOrRef "'\8216\145"
char '\''
void $ lookAhead (satisfy (not . isSpaceChar))
singleQuoteEnd :: (Stream s m Char, UpdateSourcePos s Char)
=> ParsecT s st m ()
singleQuoteEnd = try $ do
charOrRef "'\8217\146"
char '\''
notFollowedBy alphaNum
-- | Succeeds if the parser is
@@ -142,13 +134,13 @@ doubleQuoteStart :: (HasLastStrPosition st,
doubleQuoteStart = do
failIfInQuoteContext InDoubleQuote
guard =<< notAfterString
try $ do charOrRef "\"\8220\147"
try $ do char '"'
void $ lookAhead (satisfy (not . isSpaceChar))
-- | Parses a closing quote character.
doubleQuoteEnd :: (Stream s m Char, UpdateSourcePos s Char)
=> ParsecT s st m ()
doubleQuoteEnd = void (charOrRef "\"\8221\148")
doubleQuoteEnd = void (char '"')
-- | Parses an ASCII apostrophe (@'@) or right single quotation mark and
-- returns a RIGHT SINGLE QUOtatiON MARK character.
+2 -2
View File
@@ -108,11 +108,11 @@ stringToLaTeX context zs = do
'}' -> emits "\\}"
'?' | ligatures -> -- avoid ?` ligature
case xs of
'`':_ -> emits "?{}"
'`':_ -> emits "?{\\kern0pt}" -- se #10610
_ -> emitc x
'!' | ligatures -> -- avoid !` ligature
case xs of
'`':_ -> emits "!{}"
'`':_ -> emits "!{\\kern0pt}"
_ -> emitc x
'`' | ctx == CodeString -> emitcseq "\\textasciigrave"
'$' -> emits "\\$"
+4 -4
View File
@@ -6,9 +6,9 @@ hi there?
hi there!
hi there!
^D
hi there?{}``
hi there!{}``
hi there?{}`
hi there!{}`
hi there?{\kern0pt}``
hi there!{\kern0pt}``
hi there?{\kern0pt}`
hi there!{\kern0pt}`
hi there!
```
+6 -6
View File
@@ -49,13 +49,17 @@ references:
Foo [@item1; @item2; @item3; @item4; @item5; @item6; @item7; @item8].
^D
Foo (al-ʾUdhrī, n.d.; al-ʿUdhrī, n.d.; al-\'Udhrī, n.d.; al-'Udhrī,
n.d.a, n.d.b; Uch, n.d.; Uebel, n.d.; Zzz, n.d.).
n.d.; al-'Udhrī, n.d.; Uch, n.d.; Uebel, n.d.; Zzz, n.d.).
::::::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}
::: {#ref-item6 .csl-entry}
Uch, Ann. n.d.
:::
::: {#ref-item4 .csl-entry}
'Udhrī, Jamīl al-. n.d.
:::
::: {#ref-item1 .csl-entry}
ʾUdhrī, Jamīl al-. n.d.
:::
@@ -68,12 +72,8 @@ Uch, Ann. n.d.
\'Udhrī, Jamīl al-. n.d.
:::
::: {#ref-item4 .csl-entry}
'Udhrī, Jamīl al-. n.d.a.
:::
::: {#ref-item5 .csl-entry}
---------. n.d.b.
'Udhrī, Jamīl al-. n.d.
:::
::: {#ref-item7 .csl-entry}
+2 -2
View File
@@ -316,8 +316,8 @@ Pandoc
2
( "curly-smart-quotes" , [] , [] )
[ Str "Curly" , Space , Str "smart" , Space , Str "quotes" ]
, Para [ Quoted DoubleQuote [ Str "Hi" ] ]
, Para [ Quoted SingleQuote [ Str "Hi" ] ]
, Para [ Str "\8220Hi\8221" ]
, Para [ Str "\8216Hi\8217" ]
, Header
2
( "consecutive-lists" , [] , [] )