mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 21:16:26 +01:00 
			
		
		
		
	* 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>
		
			
				
	
	
		
			138 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
package org
 | 
						|
 | 
						|
import (
 | 
						|
	"regexp"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"unicode/utf8"
 | 
						|
)
 | 
						|
 | 
						|
type Table struct {
 | 
						|
	Rows             []Row
 | 
						|
	ColumnInfos      []ColumnInfo
 | 
						|
	SeparatorIndices []int
 | 
						|
}
 | 
						|
 | 
						|
type Row struct {
 | 
						|
	Columns   []Column
 | 
						|
	IsSpecial bool
 | 
						|
}
 | 
						|
 | 
						|
type Column struct {
 | 
						|
	Children []Node
 | 
						|
	*ColumnInfo
 | 
						|
}
 | 
						|
 | 
						|
type ColumnInfo struct {
 | 
						|
	Align      string
 | 
						|
	Len        int
 | 
						|
	DisplayLen int
 | 
						|
}
 | 
						|
 | 
						|
var tableSeparatorRegexp = regexp.MustCompile(`^(\s*)(\|[+-|]*)\s*$`)
 | 
						|
var tableRowRegexp = regexp.MustCompile(`^(\s*)(\|.*)`)
 | 
						|
 | 
						|
var columnAlignAndLengthRegexp = regexp.MustCompile(`^<(l|c|r)?(\d+)?>$`)
 | 
						|
 | 
						|
func lexTable(line string) (token, bool) {
 | 
						|
	if m := tableSeparatorRegexp.FindStringSubmatch(line); m != nil {
 | 
						|
		return token{"tableSeparator", len(m[1]), m[2], m}, true
 | 
						|
	} else if m := tableRowRegexp.FindStringSubmatch(line); m != nil {
 | 
						|
		return token{"tableRow", len(m[1]), m[2], m}, true
 | 
						|
	}
 | 
						|
	return nilToken, false
 | 
						|
}
 | 
						|
 | 
						|
func (d *Document) parseTable(i int, parentStop stopFn) (int, Node) {
 | 
						|
	rawRows, separatorIndices, start := [][]string{}, []int{}, i
 | 
						|
	for ; !parentStop(d, i); i++ {
 | 
						|
		if t := d.tokens[i]; t.kind == "tableRow" {
 | 
						|
			rawRow := strings.FieldsFunc(d.tokens[i].content, func(r rune) bool { return r == '|' })
 | 
						|
			for i := range rawRow {
 | 
						|
				rawRow[i] = strings.TrimSpace(rawRow[i])
 | 
						|
			}
 | 
						|
			rawRows = append(rawRows, rawRow)
 | 
						|
		} else if t.kind == "tableSeparator" {
 | 
						|
			separatorIndices = append(separatorIndices, i-start)
 | 
						|
			rawRows = append(rawRows, nil)
 | 
						|
		} else {
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	table := Table{nil, getColumnInfos(rawRows), separatorIndices}
 | 
						|
	for _, rawColumns := range rawRows {
 | 
						|
		row := Row{nil, isSpecialRow(rawColumns)}
 | 
						|
		if len(rawColumns) != 0 {
 | 
						|
			for i := range table.ColumnInfos {
 | 
						|
				column := Column{nil, &table.ColumnInfos[i]}
 | 
						|
				if i < len(rawColumns) {
 | 
						|
					column.Children = d.parseInline(rawColumns[i])
 | 
						|
				}
 | 
						|
				row.Columns = append(row.Columns, column)
 | 
						|
			}
 | 
						|
		}
 | 
						|
		table.Rows = append(table.Rows, row)
 | 
						|
	}
 | 
						|
	return i - start, table
 | 
						|
}
 | 
						|
 | 
						|
func getColumnInfos(rows [][]string) []ColumnInfo {
 | 
						|
	columnCount := 0
 | 
						|
	for _, columns := range rows {
 | 
						|
		if n := len(columns); n > columnCount {
 | 
						|
			columnCount = n
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	columnInfos := make([]ColumnInfo, columnCount)
 | 
						|
	for i := 0; i < columnCount; i++ {
 | 
						|
		countNumeric, countNonNumeric := 0, 0
 | 
						|
		for _, columns := range rows {
 | 
						|
			if i >= len(columns) {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			if n := utf8.RuneCountInString(columns[i]); n > columnInfos[i].Len {
 | 
						|
				columnInfos[i].Len = n
 | 
						|
			}
 | 
						|
 | 
						|
			if m := columnAlignAndLengthRegexp.FindStringSubmatch(columns[i]); m != nil && isSpecialRow(columns) {
 | 
						|
				switch m[1] {
 | 
						|
				case "l":
 | 
						|
					columnInfos[i].Align = "left"
 | 
						|
				case "c":
 | 
						|
					columnInfos[i].Align = "center"
 | 
						|
				case "r":
 | 
						|
					columnInfos[i].Align = "right"
 | 
						|
				}
 | 
						|
				if m[2] != "" {
 | 
						|
					l, _ := strconv.Atoi(m[2])
 | 
						|
					columnInfos[i].DisplayLen = l
 | 
						|
				}
 | 
						|
			} else if _, err := strconv.ParseFloat(columns[i], 32); err == nil {
 | 
						|
				countNumeric++
 | 
						|
			} else if strings.TrimSpace(columns[i]) != "" {
 | 
						|
				countNonNumeric++
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if columnInfos[i].Align == "" && countNumeric >= countNonNumeric {
 | 
						|
			columnInfos[i].Align = "right"
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return columnInfos
 | 
						|
}
 | 
						|
 | 
						|
func isSpecialRow(rawColumns []string) bool {
 | 
						|
	isAlignRow := true
 | 
						|
	for _, rawColumn := range rawColumns {
 | 
						|
		if !columnAlignAndLengthRegexp.MatchString(rawColumn) && rawColumn != "" {
 | 
						|
			isAlignRow = false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return isAlignRow
 | 
						|
}
 | 
						|
 | 
						|
func (n Table) String() string { return orgWriter.WriteNodesAsString(n) }
 |