Commit 1fedc9df authored by vcjmhg's avatar vcjmhg Committed by GitHub

Merge pull request #1 from 88250/dev

Dev
parents 62e165d1 298f85dd
...@@ -8676,17 +8676,17 @@ ...@@ -8676,17 +8676,17 @@
} }
}, },
"vcmt": { "vcmt": {
"version": "1.1.6", "version": "1.1.10",
"resolved": "https://registry.npmjs.org/vcmt/-/vcmt-1.1.6.tgz", "resolved": "https://registry.npmjs.org/vcmt/-/vcmt-1.1.10.tgz",
"integrity": "sha512-gWD+HZDuFrx7YFVtBBAVqGGh68HrjrV/qQaUOiXfmR1yTO6yeoyQPoAm1vnS4ux8fDDXdu8++yIOFQG9DLAQYA==", "integrity": "sha512-zx04s0R1vYN92zjFhDZbeWi/lapxl3KyeVtV6ccnRIPxYY4yteOFGcw82qTCTvehRjDL+x7zH8BBF5eDw9fv7g==",
"requires": { "requires": {
"jquery": "^3.4.1" "jquery": "^3.4.1"
} }
}, },
"vditor": { "vditor": {
"version": "3.1.12", "version": "3.1.20",
"resolved": "https://registry.npmjs.org/vditor/-/vditor-3.1.12.tgz", "resolved": "https://registry.npmjs.org/vditor/-/vditor-3.1.20.tgz",
"integrity": "sha512-PuGnHtC3hDM8vxGWv01+jzCLT+sC4UeeGyDtQNtUJbj8TrFmqTKKVlM8NLfeGx80nHan+xByrNF4FxntUGuAfw==", "integrity": "sha512-M1z9xIcjpP2mHyKJ9+a+5GaKXx0cNPyf58yMoJOJBSljGLVO3YNkMhqHUMfoZWiz9Ohf7DZTc4LctYPeGFsl5w==",
"requires": { "requires": {
"diff-match-patch": "^1.0.4" "diff-match-patch": "^1.0.4"
} }
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
"jquery": "^3.4.1", "jquery": "^3.4.1",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"uvstat": "^1.0.7", "uvstat": "^1.0.7",
"vcmt": "^1.1.6", "vcmt": "^1.1.10",
"vditor": "^3.1.12" "vditor": "^3.1.20"
} }
} }
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
</scm> </scm>
<properties> <properties>
<org.b3log.latke.version>3.3.3</org.b3log.latke.version> <org.b3log.latke.version>3.3.4</org.b3log.latke.version>
<jsoup.version>1.12.1</jsoup.version> <jsoup.version>1.12.1</jsoup.version>
<flexmark.version>0.50.40</flexmark.version> <flexmark.version>0.50.40</flexmark.version>
......
...@@ -49,7 +49,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -49,7 +49,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* Server. * Server.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 3.0.1.4, Apr 2, 2020 * @version 3.0.1.5, Apr 30, 2020
* @since 1.2.0 * @since 1.2.0
*/ */
public final class Server extends BaseServer { public final class Server extends BaseServer {
...@@ -246,12 +246,6 @@ public final class Server extends BaseServer { ...@@ -246,12 +246,6 @@ public final class Server extends BaseServer {
} }
} }
Dispatcher.startRequestHandler = new BeforeRequestHandler();
Dispatcher.HANDLERS.add(1, new SkinHandler());
Dispatcher.HANDLERS.add(2, new InitCheckHandler());
Dispatcher.HANDLERS.add(3, new PermalinkHandler());
Dispatcher.endRequestHandler = new AfterRequestHandler();
routeProcessors(); routeProcessors();
final Latkes.RuntimeDatabase runtimeDatabase = Latkes.getRuntimeDatabase(); final Latkes.RuntimeDatabase runtimeDatabase = Latkes.getRuntimeDatabase();
...@@ -410,6 +404,12 @@ public final class Server extends BaseServer { ...@@ -410,6 +404,12 @@ public final class Server extends BaseServer {
} }
public static void routeProcessors() { public static void routeProcessors() {
Dispatcher.startRequestHandler = new BeforeRequestHandler();
Dispatcher.HANDLERS.add(1, new SkinHandler());
Dispatcher.HANDLERS.add(2, new InitCheckHandler());
Dispatcher.HANDLERS.add(3, new PermalinkHandler());
Dispatcher.endRequestHandler = new AfterRequestHandler();
routeConsoleProcessors(); routeConsoleProcessors();
routeIndexProcessors(); routeIndexProcessors();
Dispatcher.mapping(); Dispatcher.mapping();
...@@ -634,6 +634,9 @@ public final class Server extends BaseServer { ...@@ -634,6 +634,9 @@ public final class Server extends BaseServer {
final Dispatcher.RouterGroup staticSiteConsoleGroup = Dispatcher.group(); final Dispatcher.RouterGroup staticSiteConsoleGroup = Dispatcher.group();
staticSiteConsoleGroup.middlewares(consoleAdminAuthMidware::handle); staticSiteConsoleGroup.middlewares(consoleAdminAuthMidware::handle);
staticSiteConsoleGroup.put("/console/staticsite", staticSiteConsole::genSite); staticSiteConsoleGroup.put("/console/staticsite", staticSiteConsole::genSite);
final FetchUploadProcessor fetchUploadProcessor = beanManager.getReference(FetchUploadProcessor.class);
Dispatcher.post("/upload/fetch", fetchUploadProcessor::fetchUpload, consoleAuthMidware::handle);
} }
/** /**
......
...@@ -16,21 +16,11 @@ package org.b3log.solo.model; ...@@ -16,21 +16,11 @@ package org.b3log.solo.model;
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @author <a href="https://hacpai.com/member/e">Dongxu Wang</a> * @author <a href="https://hacpai.com/member/e">Dongxu Wang</a>
* @version 1.7.0.8, Jan 18, 2020 * @version 1.7.0.9, Apr 30, 2020
* @since 0.3.1 * @since 0.3.1
*/ */
public final class Common { public final class Common {
/**
* Key of skin cookie name.
*/
public static final String COOKIE_NAME_SKIN = "skin";
/**
* Key of mobile skin cookie name.
*/
public static final String COOKIE_NAME_MOBILE_SKIN = "mobile-skin";
/** /**
* Key of favicon URL. * Key of favicon URL.
*/ */
......
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-present, b3log.org
*
* Solo is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.b3log.solo.processor;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.net.MimeTypes;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.http.RequestContext;
import org.b3log.latke.ioc.Singleton;
import org.b3log.latke.util.Strings;
import org.b3log.solo.model.Common;
import org.b3log.solo.util.Images;
import org.b3log.solo.util.Solos;
import org.json.JSONObject;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* File fetch upload processor. 第三方图床自动替换为社区图床 https://github.com/88250/solo/issues/114
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.0, Apr 30, 2020
* @since 4.1.0
*/
@Singleton
public class FetchUploadProcessor {
/**
* Logger.
*/
private static final Logger LOGGER = LogManager.getLogger(FetchUploadProcessor.class);
/**
* Fetches the remote file and upload it.
*
* @param context the specified context
*/
public void fetchUpload(final RequestContext context) {
final JSONObject result = Solos.newFail();
context.renderJSONPretty(result);
final JSONObject data = new JSONObject();
final JSONObject requestJSONObject = context.requestJSON();
final String originalURL = requestJSONObject.optString(Common.URL);
if (!Strings.isURL(originalURL) || !StringUtils.startsWithIgnoreCase(originalURL, "http")) {
return;
}
if (Images.uploaded(originalURL)) {
return;
}
final JSONObject upload = Solos.getUploadToken(context);
if (null == upload) {
final String msg = "Gets upload token failed";
LOGGER.log(Level.ERROR, msg);
result.put(Keys.MSG, msg);
return;
}
String url;
byte[] bytes;
String contentType;
try {
final HttpRequest req = HttpRequest.get(originalURL).header("User-Agent", Solos.USER_AGENT);
final HttpResponse res = req.connectionTimeout(3000).timeout(5000).send();
res.close();
if (200 != res.statusCode()) {
result.put(Keys.MSG, "Fetch upload return status code is [" + res.statusCode() + "]");
return;
}
bytes = res.bodyBytes();
contentType = res.contentType();
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Fetch file [url=" + originalURL + "] failed", e);
result.put(Keys.MSG, "Fetch file [url=" + originalURL + "] failed");
return;
}
final String uploadURL = upload.optString(Common.UPLOAD_URL);
final String uploadToken = upload.optString(Common.UPLOAD_TOKEN);
try {
final String suffix = "." + getSuffix(contentType);
final Path imgFilePath = Files.createTempFile("solo-fetchupload-", suffix);
final File file = imgFilePath.toFile();
FileUtils.writeByteArrayToFile(file, bytes);
final HttpRequest req = HttpRequest.post(uploadURL).
header("User-Agent", Solos.USER_AGENT).header("X-Upload-Token", uploadToken).
connectionTimeout(3000).timeout(5000).form(
"file[]", file);
final HttpResponse res = req.send();
res.close();
if (200 != res.statusCode()) {
result.put(Keys.MSG, "Upload file to community OSS return status code is [" + res.statusCode() + "]");
return;
}
res.charset("UTF-8");
final JSONObject uploadResult = new JSONObject(res.bodyText());
final JSONObject succMap = uploadResult.optJSONObject("data").optJSONObject("succMap");
final String key = succMap.keys().next();
url = succMap.optString(key);
} catch (final Exception e) {
final String msg = "Upload file to community OSS [url=" + originalURL + "] failed";
LOGGER.log(Level.ERROR, msg, e);
result.put(Keys.MSG, msg);
return;
}
data.put(Common.URL, url);
data.put("originalURL", originalURL);
result.put(Common.DATA, data);
result.put(Keys.CODE, 0);
result.put(Keys.MSG, "");
}
/**
* Gets suffix (for example jpg) with the specified content type.
*
* @param contentType the specified content type
* @return suffix
*/
public static String getSuffix(final String contentType) {
String ret;
final String[] exts = MimeTypes.findExtensionsByMimeTypes(contentType, false);
if (null != exts && 0 < exts.length) {
ret = exts[0];
} else {
ret = StringUtils.substringAfter(contentType, "/");
ret = StringUtils.substringBefore(ret, ";");
}
return ret;
}
}
...@@ -17,10 +17,8 @@ import org.apache.logging.log4j.LogManager; ...@@ -17,10 +17,8 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.b3log.latke.Keys; import org.b3log.latke.Keys;
import org.b3log.latke.Latkes; import org.b3log.latke.Latkes;
import org.b3log.latke.http.Cookie;
import org.b3log.latke.http.Request; import org.b3log.latke.http.Request;
import org.b3log.latke.http.RequestContext; import org.b3log.latke.http.RequestContext;
import org.b3log.latke.http.Response;
import org.b3log.latke.http.renderer.AbstractFreeMarkerRenderer; import org.b3log.latke.http.renderer.AbstractFreeMarkerRenderer;
import org.b3log.latke.ioc.Inject; import org.b3log.latke.ioc.Inject;
import org.b3log.latke.ioc.Singleton; import org.b3log.latke.ioc.Singleton;
...@@ -49,7 +47,7 @@ import java.util.Map; ...@@ -49,7 +47,7 @@ import java.util.Map;
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @author <a href="https://hacpai.com/member/DASHU">DASHU</a> * @author <a href="https://hacpai.com/member/DASHU">DASHU</a>
* @author <a href="http://vanessa.b3log.org">Vanessa</a> * @author <a href="http://vanessa.b3log.org">Vanessa</a>
* @version 2.0.0.1, Apr 18, 2020 * @version 2.0.0.2, Apr 30, 2020
* @since 0.3.1 * @since 0.3.1
*/ */
@Singleton @Singleton
...@@ -92,34 +90,12 @@ public class IndexProcessor { ...@@ -92,34 +90,12 @@ public class IndexProcessor {
*/ */
public void showIndex(final RequestContext context) { public void showIndex(final RequestContext context) {
final Request request = context.getRequest(); final Request request = context.getRequest();
final Response response = context.getResponse();
final AbstractFreeMarkerRenderer renderer = new SkinRenderer(context, "index.ftl"); final AbstractFreeMarkerRenderer renderer = new SkinRenderer(context, "index.ftl");
final Map<String, Object> dataModel = renderer.getDataModel(); final Map<String, Object> dataModel = renderer.getDataModel();
try { try {
final int currentPageNum = Paginator.getPage(request); final int currentPageNum = Paginator.getPage(request);
final JSONObject preference = optionQueryService.getPreference(); final JSONObject preference = optionQueryService.getPreference();
// 前台皮肤切换 https://github.com/b3log/solo/issues/12060
String specifiedSkin = Skins.getSkinDirName(context);
if (StringUtils.isBlank(specifiedSkin)) {
final JSONObject skinOpt = optionQueryService.getSkin();
specifiedSkin = Solos.isMobile(request) ?
skinOpt.optString(Option.ID_C_MOBILE_SKIN_DIR_NAME) :
skinOpt.optString(Option.ID_C_SKIN_DIR_NAME);
}
request.setAttribute(Keys.TEMAPLTE_DIR_NAME, specifiedSkin);
Cookie cookie;
if (!Solos.isMobile(request)) {
cookie = new Cookie(Common.COOKIE_NAME_SKIN, specifiedSkin);
} else {
cookie = new Cookie(Common.COOKIE_NAME_MOBILE_SKIN, specifiedSkin);
}
cookie.setMaxAge(60 * 60); // 1 hour
cookie.setPath("/");
response.addCookie(cookie);
Skins.fillLangs(preference.optString(Option.ID_C_LOCALE_STRING), (String) context.attr(Keys.TEMAPLTE_DIR_NAME), dataModel); Skins.fillLangs(preference.optString(Option.ID_C_LOCALE_STRING), (String) context.attr(Keys.TEMAPLTE_DIR_NAME), dataModel);
dataModelService.fillIndexArticles(context, dataModel, currentPageNum, preference); dataModelService.fillIndexArticles(context, dataModel, currentPageNum, preference);
......
...@@ -33,7 +33,7 @@ import org.json.JSONObject; ...@@ -33,7 +33,7 @@ import org.json.JSONObject;
* Skin handler. * Skin handler.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.0, Nov 3, 2019 * @version 1.0.0.1, Apr 30, 2020
* @since 3.6.7 * @since 3.6.7
*/ */
public class SkinHandler implements Handler { public class SkinHandler implements Handler {
...@@ -62,11 +62,12 @@ public class SkinHandler implements Handler { ...@@ -62,11 +62,12 @@ public class SkinHandler implements Handler {
/** /**
* Resolve skin (template) for the specified HTTP request. * Resolve skin (template) for the specified HTTP request.
* 前台皮肤切换 https://github.com/b3log/solo/issues/12060 * 前台皮肤切换 https://github.com/b3log/solo/issues/12060
* 调整前台动态皮肤预览逻辑 https://github.com/88250/solo/issues/116
* *
* @param request the specified HTTP request * @param request the specified HTTP request
*/ */
private void resolveSkinDir(final Request request) { private void resolveSkinDir(final Request request) {
String skin = Skins.getSkinDirNameFromCookie(request); String skin = Skins.getQuerySkin(request);
if (StringUtils.isBlank(skin)) { if (StringUtils.isBlank(skin)) {
final BeanManager beanManager = BeanManager.getInstance(); final BeanManager beanManager = BeanManager.getInstance();
final OptionQueryService optionQueryService = beanManager.getReference(OptionQueryService.class); final OptionQueryService optionQueryService = beanManager.getReference(OptionQueryService.class);
...@@ -85,7 +86,6 @@ public class SkinHandler implements Handler { ...@@ -85,7 +86,6 @@ public class SkinHandler implements Handler {
} }
} }
} }
request.setAttribute(Keys.TEMAPLTE_DIR_NAME, skin); request.setAttribute(Keys.TEMAPLTE_DIR_NAME, skin);
} }
......
...@@ -16,15 +16,12 @@ import org.apache.logging.log4j.LogManager; ...@@ -16,15 +16,12 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.b3log.latke.Keys; import org.b3log.latke.Keys;
import org.b3log.latke.Latkes; import org.b3log.latke.Latkes;
import org.b3log.latke.http.Cookie;
import org.b3log.latke.http.RequestContext; import org.b3log.latke.http.RequestContext;
import org.b3log.latke.http.Response;
import org.b3log.latke.http.renderer.JsonRenderer; import org.b3log.latke.http.renderer.JsonRenderer;
import org.b3log.latke.ioc.Inject; import org.b3log.latke.ioc.Inject;
import org.b3log.latke.ioc.Singleton; import org.b3log.latke.ioc.Singleton;
import org.b3log.latke.service.LangPropsService; import org.b3log.latke.service.LangPropsService;
import org.b3log.latke.service.ServiceException; import org.b3log.latke.service.ServiceException;
import org.b3log.solo.model.Common;
import org.b3log.solo.model.Option; import org.b3log.solo.model.Option;
import org.b3log.solo.service.OptionQueryService; import org.b3log.solo.service.OptionQueryService;
import org.b3log.solo.service.SkinMgmtService; import org.b3log.solo.service.SkinMgmtService;
...@@ -39,7 +36,7 @@ import java.util.Set; ...@@ -39,7 +36,7 @@ import java.util.Set;
* Skin console request processing. * Skin console request processing.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 2.0.0.0, Feb 9, 2020 * @version 2.1.0.0, Apr 30, 2020
* @since 3.5.0 * @since 3.5.0
*/ */
@Singleton @Singleton
...@@ -157,16 +154,6 @@ public class SkinConsole { ...@@ -157,16 +154,6 @@ public class SkinConsole {
skinMgmtService.updateSkin(skin); skinMgmtService.updateSkin(skin);
final Response response = context.getResponse();
final Cookie skinDirNameCookie = new Cookie(Common.COOKIE_NAME_SKIN, skin.getString(Option.ID_C_SKIN_DIR_NAME));
skinDirNameCookie.setMaxAge(60 * 60); // 1 hour
skinDirNameCookie.setPath("/");
response.addCookie(skinDirNameCookie);
final Cookie mobileSkinDirNameCookie = new Cookie(Common.COOKIE_NAME_MOBILE_SKIN, skin.getString(Option.ID_C_MOBILE_SKIN_DIR_NAME));
mobileSkinDirNameCookie.setMaxAge(60 * 60); // 1 hour
mobileSkinDirNameCookie.setPath("/");
response.addCookie(mobileSkinDirNameCookie);
ret.put(Keys.STATUS_CODE, true); ret.put(Keys.STATUS_CODE, true);
ret.put(Keys.MSG, langPropsService.get("updateSuccLabel")); ret.put(Keys.MSG, langPropsService.get("updateSuccLabel"));
...@@ -179,18 +166,4 @@ public class SkinConsole { ...@@ -179,18 +166,4 @@ public class SkinConsole {
jsonObject.put(Keys.MSG, langPropsService.get("updateFailLabel")); jsonObject.put(Keys.MSG, langPropsService.get("updateFailLabel"));
} }
} }
/**
* Checks whether the specified input is a non-negative integer.
*
* @param input the specified input
* @return {@code true} if it is, returns {@code false} otherwise
*/
private boolean isNonNegativeInteger(final String input) {
try {
return 0 <= Integer.valueOf(input);
} catch (final Exception e) {
return false;
}
}
} }
...@@ -47,7 +47,7 @@ import java.util.List; ...@@ -47,7 +47,7 @@ import java.util.List;
* Solo initialization service. * Solo initialization service.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.5.2.39, Apr 6, 2020 * @version 1.5.2.40, Apr 30, 2020
* @since 0.4.0 * @since 0.4.0
*/ */
@Service @Service
...@@ -133,7 +133,7 @@ public class InitService { ...@@ -133,7 +133,7 @@ public class InitService {
/** /**
* Flag of init status. * Flag of init status.
*/ */
private static boolean inited; public static boolean inited;
/** /**
* Flag of printed init prompt. * Flag of printed init prompt.
......
...@@ -29,7 +29,7 @@ import java.util.concurrent.ThreadLocalRandom; ...@@ -29,7 +29,7 @@ import java.util.concurrent.ThreadLocalRandom;
* Image utilities. * Image utilities.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.1.2.0, Apr 12, 2020 * @version 1.2.0.0, Apr 30, 2020
* @since 2.7.0 * @since 2.7.0
*/ */
public final class Images { public final class Images {
...@@ -44,6 +44,16 @@ public final class Images { ...@@ -44,6 +44,16 @@ public final class Images {
*/ */
public static String COMMUNITY_FILE_URL = "https://img.hacpai.com"; public static String COMMUNITY_FILE_URL = "https://img.hacpai.com";
/**
* Checks whether the specified URL has uploaded.
*
* @param url the specified URL
* @return {@code true} if it has uploaded, returns {@code false} otherwise
*/
public static boolean uploaded(final String url) {
return StringUtils.startsWith(url, COMMUNITY_FILE_URL);
}
/** /**
* Qiniu image processing. * Qiniu image processing.
* *
......
...@@ -20,7 +20,6 @@ import org.apache.logging.log4j.LogManager; ...@@ -20,7 +20,6 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.b3log.latke.Keys; import org.b3log.latke.Keys;
import org.b3log.latke.Latkes; import org.b3log.latke.Latkes;
import org.b3log.latke.http.Cookie;
import org.b3log.latke.http.Request; import org.b3log.latke.http.Request;
import org.b3log.latke.http.RequestContext; import org.b3log.latke.http.RequestContext;
import org.b3log.latke.ioc.BeanManager; import org.b3log.latke.ioc.BeanManager;
...@@ -28,7 +27,6 @@ import org.b3log.latke.service.LangPropsService; ...@@ -28,7 +27,6 @@ import org.b3log.latke.service.LangPropsService;
import org.b3log.latke.service.ServiceException; import org.b3log.latke.service.ServiceException;
import org.b3log.latke.util.Locales; import org.b3log.latke.util.Locales;
import org.b3log.latke.util.Stopwatchs; import org.b3log.latke.util.Stopwatchs;
import org.b3log.solo.model.Common;
import org.b3log.solo.model.Option; import org.b3log.solo.model.Option;
import java.io.File; import java.io.File;
...@@ -43,7 +41,7 @@ import java.util.stream.Stream; ...@@ -43,7 +41,7 @@ import java.util.stream.Stream;
* Skin utilities. * Skin utilities.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.1.7.0, Jan 14, 2020 * @version 1.2.0.0, Apr 30, 2020
* @since 0.3.1 * @since 0.3.1
*/ */
public final class Skins { public final class Skins {
...@@ -232,64 +230,21 @@ public final class Skins { ...@@ -232,64 +230,21 @@ public final class Skins {
/** /**
* Gets skin directory name from the specified request. * Gets skin directory name from the specified request.
* Refers to <a href="https://github.com/b3log/solo/issues/12060">前台皮肤切换</a> for more details. * Refers to <a href="https://github.com/b3log/solo/issues/12060">前台皮肤切换</a> and
* <a href="https://github.com/88250/solo/issues/116">调整前台动态皮肤预览逻辑</a> for more details.
* *
* @param context the specified request context * @param request the specified request
* @return directory name, or {@code null} if not found * @return directory name, or {@code null} if not found
*/ */
public static String getSkinDirName(final RequestContext context) { public static String getQuerySkin(final Request request) {
// 1. Get skin from query final String specifiedSkin = request.getParameter(Option.CATEGORY_C_SKIN);
final String specifiedSkin = context.param(Option.CATEGORY_C_SKIN);
if (StringUtils.isNotBlank(specifiedSkin)) { if (StringUtils.isNotBlank(specifiedSkin)) {
final Set<String> skinDirNames = Skins.getSkinDirNames(); final Set<String> skinDirNames = Skins.getSkinDirNames();
if (skinDirNames.contains(specifiedSkin)) { if (skinDirNames.contains(specifiedSkin)) {
return specifiedSkin; return specifiedSkin;
} else {
return null;
} }
} }
// 2. Get skin from cookie
return getSkinDirNameFromCookie(context.getRequest());
}
/**
* Gets skin directory name from the specified request's cookie.
*
* @param request the specified request
* @return directory name, or {@code null} if not found
*/
public static String getSkinDirNameFromCookie(final Request request) {
final Set<String> skinDirNames = Skins.getSkinDirNames();
boolean isMobile = Solos.isMobile(request);
String skin = null, mobileSkin = null;
final Set<Cookie> cookies = request.getCookies();
if (!cookies.isEmpty()) {
for (final Cookie cookie : cookies) {
if (Common.COOKIE_NAME_SKIN.equals(cookie.getName()) && !isMobile) {
final String s = cookie.getValue();
if (skinDirNames.contains(s)) {
skin = s;
break;
}
}
if (Common.COOKIE_NAME_MOBILE_SKIN.equals(cookie.getName()) && isMobile) {
final String s = cookie.getValue();
if (skinDirNames.contains(s)) {
mobileSkin = s;
break;
}
}
}
}
if (StringUtils.isNotBlank(skin)) {
return skin;
}
if (StringUtils.isNotBlank(mobileSkin)) {
return mobileSkin;
}
return null; return null;
} }
......
...@@ -18,6 +18,7 @@ import org.apache.logging.log4j.Level; ...@@ -18,6 +18,7 @@ import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.b3log.latke.http.RequestContext; import org.b3log.latke.http.RequestContext;
import org.b3log.solo.model.Option;
import org.b3log.solo.processor.SkinRenderer; import org.b3log.solo.processor.SkinRenderer;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<#if isLoggedIn && commentable> <#if isLoggedIn && commentable>
<div style="position: fixed;bottom: -300px;width: 100%;opacity: 0;background-color: #f1f7fe;padding: 20px 0;transition: all .15s ease-in-out;z-index: 100;left: 0;" <div style="position: fixed;bottom: -300px;width: 100%;opacity: 0;background-color: #f1f7fe;padding: 20px 0;transition: all .15s ease-in-out;z-index: 100;left: 0;"
id="soloEditor"> id="soloEditor">
<div style="max-width: 768px;margin: 0 auto;padding: 0 10px;"> <div style="max-width: 920px;margin: 0 auto;padding: 0 10px;">
<div id="soloEditorComment"></div> <div id="soloEditorComment"></div>
<div style="display: flex;margin-top: 10px;line-height: 30px"> <div style="display: flex;margin-top: 10px;line-height: 30px">
<div style="flex: 1;" id="soloEditorReplyTarget"></div> <div style="flex: 1;" id="soloEditorReplyTarget"></div>
......
This diff is collapsed.
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* @author <a href="http://vanessa.b3log.org">Liyuan Li</a> * @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.6.0.0, Apr 16, 2020 * @version 1.6.0.1, Apr 30, 2020
*/ */
admin.editors = {} admin.editors = {}
...@@ -81,6 +81,7 @@ $.extend(SoloEditor.prototype, { ...@@ -81,6 +81,7 @@ $.extend(SoloEditor.prototype, {
upload: { upload: {
max: 10 * 1024 * 1024, max: 10 * 1024 * 1024,
url: Label.uploadURL, url: Label.uploadURL,
linkToImgUrl: Label.servePath + '/upload/fetch',
token: Label.uploadToken, token: Label.uploadToken,
filename: function (name) { filename: function (name) {
return name.replace(/[^(a-zA-Z0-9\u4e00-\u9fa5\.)]/g, ''). return name.replace(/[^(a-zA-Z0-9\u4e00-\u9fa5\.)]/g, '').
...@@ -116,10 +117,20 @@ $.extend(SoloEditor.prototype, { ...@@ -116,10 +117,20 @@ $.extend(SoloEditor.prototype, {
'emoji', 'emoji',
'link', 'link',
'upload', 'upload',
'insert-after',
'edit-mode', 'edit-mode',
'preview', 'code-theme',
'fullscreen', 'content-theme',
{
name: 'more',
toolbar: [
'insert-after',
'fullscreen',
'preview',
'format',
'info',
'help',
],
},
] ]
options.resize.enable = false options.resize.enable = false
options.toolbarConfig.pin = true options.toolbarConfig.pin = true
......
...@@ -23,7 +23,7 @@ window.Vcomment = Vcomment ...@@ -23,7 +23,7 @@ window.Vcomment = Vcomment
* *
* @author <a href="http://vanessa.b3log.org">Liyuan Li</a> * @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 2.2.0.1, Feb 23, 2020 * @version 2.2.1.0, Apr 30, 2020
*/ */
/** /**
...@@ -109,7 +109,14 @@ window.Util = { ...@@ -109,7 +109,14 @@ window.Util = {
return true return true
}, },
callback: function () { callback: function () {
Util.parseMarkdown() try {
// TODO vditor@3.1.21 移除 try cache
Util.parseMarkdown()
} catch (e) {
}
if (typeof Util.uvstat === 'undefined') {
Util.uvstat = new Uvstat()
}
Util.uvstat.addStat() Util.uvstat.addStat()
Util.uvstat.renderStat() Util.uvstat.renderStat()
Util.uvstat.renderCmtStat( Util.uvstat.renderCmtStat(
...@@ -303,7 +310,7 @@ window.Util = { ...@@ -303,7 +310,7 @@ window.Util = {
loadVditor: function (cb) { loadVditor: function (cb) {
$.ajax({ $.ajax({
method: 'GET', method: 'GET',
url: 'https://cdn.jsdelivr.net/npm/vditor@3.1.12/dist/index.min.js', url: 'https://cdn.jsdelivr.net/npm/vditor@3.1.20/dist/index.min.js',
dataType: 'script', dataType: 'script',
cache: true, cache: true,
success: () => { success: () => {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* @author <a href="http://vanessa.b3log.org">Liyuan Li</a> * @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 2.8.0.0, Apr 16, 2020 * @version 2.8.0.1, Apr 30, 2020
*/ */
window.Page = function (tips) { window.Page = function (tips) {
this.currentCommentId = '' this.currentCommentId = ''
...@@ -95,7 +95,8 @@ $.extend(Page.prototype, { ...@@ -95,7 +95,8 @@ $.extend(Page.prototype, {
value: shareURL, value: shareURL,
size: 99, size: 99,
}) })
$qrCode.css('background-image', `url(${qr.toDataURL('image/jpeg')})`).show() $qrCode.css('background-image', `url(${qr.toDataURL('image/jpeg')})`).
show()
} else { } else {
$qrCode.slideToggle() $qrCode.slideToggle()
} }
...@@ -132,6 +133,7 @@ $.extend(Page.prototype, { ...@@ -132,6 +133,7 @@ $.extend(Page.prototype, {
if (!$('#soloEditorComment').hasClass('vditor')) { if (!$('#soloEditorComment').hasClass('vditor')) {
var that = this var that = this
var resizeEnable = true
var toolbar = [ var toolbar = [
'emoji', 'emoji',
'headings', 'headings',
...@@ -153,29 +155,44 @@ $.extend(Page.prototype, { ...@@ -153,29 +155,44 @@ $.extend(Page.prototype, {
'table', 'table',
'insert-before', 'insert-before',
'insert-after', 'insert-after',
'|',
'undo', 'undo',
'redo', 'redo',
'|', '|',
'edit-mode',
'both',
'preview',
'format',
'|',
'fullscreen', 'fullscreen',
'devtools', 'edit-mode',
'info', {
'help', name: 'more',
], resizeEnable = true toolbar: [
'both',
'code-theme',
'content-theme',
'export',
'outline',
'preview',
'format',
'devtools',
'info',
'help',
],
}]
if ($(window).width() < 768) { if ($(window).width() < 768) {
toolbar = [ toolbar = [
'emoji', 'emoji',
'link', 'link',
'upload',
'insert-after',
'edit-mode', 'edit-mode',
'preview', 'code-theme',
'fullscreen', 'content-theme',
{
name: 'more',
toolbar: [
'insert-after',
'fullscreen',
'preview',
'format',
'info',
'help',
],
},
] ]
resizeEnable = false resizeEnable = false
} }
...@@ -214,7 +231,7 @@ $.extend(Page.prototype, { ...@@ -214,7 +231,7 @@ $.extend(Page.prototype, {
position: 'top', position: 'top',
}, },
lang: Label.langLabel, lang: Label.langLabel,
toolbar: toolbar, toolbar,
after: () => { after: () => {
vditor.focus() vditor.focus()
}, },
......
This diff is collapsed.
This diff is collapsed.
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* @author <a href="http://vanessa.b3log.org">Liyuan Li</a> * @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 3.3.0.2, Feb 9, 2020 * @version 3.3.1.0, Apr 30, 2020
*/ */
@import "reset"; @import "reset";
@import "function"; @import "function";
...@@ -960,6 +960,10 @@ button#submitArticle:hover { ...@@ -960,6 +960,10 @@ button#submitArticle:hover {
border-radius: 0 0 3px 3px; border-radius: 0 0 3px 3px;
} }
.solo-kanbanniang {
z-index: 1;
}
@media (max-width: 768px) { @media (max-width: 768px) {
#top > a { #top > a {
display: none; display: none;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -19,7 +19,6 @@ import org.b3log.latke.http.Dispatcher; ...@@ -19,7 +19,6 @@ import org.b3log.latke.http.Dispatcher;
import org.b3log.latke.http.Request; import org.b3log.latke.http.Request;
import org.b3log.latke.http.Response; import org.b3log.latke.http.Response;
import org.b3log.latke.ioc.BeanManager; import org.b3log.latke.ioc.BeanManager;
import org.b3log.latke.ioc.Discoverer;
import org.b3log.latke.model.User; import org.b3log.latke.model.User;
import org.b3log.latke.repository.jdbc.util.Connections; import org.b3log.latke.repository.jdbc.util.Connections;
import org.b3log.latke.repository.jdbc.util.JdbcRepositories; import org.b3log.latke.repository.jdbc.util.JdbcRepositories;
...@@ -40,13 +39,12 @@ import org.testng.annotations.BeforeMethod; ...@@ -40,13 +39,12 @@ import org.testng.annotations.BeforeMethod;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.sql.Connection; import java.sql.Connection;
import java.util.Collection;
/** /**
* Abstract test case. * Abstract test case.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 4.0.0.0, Feb 9, 2020 * @version 4.0.0.1, Apr 30, 2020
* @since 2.9.7 * @since 2.9.7
*/ */
public abstract class AbstractTestCase { public abstract class AbstractTestCase {
...@@ -56,6 +54,11 @@ public abstract class AbstractTestCase { ...@@ -56,6 +54,11 @@ public abstract class AbstractTestCase {
*/ */
private BeanManager beanManager; private BeanManager beanManager;
static {
Latkes.init();
Server.routeProcessors();
}
/** /**
* Before class. * Before class.
* <ol> * <ol>
...@@ -67,10 +70,7 @@ public abstract class AbstractTestCase { ...@@ -67,10 +70,7 @@ public abstract class AbstractTestCase {
*/ */
@BeforeClass @BeforeClass
public void beforeClass() throws Exception { public void beforeClass() throws Exception {
Latkes.init(); System.out.println("before class");
final Collection<Class<?>> classes = Discoverer.discover("org.b3log.solo");
BeanManager.start(classes);
beanManager = BeanManager.getInstance(); beanManager = BeanManager.getInstance();
final Connection connection = Connections.getConnection(); final Connection connection = Connections.getConnection();
...@@ -78,6 +78,7 @@ public abstract class AbstractTestCase { ...@@ -78,6 +78,7 @@ public abstract class AbstractTestCase {
connection.close(); connection.close();
JdbcRepositories.initAllTables(); JdbcRepositories.initAllTables();
InitService.inited = false;
initSolo(); initSolo();
} }
...@@ -147,8 +148,6 @@ public abstract class AbstractTestCase { ...@@ -147,8 +148,6 @@ public abstract class AbstractTestCase {
*/ */
public MockDispatcher mockDispatcher(final Request request, final Response response) { public MockDispatcher mockDispatcher(final Request request, final Response response) {
final MockDispatcher ret = new MockDispatcher(); final MockDispatcher ret = new MockDispatcher();
ret.init();
Server.routeProcessors();
ret.handle(request, response); ret.handle(request, response);
return ret; return ret;
......
...@@ -25,5 +25,6 @@ public class MockRequest extends Request { ...@@ -25,5 +25,6 @@ public class MockRequest extends Request {
public MockRequest(final FullHttpRequest req) { public MockRequest(final FullHttpRequest req) {
super(null, req); super(null, req);
req.headers().set("X-Forwarded-For", "127.0.0.1");
} }
} }
\ No newline at end of file
...@@ -22,7 +22,7 @@ import org.testng.annotations.Test; ...@@ -22,7 +22,7 @@ import org.testng.annotations.Test;
* {@link ErrorProcessor} test case. * {@link ErrorProcessor} test case.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.1.3, Feb 22, 2019 * @version 1.0.1.4, Apr 30, 2020
* @since 1.7.0 * @since 1.7.0
*/ */
@Test(suiteName = "processor") @Test(suiteName = "processor")
...@@ -33,11 +33,11 @@ public class ErrorProcessorTestCase extends AbstractTestCase { ...@@ -33,11 +33,11 @@ public class ErrorProcessorTestCase extends AbstractTestCase {
*/ */
public void showErrorPage() { public void showErrorPage() {
final MockRequest request = mockRequest(); final MockRequest request = mockRequest();
request.setRequestURI("/error/403"); request.setRequestURI("/notfound");
final MockResponse response = mockResponse(); final MockResponse response = mockResponse();
mockDispatcher(request, response); mockDispatcher(request, response);
final String content = response.getString(); final String content = response.getString();
Assert.assertTrue(StringUtils.contains(content, "<title>403 Forbidden! - Solo 的个人博客</title>")); Assert.assertTrue(StringUtils.contains(content, "<title>404 Not Found! - Solo 的个人博客</title>"));
} }
} }
...@@ -14,32 +14,16 @@ package org.b3log.solo.processor; ...@@ -14,32 +14,16 @@ package org.b3log.solo.processor;
import org.b3log.latke.http.Dispatcher; import org.b3log.latke.http.Dispatcher;
import org.b3log.latke.http.Request; import org.b3log.latke.http.Request;
import org.b3log.latke.http.Response; import org.b3log.latke.http.Response;
import org.b3log.latke.http.function.Handler;
import org.b3log.latke.http.handler.InvokeHandler;
import org.b3log.latke.http.handler.RouteHandler;
import java.util.ArrayList;
import java.util.List;
/** /**
* Mock dispatcher for unit tests. * Mock dispatcher for unit tests.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 2.0.0.0, Feb 9, 2020 * @version 2.0.0.1, Apr 30, 2020
* @since 1.7.0 * @since 1.7.0
*/ */
public class MockDispatcher { public class MockDispatcher {
/**
* Handlers
*/
private static final List<Handler> HANDLERS = new ArrayList<>();
public void init() {
HANDLERS.add(new RouteHandler());
HANDLERS.add(new InvokeHandler());
}
public void handle(final Request req, final Response resp) { public void handle(final Request req, final Response resp) {
Dispatcher.handle(req, resp); Dispatcher.handle(req, resp);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment