Makdown转换HTML
通过集成插件 commonmark-java将markdown文本转换为HTML。
- pom.xml引用commonmark和扩展插件
<!-- 核心功能 -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.14.0</version>
</dependency>
<!-- 支持表格 -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>0.14.0</version>
</dependency>
<!-- 支持head添加id,以生成目录 -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-heading-anchor</artifactId>
<version>0.14.0</version>
</dependency>
- 文本转换
工具类直接复制了大佬的代码,使用工具类对查出的Blog对象进行处理。
package com.nianhen.blog.util;
import org.commonmark.Extension;
import org.commonmark.ext.gfm.tables.TableBlock;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.ext.heading.anchor.HeadingAnchorExtension;
import org.commonmark.node.Link;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.AttributeProvider;
import org.commonmark.renderer.html.AttributeProviderContext;
import org.commonmark.renderer.html.AttributeProviderFactory;
import org.commonmark.renderer.html.HtmlRenderer;
import java.util.*;
/**
* @author nianhen
* @createTime 2020/4/9 19:10
* markdown文本转换工具
*/
public class MarkdownUtils {
/**
* markdown格式转换成HTML格式
* @param markdown
* @return
*/
public static String markdownToHtml(String markdown) {
Parser parser = Parser.builder().build();
Node document = parser.parse(markdown);
HtmlRenderer renderer = HtmlRenderer.builder().build();
return renderer.render(document);
}
/**
* 增加扩展[标题锚点,表格生成]
* Markdown转换成HTML
* @param markdown
* @return
*/
public static String markdownToHtmlExtensions(String markdown) {
//h标题生成id
Set<Extension> headingAnchorExtensions = Collections.singleton(HeadingAnchorExtension.create());
//转换table的HTML
List<Extension> tableExtension = Arrays.asList(TablesExtension.create());
Parser parser = Parser.builder()
.extensions(tableExtension)
.build();
Node document = parser.parse(markdown);
HtmlRenderer renderer = HtmlRenderer.builder()
.extensions(headingAnchorExtensions)
.extensions(tableExtension)
.attributeProviderFactory(new AttributeProviderFactory() {
public AttributeProvider create(AttributeProviderContext context) {
return new CustomAttributeProvider();
}
})
.build();
return renderer.render(document);
}
/**
* 处理标签的属性
*/
static class CustomAttributeProvider implements AttributeProvider {
@Override
public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
//改变a标签的target属性为_blank
if (node instanceof Link) {
attributes.put("target", "_blank");
}
if (node instanceof TableBlock) {
attributes.put("class", "ui celled table");
}
}
}
}
- 页面调整
这里需要使用“th:utext”,避免对博客内容中的html进行转义,直接放置到div中,交由浏览器解析。
<div id="content" class="typo typo-selection m-padded-content-reponsive js-toc-content" th:utext="${blog.content}">
</div>
后续还需要进行样式等调整。
评论功能
评论信息提交与回复
- 点击回复,文本框placeholder修改为 “@被回复者”
- 点击发布,前端对文本进行校验,将表单提交到服务,校验处理后写入数据库。需要通过隐藏域提交:博客id和被回复的评论id(若仅对博客评论,传-1,后台处理)
- 发布成功后,刷新评论列表,定位到回复的评论处,还原placeholder文本
评论信息展示
针对博客本身的评论(父级评论为空),置于第一层,按照时间倒序排列。其他评论按关联关系统一放在第二层,按时间正序排列。需要构造一个递归迭代,对数据库获取的数据重新组装。部分代码:
@Override
public List<Comment> listCommentByBlogId(Long blogId) {
Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
List<Comment> comments = commentRepository.findByBlogIdAndParentCommentNull(blogId, sort);
return eachComment(comments);
}
/**
* 循环每个顶级的评论节点
*/
private List<Comment> eachComment(List<Comment> comments) {
List<Comment> commentsView = new ArrayList<>();
for (Comment comment : comments) {
Comment c = new Comment();
BeanUtils.copyProperties(comment, c);
commentsView.add(c);
}
//合并评论的各层子代到第一级子代集合中
combineChildren(commentsView);
return commentsView;
}
private void combineChildren(List<Comment> comments) {
for (Comment comment : comments) {
List<Comment> replys1 = comment.getReplyComments();
for (Comment reply1 : replys1) {
//循环迭代,找出子代,存放在tempReplys中
recursively(reply1);
}
//修改顶级节点的reply集合为迭代处理后的集合
comment.setReplyComments(tempReplys);
//清除临时存放区
tempReplys = new ArrayList<>();
}
}
//存放迭代找出的所有子代的集合
private List<Comment> tempReplys = new ArrayList<>();
/**
* 递归迭代
*/
private void recursively(Comment comment) {
//顶节点添加到临时存放集合
tempReplys.add(comment);
//有子集的进行迭代
if (comment.getReplyComments().size() > 0) {
List<Comment> replys = comment.getReplyComments();
for (Comment reply : replys) {
recursively(reply);
}
}
}
管理员评论
管理员评论需要加上博主标签,当前博客前台并无登录、注册功能,无法判断用户,通过管理页的登录来判断当前是否为博主。保存评论时,获取Session中的user对象,若不为空,将该评论设置为博主回复评论。在comment表中新增Boolean类型字段,用以存储回复类型。
转载:https://blog.csdn.net/qq_39694599/article/details/105417518
查看评论