-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use ElementTagPostProcessor to handle image replacement (#15)
Signed-off-by: JohnNiang <[email protected]>
- Loading branch information
Showing
5 changed files
with
122 additions
and
199 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package se.webp.plugin; | ||
|
||
import static org.thymeleaf.templatemode.TemplateMode.HTML; | ||
import static se.webp.plugin.Settings.BasicConfig.GROUP; | ||
|
||
import java.net.URI; | ||
import java.net.URL; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
import org.apache.commons.lang3.ArrayUtils; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.StringUtils; | ||
import org.springframework.web.util.UriComponentsBuilder; | ||
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.Flux; | ||
import reactor.core.publisher.Mono; | ||
import run.halo.app.infra.ExternalUrlSupplier; | ||
import run.halo.app.plugin.ReactiveSettingFetcher; | ||
import run.halo.app.theme.dialect.ElementTagPostProcessor; | ||
|
||
@Component | ||
public class ImageTagProcessor implements ElementTagPostProcessor { | ||
|
||
private final MatchingElementName matchingElementName; | ||
|
||
private final ReactiveSettingFetcher settingFetcher; | ||
|
||
private final ExternalUrlSupplier externalUrlSupplier; | ||
|
||
public ImageTagProcessor(ReactiveSettingFetcher settingFetcher, | ||
ExternalUrlSupplier externalUrlSupplier) { | ||
this.settingFetcher = settingFetcher; | ||
this.externalUrlSupplier = externalUrlSupplier; | ||
this.matchingElementName = | ||
MatchingElementName.forElementName(HTML, ElementNames.forHTMLName("img")); | ||
} | ||
|
||
private static boolean urlMatches(URL firstUrl, URL secondUrl) { | ||
return Objects.equals(firstUrl.getAuthority(), secondUrl.getAuthority()); | ||
} | ||
|
||
@Override | ||
public Mono<IProcessableElementTag> process(ITemplateContext context, | ||
IProcessableElementTag tag) { | ||
if (!matchingElementName.matches(tag.getElementDefinition().getElementName())) { | ||
return Mono.empty(); | ||
} | ||
var requestContext = SpringContextUtils.getRequestContext(context); | ||
if (!(requestContext instanceof SpringWebFluxThymeleafRequestContext springWebContext)) { | ||
return Mono.empty(); | ||
} | ||
var srcValue = Optional.ofNullable(tag.getAttribute("src")) | ||
.map(IAttribute::getValue) | ||
.filter(StringUtils::hasText) | ||
.map(URI::create); | ||
if (srcValue.isEmpty()) { | ||
return Mono.empty(); | ||
} | ||
var exchange = springWebContext.getServerWebExchange(); | ||
var externalUrl = externalUrlSupplier.getURL(exchange.getRequest()); | ||
|
||
return settingFetcher.fetch(GROUP, Settings.BasicConfig.class) | ||
.filter(config -> !ArrayUtils.isEmpty(config.getProxies())) | ||
.flatMapMany(config -> Flux.fromArray(config.getProxies())) | ||
.filter(proxy -> | ||
Objects.nonNull(proxy.getProxyUrl()) && Objects.nonNull(proxy.getOriginUrl()) | ||
) | ||
.filter(proxy -> urlMatches(externalUrl, proxy.getOriginUrl())) | ||
.next() | ||
.map(proxy -> { | ||
var srcBuilder = UriComponentsBuilder.fromHttpUrl(proxy.getProxyUrl().toString()) | ||
.path(srcValue.get().getPath()) | ||
.query(srcValue.get().getQuery()) | ||
.fragment(srcValue.get().getFragment()); | ||
var newSrc = srcBuilder.toUriString(); | ||
var modelFactory = context.getModelFactory(); | ||
var newTag = tag; | ||
if (!tag.hasAttribute("srcset")) { | ||
// calculate srcset and sizes | ||
newTag = modelFactory.setAttribute(newTag, "sizes", | ||
""" | ||
(max-width: 400px) 400px, (max-width: 800px) 800px, \ | ||
(max-width: 1200px) 1200px, (max-width: 1600px) 1600px\ | ||
"""); | ||
var w400Src = srcBuilder.cloneBuilder().queryParam("width", 400) | ||
.toUriString(); | ||
var w800Src = srcBuilder.cloneBuilder().queryParam("width", 800) | ||
.toUriString(); | ||
var w1200Src = srcBuilder.cloneBuilder().queryParam("width", 1200) | ||
.toUriString(); | ||
var w1600Src = srcBuilder.cloneBuilder().queryParam("width", 1600) | ||
.toUriString(); | ||
newTag = modelFactory.setAttribute(newTag, "srcset", | ||
w400Src + " 400w, " | ||
+ w800Src + " 800w, " | ||
+ w1200Src + " 1200w, " | ||
+ w1600Src + " 1600w" | ||
); | ||
} | ||
newTag = modelFactory.setAttribute(newTag, "src", | ||
newSrc); | ||
return newTag; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,29 @@ | ||
package se.webp.plugin; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import java.net.URL; | ||
import lombok.Data; | ||
import reactor.core.publisher.Mono; | ||
import run.halo.app.plugin.ReactiveSettingFetcher; | ||
|
||
public class Settings { | ||
|
||
public static Mono<BasicConfig> getBasicConfig(ReactiveSettingFetcher settingFetcher) { | ||
return settingFetcher.fetch(BasicConfig.GROUP, BasicConfig.class); | ||
} | ||
|
||
@Data | ||
public static class BasicConfig { | ||
|
||
public static final String GROUP = "basic"; | ||
|
||
String apiKeySecret; | ||
|
||
Proxy[] proxies; | ||
|
||
} | ||
|
||
@Data | ||
public static class Proxy { | ||
String origin_url; | ||
|
||
String proxy_url; | ||
@JsonProperty("origin_url") | ||
URL originUrl; | ||
|
||
@JsonProperty("proxy_url") | ||
URL proxyUrl; | ||
} | ||
} |
189 changes: 0 additions & 189 deletions
189
src/main/java/se/webp/plugin/WebpCloudImageOptimizerWebFilter.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters