Mentions are expanded in rendered Essay. Page title reflects Essay title.
This commit is contained in:
parent
ca02af4ea1
commit
f0152093e7
14 changed files with 151 additions and 56 deletions
7
pom.xml
7
pom.xml
|
@ -82,7 +82,7 @@
|
|||
<dependency>
|
||||
<groupId>owasp-java-html-sanitizer</groupId>
|
||||
<artifactId>owasp-java-html-sanitizer</artifactId>
|
||||
<version>r117</version>
|
||||
<version>r129</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
@ -143,5 +143,10 @@
|
|||
<artifactId>guava</artifactId>
|
||||
<version>13.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.moandjiezana.tent</groupId>
|
||||
<artifactId>tent-text</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -64,7 +64,7 @@ public class EssayServlet extends HttpServlet {
|
|||
Post post = tentClient.getPost(essayId);
|
||||
|
||||
EssayistPostContent essayContent = post.getContentAs(EssayistPostContent.class);
|
||||
essayContent.setBody(csrf.stripScripts(essayContent.getBody()));
|
||||
essayContent.setBody(csrf.permissive(essayContent.getBody()));
|
||||
|
||||
EssayPage essayPage = templates.essay();
|
||||
if (user.owns(post)) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.moandjiezana.tent.client.posts.PostQuery;
|
|||
import com.moandjiezana.tent.client.posts.content.EssayContent;
|
||||
import com.moandjiezana.tent.client.users.Permissions;
|
||||
import com.moandjiezana.tent.essayist.tent.Entities;
|
||||
import com.moandjiezana.tent.essayist.text.TextTransformation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
@ -18,18 +19,18 @@ import javax.servlet.http.HttpServlet;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.pegdown.PegDownProcessor;
|
||||
|
||||
@Singleton
|
||||
public class EssaysServlet extends HttpServlet {
|
||||
|
||||
private Templates templates;
|
||||
private Users users;
|
||||
private Provider<EssayistSession> sessions;
|
||||
private TextTransformation textTransformation;
|
||||
|
||||
@Inject
|
||||
public EssaysServlet(Users users, Templates templates, Provider<EssayistSession> sessions) {
|
||||
public EssaysServlet(Users users, TextTransformation textTransformation, Templates templates, Provider<EssayistSession> sessions) {
|
||||
this.users = users;
|
||||
this.textTransformation = textTransformation;
|
||||
this.templates = templates;
|
||||
this.sessions = sessions;
|
||||
}
|
||||
|
@ -62,7 +63,7 @@ public class EssaysServlet extends HttpServlet {
|
|||
post.setLicenses(new String[] { "http://creativecommons.org/licenses/by/3.0/" });
|
||||
EssayContent essay = new EssayContent();
|
||||
essay.setTitle(req.getParameter("title"));
|
||||
essay.setBody(new PegDownProcessor().markdownToHtml(req.getParameter("body")));
|
||||
essay.setBody(textTransformation.transformEssay(req.getParameter("body")));
|
||||
essay.setExcerpt(req.getParameter("excerpt"));
|
||||
post.setContent(essay);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.moandjiezana.tent.essayist;
|
|||
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.moandjiezana.tent.essayist.auth.Authenticated;
|
||||
import com.moandjiezana.tent.essayist.security.Csrf;
|
||||
import com.moandjiezana.tent.essayist.text.TextTransformation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -13,25 +13,22 @@ import javax.servlet.http.HttpServlet;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.pegdown.PegDownProcessor;
|
||||
|
||||
@Singleton
|
||||
@Authenticated
|
||||
public class PreviewServlet extends HttpServlet {
|
||||
|
||||
private final Csrf csrf;
|
||||
private final TextTransformation textTransformation;
|
||||
|
||||
@Inject
|
||||
public PreviewServlet(Csrf csrf) {
|
||||
this.csrf = csrf;
|
||||
public PreviewServlet(TextTransformation textTransformation) {
|
||||
this.textTransformation = textTransformation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String body = CharStreams.toString(req.getReader());
|
||||
String html = new PegDownProcessor().markdownToHtml(body);
|
||||
String sanitized = csrf.stripScripts(html);
|
||||
String essay = textTransformation.transformEssay(body);
|
||||
|
||||
resp.getWriter().write(sanitized);
|
||||
resp.getWriter().write(essay);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.moandjiezana.tent.client.users.Permissions;
|
|||
import com.moandjiezana.tent.essayist.auth.Authenticated;
|
||||
import com.moandjiezana.tent.essayist.config.Routes;
|
||||
import com.moandjiezana.tent.essayist.tent.Entities;
|
||||
import com.moandjiezana.tent.essayist.text.TextTransformation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
@ -23,8 +24,6 @@ import javax.servlet.http.HttpServlet;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.pegdown.PegDownProcessor;
|
||||
|
||||
@Singleton
|
||||
@Authenticated
|
||||
public class WriteServlet extends HttpServlet {
|
||||
|
@ -33,9 +32,11 @@ public class WriteServlet extends HttpServlet {
|
|||
private Provider<EssayistSession> sessions;
|
||||
private Tasks tasks;
|
||||
private Provider<Routes> routes;
|
||||
private TextTransformation textTransformation;
|
||||
|
||||
@Inject
|
||||
public WriteServlet(Provider<EssayistSession> sessions, Templates templates, Provider<Routes> routes, Tasks tasks) {
|
||||
public WriteServlet(TextTransformation textTransformation, Provider<EssayistSession> sessions, Templates templates, Provider<Routes> routes, Tasks tasks) {
|
||||
this.textTransformation = textTransformation;
|
||||
this.sessions = sessions;
|
||||
this.templates = templates;
|
||||
this.routes = routes;
|
||||
|
@ -71,7 +72,7 @@ public class WriteServlet extends HttpServlet {
|
|||
EssayContent essay = new EssayContent();
|
||||
essay.setTitle(req.getParameter("title"));
|
||||
final String body = req.getParameter("body");
|
||||
essay.setBody(new PegDownProcessor().markdownToHtml(body));
|
||||
essay.setBody(textTransformation.transformEssay(body));
|
||||
essay.setExcerpt(req.getParameter("excerpt"));
|
||||
post.setContent(essay);
|
||||
|
||||
|
@ -89,27 +90,11 @@ public class WriteServlet extends HttpServlet {
|
|||
tentClient.write(metadataPost);
|
||||
|
||||
resp.sendRedirect(req.getContextPath() + "/" + Entities.getForUrl(tentClient.getProfile().getCore().getEntity()) + "/essay/" + newPost.getId());
|
||||
|
||||
// tasks.run(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// } else {
|
||||
// Post originalPost = posts.get(0);
|
||||
//
|
||||
// Post newPost = newPost();
|
||||
//
|
||||
// EssayistMetadataContent content = originalPost.getContentAs(EssayistMetadataContent.class);
|
||||
// content.setRaw(body);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
TentClient tentClient = newTentClient();
|
||||
// List<Post> posts = tentClient.getPosts(new PostQuery().mentionedPost(essayId).postTypes(EssayistMetadataContent.URI));
|
||||
|
||||
String essayId = req.getPathInfo().substring(1);
|
||||
Post post = newPost();
|
||||
|
@ -118,7 +103,7 @@ public class WriteServlet extends HttpServlet {
|
|||
EssayContent essay = new EssayContent();
|
||||
essay.setTitle(req.getParameter("title"));
|
||||
final String body = req.getParameter("body");
|
||||
essay.setBody(new PegDownProcessor().markdownToHtml(body));
|
||||
essay.setBody(textTransformation.transformEssay(body));
|
||||
essay.setExcerpt(req.getParameter("excerpt"));
|
||||
post.setContent(essay);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.moandjiezana.tent.client.users.Profile;
|
|||
import com.moandjiezana.tent.essayist.EssayistSession;
|
||||
import com.moandjiezana.tent.essayist.User;
|
||||
import com.moandjiezana.tent.essayist.security.Csrf;
|
||||
import com.moandjiezana.tent.essayist.text.TextTransformation;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -16,14 +17,16 @@ public class JamonContext {
|
|||
public final String contextPath;
|
||||
public final Routes routes;
|
||||
public final Csrf csrf = new Csrf();
|
||||
public final TextTransformation textTransformation;
|
||||
|
||||
private final HttpServletRequest req;
|
||||
public final String currentUrl;
|
||||
private final EssayistSession session;
|
||||
|
||||
@Inject
|
||||
public JamonContext(EssayistSession session, Routes routes, HttpServletRequest req) {
|
||||
public JamonContext(EssayistSession session, TextTransformation textTransformation, Routes routes, HttpServletRequest req) {
|
||||
this.session = session;
|
||||
this.textTransformation = textTransformation;
|
||||
this.routes = routes;
|
||||
this.req = req;
|
||||
this.contextPath = req.getContextPath();
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.moandjiezana.tent.essayist.security;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.owasp.html.HtmlPolicyBuilder;
|
||||
import org.owasp.html.PolicyFactory;
|
||||
|
||||
@Singleton
|
||||
public class Csrf {
|
||||
|
@ -13,12 +14,21 @@ public class Csrf {
|
|||
.allowStandardUrlProtocols()
|
||||
.allowStyling()
|
||||
.allowElements("iframe", "img", "a", "table", "thead", "tbody", "tr", "th", "td", "em")
|
||||
.allowAttributes("width", "height", "title").globally()
|
||||
.allowAttributes("width", "height", "title", "class").globally()
|
||||
.allowAttributes("src", "frameborder", "webkitAllowFullScreen", "mozallowfullscreen", "allowFullScreen").onElements("iframe")
|
||||
.allowAttributes("src", "alt").onElements("img")
|
||||
.allowAttributes("href").onElements("a");
|
||||
.allowAttributes("href", "rel").onElements("a");
|
||||
|
||||
private final PolicyFactory restrictive = new HtmlPolicyBuilder()
|
||||
.allowStandardUrlProtocols()
|
||||
.allowElements("a")
|
||||
.allowAttributes("href", "class", "rel").onElements("a").toFactory();
|
||||
|
||||
public String stripScripts(String html) {
|
||||
public String permissive(String html) {
|
||||
return allowScripts.toFactory().sanitize(html);
|
||||
}
|
||||
|
||||
public String restrictive(String html) {
|
||||
return restrictive.sanitize(html);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package com.moandjiezana.tent.essayist.text;
|
||||
|
||||
import com.moandjiezana.tent.essayist.security.Csrf;
|
||||
import com.moandjiezana.tent.text.Autolink;
|
||||
import com.moandjiezana.tent.text.Extractor.Entity;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.pegdown.PegDownProcessor;
|
||||
|
||||
@Singleton
|
||||
public class TextTransformation {
|
||||
|
||||
private final Csrf csrf;
|
||||
private final Autolink essayAutolink = new Autolink();
|
||||
private final Autolink commentAutolink = new Autolink();
|
||||
|
||||
@Inject
|
||||
public TextTransformation(Csrf csrf) {
|
||||
this.csrf = csrf;
|
||||
essayAutolink.setMentionIncludeSymbol(true);
|
||||
Autolink.LinkTextModifier linkTextModifier = new Autolink.LinkTextModifier() {
|
||||
@Override
|
||||
public CharSequence modify(Entity entity, CharSequence text) {
|
||||
if (text.charAt(0) == '^') {
|
||||
return text.subSequence(1, text.length());
|
||||
}
|
||||
return text;
|
||||
}
|
||||
};
|
||||
essayAutolink.setLinkTextModifier(linkTextModifier);
|
||||
essayAutolink.setMentionClass("label label-inverse");
|
||||
|
||||
commentAutolink.setMentionIncludeSymbol(true);
|
||||
commentAutolink.setLinkTextModifier(linkTextModifier);
|
||||
commentAutolink.setMentionClass("label label-inverse");
|
||||
}
|
||||
|
||||
public String transformEssay(String text) {
|
||||
essayAutolink.setNoFollow(false);
|
||||
String autoLinked = essayAutolink.autoLinkHashtags(essayAutolink.autoLinkMentionsAndLists(text));
|
||||
|
||||
String html = new PegDownProcessor().markdownToHtml(autoLinked);
|
||||
String sanitized = csrf.permissive(html);
|
||||
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
public Object transformComment(String comment) {
|
||||
return csrf.restrictive(commentAutolink.autoLink(comment));
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ final EssayContent content = essay.getContentAs(EssayContent.class);
|
|||
final SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
|
||||
final SimpleDateFormat dateTimeFormat = new SimpleDateFormat("dd MMMM yyyy HH:mm ZZZZ");
|
||||
</%java>
|
||||
<&| Layout; active = active &>
|
||||
<&| Layout; active = active; title = Entities.essayTitle(content) &>
|
||||
<& partials/Essay; essay=essay; entityForUrl=Entities.getForUrl(essay.getEntity()); entityName=Entities.getName(profile); essayId=essay.getId(); formattedPublicationDate=dateFormat.format(new Date(essay.getPublishedAt() * 1000)); display=true; &>
|
||||
|
||||
<& partials/Reactions; reactions=reactions; essay=essay; autoLoad=true; &>
|
||||
|
|
|
@ -8,6 +8,7 @@ com.moandjiezana.tent.essayist.config.*;
|
|||
<%args>
|
||||
boolean showNav = true;
|
||||
String active = null;
|
||||
String title = "Essayist";
|
||||
</%args>
|
||||
|
||||
<%def navItem>
|
||||
|
@ -21,7 +22,7 @@ String url;
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<title>Essayist</title>
|
||||
<title><% title %></title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ String formattedDate = dateTimeFormat.format(new Date(reaction.getPublishedAt()
|
|||
<%if Post.Types.equalsIgnoreVersion(Post.Types.status("v0.1.0"), reaction.getType()) %>
|
||||
<i class="icon-comment"></i> <a href="<% reaction.getEntity() %>"><% displayEntity %></a> commented <small class="muted"><% formattedDate %></small><br/>
|
||||
<p>
|
||||
<% reaction.getContentAs(StatusContent.class).getText() %>
|
||||
<% jamonContext.textTransformation.transformComment(reaction.getContentAs(StatusContent.class).getText()) #n %>
|
||||
</p>
|
||||
<%elseif Post.Types.equalsIgnoreVersion(Favorite.URI, reaction.getType()) %>
|
||||
<i class="icon-star"></i> Favourited by <a href="<% reaction.getEntity() %>"><% displayEntity %></a> <small class="muted"><% formattedDate %></small>
|
||||
|
|
|
@ -2,11 +2,15 @@ function initNavigation() {
|
|||
var essayContainers = document.querySelectorAll("[data-essay=container]");
|
||||
var i;
|
||||
|
||||
var displaySection = function (section, target) {
|
||||
var displaySection = function (section, target, title) {
|
||||
var j;
|
||||
var detailDisplay = section === "essay" ? "block" : "none";
|
||||
var listDisplay = section === "list" ? "block" : "none";
|
||||
|
||||
if (title !== undefined) {
|
||||
document.title = title;
|
||||
}
|
||||
|
||||
if (target !== document) {
|
||||
target.querySelector("[data-essay=summary]").style.display = listDisplay;
|
||||
target.querySelector("[data-essay=full]").style.display = detailDisplay;
|
||||
|
@ -46,12 +50,12 @@ function initNavigation() {
|
|||
}
|
||||
|
||||
var scrollPosition = document.body.scrollTop;
|
||||
displaySection("essay", event.currentTarget);
|
||||
displaySection("essay", event.currentTarget, event.target.text);
|
||||
|
||||
var reactionsContainer = container.querySelector('[data-essay="reactions"]');
|
||||
fetchReactions(reactionsContainer);
|
||||
|
||||
history.pushState({ essayId: event.currentTarget.dataset.essayId, essayAuthor: event.currentTarget.dataset.essayAuthor, scrollPosition: scrollPosition }, "essay title", event.target.href);
|
||||
history.pushState({ essayId: event.currentTarget.dataset.essayId, essayAuthor: event.currentTarget.dataset.essayAuthor, essayTitle: event.target.text, scrollPosition: scrollPosition }, "essay title", event.target.href);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
@ -59,11 +63,10 @@ function initNavigation() {
|
|||
var essayPopStateHandler = function (event) {
|
||||
var essayContainer;
|
||||
if (window.location.href.indexOf("/essays") > -1 || window.location.href.indexOf("/global") > -1 || window.location.href.indexOf("/read") > -1) {
|
||||
displaySection("list", document);
|
||||
window.scrollTo(0);
|
||||
displaySection("list", document, "Essayist");
|
||||
} else if (event.state !== null) {
|
||||
essayContainer = document.querySelector("[data-essay-author=\"" + event.state.essayAuthor + "\"][data-essay-id=\"" + event.state.essayId + "\"]");
|
||||
displaySection("essay", essayContainer);
|
||||
displaySection("essay", essayContainer, event.state.essayTitle);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -8,14 +8,14 @@ public class CsrfTest {
|
|||
|
||||
@Test
|
||||
public void should_remove_external_scripts() {
|
||||
String sanitized = new Csrf().stripScripts("<h1>title</h1><script src=\"other.js\"></script><h3>sub-title</h3><div>Some text</div><p>Some more text</p>");
|
||||
String sanitized = new Csrf().permissive("<h1>title</h1><script src=\"other.js\"></script><h3>sub-title</h3><div>Some text</div><p>Some more text</p>");
|
||||
|
||||
assertEquals("<h1>title</h1><h3>sub-title</h3><div>Some text</div><p>Some more text</p>", sanitized);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_remove_internal_scripts() {
|
||||
String sanitized = new Csrf().stripScripts("<h1>title</h1><script>alert('hello')</script><h3>sub-title</h3><div>Some text</div><p>Some more text</p>");
|
||||
String sanitized = new Csrf().permissive("<h1>title</h1><script>alert('hello')</script><h3>sub-title</h3><div>Some text</div><p>Some more text</p>");
|
||||
|
||||
assertEquals("<h1>title</h1><h3>sub-title</h3><div>Some text</div><p>Some more text</p>", sanitized);
|
||||
}
|
||||
|
@ -24,14 +24,14 @@ public class CsrfTest {
|
|||
public void should_allow_images() {
|
||||
String img = "<img src=\"http://f.cl.ly/items/2o2H0a193B2U3i0c3S0j/Untitled.png\" alt=\"The Magazine\" title=\"The Magazine\" height=\"100\" width=\"100\" />";
|
||||
|
||||
assertEquals(img, new Csrf().stripScripts(img));
|
||||
assertEquals(img, new Csrf().permissive(img));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_allow_links() {
|
||||
String link = "<a href=\"http://scriptogr.am/ovanrijswijk\" title=\"title\">Oskar van Rijswijk</a>";
|
||||
|
||||
assertEquals(link, new Csrf().stripScripts(link));
|
||||
assertEquals(link, new Csrf().permissive(link));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -39,20 +39,27 @@ public class CsrfTest {
|
|||
String vimeoEmbed = "<p><iframe src=\"http://player.vimeo.com/video/51827660?title=0&byline=0&portrait=0&color=08452f\" width=\"720\" height=\"527\" frameborder=\"0\" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe> <p>An excerpt from a three screen triptych which is a part of a bigger installation.<br /> Sound, photography & video by Einat Schlagmann.</p></p>";
|
||||
String expected = "<p><iframe src=\"http://player.vimeo.com/video/51827660?title=0&byline=0&portrait=0&color=08452f\" width=\"720\" height=\"527\" frameborder=\"0\" webkitallowfullscreen=\"webkitallowfullscreen\" mozallowfullscreen=\"mozallowfullscreen\" allowfullscreen=\"allowfullscreen\"></iframe> </p><p>An excerpt from a three screen triptych which is a part of a bigger installation.<br /> Sound, photography & video by Einat Schlagmann.</p>";
|
||||
|
||||
assertEquals(expected, new Csrf().stripScripts(vimeoEmbed));
|
||||
assertEquals(expected, new Csrf().permissive(vimeoEmbed));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_allow_tables() {
|
||||
String table = "<table><thead><th>header</th></thead><tbody><tr><td>cell</td></tr></tbody></table>";
|
||||
|
||||
assertEquals(table, new Csrf().stripScripts(table));
|
||||
assertEquals(table, new Csrf().permissive(table));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_allow_emphasis() {
|
||||
String emphasis = "<em>emphas</em>ised";
|
||||
|
||||
assertEquals(emphasis, new Csrf().stripScripts(emphasis));
|
||||
assertEquals(emphasis, new Csrf().permissive(emphasis));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictive_should_only_allow_links() {
|
||||
String html = "<a href=\"https://link.tent.is\" class=\"my-class\" rel=\"nofollow\">link</a> <em>emphasis</em> <b>bold</b>";
|
||||
|
||||
assertEquals("<a href=\"https://link.tent.is\" class=\"my-class\" rel=\"nofollow\">link</a> emphasis bold", new Csrf().restrictive(html));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package com.moandjiezana.tent.essayist.text;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import com.moandjiezana.tent.essayist.security.Csrf;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TextTransformationTest {
|
||||
|
||||
private final TextTransformation textTransformation = new TextTransformation(new Csrf());
|
||||
|
||||
@Test
|
||||
public void should_expand_markdown_and_all_entities_in_essay() {
|
||||
String text = "[Link](http://www.example.com) by ^mention is #good!";
|
||||
|
||||
String expected = "<p><a href=\"http://www.example.com\">Link</a> by <a class=\"label label-inverse\" href=\"https://mention.tent.is\">mention</a> is <a href=\"https://skate.io/search?q=%23good\" title=\"#good\" class=\"hashtag\">#good</a>!</p>";
|
||||
|
||||
assertEquals(expected, textTransformation.transformEssay(text));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_expand_all_entities_in_comment() {
|
||||
String comment = "Hey ^somerandombloke, have you seen https://github.com/tent/tent.io/wiki/Explaining-Tent ?";
|
||||
|
||||
String expected = "Hey <a class=\"label label-inverse\" href=\"https://somerandombloke.tent.is\" rel=\"nofollow\">somerandombloke</a>, have you seen <a href=\"https://github.com/tent/tent.io/wiki/Explaining-Tent\" rel=\"nofollow\">https://github.com/tent/tent.io/wiki/Explaining-Tent</a> ?";
|
||||
|
||||
assertEquals(expected, textTransformation.transformComment(comment));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue