From a3448adee28b954f6c20f87df500f5d32cc95761 Mon Sep 17 00:00:00 2001
From: guqing <38999863+guqing@users.noreply.github.com>
Date: Tue, 18 Oct 2022 10:22:09 +0800
Subject: [PATCH] feat: add favicon head processor (#2582)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
#### What type of PR is this?
/kind feature
/area core
/milestone 2.0
#### What this PR does / why we need it:
模板渲染自动填充 Favicon 到 head 标签
#### Which issue(s) this PR fixes:
Fixes #2581
#### Special notes for your reviewer:
how to test it?
在 console 系统设置 -> 基础设置 填写 Favicon 后,到主题端能到看它
/cc @halo-dev/sig-halo
#### Does this PR introduce a user-facing change?
```release-note
支持设置 Favicon
```
---
.../dialect/DefaultFaviconHeadProcessor.java | 46 +++++++++++++++++++
.../dialect/HaloProcessorDialectTest.java | 12 +++++
2 files changed, 58 insertions(+)
create mode 100644 src/main/java/run/halo/app/theme/dialect/DefaultFaviconHeadProcessor.java
diff --git a/src/main/java/run/halo/app/theme/dialect/DefaultFaviconHeadProcessor.java b/src/main/java/run/halo/app/theme/dialect/DefaultFaviconHeadProcessor.java
new file mode 100644
index 000000000..d8986ea64
--- /dev/null
+++ b/src/main/java/run/halo/app/theme/dialect/DefaultFaviconHeadProcessor.java
@@ -0,0 +1,46 @@
+package run.halo.app.theme.dialect;
+
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+import org.thymeleaf.context.ITemplateContext;
+import org.thymeleaf.model.IModel;
+import org.thymeleaf.model.IModelFactory;
+import org.thymeleaf.processor.element.IElementModelStructureHandler;
+import reactor.core.publisher.Mono;
+import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
+import run.halo.app.infra.SystemSetting;
+
+/**
+ * Theme template head
tag snippet injection processor for favicon.
+ *
+ * @author guqing
+ * @since 2.0.0
+ */
+@Component
+@AllArgsConstructor
+public class DefaultFaviconHeadProcessor implements TemplateHeadProcessor {
+
+ private final SystemConfigurableEnvironmentFetcher fetcher;
+
+ @Override
+ public Mono process(ITemplateContext context, IModel model,
+ IElementModelStructureHandler structureHandler) {
+ return fetchBasicSetting()
+ .filter(basic -> StringUtils.isNotBlank(basic.getFavicon()))
+ .map(basic -> {
+ IModelFactory modelFactory = context.getModelFactory();
+ model.add(modelFactory.createText(faviconSnippet(basic.getFavicon())));
+ return model;
+ })
+ .then();
+ }
+
+ private String faviconSnippet(String favicon) {
+ return String.format("\n", favicon);
+ }
+
+ private Mono fetchBasicSetting() {
+ return fetcher.fetch(SystemSetting.Basic.GROUP, SystemSetting.Basic.class);
+ }
+}
diff --git a/src/test/java/run/halo/app/theme/dialect/HaloProcessorDialectTest.java b/src/test/java/run/halo/app/theme/dialect/HaloProcessorDialectTest.java
index ee5960739..74c219dfc 100644
--- a/src/test/java/run/halo/app/theme/dialect/HaloProcessorDialectTest.java
+++ b/src/test/java/run/halo/app/theme/dialect/HaloProcessorDialectTest.java
@@ -69,6 +69,7 @@ class HaloProcessorDialectTest {
Map map = new HashMap<>();
map.put("postTemplateHeadProcessor", new PostTemplateHeadProcessor(postFinder));
map.put("templateGlobalHeadProcessor", new TemplateGlobalHeadProcessor(fetcher));
+ map.put("faviconHeadProcessor", new DefaultFaviconHeadProcessor(fetcher));
lenient().when(applicationContext.getBeansOfType(TemplateHeadProcessor.class))
.thenReturn(map);
@@ -85,6 +86,11 @@ class HaloProcessorDialectTest {
@Test
void globalHeadAndFooterProcessors() {
+ SystemSetting.Basic basic = new SystemSetting.Basic();
+ basic.setFavicon("favicon.ico");
+ when(fetcher.fetch(eq(SystemSetting.Basic.GROUP),
+ eq(SystemSetting.Basic.class))).thenReturn(Mono.just(basic));
+
Context context = getContext();
String result = templateEngine.process("index", context);
@@ -95,6 +101,7 @@ class HaloProcessorDialectTest {
Index
+
index
@@ -124,6 +131,11 @@ class HaloProcessorDialectTest {
.metadata(metadata).build();
when(postFinder.getByName(eq("fake-post"))).thenReturn(postVo);
+ SystemSetting.Basic basic = new SystemSetting.Basic();
+ basic.setFavicon(null);
+ when(fetcher.fetch(eq(SystemSetting.Basic.GROUP),
+ eq(SystemSetting.Basic.class))).thenReturn(Mono.just(basic));
+
String result = templateEngine.process("post", context);
assertThat(result).isEqualTo("""