summaryrefslogtreecommitdiff
path: root/gemini/gemtext/types.go
blob: 71f324218709d2fbde0f5cd089e07fd62db3b24c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package gemtext

// LineType represents the different types of lines in a gemtext document.
type LineType int

const (
	// LineTypeText is the default case when nothing else matches.
	//
	// It indicates that the line object is a TextLine.
	LineTypeText LineType = iota + 1

	// LineTypeLink is a link line.
	//
	// =>[<ws>]<url>[<ws><label>][\r]\n
	//
	// The line is a LinkLine.
	LineTypeLink

	// LineTypePrompt is a spartan =: prompt line.
	//
	// =:[<ws>]<url>[<ws><label>][\r]\n
	//
	// The line is a LinkLine.
	LineTypePrompt

	// LineTypePreformatToggle switches the document between pre-formatted text or not.
	//
	// ```[<alt-text>][\r]\n
	//
	// The line object is a PreformatToggleLine.
	LineTypePreformatToggle

	// LineTypePreformattedText is any line between two PreformatToggles.
	//
	// The line is a PreformattedTextLine.
	LineTypePreformattedText

	// LineTypeHeading1 is a top-level heading.
	//
	// #[<ws>]body[\r]\n
	//
	// The line is a HeadingLine.
	LineTypeHeading1

	// LineTypeHeading2 is a second-level heading.
	//
	// ##[<ws>]body[\r]\n
	//
	// The line is a HeadingLine.
	LineTypeHeading2

	// LineTypeHeading3 is a third-level heading.
	//
	// ###[<ws>]<body>[\r]\n
	//
	// The line is a HeadingLine.
	LineTypeHeading3

	// LineTypeListItem is an unordered list item.
	//
	// * <body>[\r]\n
	//
	// The line object is a ListItemLine.
	LineTypeListItem

	// LineTypeQuote is a quote line.
	//
	// ><body>[\r]\n
	//
	// The line object is a QuoteLine.
	LineTypeQuote
)

// Line is the interface implemented by all specific line types.
//
// Many of those concrete implementation types have additional useful fields,
// so it can be a good idea to cast these to their concrete types based on the
// return value of the Type() method.
type Line interface {
	// Type returns the specific type of the gemtext line.
	Type() LineType

	// Raw reproduces the original bytes from the source reader.
	Raw() []byte

	// String represents the original bytes from the source reader as a string.
	String() string
}

// Document is the list of lines that make up a full text/gemini resource.
type Document []Line

// TextLine is a line of LineTypeText.
type TextLine struct {
	raw []byte
}

func (tl TextLine) Type() LineType { return LineTypeText }
func (tl TextLine) Raw() []byte    { return tl.raw }
func (tl TextLine) String() string { return string(tl.raw) }

// LinkLine is a line of LineTypeLink.
type LinkLine struct {
	raw   []byte
	url   []byte
	label []byte
	typ   LineType
}

func (ll LinkLine) Type() LineType { return ll.typ }
func (ll LinkLine) Raw() []byte    { return ll.raw }
func (ll LinkLine) String() string { return string(ll.raw) }

// URL returns the original url portion of the line.
//
// It is not guaranteed to be a valid URL.
func (ll LinkLine) URL() string { return string(ll.url) }

// Label returns the label portion of the line.
func (ll LinkLine) Label() string { return string(ll.label) }

// PreformatToggleLine is a preformatted text toggle line.
type PreformatToggleLine struct {
	raw     []byte
	altText []byte
}

func (tl PreformatToggleLine) Type() LineType { return LineTypePreformatToggle }
func (tl PreformatToggleLine) Raw() []byte    { return tl.raw }
func (tl PreformatToggleLine) String() string { return string(tl.raw) }

// AltText returns the alt-text portion of the line.
//
// If the line was parsed as part of a full document by Parse(),
// and this is a *closing* toggle, any alt-text present will be
// stripped and this will be empty. If the line was parsed by
// ParseLine() no such correction is performed.
func (tl PreformatToggleLine) AltText() string { return string(tl.altText) }

func (tl *PreformatToggleLine) clearAlt() { tl.altText = nil }

// PreformattedTextLine represents a line between two toggles.
//
// It is never returned by ParseLine but can be part of a
// document parsed by Parse().
type PreformattedTextLine struct {
	raw []byte
}

func (tl PreformattedTextLine) Type() LineType { return LineTypePreformattedText }
func (tl PreformattedTextLine) Raw() []byte    { return tl.raw }
func (tl PreformattedTextLine) String() string { return string(tl.raw) }

// HeadingLine is a line of LineTypeHeading[1,2,3].
type HeadingLine struct {
	raw      []byte
	lineType LineType
	body     []byte
}

func (hl HeadingLine) Type() LineType { return hl.lineType }
func (hl HeadingLine) Raw() []byte    { return hl.raw }
func (hl HeadingLine) String() string { return string(hl.raw) }

// Body returns the portion of the line with the header text.
func (hl HeadingLine) Body() string { return string(hl.body) }

// ListItemLine is a line of LineTypeListItem.
type ListItemLine struct {
	raw  []byte
	body []byte
}

func (li ListItemLine) Type() LineType { return LineTypeListItem }
func (li ListItemLine) Raw() []byte    { return li.raw }
func (li ListItemLine) String() string { return string(li.raw) }

// Body returns the text of the list item.
func (li ListItemLine) Body() string { return string(li.body) }

// QuoteLine is a line of LineTypeQuote.
type QuoteLine struct {
	raw  []byte
	body []byte
}

func (ql QuoteLine) Type() LineType { return LineTypeQuote }
func (ql QuoteLine) Raw() []byte    { return ql.raw }
func (ql QuoteLine) String() string { return string(ql.raw) }

// Body returns the text of the quote.
func (ql QuoteLine) Body() string { return string(ql.body) }