package markup import ( "fmt" "regexp" "strings" "unicode" // "github.com/bouncepaw/mycorrhiza/util" ) var tableRe = regexp.MustCompile(`^table\s+{`) func MatchesTable(line string) bool { return tableRe.MatchString(line) } func TableFromFirstLine(line, hyphaName string) *Table { return &Table{ hyphaName: hyphaName, caption: line[strings.IndexRune(line, '{')+1:], rows: make([]*tableRow, 0), } } func (t *Table) Process(line string) (shouldGoBackToNormal bool) { if strings.TrimSpace(line) == "}" && !t.inMultiline { return true } if !t.inMultiline { t.pushRow() } var ( inLink bool skipNext bool escaping bool lookingForNonSpace = !t.inMultiline countingColspan bool ) for i, r := range line { switch { case skipNext: skipNext = false continue case lookingForNonSpace && unicode.IsSpace(r): case lookingForNonSpace && (r == '!' || r == '|'): t.currCellMarker = r t.currColspan = 1 lookingForNonSpace = false countingColspan = true case lookingForNonSpace: t.currCellMarker = '^' // ^ represents implicit |, not part of syntax t.currColspan = 1 lookingForNonSpace = false t.currCellBuilder.WriteRune(r) case escaping: t.currCellBuilder.WriteRune(r) case inLink && r == ']' && len(line)-1 > i && line[i+1] == ']': t.currCellBuilder.WriteString("]]") inLink = false skipNext = true case inLink: t.currCellBuilder.WriteRune(r) case t.inMultiline && r == '}': t.inMultiline = false case t.inMultiline && i == len(line)-1: t.currCellBuilder.WriteRune('\n') case t.inMultiline: t.currCellBuilder.WriteRune(r) // Not in multiline: case (r == '|' || r == '!') && !countingColspan: t.pushCell() t.currCellMarker = r t.currColspan = 1 countingColspan = true case r == t.currCellMarker && (r == '|' || r == '!') && countingColspan: t.currColspan++ case r == '{': t.inMultiline = true countingColspan = false case r == '[' && len(line)-1 > i && line[i+1] == '[': t.currCellBuilder.WriteString("[[") inLink = true skipNext = true case i == len(line)-1: t.pushCell() default: t.currCellBuilder.WriteRune(r) countingColspan = false } } return false } type Table struct { // data hyphaName string caption string rows []*tableRow // state inMultiline bool // tmp currCellMarker rune currColspan uint currCellBuilder strings.Builder } func (t *Table) pushRow() { t.rows = append(t.rows, &tableRow{ cells: make([]*tableCell, 0), }) } func (t *Table) pushCell() { tc := &tableCell{ content: t.currCellBuilder.String(), colspan: t.currColspan, } switch t.currCellMarker { case '|', '^': tc.kind = tableCellDatum case '!': tc.kind = tableCellHeader } // We expect the table to have at least one row ready, so no nil-checking tr := t.rows[len(t.rows)-1] tr.cells = append(tr.cells, tc) t.currCellBuilder = strings.Builder{} } func (t *Table) asHtml() (html string) { if t.caption != "" { html += fmt.Sprintf("