Skip to content

Commit b91c1a5

Browse files
committed
Add escaping html restricted tokens and unit tests
1 parent 9ec34f8 commit b91c1a5

File tree

2 files changed

+121
-2
lines changed

2 files changed

+121
-2
lines changed

scala3doc/src/dotty/renderers/html.scala

+10-2
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,26 @@ object HTML:
2525
case t: AppliedTag =>
2626
sb.append(t)
2727
case s: String =>
28-
sb.append(s)
28+
sb.append(s.escapeReservedTokens)
2929
case s: Seq[AppliedTag | String] =>
3030
s.foreach{
3131
case a: AppliedTag =>
3232
sb.append(a)
3333
case s: String =>
34-
sb.append(s)
34+
sb.append(s.escapeReservedTokens)
3535
}
3636
}
3737
sb.append(s"</$name>")
3838
sb
3939
}
4040

41+
extension (s: String) private def escapeReservedTokens: String =
42+
s.replace("&", "&amp;")
43+
.replace("<", "&lt;")
44+
.replace(">", "&gt;")
45+
.replace("\"", "&quot;")
46+
.replace("'", "&apos;")
47+
4148
case class Attr(name: String):
4249
def :=(value: String): AppliedAttr = AppliedAttr(s"""$name="$value"""")
4350

@@ -48,6 +55,7 @@ object HTML:
4855
val div = Tag("div")
4956
val span = Tag("span")
5057
val a = Tag("a")
58+
val p = Tag("p")
5159
val h1 = Tag("h1")
5260
val h2 = Tag("h2")
5361
val h3 = Tag("h3")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package dotty.dokka.renderers
2+
3+
import org.junit.{Test, Rule}
4+
import org.junit.Assert.{assertSame, assertTrue, assertEquals}
5+
import dotty.dokka.HTML._
6+
7+
class HtmlTagsTest {
8+
9+
@Test
10+
def simpleDiv = {
11+
val actual = div().toString
12+
val expect = "<div></div>"
13+
assertEquals(expect, actual)
14+
}
15+
16+
@Test
17+
def divWithStyles = {
18+
val actual = div(style := "some: style;")().toString
19+
val expect = """<div style="some: style;"></div>"""
20+
assertEquals(expect, actual)
21+
}
22+
23+
@Test
24+
def divWithChildren = {
25+
val actual = div(h1(), span()).toString
26+
val expect = """<div><h1></h1><span></span></div>"""
27+
assertEquals(expect, actual)
28+
}
29+
30+
@Test
31+
def divWithTextInside = {
32+
val actual = div(h1(), span("Some text"), "Some more of the text").toString
33+
val expect = """<div><h1></h1><span>Some text</span>Some more of the text</div>"""
34+
assertEquals(expect, actual)
35+
}
36+
37+
@Test
38+
def escapeAmpersand = {
39+
val actual = div("Some & text").toString
40+
val expect = """<div>Some &amp; text</div>"""
41+
assertEquals(expect, actual)
42+
}
43+
44+
@Test
45+
def escapeLessThan = {
46+
val actual = div("Some < text").toString
47+
val expect = """<div>Some &lt; text</div>"""
48+
assertEquals(expect, actual)
49+
}
50+
51+
@Test
52+
def escapeGreaterThan = {
53+
val actual = div("Some > text").toString
54+
val expect = """<div>Some &gt; text</div>"""
55+
assertEquals(expect, actual)
56+
}
57+
58+
@Test
59+
def escapeQuotationMark = {
60+
val actual = div("Some \" text").toString
61+
val expect = """<div>Some &quot; text</div>"""
62+
assertEquals(expect, actual)
63+
}
64+
65+
@Test
66+
def escapeApostrophe = {
67+
val actual = div("Some ' text").toString
68+
val expect = """<div>Some &apos; text</div>"""
69+
assertEquals(expect, actual)
70+
}
71+
72+
@Test
73+
def nestedTagsWithAttributes = {
74+
val actual = html(
75+
head(
76+
script(src:="..."),
77+
script(raw("alert('Hello World')"))
78+
),
79+
body(
80+
div(
81+
h1(id:="title")("This is a title"),
82+
p("This is a big paragraph of text")
83+
)
84+
)
85+
).toString
86+
val expect = """<html><head><script src="..."></script><script>alert('Hello World')</script></head><body><div><h1 id="title">This is a title</h1><p>This is a big paragraph of text</p></div></body></html>"""
87+
assertEquals(expect, actual)
88+
}
89+
90+
@Test
91+
def anotherNestedTagsWithAttributes = {
92+
val actual = html(
93+
head(
94+
script("some script")
95+
),
96+
body(
97+
h1(style:="background-color: blue; color: red;")("This is my title"),
98+
div(style:="background-color: blue; color: red;")(
99+
p(cls :="contentpara first")(
100+
"This is my first paragraph"
101+
),
102+
a(style:="opacity: 0.9;")(
103+
p(cls := "contentpara")("Goooogle")
104+
)
105+
)
106+
)
107+
).toString
108+
val expect = """<html><head><script>some script</script></head><body><h1 style="background-color: blue; color: red;">This is my title</h1><div style="background-color: blue; color: red;"><p class="contentpara first">This is my first paragraph</p><a style="opacity: 0.9;"><p class="contentpara">Goooogle</p></a></div></body></html>"""
109+
assertEquals(expect, actual)
110+
}
111+
}

0 commit comments

Comments
 (0)