aboutsummaryrefslogtreecommitdiff
path: root/juick-www/src
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2016-08-26 14:13:37 +0300
committerGravatar Vitaly Takmazov2016-08-30 10:52:51 +0300
commit6ea4235635c296991bbae3689d0b7dd735b17480 (patch)
tree33e5e931ea7638ef248c6413d41fcdc8bef0ee22 /juick-www/src
parent05b8019ab6dece881fb6a282c1bd50ff5ba22b69 (diff)
pebble WIP
Diffstat (limited to 'juick-www/src')
-rw-r--r--juick-www/src/main/java/com/juick/www/Main.java8
-rw-r--r--juick-www/src/main/java/com/juick/www/PM.java67
-rw-r--r--juick-www/src/main/java/com/juick/www/PageTemplates.java98
-rw-r--r--juick-www/src/main/java/com/juick/www/RSS.java2
-rw-r--r--juick-www/src/main/java/com/juick/www/UserThread.java9
-rw-r--r--juick-www/src/main/java/com/juick/www/Utils.java100
-rw-r--r--juick-www/src/main/resources/layouts/content.html29
-rw-r--r--juick-www/src/main/resources/views/partial/homecolumn.html6
-rw-r--r--juick-www/src/main/resources/views/partial/navigation.html37
-rw-r--r--juick-www/src/main/resources/views/partial/tags.html7
-rw-r--r--juick-www/src/main/resources/views/pm_inbox.html36
11 files changed, 244 insertions, 155 deletions
diff --git a/juick-www/src/main/java/com/juick/www/Main.java b/juick-www/src/main/java/com/juick/www/Main.java
index c249995f..1e755ca3 100644
--- a/juick-www/src/main/java/com/juick/www/Main.java
+++ b/juick-www/src/main/java/com/juick/www/Main.java
@@ -21,6 +21,7 @@ import com.juick.server.UserQueries;
import com.juick.xmpp.JID;
import com.juick.xmpp.Stream;
import com.juick.xmpp.StreamComponent;
+import com.mitchellbosecke.pebble.error.PebbleException;
import net.jodah.failsafe.Execution;
import net.jodah.failsafe.RetryPolicy;
import org.apache.commons.dbcp2.BasicDataSource;
@@ -181,7 +182,12 @@ public class Main extends HttpServlet implements Stream.StreamListener {
} else {
switch (uri) {
case "/pm/inbox":
- pm.doGetInbox(sql, request, response, visitor);
+ try {
+ pm.doGetInbox(sql, request, response, visitor);
+ } catch (PebbleException e) {
+ log("pebble exception", e);
+ response.sendError(500);
+ }
break;
case "/pm/sent":
pm.doGetSent(sql, request, response, visitor);
diff --git a/juick-www/src/main/java/com/juick/www/PM.java b/juick-www/src/main/java/com/juick/www/PM.java
index 9d7da65b..ac2cbb76 100644
--- a/juick-www/src/main/java/com/juick/www/PM.java
+++ b/juick-www/src/main/java/com/juick/www/PM.java
@@ -18,11 +18,14 @@
package com.juick.www;
import com.juick.server.PMQueries;
+import com.juick.server.TagQueries;
import com.juick.server.UserQueries;
import com.juick.xmpp.JID;
import com.juick.xmpp.Message;
import com.juick.xmpp.Stream;
import com.juick.xmpp.extensions.JuickMessage;
+import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.template.PebbleTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.servlet.ServletException;
@@ -30,7 +33,9 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -41,64 +46,20 @@ import java.util.logging.Logger;
public class PM {
private static final Logger logger = Logger.getLogger(PM.class.getName());
- protected void doGetInbox(JdbcTemplate sql, HttpServletRequest request, HttpServletResponse response, com.juick.User visitor) throws ServletException, IOException {
- /*
- int paramBefore = 0;
- String paramBeforeStr = request.getParameter("before");
- if (paramBeforeStr != null) {
- try {
- paramBefore = Integer.parseInt(paramBeforeStr);
- } catch (NumberFormatException e) {
- }
- }
- */
+ protected void doGetInbox(JdbcTemplate sql, HttpServletRequest request, HttpServletResponse response, com.juick.User visitor) throws ServletException, IOException, PebbleException {
String title = "PM: Inbox";
List<com.juick.Message> msgs = PMQueries.getLastPMInbox(sql, visitor.getUID());
response.setContentType("text/html; charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
- PageTemplates.pageHead(out, visitor, title, null);
- PageTemplates.pageNavigation(out, visitor, null);
-
- out.println("<section id=\"content\">");
-
- if (!msgs.isEmpty()) {
- out.println("<ul id=\"private-messages\">");
- for (com.juick.Message msg : msgs) {
-
- String txt = PageTemplates.formatMessage(msg.getText());
-
- out.println(" <li class=\"msg\">");
- out.println(" <div class=\"msg-cont\">");
- out.println(" <div class=\"msg-ts\"><a href=\"#\" onclick=\"return false\" title=\"" + PageTemplates.sdfSQL.format(msg.getDate()) + " GMT\">" + PageTemplates.formatDate(msg.TimeAgo, msg.getDate()) + "</a></div>");
- out.println(" <div class=\"msg-avatar\"><a href=\"/" + msg.getUser().getUName() + "/\"><img src=\"//i.juick.com/a/" + msg.getUser().getUID() + ".png\" alt=\"" + msg.getUser().getUName() + "\"/></a></div>");
- out.println(" <div class=\"msg-header\">@<a href=\"/" + msg.getUser().getUName() + "/\">" + msg.getUser().getUName() + "</a>:</div>");
- out.println(" <div class=\"msg-txt\">" + txt + "</div>");
-
- out.println(" <form action=\"/pm/send\" method=\"POST\" enctype=\"multipart/form-data\"><input type=\"hidden\" name=\"uname\" value=\"" + msg.getUser().getUName() + "\"/>");
- out.println(" <div class=\"msg-comment\"><div class=\"ta-wrapper\"><textarea name=\"body\" rows=\"1\" class=\"replypm\" placeholder=\"Написать ответ\"></textarea></div></div>");
- out.println(" </form>");
-
- out.println(" </div>");
- out.println(" </li>");
- }
- out.println("</ul>");
- }
-
- /*
- if (msgs.size() >= 20) {
- String nextpage = "?before=" + msgs.get(msgs.size() - 1);
- out.println("<p class=\"page\"><a href=\"" + nextpage + "\">Читать дальше →</a></p>");
- }
- */
-
- out.println("</section>");
-
- PageTemplates.pageHomeColumn(out, sql, visitor);
-
- PageTemplates.pageFooter(request, out, visitor, false);
- PageTemplates.pageEnd(out);
+ PebbleTemplate template = Utils.getEngine().getTemplate("views/pm_inbox.html");
+ Map<String, Object> context = new HashMap<>();
+ context.put("title", title);
+ context.put("visitor", visitor);
+ context.put("msgs", msgs);
+ context.put("tags", TagQueries.getPopularTags(sql));
+ template.evaluate(out, context);
}
}
@@ -142,7 +103,7 @@ public class PM {
out.println("<ul>");
for (com.juick.Message msg : msgs) {
- String txt = PageTemplates.formatMessage(msg.getText());
+ String txt = Utils.formatMessage(msg.getText());
out.println(" <li class=\"msg\">");
out.println(" <div class=\"msg-avatar\"><img src=\"//i.juick.com/a/" + visitor.getUID() + ".png\"/></div>");
diff --git a/juick-www/src/main/java/com/juick/www/PageTemplates.java b/juick-www/src/main/java/com/juick/www/PageTemplates.java
index 0cdf2184..c3b0d6f8 100644
--- a/juick-www/src/main/java/com/juick/www/PageTemplates.java
+++ b/juick-www/src/main/java/com/juick/www/PageTemplates.java
@@ -23,6 +23,7 @@ import com.juick.server.MessagesQueries;
import com.juick.server.TagQueries;
import com.juick.server.UserQueries;
import org.apache.commons.lang3.StringEscapeUtils;
+import com.mitchellbosecke.pebble.PebbleEngine;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StringUtils;
import ru.sape.Sape;
@@ -279,99 +280,6 @@ public class PageTemplates {
return replies + " ответов";
}
}
- private static Pattern regexLinks2 = Pattern.compile("((?<=\\s)|(?<=\\A))([\\[\\{]|&lt;)((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\\"\\)\\!]+)/?(?:[^\\]\\}](?<!&gt;))*)([\\]\\}]|&gt;)");
-
- public static String formatMessageCode(String msg) {
- msg = msg.replaceAll("&", "&amp;");
- msg = msg.replaceAll("<", "&lt;");
- msg = msg.replaceAll(">", "&gt;");
-
- // http://juick.com/last?page=2
- // <a href="http://juick.com/last?page=2" rel="nofollow">http://juick.com/last?page=2</a>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A))((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\n\\\"]+)/?[^\\s\\n\\\"]*)", "$1<a href=\"$2\" rel=\"nofollow\">$2</a>");
-
- // (http://juick.com/last?page=2)
- // (<a href="http://juick.com/last?page=2" rel="nofollow">http://juick.com/last?page=2</a>)
- Matcher m = regexLinks2.matcher(msg);
- StringBuffer sb = new StringBuffer();
- while (m.find()) {
- String url = m.group(3).replace(" ", "%20").replaceAll("\\s+", "");
- m.appendReplacement(sb, "$1$2<a href=\"" + url + "\" rel=\"nofollow\">" + url + "</a>$5");
- }
- m.appendTail(sb);
- msg = sb.toString();
-
- return "<pre>" + msg + "</pre>";
- }
-
- public static String formatMessage(String msg) {
- msg = msg.replaceAll("&", "&amp;");
- msg = msg.replaceAll("<", "&lt;");
- msg = msg.replaceAll(">", "&gt;");
-
- // --
- // &mdash;
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A))\\-\\-?((?=\\s)|(?=\\Z))", "$1&mdash;$2");
-
- // http://juick.com/last?page=2
- // <a href="http://juick.com/last?page=2" rel="nofollow">juick.com</a>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A))((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\n\\\"]+)/?[^\\s\\n\\\"]*)", "$1<a href=\"$2\" rel=\"nofollow\">$3</a>");
-
- // [link text][http://juick.com/last?page=2]
- // <a href="http://juick.com/last?page=2" rel="nofollow">link text</a>
- msg = msg.replaceAll("\\[([^\\]]+)\\]\\[((?:ht|f)tps?://[^\\]]+)\\]", "<a href=\"$2\" rel=\"nofollow\">$1</a>");
- msg = msg.replaceAll("\\[([^\\]]+)\\]\\(((?:ht|f)tps?://[^\\)]+)\\)", "<a href=\"$2\" rel=\"nofollow\">$1</a>");
-
- // #12345
- // <a href="http://juick.com/12345">#12345</a>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))#(\\d+)((?=\\s)|(?=\\Z)|(?=\\))|(?=\\.)|(?=\\,))", "$1<a href=\"http://juick.com/$2\">#$2</a>$3");
-
- // #12345/65
- // <a href="http://juick.com/12345#65">#12345/65</a>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))#(\\d+)/(\\d+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<a href=\"http://juick.com/$2#$3\">#$2/$3</a>$4");
-
- // *bold*
- // <b>bold</b>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))\\*([^\\*\\n<>]+)\\*((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<b>$2</b>$3");
-
- // /italic/
- // <i>italic</i>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A))/([^\\/\\n<>]+)/((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<i>$2</i>$3");
-
- // _underline_
- // <span class="u">underline</span>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A))_([^\\_\\n<>]+)_((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<span class=\"u\">$2</span>$3");
-
- // /12
- // <a href="#12">/12</a>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A))\\/(\\d+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<a href=\"#$2\">/$2</a>$3");
-
- // @username@jabber.org
- // <a href="http://juick.com/username@jabber.org/">@username@jabber.org</a>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A))@([\\w\\-\\.]+@[\\w\\-\\.]+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<a href=\"http://juick.com/$2/\">@$2</a>$3");
-
- // @username
- // <a href="http://juick.com/username/">@username</a>
- msg = msg.replaceAll("((?<=\\s)|(?<=\\A))@([\\w\\-]{2,16})((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<a href=\"http://juick.com/$2/\">@$2</a>$3");
-
- // (http://juick.com/last?page=2)
- // (<a href="http://juick.com/last?page=2" rel="nofollow">juick.com</a>)
- Matcher m = regexLinks2.matcher(msg);
- StringBuffer sb = new StringBuffer();
- while (m.find()) {
- String url = m.group(3).replace(" ", "%20").replaceAll("\\s+", "");
- m.appendReplacement(sb, "$1$2<a href=\"" + url + "\" rel=\"nofollow\">$4</a>$5");
- }
- m.appendTail(sb);
- msg = sb.toString();
-
- // > citate
- msg = msg.replaceAll("(?:(?<=\\n)|(?<=\\A))&gt; *(.*)?(\\n|(?=\\Z))", "<q>$1</q>");
- msg = msg.replaceAll("</q><q>", "\n");
-
- msg = msg.replaceAll("\n", "<br/>\n");
- return msg;
- }
public static void printMessages(PrintWriter out, JdbcTemplate sql, com.juick.User user, List<Integer> mids, com.juick.User visitor, int YandexID, int ad_mid) {
List<com.juick.Message> msgs = MessagesQueries.getMessages(sql, mids);
@@ -409,9 +317,9 @@ public class PageTemplates {
String txt;
if (!msg.Tags.isEmpty() && msg.Tags.contains("code")) {
- txt = formatMessageCode(msg.getText());
+ txt = Utils.formatMessageCode(msg.getText());
} else {
- txt = formatMessage(msg.getText());
+ txt = Utils.formatMessage(msg.getText());
}
out.println("<article data-mid=\"" + msg.getMID() + "\">");
diff --git a/juick-www/src/main/java/com/juick/www/RSS.java b/juick-www/src/main/java/com/juick/www/RSS.java
index 48510ce3..23120140 100644
--- a/juick-www/src/main/java/com/juick/www/RSS.java
+++ b/juick-www/src/main/java/com/juick/www/RSS.java
@@ -70,7 +70,7 @@ public class RSS {
}
}
out.println("]]></title>");
- out.println("<description><![CDATA[" + PageTemplates.formatMessage(msg.getText()) + "]]></description>");
+ out.println("<description><![CDATA[" + Utils.formatMessage(msg.getText()) + "]]></description>");
Date date = msg.getDate();
out.println("<pubDate>" + sdfRSS.format(date) + "</pubDate>");
diff --git a/juick-www/src/main/java/com/juick/www/UserThread.java b/juick-www/src/main/java/com/juick/www/UserThread.java
index c201fca3..c3228e17 100644
--- a/juick-www/src/main/java/com/juick/www/UserThread.java
+++ b/juick-www/src/main/java/com/juick/www/UserThread.java
@@ -106,9 +106,9 @@ public class UserThread {
String txt;
if (!msg.Tags.isEmpty() && msg.Tags.contains("code")) {
- txt = PageTemplates.formatMessageCode(msg.getText());
+ txt = Utils.formatMessageCode(msg.getText());
} else {
- txt = PageTemplates.formatMessage(msg.getText());
+ txt = Utils.formatMessage(msg.getText());
}
if (!tags.isEmpty()) {
@@ -288,7 +288,7 @@ public class UserThread {
out.println(" <div class=\"msg-avatar\"><img src=\"//i.juick.com/av-96.png\"/></div>");
out.println(" <div class=\"msg-header\">[удалено]:</div>");
}
- out.println(" <div class=\"msg-txt\">" + PageTemplates.formatMessage(msg.getText()) + "</div>");
+ out.println(" <div class=\"msg-txt\">" + Utils.formatMessage(msg.getText()) + "</div>");
if (msg.AttachmentType != null) {
out.println(" <div class=\"msg-media\"><a href=\"//i.juick.com/p/" + msg.getMID() + "-" + msg.getRID() + "." + msg.AttachmentType + "\"><img src=\"//i.juick.com/photos-512/" + msg.getMID() + "-" + msg.getRID() + "." + msg.AttachmentType + "\" alt=\"\"/></a></div>");
}
@@ -328,8 +328,7 @@ public class UserThread {
out.println(" <div class=\"msg-avatar\"><img src=\"//i.juick.com/av-96.png\"/></div>");
out.println(" <div class=\"msg-header\">[удалено]:</div>");
}
-
- out.println(" <div class=\"msg-txt\">" + PageTemplates.formatMessage(msg.getText()) + "</div>");
+ out.println(" <div class=\"msg-txt\">" + Utils.formatMessage(msg.getText()) + "</div>");
if (msg.AttachmentType != null) {
out.println(" <div class=\"msg-media\"><a href=\"//i.juick.com/p/" + msg.getMID() + "-" + msg.getRID() + "." + msg.AttachmentType + "\"><img src=\"//i.juick.com/photos-512/" + msg.getMID() + "-" + msg.getRID() + "." + msg.AttachmentType + "\" alt=\"\"/></a></div>");
}
diff --git a/juick-www/src/main/java/com/juick/www/Utils.java b/juick-www/src/main/java/com/juick/www/Utils.java
index 26e938a7..ee2fa212 100644
--- a/juick-www/src/main/java/com/juick/www/Utils.java
+++ b/juick-www/src/main/java/com/juick/www/Utils.java
@@ -18,6 +18,7 @@
package com.juick.www;
import com.juick.User;
+import com.mitchellbosecke.pebble.PebbleEngine;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.servlet.http.Cookie;
@@ -30,6 +31,8 @@ import java.net.URLConnection;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
*
@@ -38,6 +41,7 @@ import java.util.logging.Logger;
public class Utils {
private static final Logger logger = Logger.getLogger(Utils.class.getName());
+ private static final PebbleEngine engine = new PebbleEngine.Builder().build();
public static String getCookie(HttpServletRequest request, String name) {
Cookie cookies[] = request.getCookies();
@@ -199,4 +203,100 @@ public class Utils {
return attachmentFName;
}
}
+
+ private static Pattern regexLinks2 = Pattern.compile("((?<=\\s)|(?<=\\A))([\\[\\{]|&lt;)((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\\"\\)\\!]+)/?(?:[^\\]\\}](?<!&gt;))*)([\\]\\}]|&gt;)");
+
+ public static String formatMessageCode(String msg) {
+ msg = msg.replaceAll("&", "&amp;");
+ msg = msg.replaceAll("<", "&lt;");
+ msg = msg.replaceAll(">", "&gt;");
+
+ // http://juick.com/last?page=2
+ // <a href="http://juick.com/last?page=2" rel="nofollow">http://juick.com/last?page=2</a>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A))((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\n\\\"]+)/?[^\\s\\n\\\"]*)", "$1<a href=\"$2\" rel=\"nofollow\">$2</a>");
+
+ // (http://juick.com/last?page=2)
+ // (<a href="http://juick.com/last?page=2" rel="nofollow">http://juick.com/last?page=2</a>)
+ Matcher m = regexLinks2.matcher(msg);
+ StringBuffer sb = new StringBuffer();
+ while (m.find()) {
+ String url = m.group(3).replace(" ", "%20").replaceAll("\\s+", "");
+ m.appendReplacement(sb, "$1$2<a href=\"" + url + "\" rel=\"nofollow\">" + url + "</a>$5");
+ }
+ m.appendTail(sb);
+ msg = sb.toString();
+
+ return "<pre>" + msg + "</pre>";
+ }
+ public static String formatMessage(String msg) {
+ msg = msg.replaceAll("&", "&amp;");
+ msg = msg.replaceAll("<", "&lt;");
+ msg = msg.replaceAll(">", "&gt;");
+
+ // --
+ // &mdash;
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A))\\-\\-?((?=\\s)|(?=\\Z))", "$1&mdash;$2");
+
+ // http://juick.com/last?page=2
+ // <a href="http://juick.com/last?page=2" rel="nofollow">juick.com</a>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A))((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\n\\\"]+)/?[^\\s\\n\\\"]*)", "$1<a href=\"$2\" rel=\"nofollow\">$3</a>");
+
+ // [link text][http://juick.com/last?page=2]
+ // <a href="http://juick.com/last?page=2" rel="nofollow">link text</a>
+ msg = msg.replaceAll("\\[([^\\]]+)\\]\\[((?:ht|f)tps?://[^\\]]+)\\]", "<a href=\"$2\" rel=\"nofollow\">$1</a>");
+ msg = msg.replaceAll("\\[([^\\]]+)\\]\\(((?:ht|f)tps?://[^\\)]+)\\)", "<a href=\"$2\" rel=\"nofollow\">$1</a>");
+
+ // #12345
+ // <a href="http://juick.com/12345">#12345</a>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))#(\\d+)((?=\\s)|(?=\\Z)|(?=\\))|(?=\\.)|(?=\\,))", "$1<a href=\"http://juick.com/$2\">#$2</a>$3");
+
+ // #12345/65
+ // <a href="http://juick.com/12345#65">#12345/65</a>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))#(\\d+)/(\\d+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<a href=\"http://juick.com/$2#$3\">#$2/$3</a>$4");
+
+ // *bold*
+ // <b>bold</b>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A)|(?<=\\p{Punct}))\\*([^\\*\\n<>]+)\\*((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<b>$2</b>$3");
+
+ // /italic/
+ // <i>italic</i>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A))/([^\\/\\n<>]+)/((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<i>$2</i>$3");
+
+ // _underline_
+ // <span class="u">underline</span>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A))_([^\\_\\n<>]+)_((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<span class=\"u\">$2</span>$3");
+
+ // /12
+ // <a href="#12">/12</a>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A))\\/(\\d+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<a href=\"#$2\">/$2</a>$3");
+
+ // @username@jabber.org
+ // <a href="http://juick.com/username@jabber.org/">@username@jabber.org</a>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A))@([\\w\\-\\.]+@[\\w\\-\\.]+)((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<a href=\"http://juick.com/$2/\">@$2</a>$3");
+
+ // @username
+ // <a href="http://juick.com/username/">@username</a>
+ msg = msg.replaceAll("((?<=\\s)|(?<=\\A))@([\\w\\-]{2,16})((?=\\s)|(?=\\Z)|(?=\\p{Punct}))", "$1<a href=\"http://juick.com/$2/\">@$2</a>$3");
+
+ // (http://juick.com/last?page=2)
+ // (<a href="http://juick.com/last?page=2" rel="nofollow">juick.com</a>)
+ Matcher m = regexLinks2.matcher(msg);
+ StringBuffer sb = new StringBuffer();
+ while (m.find()) {
+ String url = m.group(3).replace(" ", "%20").replaceAll("\\s+", "");
+ m.appendReplacement(sb, "$1$2<a href=\"" + url + "\" rel=\"nofollow\">$4</a>$5");
+ }
+ m.appendTail(sb);
+ msg = sb.toString();
+
+ // > citate
+ msg = msg.replaceAll("(?:(?<=\\n)|(?<=\\A))&gt; *(.*)?(\\n|(?=\\Z))", "<q>$1</q>");
+ msg = msg.replaceAll("</q><q>", "\n");
+
+ msg = msg.replaceAll("\n", "<br/>\n");
+ return msg;
+ }
+ public static PebbleEngine getEngine() {
+ return engine;
+ }
}
diff --git a/juick-www/src/main/resources/layouts/content.html b/juick-www/src/main/resources/layouts/content.html
new file mode 100644
index 00000000..4cc1e2bf
--- /dev/null
+++ b/juick-www/src/main/resources/layouts/content.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <script type="text/javascript" src="/scripts.js"></script>
+ <link rel="stylesheet" type="text/css" href="/style.css"/>
+ {% block headers %}
+ {{ headers | raw }}
+ {% endblock %}
+ <title>{{ title }}</title>
+ <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/>
+ <link rel="icon" href="//i.juick.com/favicon.png"/>
+ <!--[if lt IE 9 & (!IEMobile 7)]>
+ <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
+ <![endif]-->
+</head>
+<body>
+{% include "views/partial/navigation.html" %}
+ <section id="content">
+ {% block content %}
+ {% endblock %}
+ </section>
+ <aside id="column">
+ {% block column %}
+ {% endblock %}
+ </aside>
+</body>
+</html> \ No newline at end of file
diff --git a/juick-www/src/main/resources/views/partial/homecolumn.html b/juick-www/src/main/resources/views/partial/homecolumn.html
new file mode 100644
index 00000000..5293918d
--- /dev/null
+++ b/juick-www/src/main/resources/views/partial/homecolumn.html
@@ -0,0 +1,6 @@
+<p class="tags">
+ {% include "views/partial/tags.html" %}
+ {% if showAdv %}
+ <a href="http://ru.wix.com/">конструктор сайтов</a>
+ {% endif %}
+</p> \ No newline at end of file
diff --git a/juick-www/src/main/resources/views/partial/navigation.html b/juick-www/src/main/resources/views/partial/navigation.html
new file mode 100644
index 00000000..7cacf66f
--- /dev/null
+++ b/juick-www/src/main/resources/views/partial/navigation.html
@@ -0,0 +1,37 @@
+<header>
+ <div id="logo"><a href="/">Juick</a></div>
+ <nav id="global">
+ <ul>
+ <li><a href="/">Популярные</a></li>
+ <li><a href="/?show=all" rel="nofollow">Все сообщения</a></li>
+ <li><a href="/?show=photos" rel="nofollow">Фотографии</a></li>
+ </ul>
+ </nav>
+ <div id="search">
+ <form action="/">
+ <input type="text" name="search" class="text" placeholder="Поиск" value="{{ search }}"/>
+ </form>
+ </div>
+ <section id="headdiv">
+ {% if visitor.getUID() > 0 %}
+ <nav id="user">
+ <ul>
+ <li><a href="/?show=my">Моя лента</a></li>
+ <li><a href="/pm/inbox">Приватные</a></li>
+ <li><a href="/?show=discuss">Обсуждения</a></li>
+ <li><a href="/?show=recommended">Рекомендации</a></li>
+ </ul>
+ </nav>
+ <nav id="actions">
+ <ul>
+ <li><a href="/#post">Написать</a></li>
+ <li><a href="/{{ visitor.getUName() }}">@{{ visitor.getUName() }}</a></li>
+ <li><a href="/logout">Выйти</a></li>
+ </ul>
+ </nav>
+ {% else %}
+ <p>Чтобы добавлять сообщения и комментарии, <a href="#" onclick="return Juick.openDialogLogin()">представьтесь</a>.
+ </p>
+ {% endif %}
+ </section>
+</header> \ No newline at end of file
diff --git a/juick-www/src/main/resources/views/partial/tags.html b/juick-www/src/main/resources/views/partial/tags.html
new file mode 100644
index 00000000..e69a949d
--- /dev/null
+++ b/juick-www/src/main/resources/views/partial/tags.html
@@ -0,0 +1,7 @@
+{% for tag in tags %}
+<span>
+ <!-- TODO: tagscloud: font-size: small, large, x-large, xx-large !-->
+ <a onclick="return addTag('{{ tag.Name }}')" href="/{{ user.getUName() }}/?tag={{tag.Name}}"
+ title="{{ tag.Name }}" class="usage_{{ tag.UsageCnt }}">{{ tag.Name }}</a>
+</span>
+{% endfor %} \ No newline at end of file
diff --git a/juick-www/src/main/resources/views/pm_inbox.html b/juick-www/src/main/resources/views/pm_inbox.html
new file mode 100644
index 00000000..d53c81ba
--- /dev/null
+++ b/juick-www/src/main/resources/views/pm_inbox.html
@@ -0,0 +1,36 @@
+{% extends "layouts/content.html" %}
+{% block content %}
+{% if not msgs.isEmpty() %}
+<ul id="private-messages">
+ {% for msg in msgs %}
+ <li class="msg">
+ <div class="msg-cont">
+ <div class="msg-ts">{{ msg.getDate() }}</div>
+ <div class="msg-avatar">
+ <a href="/{{ msg.getUser().getUName() }}/">
+ <img src="//i.juick.com/a/{{ msg.getUser().getUID() }}.png" alt="{{ msg.getUser().getUName() }}"/>
+ </a>
+ </div>
+ <div class="msg-header">
+ <a href="/{{ msg.getUser().getUName() }}/">@{{ msg.getUser().getUName() }}</a>:
+ </div>
+ <div class="msg-txt">{{ msg.getText() | raw }}</div>
+
+ <form action="/pm/send" method="POST" enctype="multipart/form-data">
+ <input type="hidden" name="uname" value="{{ msg.getUser().getUName() }}"/>
+ <div class="msg-comment">
+ <div class="ta-wrapper">
+ <textarea name="body" rows="1" class="replypm" placeholder="Написать ответ"></textarea>
+ </div>
+ </div>
+ </form>
+
+ </div>
+ </li>
+ {% endfor %}
+</ul>
+{% endif %}
+{% endblock %}
+{% block "column" %}
+{% include "views/partial/homecolumn.html" %}
+{% endblock %} \ No newline at end of file