Skip to content

Commit

Permalink
feat:implement global HTML injection for head and footer
Browse files Browse the repository at this point in the history
  • Loading branch information
CaiHaosen committed Aug 7, 2024
1 parent 864f49b commit f36ae3f
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 2 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ repositories {
}

dependencies {
implementation platform('run.halo.tools.platform:plugin:2.11.0-SNAPSHOT')
implementation platform('run.halo.tools.platform:plugin:2.17.0-SNAPSHOT')
compileOnly 'run.halo.app:api'

testImplementation 'run.halo.app:api'
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/run/halo/injection/AbstractHtmlProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package run.halo.injection;

import java.util.Set;
import org.thymeleaf.context.ITemplateContext;

public abstract class AbstractHtmlProcessor {

protected static final String TEMPLATE_ID_VARIABLE = "_templateId";

protected boolean isContentTemplate(ITemplateContext context) {
return "post".equals(context.getVariable(TEMPLATE_ID_VARIABLE))
|| "page".equals(context.getVariable(TEMPLATE_ID_VARIABLE));
}

// 匹配路径接口
protected boolean isRequestPathMatchingRoute(String requestRoute, Set<String> pageRules) {
return true;
}
}
41 changes: 41 additions & 0 deletions src/main/java/run/halo/injection/HtmlFooterProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package run.halo.injection;


import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import reactor.core.publisher.Mono;
import run.halo.app.theme.dialect.TemplateFooterProcessor;



@Slf4j
@Component
@RequiredArgsConstructor
public class HtmlFooterProcessor extends AbstractHtmlProcessor implements TemplateFooterProcessor {

private final HtmlService htmlService;

@Override
public Mono<Void> process(ITemplateContext context, IProcessableElementTag tag,
IElementTagStructureHandler structureHandler, IModel model) {
return htmlService.getFooterEnabledInjections()
.doOnNext(htmlInjection -> {
if (htmlInjection != null && isContentTemplate(context)) {
model.add(
context.getModelFactory().createText(
htmlInjection.getSpec().getFragment()));
}
})
.onErrorResume(e -> {
log.error("HtmlFooterProcessor process failed", e);
return Mono.empty();
})
.then();
}

}
38 changes: 38 additions & 0 deletions src/main/java/run/halo/injection/HtmlHeadProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package run.halo.injection;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.model.IModel;
import org.thymeleaf.processor.element.IElementModelStructureHandler;
import reactor.core.publisher.Mono;
import run.halo.app.theme.dialect.TemplateHeadProcessor;


@Slf4j
@Component
@RequiredArgsConstructor
public class HtmlHeadProcessor extends AbstractHtmlProcessor implements TemplateHeadProcessor {

private final HtmlService htmlService;

@Override
public Mono<Void> process(ITemplateContext context, IModel model,
IElementModelStructureHandler structureHandler) {
return htmlService.getHeadEnabledInjections()
.doOnNext(htmlInjection -> {
if (htmlInjection != null && isContentTemplate(context)) {
model.add(
context.getModelFactory().createText(
htmlInjection.getSpec().getFragment()));
}
})
.onErrorResume(e -> {
log.error("HtmlHeadProcessor process failed", e);
return Mono.empty();
})
.then();
}

}
46 changes: 46 additions & 0 deletions src/main/java/run/halo/injection/HtmlService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package run.halo.injection;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.index.query.QueryFactory;

@Service
@RequiredArgsConstructor
public class HtmlService {
private final ReactiveExtensionClient client;

/**
* 获取所有启用的 HtmlInjection 对象.
*/
public Flux<HtmlInjection> getAllEnabledInjections() {
ListOptions options = ListOptions.builder()
// 在这里添加查询条件,只获取正在启用的代码
.fieldQuery(QueryFactory.equal("spec.enabled", "true"))
.build();
return client.listAll(HtmlInjection.class, options,
Sort.by(Sort.Order.asc("metadata.name")));
}

/**
* 获取启用的注入点为 HEAD 的 HtmlInjection 对象.
*/
public Flux<HtmlInjection> getHeadEnabledInjections() {
return getAllEnabledInjections()
.filter(htmlInjection ->
htmlInjection.getSpec().getInjectionPoint() == HtmlInjection.InjectionPoint.HEADER);
}

/**
* 获取启用的注入点为 FOOTER 的 HtmlInjection 对象.
*/
public Flux<HtmlInjection> getFooterEnabledInjections() {
return getAllEnabledInjections()
.filter(htmlInjection ->
htmlInjection.getSpec().getInjectionPoint() == HtmlInjection.InjectionPoint.FOOTER);
}
}

22 changes: 21 additions & 1 deletion src/main/java/run/halo/injection/InjectionPlugin.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package run.halo.injection;


import static run.halo.app.extension.index.IndexAttributeFactory.simpleAttribute;

import org.springframework.stereotype.Component;
import run.halo.app.extension.Scheme;
import run.halo.app.extension.SchemeManager;
import run.halo.app.extension.index.IndexSpec;
import run.halo.app.plugin.BasePlugin;
import run.halo.app.plugin.PluginContext;

Expand All @@ -18,7 +22,23 @@ public InjectionPlugin(PluginContext pluginContext, SchemeManager schemeManager)

@Override
public void start() {
schemeManager.register(HtmlInjection.class);
schemeManager.register(HtmlInjection.class, indexSpecs -> {
// 为 enabled 添加索引方便根据启用状态查询
indexSpecs.add(new IndexSpec()
.setName("spec.enabled")
.setIndexFunc(simpleAttribute(HtmlInjection.class, htmlInjection -> {
return Boolean.toString(htmlInjection.getSpec().isEnabled());
}))
);
// 为 injectionPoint 添加索引
indexSpecs.add(new IndexSpec()
.setName("spec.injectionPoint")
.setIndexFunc(simpleAttribute(HtmlInjection.class, htmlInjection -> {
HtmlInjection.InjectionPoint injectionPoint = htmlInjection.getSpec().getInjectionPoint();
return injectionPoint != null ? injectionPoint.name() : "";
}))
);
});
}

@Override
Expand Down

0 comments on commit f36ae3f

Please sign in to comment.