说明
我们列表展示区域的内容基本已经做完了,我们的站点前台就只差文章页面的部分功能,我们这节课先把文章的渲染展示做一下
第三方
- 排版:本来页面的排版是想用Typo.css来排版的,后来觉得那个排版与我们博客的主体不搭,就自己写了版的css,文章排版其实就是把那些
markdown
渲染的html
代码出现的标签加个样式就行了 - 代码高亮:这里用的是prism,其实还有很多,只是这个用起来比较简单,导入一下就行了,不需要手动渲染
- markdown解析:我们用的是commonmark-java这个包,而其它java的
markdown
解析也基本都用的是它,但它只能支持一些比较简单的markdown
语法,稍微复杂一点就不能支持了,但官我给我们很多扩展选项,对我们来说它的基本功能再加上表格的支持就够了
详情页的展示
- 导入依赖
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>0.18.1</version>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>0.18.1</version>
</dependency>
- 我们创建一个
MarkdownUtil
的工具类用于解析markdown
package cn.kevinlu98.utils;
import org.commonmark.Extension;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.Heading;
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.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Author: Mr丶冷文
* Date: 2022/10/13 14:08
* Email: kevinlu98@qq.com
* Description:
*/
public interface MarkdownUtil {
List<Extension> EXTENSIONS = Collections.singletonList(TablesExtension.create());
Parser parser = Parser.builder()
.extensions(EXTENSIONS)
.build();
HtmlRenderer renderer = HtmlRenderer.builder()
.extensions(EXTENSIONS)
.attributeProviderFactory(attributeProviderContext -> (node, tagName, attributes) -> {
if (node instanceof Link) {
attributes.put("target", "_blank");
}
if (node instanceof Heading) {
attributes.put("id", UUID.randomUUID().toString().replace("-", ""));
attributes.put("class", "lw-title-toc");
}
})
.build();
/**
* 将markdown代码解析成html
*
* @param markdown markdown源码
* @return html代码
*/
static String parse(String markdown) {
Node document = parser.parse(markdown);
return renderer.render(document);
}
}
- 在
Article
中定义一个showHtml()
的方法用于将content
转化为html代码
public String showHtml() {
return MarkdownUtil.parse(this.content);
}
- 定义路由并查询文章详情
@GetMapping("/{id}.html")
public String detail(@PathVariable Integer id, Model model) {
Article article = articleService.detail(id);
//todo 当文章不存在时的处理
model.addAttribute("article", article);
return "detail";
}
- 页面展示并引入
prism
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head th:replace="common::header(~{::title},~{::link},~{})">
<title th:text="${ article.title +' - '+@webSite.title}"></title>
<link rel="stylesheet" href="/static/css/detail.css">
<link rel="stylesheet" href="/static/plugin/prism/prism.css">
</head>
<body>
<th:block th:include="common::nav"></th:block>
<div class="lw-container lw-main lw-posr">
<div class="lw-left-list">
<div class="lw-article-list">
<ol class="breadcrumb lw-crumb">
<li><a href="/">首页</a></li>
<li><a th:href="@{/category/{id}.html(id=${article.category.id})}" th:text="${article.category.name}"></a></li>
<li class="active">正文</li>
</ol>
<div class="lw-article">
<div class="lw-article-title">
<h1 th:text="${article.title}"></h1>
<p>
<i class="fa fa-clock-o lw-mr5"></i>
<th:block th:text="${#dates.format(article.created,'yyyy-MM-dd HH:mm')}"></th:block>
<i class="fa fa-eye lw-mr5 lw-ml10"></i>
<th:block th:text="${article.views}"></th:block>
<i class="fa fa-comment lw-ml10 lw-mr5"></i>
<th:block th:text="${article.commentCount}"></th:block>
<i class="fa fa-folder lw-ml10 lw-mr5"></i> <a th:href="@{/category/{id}.html(id=${article.category.id})}" th:text="${article.category.name}"></a></a>
<i class="fa fa-tags lw-ml10 lw-mr5"></i> <a th:each="tag:${article.tags}" th:href="@{/tag/{id}.html(id=${tag.id})}" th:text="${tag.name}"></a>
</p>
</div>
<div class="lw-article-content" id="lw-article-content" th:utext="${article.showHtml()}"></div>
<ul class="lw-article-right">
<li>
<svg t="1664366825703" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="919" width="200" height="200">
<path d="M512 512m-448 0a448 448 0 1 0 896 0 448 448 0 1 0-896 0Z" fill="#FB3A83"
p-id="920"></path>
<path d="M676.5 701c-9 0-16.6-6.3-18.1-15-1.1-6-2.5-11.6-4.2-16.7l-0.1-0.2-0.1-0.2c-9.1-31.5-29.1-59-56.6-78-26.2 13.2-55.6 20.1-85.3 20.1-29.8 0-59.2-7-85.5-20.2-27.6 19-47.7 46.5-56.8 78.1-0.2 0.7-2.1 7.9-4.8 18.5-2 8.1-9.3 13.7-17.8 13.7h-10.7c-4.8 0-9.4-2-12.5-5.6-3.1-3.5-4.6-8.2-4-12.8 8.1-60.2 46.2-113.1 101.7-141.5l5.4-2.8 5.1 3.4c23.5 15.9 51.1 24.3 79.8 24.3 28.7 0 56.2-8.4 79.7-24.2l5.1-3.4 5.4 2.8c55.4 28.4 93.4 81.3 101.5 141.4 0.6 4.6-0.8 9.3-4 12.8s-7.7 5.6-12.5 5.6h-10.7zM512.2 526.3c-74.5 0-135-60-135-133.6S437.7 259 512.2 259s135 60 135 133.6c0 73.7-60.5 133.7-135 133.7z m0-222.4c-49.6 0-89.9 39.8-89.9 88.8s40.3 88.8 89.9 88.8c49.6 0 89.9-39.8 89.9-88.8s-40.3-88.8-89.9-88.8z"
fill="#FFFFFF" p-id="921"></path>
</svg>
<span>版权所属: <a href="https://kevinlu98.cn/">冷文学习者</a></span>
</li>
<li>
<svg t="1664366893739" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="1067" width="200" height="200">
<path d="M512 512m-448 0a448 448 0 1 0 896 0 448 448 0 1 0-896 0Z" fill="#FA5151"
p-id="1068"></path>
<path d="M610.2 324c22.6 20.5 33.8 49 33.8 85.2 0 26.6-7.5 50.2-22.4 70.7-5.6 6.9-22.2 22.4-49.6 46.5-12.5 10.5-21.8 21.4-27.8 32.6-7.7 12.9-11.5 27.8-11.5 44.7v13.9h-49v-13.9c0-20.1 3.8-37.7 11.5-52.6 7.3-17.3 27.6-40.7 61-70.1 8.1-8.1 14.9-15.3 20.5-21.8 11.7-15.3 17.5-31.2 17.5-47.7 0-24.2-6.6-42.9-19.9-56.2-14.1-14.1-34.1-21.2-59.8-21.2-29.8 0-52.2 9.9-67.1 29.6-12.9 17.3-19.3 40.5-19.3 69.5h-48.4c0-41.9 11.9-75.7 35.7-101.5 25-26.6 58.8-39.9 101.5-39.9 39.7 0.2 70.7 10.9 93.3 32.2z m-75.5 346.4c6.8 6.9 10.3 15.3 10.3 25.4 0 10.5-3.4 19.1-10.3 26-7.7 6.9-16.3 10.3-26 10.3-10.5 0-19.1-3.4-26-10.3-7.3-7.3-10.9-15.9-10.9-26 0-10.5 3.6-18.9 10.9-25.4 6.4-6.8 15.1-10.3 26-10.3 10.4 0 19.1 3.4 26 10.3z"
fill="#FFFFFF" p-id="1069"></path>
</svg>
<span>本文链接: <a href="https://kevinlu98.cn/archives/101.html">https://kevinlu98.cn/archives/101.html</a></span>
</li>
<li>
<svg t="1664366925081" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="1215" width="200" height="200">
<path d="M800.3 205.1L534.8 116c-16-5.4-33.3-5.3-49.2 0.2l-264.5 92.3c-29.3 10-49 37.5-49.1 68.4l1.7 265.4c0.7 81 31.1 158.9 85.6 218.9 25 27.7 56.9 51.5 97.8 72.7l144 74.6c9 4.7 19.7 4.6 28.7-0.2L672.5 832c40.4-21.6 72.2-45.7 96.9-73.8 53.6-60.6 83-138.9 82.6-219.8l-1.7-265.6c-0.5-30.9-20.5-58.1-50-67.7z"
fill="#FFC300" p-id="1216"></path>
<path d="M512 597c-13.9 0-25.2-11.3-25.2-25.2V345.2c0-13.9 11.3-25.2 25.2-25.2 13.9 0 25.2 11.3 25.2 25.2v226.6c0 13.9-11.3 25.2-25.2 25.2z"
fill="#FFFFFF" p-id="1217"></path>
<path d="M512 674.1m-29.9 0a29.9 29.9 0 1 0 59.8 0 29.9 29.9 0 1 0-59.8 0Z" fill="#FFFFFF"
p-id="1218"></path>
</svg>
<span>协议授权: <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》</a></span>
</li>
</ul>
</div>
<div class="lw-comment-box row lw-m0">
<h2>评论(6)</h2>
<form action="">
<div class="col-md-12 lw-p0" style="padding-right: 10px;">
<textarea placeholder="请输入你的评论..."></textarea>
</div>
<div class="col-md-4 col-xs-12 lw-comment-input lw-posr">
<input type="text" placeholder="请输入昵称...">
<i class="fa fa-user lw-comment-input lw-posa"></i>
</div>
<div class="col-md-4 col-xs-12 lw-comment-input lw-posr">
<input type="email" placeholder="请输入电子邮件...">
<i class="fa fa-envelope lw-posa"></i>
</div>
<div class="col-md-4 col-xs-12 lw-comment-input lw-posr">
<input type="url" placeholder="请输入主页地址...">
<i class="fa fa-link fa-link lw-posa"></i>
</div>
</form>
</div>
</div>
<div class="lw-comment-list">
<ul>
<li class="lw-posr">
<div class="lw-comment-avatar lw-posa">
<img src="https://kevinlu98.cn/freecdn-1.4/image/avatar/22.png" alt="">
</div>
<div class="lw-comment-content">
<p><b>xpboy</b> <span>2022-06-03 18:32</span> <a href="">回复</a></p>
<p class="lw-comment-info">
已经解决,问题是后台的的永久链接--重写功能,一定要开启成功,我是开启没有成功,但是可以使用,部分功能受限,如点赞、登录、注册等。我是windows
iis,添加web.config放到网站根目录就可以了,希望踩坑的朋友注意了。具体的web.config伪静态规则代码,可以联系我免费提供哦
qq24985536,希望帮助到大家</p>
</div>
<ul>
<li class="lw-posr">
<div class="lw-comment-avatar lw-posa">
<img src="https://q1.qlogo.cn/g?b=qq&nk=1518228633&s=100" alt="">
</div>
<div class="lw-comment-content">
<p><b>VOODOO</b> <span>2022-09-28 19:53</span> <a href="">回复</a></p>
<p class="lw-comment-info">
@xpboy
<br>
谢谢</p>
</div>
</li>
</ul>
</li>
<li class="lw-posr">
<div class="lw-comment-avatar lw-posa">
<img src="https://q1.qlogo.cn/g?b=qq&nk=68159424&s=100" alt="">
</div>
<div class="lw-comment-content">
<p><b>anle</b> <span>2022-06-03 18:32</span> <a href="">回复</a></p>
<p class="lw-comment-info">
您好~我是俺没偷前端的运营,关注了您在分享的技术文章,觉得您的这套模板很棒,我们诚挚邀请您加入俺没偷前端CP主计划。完整福利和详细介绍请见:https://anlenotes.com/cp
我们会给作者提供包括流量、创作分成等, 我们诚挚的邀请您并期待您的加入~</p>
</div>
</li>
<li class="lw-posr">
<div class="lw-comment-avatar lw-posa">
<img src="https://q1.qlogo.cn/g?b=qq&nk=602314742&s=100" alt="">
</div>
<div class="lw-comment-content">
<p><b>王伟忘记使自己快乐</b> <span>2022-06-03 18:32</span> <a href="">回复</a></p>
<p class="lw-comment-info">
你好,请问一下,搭建的网页,在本地访问一点问题都没有,通过互联网域名访问,打开很慢,而且显示不正常,电脑手机都是一样的,是什么问题呢</p>
</div>
</li>
<li class="lw-posr">
<div class="lw-comment-avatar lw-posa">
<img src="https://q1.qlogo.cn/g?b=qq&nk=545431&s=100" alt="">
</div>
<div class="lw-comment-content">
<p><b>小布丁</b> <span>2022-06-03 18:32</span> <a href="">回复</a></p>
<p class="lw-comment-info">
为什么启用这个主题 后,评论用不了了,报错。</p>
</div>
</li>
</ul>
</div>
<ul class="lw-pagenation">
<li><a href="">首页</a></li>
<li><a href="">1</a></li>
<li><a href="">2</a></li>
<li><a href="">3</a></li>
<li><a href="">4</a></li>
<li><a href="">5</a></li>
<li><a href="">尾页</a></li>
</ul>
</div>
<div class="lw-right-list lw-md-show lw-posa">
<th:block th:include="common::right"></th:block>
</div>
</div>
<th:block th:include="common::footer"></th:block>
<script src="/static/plugin/prism/prism.js"></script>
</body>
</html>
文章目录处理
- 给
h
标签加上id - 取到所有的
h
标签 - 生成
a
标签,href
是#hid
- 给
$(function () {
let offset = [10, 20, 30, 40, 50, 60]
let hTag = $('#lw-article-content .lw-title-toc')
let hMax = 6;
hTag.each((i, ele) => {
hMax = Math.min(ele.tagName.charAt(1), hMax)
})
for (let i = 0; i < offset.length; i++) {
offset[i] -= (hMax - 1) * 10
}
hTag.each((index, element) => {
let level = element.tagName.charAt(1)
let left = offset[level - 1]
$('#lw-article-toc').append(`<li><a style="padding-left: ${left}px;" href="#${$(element).attr('id')}">${$(element).text()}</a></li>`)
})
})
john 游客 2024-05-17 14:01 回复
学习
游客1111 游客 2023-12-04 10:31 回复
学习
print 游客 2023-02-23 16:05 回复
好
寻路。 游客 2022-10-21 21:02 回复
你好