Package: collective.handlebars
The idea of this package is to provide handlebars.js support for Plone.
It is a developer addon and provides additional variants of
BrowserView, Portlet, Viewlet and Tile which utilizeshandlebars.jstemplating instead of TAL. It can be used to optimze the workflow
between designers and Plone developers.The product was developed and tested with Plone 5 but might work
with older versions too.This product does not do anything user related on itself!
It can not be installed as a Plone addon. What it does is to provide an API
for developers to integrate an alternative templating engine into Plone.FeaturesThe prodcut provides the following view components with handlebars support:BrowserViewPlone templateTilePersistent TileSince portlets and viewlets do not make any assumtion on the
templating and return everything which is returned by the
render-method of the Renderer they are supported too.ExamplesA handlebars BrowserView:from collective.handlebars.browser.views import HandlebarsBrowserView

class HBSBrowserView(HandlebarsBrowserView):

    def get_contents(self):
        return {'msg': u'Hello World!'}And the according configure.zcml:<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser"
    i18n_domain="mydomain">

  <browser:page
       name="carousel_view"
       for="*"
       class=".views.HBSBrowserView"
       template="helloworld.hbs"
       permission="zope2.View"
       />A handlebar Plone template:from collective.handlebars.browser.views import HandlebarsPloneView

class CarouselView(HandlebarsPloneView):

    def get_contents(self):
        images = self.context.listFolderContents(
            contentFilter={'portal_type': ['Image', ]})

         slides = [{'title': safe_unicode(img.Title()),
                    'category': safe_unicode(img.Description()),
                    'link': img.remoteUrl,
                    'image': scale(img)} for img in images]

         return {'slides': slides, }}And the according configure.zcml:<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser"
    i18n_domain="mydomain">

  <browser:page
       name="carousel_view"
       for="*"
       class=".views.CarouselView"
       template="carousel.hbs"
       permission="zope2.View"
       />

</configure>A handlebars portlet:from collective.handlebars.browser.views import HandlebarsMixin
from plone.app.multilingual.browser.selector import LanguageSelectorViewlet

class LanguageSwitcherRenderer(base.Renderer, HandlebarsMixin):
    """ Render a language switcher portlet
    """

    def get_contents(self):
        """ Get available and current site language
        :return: dictonary ()
        """
        viewlet = LanguageSelectorViewlet(self.context, self.request, self, None)
        viewlet.update()
        result = []
        for lang in viewlet.languages():
            result.append(
                {"lang": lang['code'].upper(),
                 "url": lang['url'],
                 "active": lang['selected'] and 'is_active' or ''})

        return {"languages": result}

    def render(self):
        return self.hbs_snippet(filename='langswitcher.hbs')A handlebars tile:class ContactPersonTile(HandlebarsTile):

    def get_contents(self):
        """ Get CMS data and put it in a JSON format
        """

        return {
            'fullname': u'George Miller',
            'phone': '+1 50 206 67 99',
            'email': 'george@example.com',
        }Or a persistent handlebars tile:class ContactPersonTile(HandlebarsPersistentTile):

    def get_contents(self):
        """ Get CMS data and put it in a JSON format
        """

        return {
            'fullname': u'George Miller',
            'phone': '+1 50 206 67 99',
            'email': 'george@example.com',
        }And the according configure.zcml:<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:plone="http://namespaces.plone.org/plone"
    i18n_domain="fhnw.contentwidgets">

  <include package="plone.app.mosaic" />

  <plone:tile
      name="myproduct.contactpersontile"
      title="ContactPerson"
      description="A card of a person"
      add_permission="cmf.ModifyPortalContent"
      class=".tiles.ContactPersonTile"
      for="*"
      permission="zope.Public"
      schema=".tiles.ContactPersonTile"
      template="contactperson.hbs"
  />
</configure>DocumentationFull documentation for end users can be found in the “docs” folder.InstallationInstall collective.handlebars by adding it to your buildout:[buildout]

...

eggs =
    collective.handlebarsand then runningbin/buildoutContributeIssue Tracker:https://github.com/collective/collective.handlebars/issuesSource Code:https://github.com/collective/collective.handlebarsDocumentation:https://github.com/collective/collective.handlebars/docsLicenseThe project is licensed under the GPLv2.ContributorsTom Gross,itconsense@gmail.comChangelog1.5 (2021-08-28)Python 3 / Plone 5.2 compatibility
[adrianschulz, tomgross]Update dependenciesMove to Github CIApply black formatting
[tomgross]1.4.1 (2018-10-22)Add div-element to wrapper to support cases where only text is provided
(otherwise plone.protect can fail)
[tomgross]1.4 (2018-09-10)Wrap tile so it works with newer versions of Mosaic
[tomgross]1.3 (2018-04-26)Set html/body parenthesis for tiles
[tomgross]1.2 (2016-10-31)Explicitly set UTF-8 encoding in response
[tomgross]1.1 (2016-10-28)Add support for helpers
[tomgross]1.0 (2016-10-28)Add persistent tile wrapper
[tomgross]Unify names. It is nowHandlebarsTile[tomgross]1.0rc1 (2016-08-29)Add registry for templates
[tomgross]Fix i18n translate tests
[tomgross]1.0b1 (2016-07-25)Initial release.
[tomgross]