예제 #1
0
파일: olist.go 프로젝트: akavel/vfmd
func DetectOrderedList(start, second Line, detectors Detectors) Handler {
	m := reOrderedList.FindSubmatch(start.Bytes)
	if m == nil {
		return nil
	}
	var buf *defaultContext
	block := &md.OrderedListBlock{
		Starter: md.Run{start.Line, m[1]},
		// firstNumber, _ := strconv.Atoi(string(m[2]))
	}
	var item *md.ItemBlock
	var carry *Line
	var parser *Parser
	return HandlerFunc(func(next Line, ctx Context) (bool, error) {
		if next.EOF() {
			return listEnd2(parser, buf, ctx)
		}
		prev := carry
		carry = &next
		if prev == nil {
			buf = &defaultContext{
				mode:          ctx.GetMode(),
				detectors:     changedParagraphDetector(ctx, false, true),
				spanDetectors: ctx.GetSpanDetectors(),
			}
			block.Raw = append(block.Raw, md.Run(next))
			buf.Emit(block)
			if ctx.GetMode() != TopBlocks {
				item = &md.ItemBlock{}
				item.Raw = append(item.Raw, md.Run(next))
				buf.Emit(item)
				parser = &Parser{
					Context: buf,
				}
			}
			return pass(parser, next, next.Bytes[len(block.Starter.Bytes):])
		}

		nextBytes := bytes.TrimRight(next.Bytes, "\n")
		if prev.isBlank() {
			if next.isBlank() {
				return listEnd2(parser, buf, ctx)
			}
			if !reOrderedList.Match(nextBytes) &&
				next.hasNonSpaceInPrefix(len(block.Starter.Bytes)) {
				return listEnd2(parser, buf, ctx)
			}
		} else {
			if !reOrderedList.Match(nextBytes) &&
				next.hasNonSpaceInPrefix(len(block.Starter.Bytes)) &&
				!next.hasFourSpacePrefix() &&
				(reUnorderedList.Match(nextBytes) ||
					reHorizontalRule.Match(nextBytes)) {
				return listEnd2(parser, buf, ctx)
			}
		}

		block.Raw = append(block.Raw, md.Run(next))
		m := reOrderedList.FindSubmatch(next.Bytes)
		if m != nil {
			text := bytes.TrimLeft(m[1], " ")
			spaces, _ := mdutils.OffsetIn(m[1], text)
			if spaces >= len(block.Starter.Bytes) {
				m = nil
			}
		}
		if m != nil {
			if ctx.GetMode() != TopBlocks {
				_, err := end(parser, buf)
				if err != nil {
					return false, err
				}
				item = &md.ItemBlock{}
				item.Raw = append(item.Raw, md.Run(next))
				buf.Emit(item)
				parser = &Parser{
					Context: buf,
				}
			}
			return pass(parser, next, next.Bytes[len(m[1]):])
		}
		if ctx.GetMode() != TopBlocks {
			item.Raw = append(item.Raw, md.Run(next))
		}
		return pass(parser, next, trimLeftN(next.Bytes, " ", len(block.Starter.Bytes)))
	})
}
예제 #2
0
파일: ulist.go 프로젝트: akavel/vfmd
func DetectUnorderedList(start, second Line, detectors Detectors) Handler {
	m := reUnorderedList.FindSubmatch(start.Bytes)
	if m == nil {
		return nil
	}
	var buf *defaultContext
	block := &md.UnorderedListBlock{
		Starter: md.Run{start.Line, m[1]},
	}
	var item *md.ItemBlock
	var carry *Line
	var parser *Parser
	return HandlerFunc(func(next Line, ctx Context) (bool, error) {
		if next.EOF() {
			return listEnd2(parser, buf, ctx)
		}
		prev := carry
		carry = &next
		// First line? Init stuff and accept unconditionally, already tested.
		if prev == nil {
			buf = &defaultContext{
				mode:          ctx.GetMode(),
				detectors:     changedParagraphDetector(ctx, false, true),
				spanDetectors: ctx.GetSpanDetectors(),
			}
			block.Raw = append(block.Raw, md.Run(next))
			buf.Emit(block)
			if ctx.GetMode() != TopBlocks {
				item = &md.ItemBlock{}
				item.Raw = append(item.Raw, md.Run(next))
				buf.Emit(item)
				parser = &Parser{
					Context: buf,
				}
			}
			return pass(parser, next, next.Bytes[len(block.Starter.Bytes):])
		}

		if prev.isBlank() {
			if next.isBlank() {
				return listEnd2(parser, buf, ctx)
			}
			if !bytes.HasPrefix(next.Bytes, block.Starter.Bytes) &&
				// FIXME(akavel): spec refers to runes ("characters"), not bytes; fix this everywhere
				next.hasNonSpaceInPrefix(len(block.Starter.Bytes)) {
				return listEnd2(parser, buf, ctx)
			}
		} else {
			nextBytes := bytes.TrimRight(next.Bytes, "\n")
			if !bytes.HasPrefix(next.Bytes, block.Starter.Bytes) &&
				next.hasNonSpaceInPrefix(len(block.Starter.Bytes)) &&
				!next.hasFourSpacePrefix() &&
				(reUnorderedList.Match(nextBytes) ||
					reOrderedList.Match(nextBytes) ||
					reHorizontalRule.Match(nextBytes)) {
				return listEnd2(parser, buf, ctx)
			}
		}

		block.Raw = append(block.Raw, md.Run(next))
		if bytes.HasPrefix(next.Bytes, block.Starter.Bytes) {
			if ctx.GetMode() != TopBlocks {
				_, err := end(parser, buf)
				if err != nil {
					return false, err
				}
				item = &md.ItemBlock{}
				item.Raw = append(item.Raw, md.Run(next))
				buf.Emit(item)
				parser = &Parser{
					Context: buf,
				}
			}
			return pass(parser, next, next.Bytes[len(block.Starter.Bytes):])
		}
		if ctx.GetMode() != TopBlocks {
			item.Raw = append(item.Raw, md.Run(next))
		}
		return pass(parser, next, trimLeftN(next.Bytes, " ", len(block.Starter.Bytes)))
	})
}