示例#1
0
文件: detector.go 项目: akavel/vfmd
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)
}
示例#2
0
文件: detector.go 项目: akavel/vfmd
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])
}
示例#3
0
文件: detector.go 项目: akavel/vfmd
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
}