* Update to go-org 1.3.2 Fix #12727 Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix unit test Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
		
			
				
	
	
		
			102 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| package org
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"regexp"
 | |
| 	"strings"
 | |
| 	"unicode"
 | |
| )
 | |
| 
 | |
| type Outline struct {
 | |
| 	*Section
 | |
| 	last  *Section
 | |
| 	count int
 | |
| }
 | |
| 
 | |
| type Section struct {
 | |
| 	Headline *Headline
 | |
| 	Parent   *Section
 | |
| 	Children []*Section
 | |
| }
 | |
| 
 | |
| type Headline struct {
 | |
| 	Index      int
 | |
| 	Lvl        int
 | |
| 	Status     string
 | |
| 	Priority   string
 | |
| 	Properties *PropertyDrawer
 | |
| 	Title      []Node
 | |
| 	Tags       []string
 | |
| 	Children   []Node
 | |
| }
 | |
| 
 | |
| var headlineRegexp = regexp.MustCompile(`^([*]+)\s+(.*)`)
 | |
| var tagRegexp = regexp.MustCompile(`(.*?)\s+(:[A-Za-z0-9_@#%:]+:\s*$)`)
 | |
| 
 | |
| func lexHeadline(line string) (token, bool) {
 | |
| 	if m := headlineRegexp.FindStringSubmatch(line); m != nil {
 | |
| 		return token{"headline", 0, m[2], m}, true
 | |
| 	}
 | |
| 	return nilToken, false
 | |
| }
 | |
| 
 | |
| func (d *Document) parseHeadline(i int, parentStop stopFn) (int, Node) {
 | |
| 	t, headline := d.tokens[i], Headline{}
 | |
| 	headline.Lvl = len(t.matches[1])
 | |
| 
 | |
| 	headline.Index = d.addHeadline(&headline)
 | |
| 
 | |
| 	text := t.content
 | |
| 	todoKeywords := strings.FieldsFunc(d.Get("TODO"), func(r rune) bool { return unicode.IsSpace(r) || r == '|' })
 | |
| 	for _, k := range todoKeywords {
 | |
| 		if strings.HasPrefix(text, k) && len(text) > len(k) && unicode.IsSpace(rune(text[len(k)])) {
 | |
| 			headline.Status = k
 | |
| 			text = text[len(k)+1:]
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if len(text) >= 4 && text[0:2] == "[#" && strings.Contains("ABC", text[2:3]) && text[3] == ']' {
 | |
| 		headline.Priority = text[2:3]
 | |
| 		text = strings.TrimSpace(text[4:])
 | |
| 	}
 | |
| 
 | |
| 	if m := tagRegexp.FindStringSubmatch(text); m != nil {
 | |
| 		text = m[1]
 | |
| 		headline.Tags = strings.FieldsFunc(m[2], func(r rune) bool { return r == ':' })
 | |
| 	}
 | |
| 
 | |
| 	headline.Title = d.parseInline(text)
 | |
| 
 | |
| 	stop := func(d *Document, i int) bool {
 | |
| 		return parentStop(d, i) || d.tokens[i].kind == "headline" && len(d.tokens[i].matches[1]) <= headline.Lvl
 | |
| 	}
 | |
| 	consumed, nodes := d.parseMany(i+1, stop)
 | |
| 	if len(nodes) > 0 {
 | |
| 		if d, ok := nodes[0].(PropertyDrawer); ok {
 | |
| 			headline.Properties = &d
 | |
| 			nodes = nodes[1:]
 | |
| 		}
 | |
| 	}
 | |
| 	headline.Children = nodes
 | |
| 	return consumed + 1, headline
 | |
| }
 | |
| 
 | |
| func (h Headline) ID() string {
 | |
| 	if customID, ok := h.Properties.Get("CUSTOM_ID"); ok {
 | |
| 		return customID
 | |
| 	}
 | |
| 	return fmt.Sprintf("headline-%d", h.Index)
 | |
| }
 | |
| 
 | |
| func (parent *Section) add(current *Section) {
 | |
| 	if parent.Headline == nil || parent.Headline.Lvl < current.Headline.Lvl {
 | |
| 		parent.Children = append(parent.Children, current)
 | |
| 		current.Parent = parent
 | |
| 	} else {
 | |
| 		parent.Parent.add(current)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (n Headline) String() string { return orgWriter.WriteNodesAsString(n) }
 |