尤娜主题渲染标签指南-Part I(尤娜v1.2.2版本)

2020-04-05 · 树下魅狐 · · 本文共3,103个字,预计阅读需要15分钟。

Una | 尤娜

一个基于Spring Boot 2.0构建的Java博客系统

序言

实现尤娜主题渲染标签的目的是为了能够加快主题皮肤的制作,对于不熟悉Java语言或者对Spring Boot不太了解的朋友也能快速的定制出自己的博客主题。尤娜主题渲染标签是在Freemarker框架的基础上实现的,沿用了Freemarker的基础标签,如逻辑判断(if语句,if…else语句,多重if…else语句,switch语句等),数据迭代(对象数组,分页),数据格式化(时间格式化)以及数据排序等。尤娜主题渲染标签分为全局常量,内容标签,格式化函数,脚本函数和分页函数五类,在接下来的内容中,将做详细介绍。下面是Freemarker的基本原理图,对Freemarker不是太熟悉的朋友可访问其官网(https://freemarker.apache.org/) 了解更多详细的知识。

1.扩展

尤娜主题渲染标签支持二次扩展,只需要让自定义的解析类继承AbstractUnaBootDirectiveModel.java类或者AbstractMethodModel.java类即可。尤娜会自动将扩展的解析类配置到Freemarker的上下文中。AbstractUnaBootDirectiveModel.java主要用于定义取值标签,而AbstractMethodModel.java类主要用于定义插件函数。你可以在com.ramostear.unaboot.freemarker包中找到这两个类。接下来,将列举两个小列子,演示如何扩展尤娜的主题渲染标签。

NumberFormat.java

@Service
public class NumberFormat extends AbstractMethodModel {
    @Override
    public Object exec(List arguments) throws TemplateModelException {
        int number = getInteger(arguments,0);
        DecimalFormat format = new DecimalFormat("###,###");
        return format.format(number);
    }
}

首先,需要使用@Service对类进行注解,表面这是一个被Spring容器所管理的Bean,然后继承AbstractMethodModel类,并重写exec()方法。这样就简单的定制了一个数值格式化的函数。在尤娜系统中,对函数和标签的名称做了区分(前缀都为“u_”),函数采用驼峰命名法且首字母小写,标签名称在驼峰命名法的基础上使用下滑线进行分割(无大写)。定义完函数后,便可通过下面的方式使用NumberFormat:

html

<div class="meta">
    <i class="fa fa-info"> ${u_numberFormat(1024666996)}</i>
</div>

Output

1,024,666,996

说明:

传入的1024666996将会以科学计数法的方式进行格式化,最后输出1,024,666,996

Navigation.java

@Service
public class Navigation extends AbstractUnaBootDirectiveModel {

    @Autowired
    private CategoryService categoryService;

    @Override
    public void execute(DirectiveHandler handler) throws Exception {
        List<Category> data = categoryService.navigation();
        if(CollectionUtils.isEmpty(data)){
            handler.put(MULTI,new ArrayList<Category>()).render();
        }else{
            handler.put(MULTI,data).render();
        }
    }
}

最后,以导航栏标签为例,介绍取值标签的定义。取值标签需要继承AbstractUnaBootDirectiveModel类,然后使用@Service进行注解,然后重写execute()方法,实现具体的业务逻辑,最后将数据通过handler返回到模板中。尤娜系统默认了两个数据的名称:SINGLE和MULTI,值分别是“result”和“results”。现在,我们可以在模板中按照以下的方式使用Navigation标签:

html

<@u_navigation>
    <#if results?? && results?size gt 0>
        <#list results as nav>
            <a class="" href="${una}/category/${nav.slug}">
                <span>${nav.name}</span>
            </a>
        </#list>
    </#if>
</@u_navigation>

此外,我们还可以使用Freemarker的sort_by()对数据进行排序,例如:

<@u_navigation>
    <#if results?? && results?size gt 0>
        <#list results?sort_by("id")?reverse as nav>
            <a class="" href="${una}/category/${nav.slug}">
                <span>${nav.name}</span>
            </a>
        </#list>
    </#if>
</@u_navigation>

注意:

sort_by()和reverse可以单独使用,sort_by()是升序排列,reverse是降序排列;两者也可以同时使用,上面的例子中,将导航栏目按照id进行降序排列。

2.全局常量

全局常量主要针对尤娜博客的基本配置信息,如站点名称,域名,Logo,备案号,版权信息等。下表列出了尤娜主题渲染标签所包含的所有全局常量标签(una-boot-v1.2.2版本):

KEY VALUE DEMO
copyright 版权号 ${copyright!’’}
domain 域名 ${domain!’’}
description 站点简介 ${description!’’}
email 联系邮箱 ${email!’’}
favicon 浏览器小图标,Base64格式 ${favicon!’’}
gitalk_client_id Gitalk评论插件ID ${gitalk_client_id!’’}
gitalk_client_secret Gitalk评论插件密钥 ${gitalk_client_secret!’’}
gitalk_admin Gitalk仓库管理员 ${gitalk_admin!’’}
gitalk_owner Gitalk仓库所有者 ${gitalk_owner!’’}
gitalk_repo Gitalk仓库名称 ${gitalk_repo!’’}
gitalk_enabled Gitalk评论插件开关 ${gitalk_enabled}
icp ICP备案号 ${icp!’’}
iscp 网安备案号 ${iscp!’’}
keywords 网站关键词 ${keywords!’’}
logo Logo,Base64格式 ${logo!’’}
title 网站标题 ${title!’’}
theme 网站主题名称,默认为default ${theme}
una 网站的上下文路径 ${una}

提示:

在使用全局常量时,最好做空值处理(!’xxxx’),提供一个默认值,因为尤娜主题渲染标签是在Freemarker的基础上实现的,Freemarker就像一个玻璃制品,好用漂亮,但易碎!!!最好是在取值时做好空值处理。

3.格式化函数

在尤娜v1.2.2版本中,共提供了5个格式化函数,它们时字符串长度截取函数u_ellipsis(),数值格式化函数u_numberFormat(),字数统计函数u_wordNumber(),时间格式化函数u_timeAgo()和阅读时间计算函数u_readTime()。

3.1 u_ellipsis()

在制作主题时,往往会遇到字符串的长度超过div的宽度,需要对字符串进行截取。我们可以通过CSS3或者Freemarker自带的substring()对字符串进行截取,但两种方式相对来说都比较麻烦,因此,从尤娜1.2.0版本开始便提供了内置的字符串截取函数u_ellipsis()。该函数接收两个参数,一个是字符串,一个是截取长度,当字符串长度超过所设置的长度时,会自动对字符串进行截取,并在截取的字符串末尾添加“…”。下面是u_ellipsis()函数使用示例:

Data

String msg = "尤娜是一个开源免费的博客系统,使用Java语言进行开发";

u_ellipsis()

${u_ellipsis(msg 17)}

Output

尤娜是一个开源免费的博客系统...

3.2 u_numberFormat()

通常,我们都会在网页中对数字进行格式化输出,如科学计数法(1,100,000),用K代表千(1K,10K)。在尤娜系统中,提供了以科学计数法对数值进行格式化输出的函数u_numberFoarmat(),该函数接收一个数值参数,下面是函数使用示例:

Data

Integer total = 1314996;

u_numberFormat()

<span> ${u_numberFormat(total)}</span>

Output

1,314,996

3.3 u_wordNumber()

在尤娜主题中,可以使用u_wordNumber()函数对文章的字数进行统计,在醒目的位置告知读者当前文章有多少字。下面是我个人博客中的一个截图:

下面是u_wordNumber()使用示例,该函数接收一个字符串参数:

Data

String content = "尤娜是一个基于Spring Boot 2.0 进行构建的Java博客系统"

u_wordNumber()

<span>本文共计${u_wordNumber(content)}个字</span>

Output

本文共计21个字

补充

u_wordNumber()会自动将内容中的空格,标点符号,换行符等剔除再计算字数,英文以空格切分计算。

3.4 u_timeAgo()

u_timeAge()函数用于计算文章发布时间到当前的时间长度,并以秒,分,小时,天,月和年格式化时间。假设我们有如下的几个文章发布时间:

Data

String date1 = "2019-01-01 12:00:00";
String date2 = "2019-12-31 00:59:00";
String data3 = "2020-01-01 00:00:00";

假设当前时间为2020-01-01 00:00:00,使用u_timeAgo()对上述三个发布时间进行格式化:

<span>${u_timeAgo(date1)}</span>
<span>${u_timeAgo(date2)}</span>
<span>${u_timeAgo(date3)}</span>

Output

1年以前
1分钟以前
刚刚

补充

除了使用u_timeAgo()函数对时间进行格式化外,你还可以选择Freemarker自带的格式化函数对时间进行格式化,例如对2020-04-05 06:11进行格式化:

Data

String date = "2020-04-05 06:11";

html

<span>${date?string("yyyy年MM月dd日")}</span>

Output

2020年04月05日

3.5 u_readTime()

u_readTime()是尤娜1.2.2版本中新增的一个趣味性函数,用于估算正常情况下阅读文章完文章所需要的时间。u_readTime()函数接收一个字符串变量(文章内容),并以200字/分钟的阅读速度计算阅读时间。下面是我个人网站的一个截图:

下面是u_readTime()函数的使用示例:

Data

String content = "你假装这里有4512个字";

u_readTime()

<span>预计阅读需要${u_readTime(content)}分钟</span>

Output

预计阅读需要22分钟

4.脚本函数

在尤娜v1.2.2版本中,新增了两个脚本函数u_gitalkScript()和u_gitalkSource()。u_gitalkScript()函数用于生成Gitalk的JavaScript初始化脚本,u_gitalkSource()函数用于生成Gitalk的样式文件连接和JS脚本的链接地址。

4.1 u_gitalkSource()

u_gitalkSource()函数接收一个String类型参数,该参数的可选值有”css”和”js”(u_gitalkSource()函数会忽略大小写)。下面是使用示例:

html

<html>
    <head>
        <link href="${u_gitalkSource("css")}" rel="stylesheet"/>
    </head>
    <body>
        ...
        <script src="${u_gitalkSource("js")}" type="text/javascript"></script>
    </body>
</html>

Output

<html>
    <head>
        <link href="https://cdn.bootcss.com/gitalk/1.5.0/gitalk.css" rel="stylesheet"/>
    </head>
    <body>
        ...
        <script src="https://cdn.bootcss.com/gitalk/1.5.0/gitalk.js" type="text/javascript"></script>
    </body>
</html>

4.2 u_gitalkScript()

u_gitalkScript()函数接收两个参数,文章ID和评论区的DOM属性(可以是div的id或class属性值)。使用此函数后,会生成一段Gitalk评论插件的初始化脚本(使用该函数的前提是在尤娜系统后台配置了Gitalk插件的相关信息)。下面是u_gitalkScript()使用示例:

Data

Integer postId = 1101;

u_gitalkScript()

<html>
    <head>
        <link href="${u_gitalkSource("css")}" rel="stylesheet"/>
    </head>
    <body>
        <div id="gitalk-container"></div>
         <script src="${u_gitalkSource("js")}" type="text/javascript"></script>       
        <script type="text/javascript">
            ${u_gitalkScript(postId "gitalk-container")}
        </script>
    </body>
</html>

Output

<html>
    <head>
        <link href="https://cdn.bootcss.com/gitalk/1.5.0/gitalk.css" rel="stylesheet"/>
    </head>
    <body>
        <div id="gitalk-container"></div>
         <script src="https://cdn.bootcss.com/gitalk/1.5.0/gitalk.js" type="text/javascript"></script>       
        <script type="text/javascript">
            var gitalk = new Gitalk({
                clientID:'e29f4c******e0e90',
                clientSecret:'093e887a62************f01b04bef23d3',
                repo:'your gitalk repository',
                owner:'ramostear',
                admin:'ramostear',
                id:'2564367701**************212042061'
            });
            gitalk.render('gitalk-container');
        </script>
    </body>
</html>

下图是u_gitalkScript()使用的实际效果图:

本小节介绍了尤娜V1.2.2版本中的主题渲染标签,包括二次扩展,全局常量,格式化函数和脚本函数,并给出了相应的示例代码。在第二部分中,将详细讲解尤娜主题渲染标签中的分页函数和内容标签。