complate theme system

pull/137/head
ruibaby 2019-03-17 15:15:35 +08:00
parent cfb261eb4f
commit fe1204f441
7 changed files with 90 additions and 125 deletions

View File

@ -5,9 +5,7 @@ import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
/** /**
* <pre> * Theme DTO
*
* </pre>
* *
* @author : RYAN0UP * @author : RYAN0UP
* @date : 2018/1/3 * @date : 2018/1/3
@ -18,17 +16,22 @@ public class Theme implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* * theme name
*/ */
private String themeName; private String themeName;
/** /**
* * is support setting options
*/ */
private boolean hasOptions; private boolean hasOptions;
/** /**
* * is support update
*/ */
private boolean hasUpdate; private boolean hasUpdate;
/**
* is internal theme
*/
private boolean isInternal;
} }

View File

@ -1,6 +1,9 @@
package cc.ryanc.halo.utils; package cc.ryanc.halo.utils;
import cc.ryanc.halo.model.support.HaloConst;
import cc.ryanc.halo.model.support.Theme; import cc.ryanc.halo.model.support.Theme;
import cc.ryanc.halo.web.controller.core.BaseContentController;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ResourceUtils; import org.springframework.util.ResourceUtils;
@ -27,8 +30,8 @@ public class ThemeUtils {
public static List<Theme> getThemes() { public static List<Theme> getThemes() {
final List<Theme> themes = new ArrayList<>(); final List<Theme> themes = new ArrayList<>();
try { try {
themes.addAll(getThemesByPath(getInternalThemesPath())); themes.addAll(getThemesByPath(getInternalThemesPath(), true));
themes.addAll(getThemesByPath(getUsersThemesPath())); themes.addAll(getThemesByPath(getUsersThemesPath(), false));
} catch (Exception e) { } catch (Exception e) {
log.error("Themes scan failed", e); log.error("Themes scan failed", e);
} }
@ -41,7 +44,7 @@ public class ThemeUtils {
* @param file file * @param file file
* @return List<Theme> * @return List<Theme>
*/ */
private static List<Theme> getThemesByPath(File themesPath) { private static List<Theme> getThemesByPath(File themesPath, boolean isInternal) {
final List<Theme> themes = new ArrayList<>(); final List<Theme> themes = new ArrayList<>();
try { try {
final File[] files = themesPath.listFiles(); final File[] files = themesPath.listFiles();
@ -67,6 +70,7 @@ public class ThemeUtils {
} else { } else {
theme.setHasUpdate(false); theme.setHasUpdate(false);
} }
theme.setInternal(isInternal);
themes.add(theme); themes.add(theme);
} }
} }
@ -78,7 +82,7 @@ public class ThemeUtils {
} }
/** /**
* Get internal themes * Get internal themes path
* *
* @return File * @return File
* @throws FileNotFoundException FileNotFoundException * @throws FileNotFoundException FileNotFoundException
@ -88,7 +92,7 @@ public class ThemeUtils {
} }
/** /**
* Get user's themes * Get user's themes path
* *
* @return File * @return File
*/ */
@ -96,6 +100,20 @@ public class ThemeUtils {
return new File(System.getProperties().getProperty("user.home"), "halo/templates/themes"); return new File(System.getProperties().getProperty("user.home"), "halo/templates/themes");
} }
/**
* Get themes path by theme name
*
* @param themeName themeName
* @return File
*/
public static File getThemesPath(String themeName) throws FileNotFoundException {
if (isInternal(themeName)) {
return getInternalThemesPath();
} else {
return getUsersThemesPath();
}
}
/** /**
* Get theme templates * Get theme templates
* *
@ -105,7 +123,7 @@ public class ThemeUtils {
public static List<String> getTplName(String theme) { public static List<String> getTplName(String theme) {
final List<String> templates = new ArrayList<>(); final List<String> templates = new ArrayList<>();
try { try {
final File themesPath = new File(getUsersThemesPath(), "templates/themes/" + theme); final File themesPath = new File(getThemesPath(theme), theme);
final File modulePath = new File(themesPath.getAbsolutePath(), "module"); final File modulePath = new File(themesPath.getAbsolutePath(), "module");
final File[] baseFiles = themesPath.listFiles(); final File[] baseFiles = themesPath.listFiles();
final File[] moduleFiles = modulePath.listFiles(); final File[] moduleFiles = modulePath.listFiles();
@ -134,9 +152,9 @@ public class ThemeUtils {
* *
* @return List * @return List
*/ */
public static List<String> getCustomTpl(String theme) { public static List<String> getCustomTpl(String theme) throws FileNotFoundException {
final List<String> templates = new ArrayList<>(); final List<String> templates = new ArrayList<>();
final File themePath = new File(getUsersThemesPath(), "templates/themes/" + theme); final File themePath = new File(getThemesPath(theme), theme);
final File[] themeFiles = themePath.listFiles(); final File[] themeFiles = themePath.listFiles();
if (null != themeFiles && themeFiles.length > 0) { if (null != themeFiles && themeFiles.length > 0) {
for (File file : themeFiles) { for (File file : themeFiles) {
@ -148,4 +166,41 @@ public class ThemeUtils {
} }
return templates; return templates;
} }
/**
* Judging whether template exists under the specified theme
*
* @param template template
* @return boolean
*/
public static boolean isTemplateExist(String template) throws FileNotFoundException {
boolean result = false;
StrBuilder templatePath = new StrBuilder(BaseContentController.THEME);
templatePath.append("/");
templatePath.append(template);
File file = new File(getThemesPath(BaseContentController.THEME), templatePath.toString());
if (file.exists()) {
result = true;
}
return result;
}
/**
* Judging whether the theme is a internal theme or not
*
* @param themeName themeName
* @return boolean
*/
public static boolean isInternal(String themeName) {
boolean result = false;
List<Theme> themes = HaloConst.THEMES;
for (Theme theme : themes) {
if (theme.getThemeName().equals(themeName) && theme.isInternal()) {
result = true;
break;
}
}
return result;
}
} }

View File

@ -129,7 +129,7 @@ public class ThemeController extends BaseController {
@GetMapping(value = "/remove") @GetMapping(value = "/remove")
public String removeTheme(@RequestParam("themeName") String themeName) { public String removeTheme(@RequestParam("themeName") String themeName) {
try { try {
final File themePath = new File(ThemeUtils.getUsersThemesPath(), themeName); final File themePath = new File(ThemeUtils.getThemesPath(themeName), themeName);
FileUtil.del(themePath); FileUtil.del(themePath);
} catch (Exception e) { } catch (Exception e) {
log.error("Delete theme failed: {}", e.getMessage()); log.error("Delete theme failed: {}", e.getMessage());
@ -244,7 +244,7 @@ public class ThemeController extends BaseController {
public String getTplContent(@RequestParam("tplName") String tplName) { public String getTplContent(@RequestParam("tplName") String tplName) {
String tplContent = ""; String tplContent = "";
try { try {
final StrBuilder themePath = new StrBuilder(ThemeUtils.getUsersThemesPath().getAbsolutePath()); final StrBuilder themePath = new StrBuilder(ThemeUtils.getThemesPath(BaseContentController.THEME).getAbsolutePath());
themePath.append(BaseContentController.THEME); themePath.append(BaseContentController.THEME);
themePath.append("/"); themePath.append("/");
themePath.append(tplName); themePath.append(tplName);
@ -272,7 +272,7 @@ public class ThemeController extends BaseController {
return new JsonResult(0, localeMessage("code.admin.theme.edit.no-content")); return new JsonResult(0, localeMessage("code.admin.theme.edit.no-content"));
} }
try { try {
final StrBuilder themePath = new StrBuilder(ThemeUtils.getUsersThemesPath().getAbsolutePath()); final StrBuilder themePath = new StrBuilder(ThemeUtils.getThemesPath(BaseContentController.THEME).getAbsolutePath());
themePath.append(BaseContentController.THEME); themePath.append(BaseContentController.THEME);
themePath.append("/"); themePath.append("/");
themePath.append(tplName); themePath.append(tplName);

View File

@ -3,6 +3,7 @@ package cc.ryanc.halo.web.controller.core;
import cc.ryanc.halo.logging.Logger; import cc.ryanc.halo.logging.Logger;
import cc.ryanc.halo.model.entity.User; import cc.ryanc.halo.model.entity.User;
import cc.ryanc.halo.model.support.HaloConst; import cc.ryanc.halo.model.support.HaloConst;
import cc.ryanc.halo.utils.ThemeUtils;
import cn.hutool.core.text.StrBuilder; import cn.hutool.core.text.StrBuilder;
import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -11,6 +12,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import java.io.FileNotFoundException;
/** /**
* <pre> * <pre>
@ -92,7 +94,10 @@ public class CommonController implements ErrorController {
* @return String * @return String
*/ */
@GetMapping(value = "/404") @GetMapping(value = "/404")
public String contentNotFround() { public String contentNotFround() throws FileNotFoundException {
if(ThemeUtils.isTemplateExist("404.ftl")){
return "common/error/404";
}
StrBuilder path = new StrBuilder("themes/"); StrBuilder path = new StrBuilder("themes/");
path.append(BaseContentController.THEME); path.append(BaseContentController.THEME);
path.append("/404"); path.append("/404");
@ -105,7 +110,10 @@ public class CommonController implements ErrorController {
* @return template path: * @return template path:
*/ */
@GetMapping(value = "/500") @GetMapping(value = "/500")
public String contentInternalError() { public String contentInternalError() throws FileNotFoundException {
if(ThemeUtils.isTemplateExist("500.ftl")){
return "common/error/404";
}
StrBuilder path = new StrBuilder("themes/"); StrBuilder path = new StrBuilder("themes/");
path.append(BaseContentController.THEME); path.append(BaseContentController.THEME);
path.append("/500"); path.append("/500");

View File

@ -2,6 +2,7 @@ package cc.ryanc.halo.web.controller.core;
import cc.ryanc.halo.model.entity.*; import cc.ryanc.halo.model.entity.*;
import cc.ryanc.halo.model.enums.CommentStatus; import cc.ryanc.halo.model.enums.CommentStatus;
import cc.ryanc.halo.model.enums.PostStatus;
import cc.ryanc.halo.model.support.JsonResult; import cc.ryanc.halo.model.support.JsonResult;
import cc.ryanc.halo.service.*; import cc.ryanc.halo.service.*;
import cc.ryanc.halo.utils.MarkdownUtils; import cc.ryanc.halo.utils.MarkdownUtils;
@ -133,9 +134,9 @@ public class InstallController {
"欢迎使用Halo进行创作删除这篇文章后赶紧开始吧。"); "欢迎使用Halo进行创作删除这篇文章后赶紧开始吧。");
post.setFormatContent(MarkdownUtils.renderMarkdown(post.getOriginalContent())); post.setFormatContent(MarkdownUtils.renderMarkdown(post.getOriginalContent()));
post.setSummary("欢迎使用Halo进行创作删除这篇文章后赶紧开始吧。"); post.setSummary("欢迎使用Halo进行创作删除这篇文章后赶紧开始吧。");
post.setStatus(0); post.setStatus(PostStatus.PUBLISHED);
post.setUrl("hello-halo"); post.setUrl("hello-halo");
post.setDisallowComment(1); post.setDisallowComment(true);
post.setThumbnail("/static/halo-frontend/images/thumbnail/thumbnail-" + RandomUtil.randomInt(1, 11) + ".jpg"); post.setThumbnail("/static/halo-frontend/images/thumbnail/thumbnail-" + RandomUtil.randomInt(1, 11) + ".jpg");
postService.create(post); postService.create(post);

View File

@ -1,52 +1 @@
<#compress> 404 Not Found
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>404 Not Found</title>
<link href="//cdnjs.loli.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link href="//cdnjs.loli.net/ajax/libs/animate.css/3.7.0/animate.min.css" rel="stylesheet">
<style type="text/css" rel="stylesheet">
body{margin:0}*{box-sizing:border-box}h1,h2{margin:0}a{color:#fff;text-decoration:none}body,html{font-family:-apple-system,system-ui,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.fullscreen{background-position:50% 50%;background-size:cover}.fullscreen,.fullscreen .backColor{position:absolute;top:0;left:0;width:100%;height:100%}.fullscreen .backColor{background-color:rgba(0,0,0,.1)}.infos{display:flex;text-align:center;align-items:center;justify-content:center}.infos,.main-content{position:absolute;top:0;left:0;width:100%;height:100%;color:#fff}.main-content{background: #833ab4;background: -webkit-linear-gradient(to right, #833ab4, #fd1d1d, #fcb045);background: linear-gradient(to right, #833ab4, #fd1d1d, #fcb045);}.errorPage{position:relative;width:100vw;height:100vh}.infos-h1{margin:0;font-size:5em;line-height:1}.infos-h1 h1{font-weight:200}.footer{position:absolute;right:1rem;bottom:1rem;left:1rem;z-index:9999;font-size:14px}.infos-h2{font-size:24px}.infos-h2 a:hover{color:#7a8d85}
</style>
</head>
<body>
<div class="container">
<div class="errorPage">
<div class="main-content ">
<div class="fullscreen">
<div class="backColor"></div>
</div>
<div class="infos">
<div class="infos-main">
<div class="infos-h1"><h1>404</h1></div>
<div class="infos-h2">
<a href="javascript:window.history.back()" title="返回上一页">
<i class="fa fa-chevron-left"></i>
</a>
<a href="/" title="返回到主页">
<i class="fa fa-home"></i>
</a>
</div>
</div>
</div>
<div class="footer">
<span>Copyright © 2018</span>
<a href="${options.blog_url!}">${options.blog_title!'Halo'}</a>
<span style="float: right">
Background image from <a href="https://cn.bing.com/" target="_blank">Bing</a>.
</span>
</div>
</div>
</div>
</div>
</body>
<script src="//cdnjs.loli.net/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('$.o(\'m://q.8.n/?1=4%y%z%B.5.9%d.e%f%g%h%i%j%k\',l(b){6 a=b.p[0].1;6 c=$(\'.r\');c.t("u-v","1(4://s.w.5.x"+a+")");c.2(\'3 A\');$(\'.7-C\').2(\'3 D\');$(\'.7-E\').2(\'3 F\')});',42,42,'|url|addClass|animated|http|bing|var|infos|afeld|com||||2FHPImageArchive|aspx|3Fformat|3Djs|26idx|3D0|26n|3D1|function|https|me|get|images|jsonp|fullscreen||css|background|image|cn|net|3A|2F|fadeIn|2Fcn|h1|shake|h2|fadeInDown'.split('|'),0,{}))
</script>
</html>
</#compress>

View File

@ -1,52 +1 @@
<#compress> 500 Internal Error
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>500 Error Page</title>
<link href="//cdnjs.loli.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link href="//cdnjs.loli.net/ajax/libs/animate.css/3.7.0/animate.min.css" rel="stylesheet">
<style type="text/css" rel="stylesheet">
body{margin:0}*{box-sizing:border-box}h1,h2{margin:0}a{color:#fff;text-decoration:none}body,html{font-family:-apple-system,system-ui,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.fullscreen{background-position:50% 50%;background-size:cover}.fullscreen,.fullscreen .backColor{position:absolute;top:0;left:0;width:100%;height:100%}.fullscreen .backColor{background-color:rgba(0,0,0,.1)}.infos{display:flex;text-align:center;align-items:center;justify-content:center}.infos,.main-content{position:absolute;top:0;left:0;width:100%;height:100%;color:#fff}.main-content{background: #833ab4;background: -webkit-linear-gradient(to right, #833ab4, #fd1d1d, #fcb045);background: linear-gradient(to right, #833ab4, #fd1d1d, #fcb045);}.errorPage{position:relative;width:100vw;height:100vh}.infos-h1{margin:0;font-size:5em;line-height:1}.infos-h1 h1{font-weight:200}.footer{position:absolute;right:1rem;bottom:1rem;left:1rem;z-index:9999;font-size:14px}.infos-h2{font-size:24px}.infos-h2 a:hover{color:#7a8d85}
</style>
</head>
<body>
<div class="container">
<div class="errorPage">
<div class="main-content ">
<div class="fullscreen">
<div class="backColor"></div>
</div>
<div class="infos">
<div class="infos-main">
<div class="infos-h1"><h1>500</h1></div>
<div class="infos-h2">
<a href="javascript:window.history.back()" title="返回上一页">
<i class="fa fa-chevron-left"></i>
</a>
<a href="/" title="返回到主页">
<i class="fa fa-home"></i>
</a>
</div>
</div>
</div>
<div class="footer">
<span>Copyright © 2018</span>
<a href="${options.blog_title!}">${options.blog_title!'Halo'}</a>
<span style="float: right">
Background image from <a href="https://cn.bing.com/" target="_blank">Bing</a>.
</span>
</div>
</div>
</div>
</div>
</body>
<script src="//cdnjs.loli.net/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('$.o(\'m://q.8.n/?1=4%y%z%B.5.9%d.e%f%g%h%i%j%k\',l(b){6 a=b.p[0].1;6 c=$(\'.r\');c.t("u-v","1(4://s.w.5.x"+a+")");c.2(\'3 A\');$(\'.7-C\').2(\'3 D\');$(\'.7-E\').2(\'3 F\')});',42,42,'|url|addClass|animated|http|bing|var|infos|afeld|com||||2FHPImageArchive|aspx|3Fformat|3Djs|26idx|3D0|26n|3D1|function|https|me|get|images|jsonp|fullscreen||css|background|image|cn|net|3A|2F|fadeIn|2Fcn|h1|shake|h2|fadeInDown'.split('|'),0,{}))
</script>
</html>
</#compress>