diff --git a/application/src/main/java/run/halo/app/core/attachment/ThumbnailImgTagPostProcessor.java b/application/src/main/java/run/halo/app/core/attachment/ThumbnailImgTagPostProcessor.java index 65293ca5b..f87537204 100644 --- a/application/src/main/java/run/halo/app/core/attachment/ThumbnailImgTagPostProcessor.java +++ b/application/src/main/java/run/halo/app/core/attachment/ThumbnailImgTagPostProcessor.java @@ -3,21 +3,18 @@ package run.halo.app.core.attachment; import static org.thymeleaf.templatemode.TemplateMode.HTML; import java.net.URI; -import java.util.Objects; +import java.util.Map; import java.util.Optional; +import java.util.function.Predicate; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FilenameUtils; import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.thymeleaf.context.ITemplateContext; import org.thymeleaf.engine.ElementNames; import org.thymeleaf.model.IAttribute; import org.thymeleaf.model.IProcessableElementTag; import org.thymeleaf.processor.element.MatchingElementName; -import org.thymeleaf.spring6.context.SpringContextUtils; -import org.thymeleaf.spring6.context.webflux.SpringWebFluxThymeleafRequestContext; import reactor.core.publisher.Mono; import run.halo.app.infra.ExternalUrlSupplier; import run.halo.app.theme.dialect.ElementTagPostProcessor; @@ -30,8 +27,12 @@ class ThumbnailImgTagPostProcessor implements ElementTagPostProcessor { private final ExternalUrlSupplier externalUrlSupplier; - public ThumbnailImgTagPostProcessor(ExternalUrlSupplier externalUrlSupplier) { + private final ThumbnailService thumbnailService; + + public ThumbnailImgTagPostProcessor(ExternalUrlSupplier externalUrlSupplier, + ThumbnailService thumbnailService) { this.externalUrlSupplier = externalUrlSupplier; + this.thumbnailService = thumbnailService; this.matchingElementName = MatchingElementName.forElementName(HTML, ElementNames.forHTMLName("img")); } @@ -57,63 +58,29 @@ class ThumbnailImgTagPostProcessor implements ElementTagPostProcessor { // get img tag var imageUri = srcValue.get(); - if (imageUri.isAbsolute()) { - // check if the uri is belonged to current site - var requestContext = SpringContextUtils.getRequestContext(context); - if (!(requestContext instanceof SpringWebFluxThymeleafRequestContext wrc)) { - log.debug("Skip processing img tag with absolute url: {}, " - + "because the request context is not webflux", imageUri); - return Mono.empty(); - } - var externalUri = externalUrlSupplier.get(); - if (!externalUri.isAbsolute()) { - externalUri = wrc.getServerWebExchange().getRequest().getURI(); - } - if (!Objects.equals(externalUri.getAuthority(), imageUri.getAuthority())) { - log.debug(""" - Skip processing img tag with external absolute url: {} because \ - the url does not belong to the current site\ - """, imageUri); - return Mono.empty(); - } - } - - var path = imageUri.getPath(); - if (!path.startsWith("/upload/")) { - log.debug("Skip processing img tag with non-upload path: {}", path); - return Mono.empty(); - } - - var fileSuffix = FilenameUtils.getExtension(imageUri.getPath()); - if (!ThumbnailUtils.isSupportedImage(fileSuffix)) { - log.debug("Skip processing img tag with unsupported image suffix: {}", fileSuffix); - return Mono.empty(); - } - - // build thumbnails - var thumbnails = ThumbnailUtils.buildSrcsetMap(imageUri); - if (CollectionUtils.isEmpty(thumbnails)) { - log.debug("Skip processing img tag because the image is not supported: {}", imageUri); - return Mono.empty(); - } - - var modelFactory = context.getModelFactory(); - if (!tag.hasAttribute("sizes")) { - tag = modelFactory.setAttribute(tag, "sizes", """ - (max-width: 640px) 94vw, \ - (max-width: 768px) 92vw, \ - (max-width: 1024px) 88vw, \ - min(800px, 85vw)\ - """); - } - var srcset = thumbnails.keySet().stream() - .map(size -> { - var uri = thumbnails.get(size); - return uri + " " + size.getWidth() + "w"; + return thumbnailService.get(imageUri) + .filter(Predicate.not(Map::isEmpty)) + .map(thumbnails -> { + var modelFactory = context.getModelFactory(); + var newTag = tag; + if (!newTag.hasAttribute("sizes")) { + newTag = modelFactory.setAttribute(newTag, "sizes", """ + (max-width: 640px) 94vw, \ + (max-width: 768px) 92vw, \ + (max-width: 1024px) 88vw, \ + min(800px, 85vw)\ + """); + } + var srcset = thumbnails.keySet().stream() + .map(size -> { + var uri = thumbnails.get(size); + return uri + " " + size.getWidth() + "w"; + }) + .collect(Collectors.joining(", ")); + newTag = modelFactory.setAttribute(newTag, "srcset", srcset); + return newTag; }) - .collect(Collectors.joining(", ")); - tag = modelFactory.setAttribute(tag, "srcset", srcset); - return Mono.just(tag); + .defaultIfEmpty(tag); } }