mirror of https://github.com/halo-dev/halo
Fix the problem of showing 500 error while containing special chars in excerpt (#5263)
#### What type of PR is this? /kind bug /area core /milestone 2.12.0 #### What this PR does / why we need it: This PR refactors building html meta by using `modelFactory#createStandaloneElementTag`. See https://github.com/halo-dev/halo/issues/4755 for more. #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/4755 #### Special notes for your reviewer: Validate via <https://github.com/halo-dev/halo/issues/4755#issuecomment-1776391345>. #### Does this PR introduce a user-facing change? ```release-note 修复摘要中包含特殊字符导致无法解析页面的问题 ```pull/5274/head^2
parent
9137d50a31
commit
47a1aa7631
|
@ -2,11 +2,13 @@ package run.halo.app.theme.dialect;
|
|||
|
||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
|
||||
import static org.thymeleaf.model.AttributeValueQuotes.DOUBLE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
@ -15,6 +17,7 @@ import org.springframework.web.util.HtmlUtils;
|
|||
import org.thymeleaf.context.ITemplateContext;
|
||||
import org.thymeleaf.model.IModel;
|
||||
import org.thymeleaf.model.IModelFactory;
|
||||
import org.thymeleaf.model.ITemplateEvent;
|
||||
import org.thymeleaf.processor.element.IElementModelStructureHandler;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.theme.DefaultTemplateEnum;
|
||||
|
@ -62,11 +65,9 @@ public class ContentTemplateHeadProcessor implements TemplateHeadProcessor {
|
|||
}
|
||||
|
||||
return htmlMetasMono
|
||||
.doOnNext(htmlMetas -> {
|
||||
String metaHtml = headMetaBuilder(htmlMetas);
|
||||
IModelFactory modelFactory = context.getModelFactory();
|
||||
model.add(modelFactory.createText(metaHtml));
|
||||
})
|
||||
.doOnNext(
|
||||
htmlMetas -> buildMetas(context.getModelFactory(), htmlMetas).forEach(model::add)
|
||||
)
|
||||
.then();
|
||||
}
|
||||
|
||||
|
@ -97,19 +98,12 @@ public class ContentTemplateHeadProcessor implements TemplateHeadProcessor {
|
|||
String CONTENT = "content";
|
||||
}
|
||||
|
||||
private String headMetaBuilder(List<Map<String, String>> htmlMetas) {
|
||||
if (htmlMetas == null) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map<String, String> htmlMeta : htmlMetas) {
|
||||
sb.append("<meta");
|
||||
htmlMeta.forEach((k, v) -> {
|
||||
sb.append(" ").append(k).append("=\"").append(v).append("\"");
|
||||
});
|
||||
sb.append(" />\n");
|
||||
}
|
||||
return sb.toString();
|
||||
private List<ITemplateEvent> buildMetas(IModelFactory modelFactory,
|
||||
List<Map<String, String>> metas) {
|
||||
return metas.stream()
|
||||
.map(metaMap ->
|
||||
modelFactory.createStandaloneElementTag("meta", metaMap, DOUBLE, false, true)
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean isPostTemplate(ITemplateContext context) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.springframework.core.annotation.Order;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.thymeleaf.context.ITemplateContext;
|
||||
import org.thymeleaf.model.IModel;
|
||||
import org.thymeleaf.model.IProcessableElementTag;
|
||||
import org.thymeleaf.model.ITemplateEvent;
|
||||
import org.thymeleaf.model.IText;
|
||||
import org.thymeleaf.processor.element.IElementModelStructureHandler;
|
||||
|
@ -59,9 +60,19 @@ public class DuplicateMetaTagProcessor implements TemplateHeadProcessor {
|
|||
IText otherText = context.getModelFactory()
|
||||
.createText(text);
|
||||
otherModel.add(new IndexedModel(i, otherText));
|
||||
} else {
|
||||
otherModel.add(new IndexedModel(i, templateEvent));
|
||||
continue;
|
||||
}
|
||||
if (templateEvent instanceof IProcessableElementTag tag) {
|
||||
var indexedModel = new IndexedModel(i, tag);
|
||||
if ("meta".equals(tag.getElementCompleteName())) {
|
||||
var attribute = tag.getAttribute("name");
|
||||
if (attribute != null) {
|
||||
uniqueMetaTags.put(attribute.getValue(), indexedModel);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
otherModel.add(new IndexedModel(i, templateEvent));
|
||||
}
|
||||
|
||||
otherModel.addAll(uniqueMetaTags.values());
|
||||
|
|
|
@ -146,8 +146,8 @@ class ContentTemplateHeadProcessorIntegrationTest {
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Post detail</title>
|
||||
<meta name="description" content="post-description">
|
||||
<meta name="keyword" content="postK1,postK2">
|
||||
<meta name="description" content="post-description">
|
||||
<meta name="other" content="post-other-meta">
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -174,9 +174,9 @@ class HaloProcessorDialectTest {
|
|||
<title>Post</title>
|
||||
<meta name="global-head-test" content="test" />
|
||||
<meta name="content-head-test" content="test" />
|
||||
<meta content="post-meta-V1" name="post-meta-V1" />
|
||||
<meta content="post-meta-V2" name="post-meta-V2" />
|
||||
<meta name="description" content="" />
|
||||
<meta content="post-meta-V1" name="post-meta-V1"/>\
|
||||
<meta content="post-meta-V2" name="post-meta-V2"/>\
|
||||
<meta name="description" content=""/>\
|
||||
</head>
|
||||
<body>
|
||||
<p>post</p>
|
||||
|
|
Loading…
Reference in New Issue