func imageParen(s *Context, altText []byte, prefix int, residual []byte) (consumed int) { // fmt.Println("imageParen @", s.Pos, string(s.Buf[s.Pos:s.Pos+prefix])) // e.g.: "] (" if !reImageParen.Match(residual) { // fmt.Println("no ](") return 0 } // fmt.Println("yes ](") r := reImageURLWithoutAngle.FindSubmatch(residual) if r == nil { r = reImageURLWithAngle.FindSubmatch(residual) } if r == nil { // fmt.Println("no imgurl") return 0 } // fmt.Println("yes imgurl") unprocessedSrc, attrs := r[1], r[2] a := reImageAttrParen.FindSubmatch(attrs) if a == nil { a = reImageAttrTitle.FindSubmatch(attrs) } if a == nil { // fmt.Println("no imgattr") return 0 } // fmt.Println("yes imgattr") title := "" if len(a) >= 2 { unprocessedTitle := a[1][1 : len(a[1])-1] title = strings.Replace(string(unprocessedTitle), "\x0a", "", -1) } rest := s.Buf[s.Pos:] tag := rest[:prefix+(len(residual)-len(attrs))+len(a[0])] s.Emit(tag, md.Image{ // TODO(akavel): keep only raw slices as fields, add methods to return processed strings URL: mdutils.DelWhites(string(unprocessedSrc)), Title: mdutils.DeEscape(title), AltText: mdutils.DeEscape(string(altText)), RawEnd: md.Raw{ md.Run{-1, tag[prefix:]}, }, }, true) return len(tag) }
func closingLinkTag(s *Context) (consumed int) { // TODO(akavel): refactor to use s.PopTo (or not, for efficiency?) if s.Openings.NullTopmostTagged("[") { return 1 // consume the ']' } rest := s.Buf[s.Pos:] // e.g.: "] [ref id]" ? m := reClosingTagRef.FindSubmatch(rest) if m != nil { // cancel all unclosed spans inside the link for s.Openings.Peek().Tag != "[" { s.Openings.Pop() } // emit a link opening := s.Openings.Peek() s.Emit(s.Buf[opening.Pos:][:len(opening.Tag)], md.Link{ ReferenceID: mdutils.Simplify(m[1]), RawEnd: md.Raw{ md.Run{-1, m[0]}, }, }, false) s.Emit(m[0], md.End{}, false) s.Openings.Pop() // cancel all unclosed links s.Openings.deleteLinks() return len(m[0]) } // e.g.: "] (http://www.example.net"... ? m = reClosingTagWithoutAngle.FindSubmatch(rest) if m == nil { // e.g.: "] ( <http://example.net/?q=)>"... ? m = reClosingTagWithAngle.FindSubmatch(rest) } if m != nil { linkURL := mdutils.DelWhites(string(m[1])) residual := m[2] title := "" t := reJustClosingParen.FindSubmatch(residual) if t == nil { t = reTitleAndClosingParen.FindSubmatch(residual) } if t != nil { if len(t) > 1 { attribs := t[1] unquoted := attribs[1 : len(attribs)-1] title = strings.Replace(string(unquoted), "\u000a", "", -1) } // cancel all unclosed spans inside the link for s.Openings.Peek().Tag != "[" { s.Openings.Pop() } // emit a link opening := s.Openings.Peek() closing := rest[:len(rest)-len(residual)+len(t[0])] s.Emit(s.Buf[opening.Pos:][:len(opening.Tag)], md.Link{ URL: linkURL, Title: mdutils.DeEscape(title), RawEnd: md.Raw{ md.Run{-1, closing}, }, }, false) s.Emit(closing, md.End{}, false) s.Openings.Pop() // cancel all unclosed links s.Openings.deleteLinks() return len(closing) } } // e.g.: "] []" ? m = reEmptyRef.FindSubmatch(rest) if m == nil { // just: "]" m = [][]byte{rest[:1]} } // cancel all unclosed spans inside the link for s.Openings.Peek().Tag != "[" { s.Openings.Pop() } // emit a link begin := s.Openings.Peek() s.Emit(s.Buf[begin.Pos:][:len(begin.Tag)], md.Link{ ReferenceID: mdutils.Simplify(s.Buf[begin.Pos+len(begin.Tag) : s.Pos]), RawEnd: md.Raw{ md.Run{-1, m[0]}, }, }, false) s.Emit(m[0], md.End{}, false) s.Openings.Pop() // cancel all unclosed links s.Openings.deleteLinks() return len(m[0]) }
func DetectAutomaticLink(s *Context) (consumed int) { rest := s.Buf[s.Pos:] if s.Pos > 0 && rest[0] != '<' { r, _ := utf8.DecodeLastRune(s.Buf[:s.Pos]) if r == utf8.RuneError || !isWordSep(r) { return 0 } } // "potential-auto-link-start-position" // fmt.Printf("potential autolink start at %d: %-15q...\n", // s.Pos, string(rest)) // e.g. "<http://example.net>" m := reURLWithinAngle.FindSubmatch(rest) // e.g. "<mailto:[email protected]?subject=Hi+there>" if m == nil { m = reMailtoURLWithinAngle.FindSubmatch(rest) } if m != nil { url := mdutils.DelWhites(string(m[1])) s.Emit(m[0], md.AutomaticLink{ URL: url, Text: url, }, true) return len(m[0]) } // e.g.: "<*****@*****.**>" m = reMailWithinAngle.FindSubmatch(rest) if m != nil { s.Emit(m[0], md.AutomaticLink{ URL: "mailto:" + string(m[1]), Text: string(m[1]), }, true) return len(m[0]) } // e.g.: "http://example.net" m = reURLWithoutAngle.FindSubmatch(rest) if m == nil { m = reMailtoURLWithoutAngle.FindSubmatch(rest) } if m != nil { // fmt.Printf("matched url w/o angle at %d: %s\n", // s.Pos, string(m[0])) scheme := m[1] tag := m[0] // remove any trailing "speculative-url-end" characters for len(tag) > 0 { r, n := utf8.DecodeLastRune(tag) if !isSpeculativeURLEnd(r) { break } tag = tag[:len(tag)-n] } if len(tag) <= len(scheme) { return len(scheme) } s.Emit(tag, md.AutomaticLink{ URL: string(tag), Text: string(tag), }, true) return len(tag) } return 0 }