Skip to content

Commit 0946121

Browse files
authored
Merge pull request #10120 from BarkingBad/scalatags-test
Scalatags test
2 parents 1ab76c1 + 23a5127 commit 0946121

File tree

2 files changed

+208
-3
lines changed

2 files changed

+208
-3
lines changed

scala3doc/src/dotty/renderers/html.scala

+11-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ object HTML:
1414
def apply(attrs: AttrArg*)(tags: TagArg*): AppliedTag = {
1515
val sb = StringBuilder()
1616
sb.append(s"<$name")
17-
attrs.foreach{
17+
attrs.filter(_ != Nil).foreach{
1818
case s: Seq[AppliedAttr] =>
1919
s.foreach(sb.append(" ").append)
2020
case e: AppliedAttr =>
@@ -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,197 @@
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+
112+
@Test
113+
def appliedTagAndSeqAppliedTag = {
114+
val actual = div(h1("AppliedTag"), Seq(h1("SeqAppliedTag"))).toString
115+
val expect = """<div><h1>AppliedTag</h1><h1>SeqAppliedTag</h1></div>"""
116+
assertEquals(expect, actual)
117+
}
118+
119+
@Test
120+
def stringAndSeqString = {
121+
val actual = div("String", Seq("SeqString")).toString
122+
val expect = """<div>StringSeqString</div>"""
123+
assertEquals(expect, actual)
124+
}
125+
126+
@Test
127+
def mixingAllTagArgs = {
128+
val actual = div("String", Seq("SeqString"), h1("AppliedTag"), Seq(h1("SeqAppliedTag")), Seq("SeqString"), h1("AppliedTag")).toString
129+
val expect = """<div>StringSeqString<h1>AppliedTag</h1><h1>SeqAppliedTag</h1>SeqString<h1>AppliedTag</h1></div>"""
130+
assertEquals(expect, actual)
131+
}
132+
133+
@Test
134+
def appliedAttrAndSeqAppliedAttr = {
135+
val actual = div(cls := "someClass", Seq(style := "some: style;")).toString
136+
val expect = """<div class="someClass" style="some: style;"></div>"""
137+
assertEquals(expect, actual)
138+
}
139+
140+
@Test
141+
def seqAppliedAttrAndAppliedAttr = {
142+
val actual = div(Seq(cls := "someClass"), style := "some: style;").toString
143+
val expect = """<div class="someClass" style="some: style;"></div>"""
144+
assertEquals(expect, actual)
145+
}
146+
147+
@Test
148+
def seqAppliedAttrAndSeqAppliedAttr = {
149+
val actual = div(Seq(cls := "someClass"), Seq(style := "some: style;")).toString
150+
val expect = """<div class="someClass" style="some: style;"></div>"""
151+
assertEquals(expect, actual)
152+
}
153+
154+
@Test
155+
def mixingAllTagArgsAndAllAttrArgs = {
156+
val actual = div(Seq(cls := "someClass"), id := "myId", Seq(style := "some: style;"))("String", Seq("SeqString"), h1("AppliedTag"), Seq(h1("SeqAppliedTag")), Seq("SeqString"), h1("AppliedTag")).toString
157+
val expect = """<div class="someClass" id="myId" style="some: style;">StringSeqString<h1>AppliedTag</h1><h1>SeqAppliedTag</h1>SeqString<h1>AppliedTag</h1></div>"""
158+
assertEquals(expect, actual)
159+
}
160+
161+
@Test
162+
def nilTagArg = {
163+
val nil: TagArg = Nil
164+
val actual = div(nil).toString
165+
val expect = """<div></div>"""
166+
assertEquals(expect, actual)
167+
}
168+
169+
@Test
170+
def nilAttrArg = {
171+
val nil: AttrArg = Nil
172+
val actual = div(nil).toString
173+
val expect = """<div></div>"""
174+
assertEquals(expect, actual)
175+
}
176+
177+
@Test
178+
def nilAmongTags = {
179+
val actual = div("name", Nil, div("ala")).toString
180+
val expect = """<div>name<div>ala</div></div>"""
181+
assertEquals(expect, actual)
182+
}
183+
184+
@Test
185+
def nilAmongArgs = {
186+
val actual = div(cls := "someClass", Nil, style := "some: style;").toString
187+
val expect = """<div class="someClass" style="some: style;"></div>"""
188+
assertEquals(expect, actual)
189+
}
190+
191+
@Test
192+
def nilAmongArgsAndTags = {
193+
val actual = div(cls := "someClass", Nil, style := "some: style;")("name", Nil, div("ala")).toString
194+
val expect = """<div class="someClass" style="some: style;">name<div>ala</div></div>"""
195+
assertEquals(expect, actual)
196+
}
197+
}

0 commit comments

Comments
 (0)