Skip to content

Commit

Permalink
Improve typographer
Browse files Browse the repository at this point in the history
  • Loading branch information
yuin committed Jun 4, 2020
1 parent 4a49786 commit 33089e2
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 9 deletions.
7 changes: 7 additions & 0 deletions extension/_test/typographer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,10 @@ reported "issue 1 (IE-only)", "issue 2", 'issue3 (FF-only)', 'issue4'
//- - - - - - - - -//
<p>reported &ldquo;issue 1 (IE-only)&rdquo;, &ldquo;issue 2&rdquo;, &lsquo;issue3 (FF-only)&rsquo;, &lsquo;issue4&rsquo;</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

8: handle inches in qoutes
//- - - - - - - - -//
"Monitor 21"" and "Monitor""
//- - - - - - - - -//
<p>&ldquo;Monitor 21&quot;&rdquo; and &ldquo;Monitor&rdquo;&quot;</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//
44 changes: 35 additions & 9 deletions extension/typographer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ import (
"github.com/yuin/goldmark/util"
)

var uncloseCounterKey = parser.NewContextKey()

type unclosedCounter struct {
Single int
Double int
}

func (u *unclosedCounter) Reset() {
u.Single = 0
u.Double = 0
}

func getUnclosedCounter(pc parser.Context) *unclosedCounter {
v := pc.Get(uncloseCounterKey)
if v == nil {
v = &unclosedCounter{}
pc.Set(uncloseCounterKey, v)
}
return v.(*unclosedCounter)
}

// TypographicPunctuation is a key of the punctuations that can be replaced with
// typographic entities.
type TypographicPunctuation int
Expand Down Expand Up @@ -193,6 +214,7 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser
if d == nil {
return nil
}
counter := getUnclosedCounter(pc)
if c == '\'' {
if s.Substitutions[Apostrophe] != nil {
// Handle decade abbrevations such as '90s
Expand Down Expand Up @@ -227,43 +249,47 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser
if len(line) > 2 && ((line[1] == 'v' && line[2] == 'e') || (line[1] == 'l' && line[2] == 'l') || (line[1] == 'r' && line[2] == 'e')) && (len(line) < 4 || util.IsPunct(line[3]) || util.IsSpace(line[3])) {
nt = RightSingleQuote
}
if nt == LeftSingleQuote {
counter.Single++
}

node := gast.NewString(s.Substitutions[nt])
node.SetCode(true)
block.Advance(1)
return node
}
if s.Substitutions[RightSingleQuote] != nil {
if s.Substitutions[RightSingleQuote] != nil && counter.Single > 0 {
isClose := d.CanClose && !d.CanOpen
maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && (line[1] == ',' || line[1] == '.' || line[1] == '!' || line[1] == '?') && (len(line) == 2 || (len(line) > 2 && util.IsPunct(line[2]) || util.IsSpace(line[2])))
if isClose || maybeClose {
node := gast.NewString(s.Substitutions[RightSingleQuote])
node.SetCode(true)
block.Advance(1)
counter.Single--
return node
}
}
}
if c == '"' {
// special case: 7'1""
if len(line) > 1 && line[1] == '"' && unicode.IsDigit(before) {
node := gast.NewString(line[0:2])
block.Advance(2)
return node
}
if s.Substitutions[LeftDoubleQuote] != nil && d.CanOpen && !d.CanClose {
node := gast.NewString(s.Substitutions[LeftDoubleQuote])
node.SetCode(true)
block.Advance(1)
counter.Double++
return node
}
if s.Substitutions[RightDoubleQuote] != nil {
if s.Substitutions[RightDoubleQuote] != nil && counter.Double > 0 {
isClose := d.CanClose && !d.CanOpen
maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && (line[1] == ',' || line[1] == '.' || line[1] == '!' || line[1] == '?') && (len(line) == 2 || (len(line) > 2 && util.IsPunct(line[2]) || util.IsSpace(line[2])))
if isClose || maybeClose {
// special case: "Monitor 21""
if len(line) > 1 && line[1] == '"' && unicode.IsDigit(before) {
return nil
}
node := gast.NewString(s.Substitutions[RightDoubleQuote])
node.SetCode(true)
block.Advance(1)
counter.Double--
return node
}
}
Expand All @@ -273,7 +299,7 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser
}

func (s *typographerParser) CloseBlock(parent gast.Node, pc parser.Context) {
// nothing to do
getUnclosedCounter(pc).Reset()
}

type typographer struct {
Expand Down

0 comments on commit 33089e2

Please sign in to comment.