diff --git a/extension/_test/typographer.txt b/extension/_test/typographer.txt index ef90bce..556353c 100644 --- a/extension/_test/typographer.txt +++ b/extension/_test/typographer.txt @@ -64,3 +64,73 @@ reported "issue 1 (IE-only)", "issue 2", 'issue3 (FF-only)', 'issue4' //- - - - - - - - -//
“Monitor 21"” and “Monitor”"
//= = = = = = = = = = = = = = = = = = = = = = = =// + +9: Closing quotation marks within italics +//- - - - - - - - -// +*"At first, things were not clear."* +//- - - - - - - - -// +“At first, things were not clear.”
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +10: Closing quotation marks within boldfacing +//- - - - - - - - -// +**"At first, things were not clear."** +//- - - - - - - - -// +“At first, things were not clear.”
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +11: Closing quotation marks within boldfacing and italics +//- - - - - - - - -// +***"At first, things were not clear."*** +//- - - - - - - - -// +“At first, things were not clear.”
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +12: Closing quotation marks within boldfacing and italics +//- - - - - - - - -// +***"At first, things were not clear."*** +//- - - - - - - - -// +“At first, things were not clear.”
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +13: Plural possessives +//- - - - - - - - -// +John's dog is named Sam. The Smiths' dog is named Rover. +//- - - - - - - - -// +John’s dog is named Sam. The Smiths’ dog is named Rover.
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +14: Links within quotation marks and parenthetical phrases +//- - - - - - - - -// +This is not difficult (see "[Introduction to Hugo Templating](https://gohugo.io/templates/introduction/)"). +//- - - - - - - - -// +This is not difficult (see “Introduction to Hugo Templating”).
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +15: Quotation marks within links +//- - - - - - - - -// +Apple's early Cairo font gave us ["moof" and the "dogcow."](https://www.macworld.com/article/2926184/we-miss-you-clarus-the-dogcow.html) +//- - - - - - - - -// +Apple’s early Cairo font gave us “moof” and the “dogcow.”
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +16: Single closing quotation marks with slang/informalities +//- - - - - - - - -// +"I'm not doin' that," Bill said with emphasis. +//- - - - - - - - -// +“I’m not doin’ that,” Bill said with emphasis.
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +17: Closing single quotation marks in quotations-within-quotations +//- - - - - - - - -// +Janet said, "When everything is 'breaking news,' nothing is 'breaking news.'" +//- - - - - - - - -// +Janet said, “When everything is ‘breaking news,’ nothing is ‘breaking news.’”
+//= = = = = = = = = = = = = = = = = = = = = = = =// + +18: Opening single quotation marks for abbreviations +//- - - - - - - - -// +We're talking about the internet --- 'net for short. Let's rock 'n roll! +//- - - - - - - - -// +We’re talking about the internet — ’net for short. Let’s rock ’n roll!
+//= = = = = = = = = = = = = = = = = = = = = = = =// diff --git a/extension/typographer.go b/extension/typographer.go index 2c34730..f56c06f 100644 --- a/extension/typographer.go +++ b/extension/typographer.go @@ -160,7 +160,7 @@ func NewTypographerParser(opts ...TypographerOption) parser.InlineParser { } func (s *typographerParser) Trigger() []byte { - return []byte{'\'', '"', '-', '.', '<', '>'} + return []byte{'\'', '"', '-', '.', ',', '<', '>', '*', '['} } func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node { @@ -230,6 +230,13 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser return node } } + // special cases: 'twas, 'em, 'net + if len(line) > 1 && (unicode.IsPunct(before) || unicode.IsSpace(before)) && (line[1] == 't' || line[1] == 'e' || line[1] == 'n' || line[1] == 'l') { + 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)) && (unicode.IsLetter(util.ToRune(line, 1))) { @@ -241,7 +248,7 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser } if s.Substitutions[LeftSingleQuote] != nil && d.CanOpen && !d.CanClose { nt := LeftSingleQuote - // special cases: Alice's, I'm ,Don't, You'd + // special cases: Alice's, I'm, Don't, You'd if len(line) > 1 && (line[1] == 's' || line[1] == 'm' || line[1] == 't' || line[1] == 'd') && (len(line) < 3 || util.IsPunct(line[2]) || util.IsSpace(line[2])) { nt = RightSingleQuote } @@ -258,9 +265,18 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser block.Advance(1) return node } + if s.Substitutions[RightSingleQuote] != nil { + // plural possesives and abbreviations: Smiths', doin' + if len(line) > 1 && unicode.IsSpace(util.ToRune(line, 0)) || unicode.IsPunct(util.ToRune(line, 0)) && (len(line) > 2 && !unicode.IsDigit(util.ToRune(line, 1))) { + node := gast.NewString(s.Substitutions[RightSingleQuote]) + node.SetCode(true) + block.Advance(1) + return node + } + } 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]))) + maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && unicode.IsPunct(util.ToRune(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) @@ -280,7 +296,7 @@ func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser } 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]))) + maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && (unicode.IsPunct(util.ToRune(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) {