From 9f27943455ba64188de46b4e8f282a3d2785fcdf Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Tue, 10 Sep 2024 13:04:25 +0200 Subject: [PATCH] add `allowMultipleIncludes` - by default, multiple includes of the same script in a single request are eliminated. If setting this property to `true`, they are included multiple times if requested --- .../ui/clientlibs/components/CSSInclude.java | 17 ++++++++++------- .../ui/clientlibs/components/JSInclude.java | 17 ++++++++++------- .../components/RequestIncludedLibraries.java | 12 ++++++++---- .../app-root/sightly/templates/clientlib.html | 12 ++++++++---- src/site/markdown/usage.md | 2 ++ .../clientlibs/components/CSSIncludeTest.java | 19 +++++++++++++++++++ .../clientlibs/components/JSIncludeTest.java | 18 ++++++++++++++++++ 7 files changed, 75 insertions(+), 22 deletions(-) diff --git a/src/main/java/io/wcm/wcm/ui/clientlibs/components/CSSInclude.java b/src/main/java/io/wcm/wcm/ui/clientlibs/components/CSSInclude.java index c6035bf..b3f5e06 100644 --- a/src/main/java/io/wcm/wcm/ui/clientlibs/components/CSSInclude.java +++ b/src/main/java/io/wcm/wcm/ui/clientlibs/components/CSSInclude.java @@ -65,6 +65,8 @@ public class CSSInclude { @RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL) private String rel; @RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL) + private String allowMultipleIncludes; + @RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL) private Object customAttributes; private String include; @@ -111,13 +113,14 @@ private void activate() { */ private @NotNull String buildIncludeString(@NotNull List libraryPaths, @NotNull Map attrs, @NotNull Map customAttrs) { - return new RequestIncludedLibraries(request).buildMarkupIgnoringDuplicateLibraries(libraryPaths, libraryPath -> { - HtmlTagBuilder builder = new HtmlTagBuilder("link", false, xssApi); - builder.setAttrs(attrs); - builder.setAttrs(customAttrs); - builder.setAttr("href", request.getContextPath() + libraryPath); - return builder; - }); + return new RequestIncludedLibraries(request, allowMultipleIncludes) + .buildMarkupIgnoringDuplicateLibraries(libraryPaths, libraryPath -> { + HtmlTagBuilder builder = new HtmlTagBuilder("link", false, xssApi); + builder.setAttrs(attrs); + builder.setAttrs(customAttrs); + builder.setAttr("href", request.getContextPath() + libraryPath); + return builder; + }); } /** diff --git a/src/main/java/io/wcm/wcm/ui/clientlibs/components/JSInclude.java b/src/main/java/io/wcm/wcm/ui/clientlibs/components/JSInclude.java index 089fc42..c11dc26 100644 --- a/src/main/java/io/wcm/wcm/ui/clientlibs/components/JSInclude.java +++ b/src/main/java/io/wcm/wcm/ui/clientlibs/components/JSInclude.java @@ -85,6 +85,8 @@ public class JSInclude { @RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL) private String type; @RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL) + private String allowMultipleIncludes; + @RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL) private Object customAttributes; private String include; @@ -147,13 +149,14 @@ private void activate() { */ private @NotNull String buildIncludeString(@NotNull List libraryPaths, @NotNull Map attrs, @NotNull Map customAttrs) { - return new RequestIncludedLibraries(request).buildMarkupIgnoringDuplicateLibraries(libraryPaths, libraryPath -> { - HtmlTagBuilder builder = new HtmlTagBuilder("script", true, xssApi); - builder.setAttrs(attrs); - builder.setAttrs(customAttrs); - builder.setAttr("src", request.getContextPath() + libraryPath); - return builder; - }); + return new RequestIncludedLibraries(request, allowMultipleIncludes) + .buildMarkupIgnoringDuplicateLibraries(libraryPaths, libraryPath -> { + HtmlTagBuilder builder = new HtmlTagBuilder("script", true, xssApi); + builder.setAttrs(attrs); + builder.setAttrs(customAttrs); + builder.setAttr("src", request.getContextPath() + libraryPath); + return builder; + }); } /** diff --git a/src/main/java/io/wcm/wcm/ui/clientlibs/components/RequestIncludedLibraries.java b/src/main/java/io/wcm/wcm/ui/clientlibs/components/RequestIncludedLibraries.java index 22e9325..44f475c 100644 --- a/src/main/java/io/wcm/wcm/ui/clientlibs/components/RequestIncludedLibraries.java +++ b/src/main/java/io/wcm/wcm/ui/clientlibs/components/RequestIncludedLibraries.java @@ -24,7 +24,9 @@ import java.util.Set; import java.util.function.Function; +import org.apache.commons.lang3.BooleanUtils; import org.apache.sling.api.SlingHttpServletRequest; +import org.jetbrains.annotations.Nullable; import com.adobe.granite.ui.clientlibs.HtmlLibraryManager; import com.drew.lang.annotations.NotNull; @@ -38,9 +40,12 @@ class RequestIncludedLibraries { private static final String RA_INCLUDED_LIBRARY_PATHS = HtmlLibraryManager.class.getName() + ".included"; private final SlingHttpServletRequest request; + private final boolean allowMultipleIncludes; - RequestIncludedLibraries(SlingHttpServletRequest request) { + RequestIncludedLibraries(@NotNull SlingHttpServletRequest request, + @Nullable String allowMultipleIncludes) { this.request = request; + this.allowMultipleIncludes = BooleanUtils.toBoolean(allowMultipleIncludes); } /** @@ -81,17 +86,16 @@ void storeIncluded(@NotNull String libraryPath) { */ String buildMarkupIgnoringDuplicateLibraries(@NotNull List libraryPaths, @NotNull Function htmlTagBuilderFactory) { - RequestIncludedLibraries includedLibraries = new RequestIncludedLibraries(request); StringBuilder markup = new StringBuilder(); for (String libraryPath : libraryPaths) { // ignore libraries that are already included - if (includedLibraries.isInlucded(libraryPath)) { + if (!allowMultipleIncludes && isInlucded(libraryPath)) { continue; } // build markup for library markup.append(htmlTagBuilderFactory.apply(libraryPath).build()); // mark library as included - includedLibraries.storeIncluded(libraryPath); + storeIncluded(libraryPath); } return markup.toString(); } diff --git a/src/main/webapp/app-root/sightly/templates/clientlib.html b/src/main/webapp/app-root/sightly/templates/clientlib.html index b412248..d766bcd 100644 --- a/src/main/webapp/app-root/sightly/templates/clientlib.html +++ b/src/main/webapp/app-root/sightly/templates/clientlib.html @@ -9,14 +9,16 @@ * @param nonce see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-nonce * @param referrerpolicy see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-referrerpolicy * @param type see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type + * @param allowMultipleIncludes If set to true, duplicate inclusions of this client library in a single request are not eliminated. * @param customAttributes List of custom attributes, each list item in syntax 'attr=value' or just 'attr' */--> @@ -25,12 +27,14 @@ * Template used for including CSS client libraries. * @param categories Client Library categories * @param rel prefetch|preload see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel + * @param allowMultipleIncludes If set to true, duplicate inclusions of this client library in a single request are not eliminated. * @param customAttributes List of custom attributes, each list item in syntax 'attr=value' or just 'attr' */--> -