typographer: add basic support for apostrophes

This commit is contained in:
Daniel Tang 2020-01-09 15:33:37 -08:00
parent 5294fa5c4f
commit 45fa0e2645
2 changed files with 32 additions and 0 deletions

View file

@ -18,3 +18,10 @@ This should "be" replaced
//- - - - - - - - -// //- - - - - - - - -//
<p><strong>&ndash;</strong> <em>&mdash;</em> a&hellip;&laquo; b&raquo;</p> <p><strong>&ndash;</strong> <em>&mdash;</em> a&hellip;&laquo; b&raquo;</p>
//= = = = = = = = = = = = = = = = = = = = = = = =// //= = = = = = = = = = = = = = = = = = = = = = = =//
4
//- - - - - - - - -//
Some say '90s, others say 90's, but I can't say which is best.
//- - - - - - - - -//
<p>Some say &rsquo;90s, others say 90&rsquo;s, but I can&rsquo;t say which is best.</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

View file

@ -1,6 +1,8 @@
package extension package extension
import ( import (
"unicode"
"github.com/yuin/goldmark" "github.com/yuin/goldmark"
gast "github.com/yuin/goldmark/ast" gast "github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/parser" "github.com/yuin/goldmark/parser"
@ -31,6 +33,8 @@ const (
LeftAngleQuote LeftAngleQuote
// RightAngleQuote is >> // RightAngleQuote is >>
RightAngleQuote RightAngleQuote
// Apostrophe is '
Apostrophe
typographicPunctuationMax typographicPunctuationMax
) )
@ -52,6 +56,7 @@ func newDefaultSubstitutions() [][]byte {
replacements[Ellipsis] = []byte("&hellip;") replacements[Ellipsis] = []byte("&hellip;")
replacements[LeftAngleQuote] = []byte("&laquo;") replacements[LeftAngleQuote] = []byte("&laquo;")
replacements[RightAngleQuote] = []byte("&raquo;") replacements[RightAngleQuote] = []byte("&raquo;")
replacements[Apostrophe] = []byte("&rsquo;")
return replacements return replacements
} }
@ -189,6 +194,26 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser
return nil return nil
} }
if c == '\'' { if c == '\'' {
if s.Substitutions[Apostrophe] != nil {
// Handle decade abbrevations such as '90s
if d.CanOpen && !d.CanClose && len(line) > 3 && util.IsNumeric(line[1]) && util.IsNumeric(line[2]) && line[3] == 's' {
after := util.ToRune(line, 4)
if len(line) == 3 || unicode.IsSpace(after) || unicode.IsPunct(after) {
node := gast.NewString(s.Substitutions[Apostrophe])
node.SetCode(true)
block.Advance(1)
return node
}
}
// Convert normal apostrophes. This is probably more flexible than necessary but
// converts any apostrophe in between two alphanumerics.
if len(line) > 1 && (unicode.IsDigit(before) || unicode.IsLetter(before)) && (util.IsAlphaNumeric(line[1])) {
node := gast.NewString(s.Substitutions[Apostrophe])
node.SetCode(true)
block.Advance(1)
return node
}
}
if s.Substitutions[LeftSingleQuote] != nil && d.CanOpen && !d.CanClose { if s.Substitutions[LeftSingleQuote] != nil && d.CanOpen && !d.CanClose {
node := gast.NewString(s.Substitutions[LeftSingleQuote]) node := gast.NewString(s.Substitutions[LeftSingleQuote])
node.SetCode(true) node.SetCode(true)