Skip to content

Commit 4289f94

Browse files
committed
Escape HTML special characters
1 parent 3ade99f commit 4289f94

File tree

5 files changed

+67
-27
lines changed

5 files changed

+67
-27
lines changed

generator.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ func ToGemtextFile(name string, asl ASL, perm os.FileMode) error {
5959
return os.WriteFile(name, []byte(ToGemtext(asl)), perm)
6060
}
6161

62+
var escaper = strings.NewReplacer(
63+
"&", "&",
64+
`"`, """,
65+
"'", "'",
66+
"<", "&lt;",
67+
">", "&gt;",
68+
)
69+
6270
// ToHTML turns asl into HTML.
6371
func ToHTML(asl ASL) string {
6472
// Possible improvement for later:
@@ -77,29 +85,30 @@ func ToHTML(asl ASL) string {
7785
b.WriteString("</ul>\n")
7886
}
7987

88+
text := escaper.Replace(e.Text())
8089
switch e.Type() {
8190

8291
case ElementTypes.Text():
8392
if isPreformattedMode {
84-
b.WriteString(e.Text())
93+
b.WriteString(text)
8594
break
8695
}
87-
if e.Text() == "" {
96+
if text == "" {
8897
b.WriteString("<br />")
8998
} else {
9099
b.WriteString("<p>")
91-
b.WriteString(e.Text())
100+
b.WriteString(text)
92101
b.WriteString("</p>")
93102
}
94103

95104
case ElementTypes.Link():
96-
b.WriteString("<p><a href=\"")
105+
b.WriteString(`<p><a href="`)
97106
b.WriteString(e.URL())
98-
b.WriteString("\">")
99-
if e.Text() == "" {
100-
b.WriteString(e.URL())
107+
b.WriteString(`">`)
108+
if text == "" {
109+
b.WriteString(escaper.Replace(e.URL()))
101110
} else {
102-
b.WriteString(e.Text())
111+
b.WriteString(text)
103112
}
104113
b.WriteString("</a></p>")
105114

@@ -118,20 +127,20 @@ func ToHTML(asl ASL) string {
118127
close = "</h3>"
119128
}
120129
b.WriteString(open)
121-
b.WriteString(e.Text())
130+
b.WriteString(text)
122131
b.WriteString(close)
123132

124133
case ElementTypes.List():
125134
if prev.Type() != ElementTypes.List() {
126135
b.WriteString("<ul>\n")
127136
}
128137
b.WriteString("<li>")
129-
b.WriteString(e.Text())
138+
b.WriteString(text)
130139
b.WriteString("</li>")
131140

132141
case ElementTypes.Quote():
133142
b.WriteString("<blockquote><p>")
134-
b.WriteString(e.Text())
143+
b.WriteString(text)
135144
b.WriteString("</p></blockquote>")
136145

137146
case ElementTypes.PreformatToggle():
@@ -142,16 +151,16 @@ func ToHTML(asl ASL) string {
142151
b.WriteString("</figure>")
143152
}
144153
} else {
145-
if e.Text() != "" {
154+
if text != "" {
146155
b.WriteString("<figure><figcaption>")
147-
b.WriteString(e.Text())
156+
b.WriteString(text)
148157
b.WriteString("</figcaption>")
149158
}
150159

151160
b.WriteString("<pre>")
152161
}
153162
isPreformattedMode = !isPreformattedMode
154-
preformatHasAltText = e.Text() != ""
163+
preformatHasAltText = text != ""
155164

156165
}
157166

testdata/input.gmi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ Random:
1111
$%^&(*^&)
1212
😂🥖🏴‍☠️
1313

14+
HTML:
15+
<h1>Title & Heading</h1>
16+
<p class="quoted">'quotes'</p>
17+
1418
Should remain as text and keep leading whitespace:
1519
space indented text
1620
tab indented text
@@ -33,6 +37,7 @@ Link
3337

3438
=>
3539
=> gemini://example.org/
40+
=> gemini://example.org:1234/a?b=c&d=e#f
3641
=> gemini://example.org Name
3742
=>gemini://example.org/some%20page User friendly link name
3843
=> path/to/some.txt Relative link

testdata/output.gmi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ Random:
1111
$%^&(*^&)
1212
😂🥖🏴‍☠️
1313

14+
HTML:
15+
<h1>Title & Heading</h1>
16+
<p class="quoted">'quotes'</p>
17+
1418
Should remain as text and keep leading whitespace:
1519
space indented text
1620
tab indented text
@@ -33,6 +37,7 @@ Link
3337

3438
=>
3539
=> gemini://example.org/
40+
=> gemini://example.org:1234/a?b=c&d=e#f
3641
=> gemini://example.org Name
3742
=> gemini://example.org/some%20page User friendly link name
3843
=> path/to/some.txt Relative link

testdata/output.html

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,23 @@
88
<br />
99
<p>Random:</p>
1010
<p>123 456 789</p>
11-
<p>$%^&(*^&)</p>
11+
<p>$%^&amp;(*^&amp;)</p>
1212
<p>😂🥖🏴‍☠️</p>
1313
<br />
14+
<p>HTML:</p>
15+
<p>&lt;h1&gt;Title &amp; Heading&lt;/h1&gt;</p>
16+
<p>&lt;p class=&quot;quoted&quot;&gt;&apos;quotes&apos;&lt;/p&gt;</p>
17+
<br />
1418
<p>Should remain as text and keep leading whitespace:</p>
1519
<p> space indented text</p>
1620
<p> tab indented text</p>
17-
<p> => Not a link because of the leading space</p>
18-
<p>= Still not a link because it's missing ></p>
21+
<p> =&gt; Not a link because of the leading space</p>
22+
<p>= Still not a link because it&apos;s missing &gt;</p>
1923
<p> ## Not a heading because of the leading spaces</p>
2024
<p> * Not a list because of the leading tab</p>
21-
<p> > Not a quote because of the leading spaces and tab</p>
25+
<p> &gt; Not a quote because of the leading spaces and tab</p>
2226
<p> ``` Not preformat toggle because of the leading tab and spaces</p>
23-
<p>``Still not preformat toggle because it's missing a `</p>
27+
<p>``Still not preformat toggle because it&apos;s missing a `</p>
2428
<br />
2529
<p>Multiple empty lines:</p>
2630
<br />
@@ -33,6 +37,7 @@
3337
<br />
3438
<p><a href=""></a></p>
3539
<p><a href="gemini://example.org/">gemini://example.org/</a></p>
40+
<p><a href="gemini://example.org:1234/a?b=c&d=e#f">gemini://example.org:1234/a?b=c&amp;d=e#f</a></p>
3641
<p><a href="gemini://example.org">Name</a></p>
3742
<p><a href="gemini://example.org/some%20page">User friendly link name</a></p>
3843
<p><a href="path/to/some.txt">Relative link</a></p>
@@ -80,13 +85,13 @@ <h3>#Still level 3</h3>
8085
<li>To test if it toggles correctly</li>
8186
</ul>
8287
<figure><figcaption>Interpreted as text because inside a preformatted block</figcaption><pre>
83-
=>gemini://example.org Name
88+
=&gt;gemini://example.org Name
8489

8590

8691

8792
#Level 1
8893
*Some
89-
>“A quote by a wise person.” ― Anonymous
94+
&gt;“A quote by a wise person.” ― Anonymous
9095
</pre></figure>
9196
<br />
9297
<figure><figcaption>ASCII art from https://www.asciiart.eu/computers/linux</figcaption><pre>
@@ -101,15 +106,15 @@ <h3>#Still level 3</h3>
101106
fZP SMMb
102107
HZM MMMM
103108
FqM MMMM
104-
__| ". |\dS"qML
105-
| `. | `' \Zq
106-
_) \.___.,| .'
107-
\____ )MMMMMP| .'
108-
`-' `--' hjm
109+
__| &quot;. |\dS&quot;qML
110+
| `. | `&apos; \Zq
111+
_) \.___.,| .&apos;
112+
\____ )MMMMMP| .&apos;
113+
`-&apos; `--&apos; hjm
109114
</pre></figure>
110115
<figure><figcaption>js</figcaption><pre>
111116
function main() {
112-
console.log("Hello World!");
117+
console.log(&quot;Hello World!&quot;);
113118
}
114119

115120
main();

testdata/parsed_input.dump

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ ASL{
3939
Text{
4040
text: "",
4141
},
42+
Text{
43+
text: "HTML:",
44+
},
45+
Text{
46+
text: "<h1>Title & Heading</h1>",
47+
},
48+
Text{
49+
text: "<p class=\"quoted\">'quotes'</p>",
50+
},
51+
Text{
52+
text: "",
53+
},
4254
Text{
4355
text: "Should remain as text and keep leading whitespace:",
4456
},
@@ -107,6 +119,10 @@ ASL{
107119
text: "",
108120
url: "gemini://example.org/",
109121
},
122+
Link{
123+
text: "",
124+
url: "gemini://example.org:1234/a?b=c&d=e#f",
125+
},
110126
Link{
111127
text: "Name",
112128
url: "gemini://example.org",

0 commit comments

Comments
 (0)