mirror of https://github.com/bvn13/VoidForum.git
implemented ability of commenting posts. implemented comments flow under the post with pagination.
parent
3186fcc0ea
commit
a250ace937
|
@ -1,8 +1,14 @@
|
|||
package ru.bvn13.voidforum.controllers;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import ru.bvn13.voidforum.forms.CommentForm;
|
||||
import ru.bvn13.voidforum.models.Comment;
|
||||
import ru.bvn13.voidforum.models.Post;
|
||||
import ru.bvn13.voidforum.models.SeoPostData;
|
||||
import ru.bvn13.voidforum.models.User;
|
||||
import ru.bvn13.voidforum.services.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -11,8 +17,11 @@ import org.springframework.stereotype.Controller;
|
|||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import ru.bvn13.voidforum.utils.DTOUtil;
|
||||
import ru.bvn13.voidforum.utils.PaginatorUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.*;
|
||||
|
||||
|
@ -29,6 +38,9 @@ public class PostController {
|
|||
@Autowired
|
||||
private PostService postService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private VisitService visitService;
|
||||
|
||||
|
@ -41,6 +53,9 @@ public class PostController {
|
|||
@Autowired
|
||||
private RequestProcessorService requestProcessorService;
|
||||
|
||||
@Autowired
|
||||
private AppSetting appSetting;
|
||||
|
||||
|
||||
@RequestMapping(value = "archive", method = GET)
|
||||
public String archive(Model model){
|
||||
|
@ -50,7 +65,7 @@ public class PostController {
|
|||
}
|
||||
|
||||
@RequestMapping(value = "{permalink}", method = GET)
|
||||
public String show(@PathVariable String permalink, Model model, HttpServletRequest request){
|
||||
public String show(@PathVariable String permalink, Model model, @RequestParam(defaultValue = "0") int page, HttpServletRequest request){
|
||||
Post post = this.postService.findPostByPermalink(permalink);
|
||||
|
||||
logger.debug(String.format("ACCESS %s from IP: %s", permalink, this.requestProcessorService.getRealIp(request)));
|
||||
|
@ -73,12 +88,48 @@ public class PostController {
|
|||
model.addAttribute("seoDescription", post.getSeoDescription());
|
||||
model.addAttribute("seoData", seoData);
|
||||
|
||||
model.addAttribute("comments", commentService.getCommentsForPost(post));
|
||||
model.addAttribute("commentForm", new CommentForm());
|
||||
CommentForm commentForm = new CommentForm();
|
||||
commentForm.setPostId(post.getId());
|
||||
|
||||
Integer commentsPageSize = appSetting.getCommentsPageSize();
|
||||
Integer lastPage = commentService.getLastPageCommentsForPost(post, commentsPageSize);
|
||||
Page<Comment> comments = null;
|
||||
if (page > 0) {
|
||||
comments = commentService.getCommentsForPost(post, page - 1, commentsPageSize);
|
||||
} else {
|
||||
page = lastPage+1;
|
||||
comments = commentService.getCommentsForPost(post, lastPage, commentsPageSize);
|
||||
}
|
||||
|
||||
model.addAttribute("page", page);
|
||||
model.addAttribute("pagesList", PaginatorUtil.createPagesList(1, lastPage+1));
|
||||
model.addAttribute("totalPages", comments.getTotalPages());
|
||||
model.addAttribute("comments", comments);
|
||||
model.addAttribute("commentForm", commentForm);
|
||||
model.addAttribute("commentFormats", commentService.getAvailableCommentFormats());
|
||||
|
||||
return "posts/show";
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping(value = "{permalink}/comments", method = POST)
|
||||
public String addComment(@PathVariable String permalink, @Valid CommentForm commentForm, Errors errors, Model model) {
|
||||
|
||||
User user = userService.currentUser();
|
||||
if (!userService.currentUserHasPrivilege(PrivilegeService.PRIVILEGE_WRITE)) {
|
||||
throw new AccessDeniedException("You are not allowed here");
|
||||
}
|
||||
|
||||
Comment comment = new Comment();
|
||||
DTOUtil.mapTo(commentForm, comment);
|
||||
comment.setUser(user);
|
||||
comment.setPost(postService.getPost(commentForm.getPostId()));
|
||||
comment.setParentComment(commentService.getCommentById(commentForm.getParentCommentId()));
|
||||
comment.setDepth(commentService.calculateDepth(comment));
|
||||
|
||||
commentService.saveComment(comment);
|
||||
|
||||
return "redirect:/posts/"+permalink+"";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
package ru.bvn13.voidforum.controllers.account;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import ru.bvn13.voidforum.forms.CommentForm;
|
||||
import ru.bvn13.voidforum.models.Comment;
|
||||
import ru.bvn13.voidforum.repositories.CommentRepository;
|
||||
import ru.bvn13.voidforum.services.CommentService;
|
||||
import ru.bvn13.voidforum.services.PostService;
|
||||
import ru.bvn13.voidforum.services.UserService;
|
||||
import ru.bvn13.voidforum.utils.DTOUtil;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
|
||||
|
@ -13,11 +24,15 @@ import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
|||
@RequestMapping("/account/comments")
|
||||
public class CommentController {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private PostService postService;
|
||||
|
||||
@Autowired
|
||||
private CommentService commentService;
|
||||
|
||||
@RequestMapping(value = "", method = POST)
|
||||
public String addComment(Model model) {
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public class AdminController {
|
|||
appSetting.setPageSize(settingsForm.getPageSize());
|
||||
appSetting.setStoragePath(settingsForm.getStoragePath());
|
||||
appSetting.setMainUri(settingsForm.getMainUri());
|
||||
appSetting.setCommentsPageSize(settingsForm.getCommentsPageSize());
|
||||
|
||||
MessageHelper.addSuccessAttribute(ra, "Update settings successfully.");
|
||||
|
||||
|
|
|
@ -16,14 +16,17 @@ import javax.validation.constraints.NotNull;
|
|||
public class CommentForm {
|
||||
|
||||
@NotNull
|
||||
private Integer postId;
|
||||
private Long postId;
|
||||
|
||||
private Integer parentCommentId;
|
||||
private Long parentCommentId;
|
||||
|
||||
@NotEmpty
|
||||
private String content;
|
||||
|
||||
@NotNull
|
||||
private CommentFormat commentFormat;
|
||||
private CommentFormat commentFormat = CommentFormat.MARKDOWN;
|
||||
|
||||
@NotNull
|
||||
private Boolean deletedMark = false;
|
||||
|
||||
}
|
||||
|
|
|
@ -27,4 +27,7 @@ public class SettingsForm {
|
|||
@NotNull
|
||||
private String mainUri;
|
||||
|
||||
@NotNull
|
||||
private Integer commentsPageSize;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package ru.bvn13.voidforum.repositories;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.bvn13.voidforum.models.Comment;
|
||||
import ru.bvn13.voidforum.models.Post;
|
||||
|
@ -12,7 +16,9 @@ public interface CommentRepository extends JpaRepository<Comment, Long> {
|
|||
List<Comment> findAllByPostOrderById(Post post);
|
||||
List<Comment> findAllByPostAndParentCommentOrderById(Post post, Comment parentComment);
|
||||
|
||||
List<Comment> findAllByPostAndDeletedMarkOrderById(Post post, Boolean deletedMark);
|
||||
Page<Comment> findAllByPostAndDeletedMarkOrderById(Post post, Boolean deletedMark, Pageable pageable);
|
||||
List<Comment> findAllByPostAndParentCommentAndDeletedMarkOrderById(Post post, Comment parentComment, Boolean deletedMark);
|
||||
|
||||
@Query("SELECT COUNT(c.id) FROM Comment AS c WHERE c.post = :post AND c.deletedMark = :deletedMark")
|
||||
Integer getCommentsCountByPostAndDeletedMark(@Param("post") Post post, @Param("deletedMark") Boolean deletedMark);
|
||||
}
|
||||
|
|
|
@ -21,12 +21,14 @@ public class AppSetting {
|
|||
private Integer pageSize = 5;
|
||||
private String storagePath = "/tmp";
|
||||
private String mainUri = "http://localhost/";
|
||||
private Integer commentsPageSize = 50;
|
||||
|
||||
public static final String SITE_NAME = "site_name";
|
||||
public static final String SITE_SLOGAN = "site_slogan";
|
||||
public static final String PAGE_SIZE = "page_size";
|
||||
public static final String STORAGE_PATH = "storage_path";
|
||||
public static final String MAIN_URI = "main_uri";
|
||||
public static final String COMMENTS_PAGE_SIZE = "comments_page_size";
|
||||
|
||||
@Autowired
|
||||
public AppSetting(SettingService settingService){
|
||||
|
@ -90,4 +92,13 @@ public class AppSetting {
|
|||
ogTypes.add("article");
|
||||
return ogTypes;
|
||||
}
|
||||
|
||||
public Integer getCommentsPageSize() {
|
||||
return (Integer) settingService.get(COMMENTS_PAGE_SIZE, pageSize);
|
||||
}
|
||||
|
||||
public void setCommentsPageSize(Integer commentsPageSize) {
|
||||
this.commentsPageSize = commentsPageSize;
|
||||
settingService.put(COMMENTS_PAGE_SIZE, commentsPageSize);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,16 @@ package ru.bvn13.voidforum.services;
|
|||
|
||||
import com.domingosuarez.boot.autoconfigure.jade4j.JadeHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.bvn13.voidforum.models.Comment;
|
||||
import ru.bvn13.voidforum.models.Post;
|
||||
import ru.bvn13.voidforum.models.User;
|
||||
import ru.bvn13.voidforum.models.support.CommentFormat;
|
||||
import ru.bvn13.voidforum.repositories.CommentRepository;
|
||||
import ru.bvn13.voidforum.support.web.MarkdownService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -28,6 +32,13 @@ public class CommentService {
|
|||
@Autowired
|
||||
private CommentRepository commentRepository;
|
||||
|
||||
@Autowired
|
||||
private MarkdownService markdownService;
|
||||
|
||||
|
||||
public Comment getCommentById(Long commentId) {
|
||||
return commentRepository.findOne(commentId);
|
||||
}
|
||||
|
||||
private static Comparator<Comment> commentComparator = new Comparator<Comment>() {
|
||||
@Override
|
||||
|
@ -37,17 +48,16 @@ public class CommentService {
|
|||
};
|
||||
|
||||
|
||||
public List<Comment> getCommentsForPost(Post post) {
|
||||
List<Comment> availableComments = null;
|
||||
//User user = userService.currentUser();
|
||||
//if (userService.hasPrivilege(user, PrivilegeService.PRIVILEGE_WRITE)) {
|
||||
availableComments = commentRepository.findAllByPostOrderById(post);
|
||||
//} else {
|
||||
// availableComments = commentRepository.findAllByPostAndDeletedMarkOrderById(post, false);
|
||||
//}
|
||||
public Page<Comment> getCommentsForPost(Post post, int page, int pageSize) {
|
||||
Page<Comment> availableComments = commentRepository.findAllByPostAndDeletedMarkOrderById(post, false, new PageRequest(page, pageSize, Sort.Direction.ASC, "createdAt"));
|
||||
return availableComments;
|
||||
}
|
||||
|
||||
public Integer getLastPageCommentsForPost(Post post, int pageSize) {
|
||||
Integer count = commentRepository.getCommentsCountByPostAndDeletedMark(post, false);
|
||||
return (int) Math.ceil(count.intValue() / pageSize);
|
||||
}
|
||||
|
||||
public List<Comment> filterListByParentComment(List<Comment> comments, Comment parent) {
|
||||
List<Comment> children = new ArrayList<>();
|
||||
comments.forEach(c -> {
|
||||
|
@ -85,4 +95,20 @@ public class CommentService {
|
|||
return formats;
|
||||
}
|
||||
|
||||
public Integer calculateDepth(Comment comment) {
|
||||
if (comment.getParentComment() == null) {
|
||||
return 0;
|
||||
}
|
||||
return 1 + calculateDepth(comment.getParentComment());
|
||||
}
|
||||
|
||||
public Comment saveComment(Comment comment) {
|
||||
if (comment.getCommentFormat() == CommentFormat.MARKDOWN) {
|
||||
comment.setRenderedContent(String.format("<div class=\"markdown-post\">%s</div>", markdownService.renderToHtml(comment.getContent())));
|
||||
} else {
|
||||
comment.setRenderedContent(String.format("<div class=\"html-post\">%s</div>", comment.getContent()));
|
||||
}
|
||||
return commentRepository.save(comment);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public class UserService implements UserDetailsService {
|
|||
User user = userRepository.findByEmail(email);
|
||||
if (user == null) {
|
||||
springUser = new org.springframework.security.core.userdetails.User(
|
||||
" ", " ", true, true, true, true,
|
||||
"", "", true, true, true, true,
|
||||
getAuthorities(Arrays.asList(
|
||||
roleRepository.findByName(RoleService.ROLE_VISITOR))
|
||||
)
|
||||
|
@ -162,6 +162,10 @@ public class UserService implements UserDetailsService {
|
|||
return this.hasPrivilege(user, privilege);
|
||||
}
|
||||
|
||||
public Boolean currentUserCanWrite() {
|
||||
return this.currentUserHasPrivilege(PrivilegeService.PRIVILEGE_WRITE);
|
||||
}
|
||||
|
||||
|
||||
public User registerNewUserAccount(User user) throws EmailExistsException, NicknameExistsException {
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package ru.bvn13.voidforum.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by bvn13 on 11.12.2017.
|
||||
*/
|
||||
public class PaginatorUtil {
|
||||
|
||||
public static List<Integer> createPagesList(Integer from, Integer to, Integer pageSize) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
Integer lastPage = (int) Math.ceil(to / pageSize);
|
||||
for (int i=from; i<=lastPage; i++) {
|
||||
result.add(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<Integer> createPagesList(Integer from, Integer to) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (int i=from; i<=to; i++) {
|
||||
result.add(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
.comment-form #content-editor {
|
||||
margin-top: 10px;
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
}
|
|
@ -71,17 +71,19 @@ block content
|
|||
|
||||
script
|
||||
:javascript
|
||||
var editor = ace.edit("content-editor");
|
||||
editor.setTheme("ace/theme/github");
|
||||
$(document).ready(function() {
|
||||
var editor = ace.edit("content-editor");
|
||||
editor.setTheme("ace/theme/github");
|
||||
|
||||
var MarkdownMode = ace.require("ace/mode/markdown").Mode;
|
||||
editor.getSession().setMode(new MarkdownMode());
|
||||
var MarkdownMode = ace.require("ace/mode/markdown").Mode;
|
||||
editor.getSession().setMode(new MarkdownMode());
|
||||
|
||||
editor.getSession().setUseWrapMode(true);
|
||||
editor.getSession().setUseWrapMode(true);
|
||||
|
||||
$("form").submit(function(){
|
||||
$("#content").val(editor.getValue());
|
||||
return true;
|
||||
$("form").submit(function(){
|
||||
$("#content").val(editor.getValue());
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,10 @@ block content
|
|||
td.setting-label Page Size
|
||||
td.input
|
||||
input.form-control(type="text", name="pageSize", value="#{settings.getPageSize()}")
|
||||
tr
|
||||
td.setting-label Comments page Size
|
||||
td.input
|
||||
input.form-control(type="text", name="commentsPageSize", value="#{settings.getCommentsPageSize()}")
|
||||
tr
|
||||
td.setting-label Storage path
|
||||
td.input
|
||||
|
|
|
@ -25,7 +25,7 @@ block content
|
|||
textarea.form-control#content(name="content", style="display:none;")
|
||||
= postForm.getContent()
|
||||
div#content-editor
|
||||
#{postForm.getContent()}
|
||||
= postForm.getContent()
|
||||
.item-row
|
||||
hr
|
||||
.row
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
// Created by bvn13 on 09.12.2017.
|
||||
|
||||
div
|
||||
.tr.comment-deleted
|
||||
.colgroup
|
||||
| Sometimes there was a comment here...
|
||||
.panel.panel-warning
|
||||
.panel-body
|
||||
| Sometimes there was a comment here...
|
||||
|
||||
|
||||
//if commentService.childrenCount(comments, comment) > 0
|
||||
|
|
|
@ -1,8 +1,46 @@
|
|||
// Created by bvn13 on 09.12.2017.
|
||||
|
||||
|
||||
form.post-form(action="/account/comments", method="POST")
|
||||
form#commentForm.comment-form(action="comments", method="POST")
|
||||
.item-row
|
||||
input(type="hidden", name='_csrf', value='#{_csrf.token}')
|
||||
.item-row
|
||||
input(type="hidden", name='parentComment', value='#{comment.getParentComment().getId()}')
|
||||
input(type="hidden", name='postId', value='#{commentForm.getPostId()}')
|
||||
.item-row
|
||||
input(type="hidden", name='parentCommentId', value='#{commentForm.getParentCommentId()}')
|
||||
|
||||
.row
|
||||
.col-sm-3
|
||||
span Format
|
||||
select.form-control(name="commentFormat")
|
||||
for format in commentFormats
|
||||
if format != commentForm.getCommentFormat()
|
||||
option(value="#{format.getId()}") #{format.getName()}
|
||||
else
|
||||
option(value="#{format.getId()}", selected="selected") #{format.getName()}
|
||||
|
||||
.item-row
|
||||
textarea.form-control#content(name="content", style="display:none;")
|
||||
= commentForm.getContent()
|
||||
div#content-editor
|
||||
= commentForm.getContent()
|
||||
|
||||
.item-row
|
||||
input.btn.btnSuccess(type="submit", value="Add comment")
|
||||
|
||||
|
||||
script
|
||||
:javascript
|
||||
$(document).ready(function() {
|
||||
var editor = ace.edit("content-editor");
|
||||
editor.setTheme("ace/theme/github");
|
||||
|
||||
var MarkdownMode = ace.require("ace/mode/markdown").Mode;
|
||||
editor.getSession().setMode(new MarkdownMode());
|
||||
|
||||
editor.getSession().setUseWrapMode(true);
|
||||
|
||||
$("#commentForm").submit(function () {
|
||||
$("#content").val(editor.getValue());
|
||||
return true;
|
||||
});
|
||||
});
|
|
@ -1,4 +1,29 @@
|
|||
// Created by bvn13 on 09.12.2017.
|
||||
|
||||
.load-more
|
||||
nav
|
||||
ul.pagination
|
||||
if page > 1
|
||||
li.previous
|
||||
a.btn(href="?page=#{page - 1}")
|
||||
span(aria-hidden="true") ←
|
||||
| Older comments
|
||||
|
||||
for pageNum in pagesList
|
||||
if pageNum==page
|
||||
li.active
|
||||
a.btn(href="?page=#{pageNum}")
|
||||
= pageNum
|
||||
else
|
||||
li
|
||||
a.btn(href="?page=#{pageNum}")
|
||||
= pageNum
|
||||
|
||||
|
||||
if totalPages > page
|
||||
li.next
|
||||
a.btn(href="?page=#{page + 1}")
|
||||
| Newer comments
|
||||
span(aria-hidden="true") →
|
||||
|
||||
for comment in comments
|
||||
if comment.getDeletedMark()
|
||||
|
@ -7,4 +32,5 @@ for comment in comments
|
|||
include one
|
||||
|
||||
|
||||
include fragments/commentCreationForm
|
||||
if userService.currentUserCanWrite()
|
||||
include fragments/commentCreationForm
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
// Created by bvn13 on 09.12.2017.
|
||||
|
||||
div
|
||||
.table
|
||||
.tr.comment
|
||||
.td
|
||||
= comment.getUser().getNickname()
|
||||
= viewHelper.getFormattedDate(comment.getCreatedAt())
|
||||
.td
|
||||
!{comment.getRenderedContext()}
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
span #{comment.getUser().getNickname()}, #{viewHelper.getFormattedDate(comment.getCreatedAt())}
|
||||
div
|
||||
if userService.isCurrentUserAdmin()
|
||||
.td
|
||||
admin
|
||||
|
||||
.panel-body
|
||||
!{comment.getRenderedContent()}
|
||||
|
||||
include fragments/commentCreationForm
|
||||
|
||||
//if userService.currentUserCanWrite()
|
||||
// div
|
||||
// = userService.currentUser().getNickname()
|
||||
// include fragments/commentCreationForm
|
||||
|
||||
//if commentService.childrenCount(comments, comment) > 0
|
||||
// .comment-children(style="padding-left: #{5 * commentService.childrenCount(comments, comment)}px")
|
||||
|
|
|
@ -2,7 +2,14 @@ extends ../layout/app
|
|||
|
||||
block title
|
||||
= viewHelper.metaTitle(post.getTitle())
|
||||
|
||||
|
||||
if userService.currentUserCanWrite()
|
||||
block head
|
||||
link(rel='stylesheet', type='text/css', href='/css/comments.css')
|
||||
script(src="/webjars/ace/1.2.8/src-noconflict/ace.js")
|
||||
script(src="/webjars/ace/1.2.8/src-noconflict/theme-github.js")
|
||||
script(src="/webjars/ace/1.2.8/src-noconflict/mode-markdown.js")
|
||||
|
||||
block page_title
|
||||
h1 #{post.getTitle()}
|
||||
include ../posts/fragments/social
|
||||
|
|
Loading…
Reference in New Issue