108 lines
2.0 KiB
Go
108 lines
2.0 KiB
Go
package gemtext
|
|
|
|
import "bytes"
|
|
|
|
// ParseLine parses a single line (including the trailing \n) into a gemtext.Line.
|
|
func ParseLine(line []byte) Line {
|
|
if len(line) == 0 {
|
|
return nil
|
|
}
|
|
|
|
switch line[0] {
|
|
case '=':
|
|
if len(line) == 1 || line[1] != '>' {
|
|
break
|
|
}
|
|
return parseLinkLine(line)
|
|
case '`':
|
|
if len(line) < 3 || line[1] != '`' || line[2] != '`' {
|
|
break
|
|
}
|
|
return parsePreformatToggleLine(line)
|
|
case '#':
|
|
level := 1
|
|
if len(line) > 1 && line[1] == '#' {
|
|
level += 1
|
|
if len(line) > 2 && line[2] == '#' {
|
|
level += 1
|
|
}
|
|
}
|
|
return parseHeadingLine(level, line)
|
|
case '*':
|
|
if len(line) == 1 || line[1] != ' ' {
|
|
break
|
|
}
|
|
return parseListItemLine(line)
|
|
case '>':
|
|
return parseQuoteLine(line)
|
|
}
|
|
|
|
return TextLine{raw: line}
|
|
}
|
|
|
|
func parseLinkLine(raw []byte) LinkLine {
|
|
line := LinkLine{raw: raw}
|
|
|
|
// move past =>[<whitespace>]
|
|
raw = bytes.TrimLeft(raw[2:], " \t")
|
|
|
|
// find the next space or tab
|
|
spIdx := bytes.IndexByte(raw, ' ')
|
|
tbIdx := bytes.IndexByte(raw, '\t')
|
|
idx := spIdx
|
|
if idx == -1 {
|
|
idx = tbIdx
|
|
}
|
|
if tbIdx >= 0 && tbIdx < idx {
|
|
idx = tbIdx
|
|
}
|
|
|
|
if idx < 0 {
|
|
line.url = bytes.TrimRight(raw, "\r\n")
|
|
return line
|
|
}
|
|
|
|
line.url = raw[:idx]
|
|
raw = raw[idx+1:]
|
|
|
|
label := bytes.TrimRight(bytes.TrimLeft(raw, " \t"), "\r\n")
|
|
if len(label) > 0 {
|
|
line.label = label
|
|
}
|
|
|
|
return line
|
|
}
|
|
|
|
func parsePreformatToggleLine(raw []byte) PreformatToggleLine {
|
|
line := PreformatToggleLine{raw: raw}
|
|
|
|
raw = bytes.TrimRight(raw[3:], "\r\n")
|
|
if len(raw) > 0 {
|
|
line.altText = raw
|
|
}
|
|
|
|
return line
|
|
}
|
|
|
|
func parseHeadingLine(level int, raw []byte) HeadingLine {
|
|
return HeadingLine{
|
|
raw: raw,
|
|
lineType: LineTypeHeading1 - 1 + LineType(level),
|
|
body: bytes.TrimRight(bytes.TrimLeft(raw[level:], " \t"), "\r\n"),
|
|
}
|
|
}
|
|
|
|
func parseListItemLine(raw []byte) ListItemLine {
|
|
return ListItemLine{
|
|
raw: raw,
|
|
body: bytes.TrimRight(raw[2:], "\r\n"),
|
|
}
|
|
}
|
|
|
|
func parseQuoteLine(raw []byte) QuoteLine {
|
|
return QuoteLine{
|
|
raw: raw,
|
|
body: bytes.TrimRight(raw[1:], "\r\n"),
|
|
}
|
|
}
|