companion object {
private val loadedImageTemplate = """<%include linked/image.html>""".parse()
+ private val loadedHtmlPageTemplate = """<%include linked/html-page.html>""".parse()
private val notLoadedImageTemplate = """<%include linked/notLoaded.html>""".parse()
private fun String.parse() = StringReader(this).use { TemplateParser.parse(it) }!!
override fun format(templateContext: TemplateContext?, data: Any?, parameters: Map<String, Any?>?) =
when {
data is LinkedElement && data.loading -> renderNotLoadedLinkedElement(data)
- data is LinkedElement -> renderLinkedImage(data)
+ data is LinkedElement && data.properties["type"] == "image" -> renderLinkedImage(data)
+ data is LinkedElement && data.properties["type"] == "html" -> renderHtmlPage(data)
else -> null
}
it
}.toString()
+ private fun renderHtmlPage(linkedElement: LinkedElement) =
+ StringWriter().use {
+ val templateContext = templateContextFactory.createTemplateContext()
+ templateContext["link"] = linkedElement.link
+ templateContext["title"] = linkedElement.properties["title"] ?: "No title"
+ templateContext["description"] = linkedElement.properties["description"] ?: "No description"
+ it.also { loadedHtmlPageTemplate.render(templateContext, it) }
+ }.toString()
+
private fun renderNotLoadedLinkedElement(linkedElement: LinkedElement) =
StringWriter().use {
val templateContext = templateContextFactory.createTemplateContext()
margin-top: 1ex;
}
-#sone .post .linked-element.loaded .image {
+#sone .linked-element.loaded .image {
display: inline-block;
border: solid 1px black;
width: 160px;
margin-bottom: 1ex;
}
+#sone .linked-element.loaded .html-page {
+ display: inline-block;
+ width: 160px;
+ max-height: 120px;
+ overflow: hidden;
+ vertical-align: top;
+}
+
+#sone .reply .linked-element.loaded .html-page {
+ width: 120px;
+ max-height: 90px;
+}
+
+#sone .linked-element.loaded .html-page .heading {
+ font-size: 125%;
+ font-weight: 600;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+#sone .linked-element.loaded .html-page {
+ display: inline-block;
+}
+
#sone .post .replies {
clear: both;
padding-top: 0.2ex;
});
if (failedElements.length > 0) {
failedElements.forEach(function(element) {
- $(getLinkedElement(element.link)).remove()
+ getLinkedElements(element.link).each(function() {
+ $(this).remove()
+ });
});
}
var loadedElements = links.filter(function(element) {
}, function (data, textStatus) {
if ((data != null) && (data.success)) {
data.linkedElements.forEach(function (linkedElement) {
- $(getLinkedElement(linkedElement.link)).replaceWith(linkedElement.html);
+ getLinkedElements(linkedElement.link).each(function() {
+ $(this).replaceWith(linkedElement.html);
+ });
});
}
});
}
}
-function getLinkedElement(link) {
- return $(".linked-element[title='" + link + "']")[0]
+function getLinkedElements(link) {
+ return $(".linked-element[title='" + link + "']")
}
/**
--- /dev/null
+<span class="linked-element loaded" title="<%link|html>">
+ <a class="html-page" href="/<% link|html>">
+ <div class="heading"><% title|html></div>
+ <div class="description"><% description|html></div>
+ </a>
+</span>
import net.pterodactylus.util.template.TemplateContextFactory
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.`is`
+import org.hamcrest.Matchers.contains
+import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.notNullValue
import org.hamcrest.Matchers.nullValue
import org.jsoup.Jsoup
+import org.jsoup.nodes.Element
import org.junit.Test
/**
@Test
fun `filter can render linked images`() {
- val html = filter.format(null, LinkedElement("KSK@gpl.png"), emptyMap<String, Any?>()) as String
+ val html = filter.format(null, LinkedElement("KSK@gpl.png", properties = mapOf("type" to "image")), emptyMap<String, Any?>()) as String
val outerSpanNode = Jsoup.parseBodyFragment(html).body().child(0)
assertThat(outerSpanNode.nodeName(), `is`("span"))
assertThat(outerSpanNode.attr("class"), `is`("linked-element loaded"))
}
@Test
+ fun `filter can render HTML pages`() {
+ val html = filter.format(null, LinkedElement("KSK@gpl.html", properties = mapOf("type" to "html", "title" to "Page Title", "description" to "This is the description.")), emptyMap<String, Any?>()) as String
+ val outerSpanNode = Jsoup.parseBodyFragment(html).body().child(0)
+ assertThat(outerSpanNode.nodeName(), equalTo("span"))
+ assertThat(outerSpanNode.attr("class"), `is`("linked-element loaded"))
+ assertThat(outerSpanNode.attr("title"), `is`("KSK@gpl.html"))
+ val linkNode = outerSpanNode.child(0)
+ assertThat(linkNode.nodeName(), equalTo("a"))
+ assertThat(linkNode.attr("href"), equalTo("/KSK@gpl.html"))
+ val divNodes = linkNode.children()
+ assertThat(divNodes.map(Element::nodeName), contains("div", "div"))
+ assertThat(divNodes.map { it.attr("class") }, contains("heading", "description"))
+ assertThat(divNodes.map(Element::text), contains("Page Title", "This is the description."))
+ }
+
+ @Test
fun `render filter can be created by guice`() {
- val injector = Guice.createInjector(TemplateContextFactory::class.isProvidedByMock())
+ val injector = Guice.createInjector(TemplateContextFactory::class.isProvidedByMock())
assertThat(injector.getInstance<LinkedElementRenderFilter>(), notNullValue())
}