// Copyright 2015 The Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package markdown import "strings" func exclquest(b byte) bool { return b == '!' || b == '?' } func byteToLower(b byte) byte { if b >= 'A' && b <= 'Z' { return b - 'A' + 'a' } return b } var replChar = [256]bool{ '(': true, '!': true, '+': true, ',': true, '-': true, '.': true, '?': true, } func performReplacements(s string) string { var ss []string start := 0 for i := 0; i < len(s); i++ { b := s[i] if replChar[b] { outer: switch b { case '(': if i+2 >= len(s) { break } b2 := s[i+1] b2 = byteToLower(b2) switch b2 { case 'c', 'r', 'p': if s[i+2] != ')' { break outer } switch b2 { case 'c': if start < i { ss = append(ss, s[start:i]) } ss = append(ss, "©") case 'r': if start < i { ss = append(ss, s[start:i]) } ss = append(ss, "®") case 'p': if start < i { ss = append(ss, s[start:i]) } ss = append(ss, "§") } i += 2 start = i + 1 continue case 't': if i+3 >= len(s) { break outer } if s[i+3] != ')' || byteToLower(s[i+2]) != 'm' { break outer } if start < i { ss = append(ss, s[start:i]) } ss = append(ss, "™") i += 3 start = i + 1 continue default: break outer } case '+': if i+1 >= len(s) || s[i+1] != '-' { break } if start < i { ss = append(ss, s[start:i]) } ss = append(ss, "±") i++ start = i + 1 continue case '.': if i+1 >= len(s) || s[i+1] != '.' { break } j := i + 2 for j < len(s) && s[j] == '.' { j++ } if start < i { ss = append(ss, s[start:i]) } if i == 0 || !(s[i-1] == '?' || s[i-1] == '!') { ss = append(ss, "…") } else { ss = append(ss, "..") } i = j - 1 start = i + 1 continue case '?', '!': if i+3 >= len(s) { break } if !(exclquest(s[i+1]) && exclquest(s[i+2]) && exclquest(s[i+3])) { break } if start < i { ss = append(ss, s[start:i]) } ss = append(ss, s[i:i+3]) j := i + 3 for j < len(s) && exclquest(s[j]) { j++ } i = j - 1 start = i + 1 continue case ',': if i+1 >= len(s) || s[i+1] != ',' { break } if start < i { ss = append(ss, s[start:i]) } ss = append(ss, ",") j := i + 2 for j < len(s) && s[j] == ',' { j++ } i = j - 1 start = i + 1 continue case '-': if i+1 >= len(s) || s[i+1] != '-' { break } if i+2 >= len(s) || s[i+2] != '-' { if start < i { ss = append(ss, s[start:i]) } ss = append(ss, "–") i++ start = i + 1 continue } if i+3 >= len(s) || s[i+3] != '-' { if start < i { ss = append(ss, s[start:i]) } ss = append(ss, "—") i += 2 start = i + 1 continue } j := i + 3 for j < len(s) && s[j] == '-' { j++ } if start < i { ss = append(ss, s[start:i]) } ss = append(ss, s[i:j]) i = j - 1 start = i + 1 continue } } } if ss == nil { return s } if start < len(s) { ss = append(ss, s[start:]) } return strings.Join(ss, "") } func ruleReplacements(s *StateCore) { if !s.Md.Typographer { return } insideLink := false for _, tok := range s.Tokens { if tok, ok := tok.(*Inline); ok { for _, itok := range tok.Children { switch itok := itok.(type) { case *LinkOpen: insideLink = true case *LinkClose: insideLink = false case *Text: if !insideLink { itok.Content = performReplacements(itok.Content) } } } } } }