CSSInclude.java
/*
* #%L
* wcm.io
* %%
* Copyright (C) 2019 wcm.io
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package io.wcm.wcm.ui.clientlibs.components;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.apache.sling.models.annotations.injectorspecific.RequestAttribute;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.xss.XSSAPI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.annotation.versioning.ProviderType;
import com.adobe.granite.ui.clientlibs.HtmlLibraryManager;
import com.adobe.granite.ui.clientlibs.LibraryType;
/**
* Include CSS client libraries.
*/
@Model(adaptables = SlingHttpServletRequest.class)
@ProviderType
public class CSSInclude {
private static final Set<String> REL_ALLOWED_VALUES = Set.of(
"prefetch", "preload");
@SlingObject
private SlingHttpServletRequest request;
@SlingObject
private ResourceResolver resourceResolver;
@OSGiService
private HtmlLibraryManager htmlLibraryManager;
@OSGiService
private XSSAPI xssApi;
@RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL)
private Object categories;
@RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL)
private String rel;
@RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL)
private Object allowMultipleIncludes;
@RequestAttribute(injectionStrategy = InjectionStrategy.OPTIONAL)
private Object customAttributes;
private String include;
@PostConstruct
private void activate() {
// build include string
String[] categoryArray = IncludeUtil.toArray(categories);
if (categoryArray != null) {
List<String> libraryPaths = IncludeUtil.getLibraryUrls(htmlLibraryManager, resourceResolver,
categoryArray, LibraryType.CSS);
if (!libraryPaths.isEmpty()) {
Map<String, String> attrs = validateAndBuildAttributes();
Map<String, String> customAttrs = IncludeUtil.getCustomAttributes(customAttributes);
this.include = buildIncludeString(libraryPaths, attrs, customAttrs);
}
}
}
/**
* Validate attribute values from HTL script, escape them properly and build a map with all attributes
* for the resulting script tag(s).
* @return Map with attribute for script tag
*/
private @NotNull Map<String, String> validateAndBuildAttributes() {
Map<String, String> attrs = new HashMap<>();
if (rel != null && REL_ALLOWED_VALUES.contains(rel)) {
attrs.put("rel", rel);
}
else {
// no specific rel defined, provide default rel/type attrs for CSS
attrs.put("rel", "stylesheet");
attrs.put("type", "text/css");
}
return attrs;
}
/**
* Build CSS link tags for all client libraries with the defined custom script tag attributes set.
* @param libraryPaths Library paths
* @param attrs HTML attributes for link tag
* @param customAttrs Custom HTML attributes for script tag
* @return HTML markup with script tags
*/
private @NotNull String buildIncludeString(@NotNull List<String> libraryPaths, @NotNull Map<String, String> attrs,
@NotNull Map<String, String> customAttrs) {
return new RequestIncludedLibraries(request, allowMultipleIncludes)
.buildMarkupIgnoringDuplicateLibraries(libraryPaths, libraryPath -> {
HtmlTagBuilder builder = new HtmlTagBuilder("link", false, xssApi);
builder.setAttrs(attrs);
builder.setAttrs(customAttrs);
builder.setAttr("href", IncludeUtil.appendRequestPath(libraryPath, request));
return builder;
});
}
/**
* @return HTML markup with script tags
*/
public @Nullable String getInclude() {
return include;
}
}