nz.net.ultraq.thymeleaf.fragments.extensions.FragmentExtensions.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of thymeleaf-layout-dialect Show documentation
Show all versions of thymeleaf-layout-dialect Show documentation
A dialect for Thymeleaf that allows you to use layout/decorator templates to style your content.
/*
* Copyright 2015, Emanuel Rabina (http://www.ultraq.net.nz/)
*
* 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.
*/
package nz.net.ultraq.thymeleaf.fragments.extensions
import org.thymeleaf.context.ITemplateContext
import org.thymeleaf.model.IModel
import org.thymeleaf.processor.element.IElementModelStructureHandler
/**
* Extensions to Thymeleaf for working with fragments.
*
* @author Emanuel Rabina
*/
class FragmentExtensions {
static final String FRAGMENT_COLLECTION_KEY = 'LayoutDialect::FragmentCollection'
/**
* Retrieves the fragment collection for the current context.
*
* @param self
* @param fromDecorator
* @return A new or existing fragment collection.
*/
static Map> getFragmentCollection(ITemplateContext self, boolean fromDecorator = false) {
// If the template stack contains only 1 template and we've been called from
// the decorator, then always return a new fragment collection. This seems
// to be one way to know if Thymeleaf is processing a new file and as such
// should have a fresh collection to work with, otherwise we may be using an
// older collection from an already-used context.
// See: https://github.com/ultraq/thymeleaf-layout-dialect/issues/189
if (self.templateStack.size() == 1 && fromDecorator) {
return [:]
}
def fragmentCollection = self[FRAGMENT_COLLECTION_KEY]
return fragmentCollection != null ? fragmentCollection : [:]
}
/**
* Set a fragment cache to contain any existing fragments, plus the given new
* fragments, with the same scope as setting a local variable.
*
* @param self
* @param context
* @param fragments The new fragments to add to the cache.
* @param fromDecorator Whether the call was from {@code DecorateProcessor},
* used for determining if a new fragment collection
* should be used and the order of collected fragments.
*/
static void setLocalFragmentCollection(IElementModelStructureHandler self, ITemplateContext context,
Map> fragments, boolean fromDecorator = false) {
self.setLocalVariable(FRAGMENT_COLLECTION_KEY,
context.getFragmentCollection(fromDecorator).inject(fragments) { accumulator, fragmentName, fragmentList ->
if (accumulator[fragmentName]) {
accumulator[fragmentName] += fragmentList
if (!fromDecorator) {
accumulator[fragmentName].reverse(true)
}
}
else {
accumulator[fragmentName] = fragmentList
}
return accumulator
}
)
}
}