Manuel de référence
    • Introduction
    • Smart Data
    • Sécurité
    • Workflow
    • Les essentiels de l'API PHP
    • Composants graphiques
    • UIs de Smart Element
    • Internationalisation
    • Scripts
    • Module
    • API REST
    • Routes
    • Moteurs de transformation
    • Recherche générale
    • Supervision
    • Techniques avancées
    • Tableaux de bord
    • Workers
    Anakeen Platform 4
    Anakeen
    • Introduction
    • Smart Data
    • Sécurité
    • Workflow
    • Les essentiels de l'API PHP
    • Composants graphiques
    • UIs de Smart Element
    • Internationalisation
    • Scripts
    • Module
    • API REST
    • Routes
    • Moteurs de transformation
    • Recherche générale
    • Supervision
    • Techniques avancées
    • Tableaux de bord
    • Workers
    Anakeen Platform 4
    Anakeen
    • Représentation des Smart Elements

      • Introduction
        • Éléments inclus
        • Illustrations
          • Responsive design
      • Concepts
        • Rendu
        • Vue
      • Masque
        • Configuration d'un masque {#maskxml}
        • Visibilité des SmartFields {#maskvisibility}
          • Visibilité des SmartFields structurants {#maskvisibilitystruc}
      • Contrôle de vue
        • Profilage du contrôle de vue
        • Choix automatique de la vue {#autochoice}
        • Libellé du menu modifier
        • Astuces
        • Configuration d'un contrôle de vue {#viewcontrolxml}
        • Configuration générale
        • Configuration d'une vue
      • Classe de rendu
        • Classes de configuration de rendu par défaut
      • Méthodes de la classe de configuration de rendu

        • smartElement/renderMethod.md
          • Éléments inclus
          • Illustrations
            • Responsive design
        • getCssReferences
        • getJsReferences
          • Mode global
        • getEtag
        • getTemplates
          • Gérer les modèles
          • Corps du Smart Element : body
          • Sections
            • Entête du Smart Element : header
            • Menu du Smart Element : menu
            • Contenu du Smart Element : content
            • Pied du Smart Element : footer
          • Variables des templates {#gettemplateVariables}
            • Variables client
            • Variables serveur
        • getContextController
          • Contrôleur par défaut
            • Propriétés
            • Attributs
            • Fonctions
          • Traduction
            • Exemples
        • getVisibilities
          • Exemple
        • getNeeded
          • Exemple
        • getCustomServerData
          • Exemple
        • setCustomClientData
          • Exemple
        • getLabel
          • Exemple
        • getMenu
          • Déclaration
          • Élément de menu simple {#itemMenu}
            • Construction
            • Arguments
            • Exemple
          • Définition de l’URL
            • Indiquer une URL statique
            • Indiquer la cible du menu
          • Émettre un événement
          • Contenu du menu
          • Liste d’éléments de menu {#listMenu}
            • Construction
            • Arguments
            • Méthode
          • Liste dynamique d’éléments de menu {#dynamicMenu}
            • Construction
            • Exemple
          • Fonction associée à un menu {#callableMenu}
            • Construction
            • Exemple
          • Menu Séparateur {#separatorMenu}
            • Construction
            • Arguments
            • Exemple
          • Intégration d’éléments dans un menu
            • Ajout d’un élément en fin de liste
            • Ajout d’un élément à une position donnée
            • _Exemple_
          • Suppression d’un élément
          • Surcharge d’un élément de menu
            • Exemple
          • Visibilité des éléments de menu
            • Exemple
          • Menus prédéfinis
            • Rendu de consultation
            • Rendu de modification
            • Événements prédéfinis
          • Menu d’envoi de courriel (mail) {#sendmenu}
            • Formulaire d’envoi
            • Choix des destinataires
            • Menu d’envoi standard
            • Menu d’envoi avec un lien personnalisé
            • Menu d’envoi avec un modèle de mail spécifique
        • getOptions
          • Remarques
          • Options personnalisées
        • getMessages
          • Déclaration
          • Arguments
          • Exemple
      • Options de rendu
        • Options de représentation type Smart Element {#smartElement-options}
          • setStickyTabs
          • setOpenFirstTab
          • setTabPlacement
        • Options de rendu communes à tout type de Smart Fields {#common-options}
          • showEmptyContent {#common-showemptycontent}
          • setLink
          • setLabelPosition {#common-setlabelposition}
          • setAttributeLabel {#common-setattributelabel}
          • setDescription {#common-setdescription}
          • displayDeleteButton {#common-displaydeletebutton}
          • setInputTooltip {#common-setinputtooltip}
          • setAutoCompleteHtmlLabel {#common-setautocompletehtmllabel}
          • addButton {#common-addbutton}
          • setTemplate {#common-settemplate}
          • addHtmlClass {#common-addhtmlclass}
          • removeHtmlClass {#common-removehtmlclass}
          • setHtmlAttribute {#common-sethtmlattribute}
          • setTranslations {#common-settranslations}
          • setCustomWidgetAttributeFunction {#common-setcustomwidgetattributefunction}
        • Options de représentation type account {#account-options}
        • Options de représentation type array {#array-options}
          • setRowCountThreshold {#array-setrowcountthreshold}
          • disableRowAdd {#array-disablerowadd}
          • disableRowDel {#array-disablerowdel}
          • disableRowMove {#array-disablerowmove}
          • setRowMinLimit {#array-setrowminlimit}
          • setRowMaxLimit {#array-setrowmaxlimit}
          • setRowMinDefault {#array-setrowmindefault}
          • setDescription (colonne de tableau) {#column-setdescription}
          • setDescription (tableau) {#array-setdescription}
          • setTranspositionWidth {#array-settranspositionwidth}
          • setTranslations {#array-settranslations}
        • Options de représentation type color {#color-options}
          • setKendoColorConfiguration {#color-setkendocolorconfiguration}
        • Options de représentation type date {#date-options}
          • setKendoDateConfiguration {#date-setkendodateconfiguration}
          • setFormat {#date-setformat}
          • setPlaceHolder {#date-setplaceholder}
        • Options de représentation type docid {#docid-options}
          • setKendoMultiSelectConfiguration {#docid-setkendomultiselectconfiguration}
          • setPlaceHolder {#docid-setplaceholder}
          • setFormat {#docid-setformat}
          • setDocumentIconSize {#docid-setdocumenticonsize}
          • addCreateDocumentButton {#docid-addcreatedocumentbutton}
        • Options de représentation type double {#double-options}
          • setDecimalPrecision {#double-setdecimalprecision}
        • Options de représentation type enum {#enum-options}
          • setDisplay {#enum-setdisplay}
          • useSourceUri {#enum-usesourceuri}
          • useFirstChoice {#enum-usefirstchoice}
          • useOtherChoice {#enum-useothertchoice}
          • setPlaceHolder {#enum-setplaceholder}
          • setTranslations {#enum-settranslations}
          • setOrderBy {#enum-setorderby}
        • Options de représentation type file {#file-options}
          • setContentDispositionInline {#file-setcontentdispositioninline}
          • setTranslations {#file-settranslations}
          • setPlaceHolder {#file-setplaceholder}
          • setMimeIconSize {#file-setmimeiconsize}
        • Options de représentation type frame {#frame-options}
          • setCollapse {#frame-setcollapse}
          • setDescription (cadre) {#frame-setdescription}
          • setResponsiveColumns {#frame-setresponsivecolumns}
        • Options de représentation type htmltext {#htmltext-options}
          • setHeight {#htmltext-setheight}
          • setToolbar {#htmltext-settoolbar}
          • setKendoEditorConfiguration {#htmltext-setKendoEditorConfiguration}
          • setAnchorsOptions {#htmltext-setanchorsoptions}
        • Options de représentation type image {#image-options}
          • setThumbnailSize {#image-setthumbnailsize}
        • Options de représentation type int {#int-options}
          • setKendoNumericConfiguration {#int-setkendonumericconfiguration}
          • setFormat {#int-setformat}
          • setTranslations {#int-settranslations}
          • setPlaceHolder {#int-setplaceholder}
        • Options de représentation type longtext {#longtext-options}
          • setMaxDisplayedLineNumber {#longtext-setmaxdisplayedlinenumber}
        • Options de représentation type money {#money-options}
          • setCurrency {#money-setcurrency}
        • Options de représentation type password {#password-options}
          • hideValue {#password-hidevalue}
          • setPlaceHolder {#password-setplaceholder}
        • Options de représentation type tab {#tab-options}
          • setTooltipLabel {#tab-settooltiplabel}
          • setDescription (onglet) {#tab-setdescription}
        • Options de représentation type text {#text-options}
          • setMaxLength {#text-setmaxlength}
          • setKendoAutoCompleteConfiguration {#text-setkendoautocompleteconfiguration}
          • setPlaceHolder {#text-setplaceholder}
          • setFormat {#text-setformat}
        • Options de représentation type time {#time-options}
          • setKendoTimeConfiguration {#time-setkendotimeconfiguration}
          • setFormat {#time-setformat}
          • setPlaceHolder {#time-setplaceholder}
        • Options de représentation type timestamp {#timestamp-options}
          • setKendoDateConfiguration {#timestamp-setkendodateconfiguration}
      • Associer une classe de rendu à un Smart Element
        • Fichiers de surcharge des éléments de rendu {#overloadRender}
          • Format
          • Prise en compte des surcharges
          • Définir l'accès à un rendu de Smart Element
          • Désactiver le calcul des etag {#disableetag}
        • Classe d'accès à un rendu de Smart Element
        • Définir les rendus dans un contrôle de vue
        • Définir un rendu par défaut pour une Smart Structure
      • Contrôleurs clients (javascript)
      • Contrôleur global
        • Méthodes du contrôleur global
          • addSmartElement
          • getScopedController
          • getControllers
          • addEventListener
          • registerFunction
          • setVerbose
      • Contrôleur restreint
        • Objets internes du contrôleur
          • Smart Element {#internal-SE}
          • Smart Field {#internal-SF}
          • Types de Smart Field {#smart-field-types}
        • Énuméré
          • Fenêtre de transition {#SE-transition}
          • Menu
        • Carte des événements du contrôleur restreint
          • Ordonnancement des événements
          • Modification
          • Sauvegarde
          • Suppression
          • Restauration
          • Passage de transition
          • Autres
        • Méthodes du contrôleur restreint de Smart Element
          • addEventListener {#addEventListener}
          • addConstraint
          • addCustomClientData
          • appendArrayRow
          • changeStateSmartElement
          • cleanSmartFieldErrorMessage
          • deleteSmartElement
          • drawTab
          • fetchSmartElement
          • getCustomServerData
          • getProperties
          • getProperty
          • getSmartFields
          • getSmartField
          • getValues
          • getValue
          • getMenus
          • getMenu
          • getCustomClientData
          • hasSmartField
          • hideSmartField
          • hasMenu
          • isLoaded
          • isModified
          • injectJS
          • injectCSS
          • insertBeforeArrayRow
          • listConstraints
          • listEventListeners
          • maskSmartElement
          • removeEventListeners
          • removeCustomClientData
          • removeArrayRow
          • restoreSmartElement
          • removeConstraint
          • reinitSmartElement
          • saveSmartElement
          • setValue
          • setSmartFieldErrorMessage
          • selectTab
          • showMessage
          • showSmartField
          • triggerEvent
          • tryToDestroy
          • unmaskSmartElement
        • Liste des événements déclenchés sur le Smart Element Ui
          • actionClick {#actionClick}
          • afterDelete
          • afterSave
          • afterRestore
          • beforeClose
          • beforeDelete
          • beforeRender
          • beforeRestore
          • beforeSave
          • beforeValidate
          • close
          • displayError
          • displayMessage
          • ready
        • Liste des événements déclenchés sur les Smart Fields
          • smartFieldAnchorClick
          • smartFieldArrayChange
          • smartFieldBeforeRender
          • smartFieldDownloadFile
          • smartFieldHelperResponse
          • smartFieldHelperSearch
          • smartFieldHelperSelect
          • smartFieldEnumResponse {#smartfieldenumresponse}
          • smartFieldEnumSearch {#smartfieldenumsearch}
          • smartFieldEnumSelect {#smartfieldenumselect}
          • smartFieldReady
          • smartFieldChange
          • smartFieldUploadFile
          • smartFieldUploadFileDone
          • smartFieldBeforeTabSelect
          • smartFieldAfterTabSelect
          • smartFieldTabChange
          • smartFieldConstraintCheck
          • smartFieldCreateDialogSmartElementReady
          • smartFieldCreateDialogSmartElementBeforeSetFormValues
          • smartFieldCreateDialogSmartElementBeforeSetTargetValue
          • smartFieldCreateDialogSmartElementBeforeClose
          • smartFieldCreateDialogSmartElementBeforeDestroy
          • beforeDisplayTransition
          • afterDisplayTransition
          • beforeTransitionClose
          • beforeTransition
          • failTransition
          • successTransition
      • Rendu de transition
        • Associer une classe de rendu de transition via le cycle de vie
        • Classe de rendu de transition
          • getCssReferences
          • getJsReferences
          • getTemplates
          • getTransitionParameters
          • getRenderOptions
    • Aide à la saisie

    # getTemplates

    La méthode getTemplates permet de modifier les templates utilisés lors de la génération du Smart Element et des Smart Fields. Cette méthode retourne un tableau de templates Mustache

    String[] getTemplates(\Anakeen\Core\Internal\SmartElement $document = null)
    

    # Gérer les modèles

    La méthode getTemplates() retourne unarray à plusieurs niveaux :

    • body : pour définir le template du corps du Smart Element. Le template est alors défini par une des clés suivantes :

      • file : Le template utilisé est identifié par un fichier le contenant. Le chemin de ce fichier est relatif au répertoire d'installation de Anakeen Platform 4.
      • content : Le template utilisé est directement indiqué sous la forme d'une chaîne de caractères.

      Lorsque les clés file et content sont toutes deux non vides, la clé content est utilisée et la clé file est ignorée.

    • sections : pour définir le template d'une section du Smart Element. Dans ce cas, sections est un tableau à 2 niveaux :

      1. Le premier niveau est le nom de la section
      2. Le second niveau est une des clés suivantes :
      • file : Le template utilisé est identifié par un fichier le contenant. Le chemin de ce fichier est relatif au répertoire d'installation de Anakeen Platform 4.
      • content : Le template utilisé est directement indiqué sous la forme d'une chaîne de caractères.

      Lorsque les clés file et content sont toutes deux non vides, la clé content est utilisée et la clé file est ignorée.

    Les modèles sont analysés côté client et côté serveur, et plusieurs clés sont utilisables.

    # Corps du Smart Element : body

    Le corps du Smart Element est constitué de 4 sections :

    1. L'entête
    2. Le menu
    3. Le contenu
    4. Le pied

    Son template par défaut est le suivant :

    {{> header }}
    
    {{> menu }}
    
    {{> content }}
    
    {{> footer }}
    

    Cette définition peut être modifiée au moyen de la clé body du tableau de templates pour ajouter des éléments HTML entre les sections ou tout simplement pour supprimer une ou plusieurs sections.

    Exemple : Insérer un titre entre chaque section.

    class MyRenderConfigCustom extends \Anakeen\Ui\DefaultView
    {
      public function getTemplates(\Anakeen\Core\Internal\SmartElement $document = null)
      {
        $templates = parent::getTemplates($document);
        $templates["body"]["file"] = "MY/customDocument.mustache";
        return $templates;
      }
    }
    

    Dans le fichier MY/customDocument.mustache :

    <h1>Pre Header</h1>
    {{> header}}
    <h1>Post Header</h1>
    
    {{> menu}}
    <h1>Post Menu</h1>
    
    {{> content}}
    <h1>Post Content</h1>
    
    {{> footer}}
    <h1>Post Footer</h1>
    

    Pied de page

    Le pied de page, de par sa css, est toujours affiché en bas du Smart Element. Pour afficher des éléments plus bas que le pied de page, il faut modifier la css (classe dcpDocument__footer).

    Chacune des sections peut être personnalisée au moyen d'un modèle de section.

    # Sections

    Les sections peuvent être modifiées au moyen de la clé sections du tableau de templates.

    # Entête du Smart Element : header

    L'entête du Smart Element est la section header de la catégorie sections.

    Le template par défaut de la section header est le suivant (version simplifiée) :

    <header class="dcpDocument__header">
      <img class="dcpDocument__header__icon" src="{{document.properties.icon}}" alt="Smart Element icon" />
      <a class="dcpDocument__header__title" href="api/v1/documents/{{document.properties.id}}.html"
        >{{document.properties.title}}</a
      >
      <div class="dcpDocument__header__family">{{document.properties.family.title}}</div>
    </header>
    

    Le template complet comporte des éléments plus spécifiques qui sont fonction du mode de rendu et aussi du fait d'afficher une révision passée ou non. Dans tous les cas, les trois éléments indiqués sont présent.

    Exemple : Afficher uniquement le titre.

    class MyRenderConfigCustom extends \Anakeen\Ui\DefaultView
    {
      public function getTemplates(\Anakeen\Core\Internal\SmartElement $document = null)
      {
        $templates = parent::getTemplates($document);
        $templates["sections"]["header"]["file"] = "MY/customHead.mustache";
        return $templates;
      }
    }
    

    Fichier MY/customHead.mustache :

    <h1>{{document.properties.title}}</h1>
    

    Cela donnera la structure suivante :

    <html>
      <head>
        ...
      </head>
      <body>
        <div class="Smart Element">
          <div class="dcpDocument">
            <h1>Mon Smart Element</h1>
            <nav class="dcpDocument__menu">...</nav>
            <section class="dcpDocument__body">...</section>
            <footer class="dcpDocument__footer" />
          </div>
        </div>
      </body>
    </html>
    

    # Menu du Smart Element : menu

    La barre de menu du Smart Element est la section menu de la catégorie sections.

    Par défaut :

    <nav class="dcpDocument__menu"></nav>
    

    Le menu, défini par ::getMenu(), est construit dans l'objet de la classe css dcpDocument__menu. La barre de menu peut être déplacée dans n'importe quelle autre section.

    Exemple : mettre le menu dans le footer du Smart Element

    class MyRenderConfigCustom extends \Anakeen\Ui\DefaultView
    {
      public function getTemplates(\Anakeen\Core\Internal\SmartElement $document = null)
      {
        $templates = parent::getTemplates($document);
        $templates["sections"]["footer"]["content"] =
          '<footer class="dcpDocument__footer"><div class="dcpDocument__menu"/></footer>';
        $templates["sections"]["menu"]["content"] = '';
        return $templates;
      }
    }
    

    Cela donnera la structure suivante :

    <html>
      <head>
        ...
      </head>
      <body>
        <div class="Smart Element">
          <div class="dcpDocument">
            <header class="dcpDocument__header">...</header>
            <!-- plus de menu ici -->
            <section class="dcpDocument__body">...</section>
            <footer class="dcpDocument__footer"><div class="dcpDocument__menu">...</div></footer>
          </div>
        </div>
      </body>
    </html>
    

    WARNING

    La barre de menu a un comportement spécifique lorsqu'elle est contenue dans un élément de type nav. Ce comportement implique que le menu passe en position fixed en haut du Smart Element lorsque le header n'est plus visible.

    # Contenu du Smart Element : content

    Le contenu du Smart Element est la section content de la catégorie sections.

    Par défaut :

    <section class="dcpDocument__body" />
    

    Le contenu par défaut du Smart Element est construit par le widget dans la section identifiée par la classe css dcpDocument__body. Si celle-ci n'est pas présente, il est nécessaire alors d'indiquer les Smart Fields à afficher explicitement en utilisant les variables mustache.

    Exemple : Affichage uniquement du contenu de l'onglet my_tabinformation.

    class MyRenderConfigCustom extends \Anakeen\Ui\DefaultView
    {
      public function getTemplates(\Anakeen\Core\Internal\SmartElement $document = null)
      {
        $templates = parent::getTemplates($document);
        $templates["sections"]["content"]["file"] = "MY/customContent.mustache";
        return $templates;
      }
    }
    

    Fichier "MY/customContent.mustache"

    <div class="container-fluid">
      <h1>Voici : {{document.properties.title}}</h1>
      {{{document.attributes.my_tabinformation.htmlContent}}}
    </div>
    

    Cela donnera la structure suivante :

    <html>
        <head>...</head>
        <body>
            <div class="Smart Element">
                <div class="dcpDocument">
                    <header class="dcpDocument__header">...</header>
                    <nav class="dcpDocument__menu">...</nav>
                    <div class="container-fluid">
                        <h1>Voici :  Mon Smart Element</h1>
                        <div class="dcpCustomTemplate--content" data-attrid="my_tabinformation">
                            <div class="dcpTab__content" data-attrid="my_tabinformation" ">
                                ...
                            </div>
                         </div>
                     </div>
                    <footer class="dcpDocument__footer"/>
                </div>
            </div>
        </body>
    </html>
    

    # Pied du Smart Element : footer

    Le bas du Smart Element est la section footer de la catégorie sections.

    Par défaut :

    <footer class="dcpDocument__footer" />
    

    La classe dcpDocument__footer fixe le pied de Smart Element en bas de la page pour être toujours visible. Les règles css pour le footer par défaut sont :

    .dcpDocument__footer {
      background-color: #f2f2f2;
      text-align: center;
      position: fixed;
      bottom: 0;
      width: 100%;
      z-index: 2;
    }
    

    Exemple : Afficher un copyright.

    class MyRenderConfigCustom extends \Anakeen\Ui\DefaultView
    {
      public function getTemplates(\Anakeen\Core\Internal\SmartElement $document = null)
      {
        $templates = parent::getTemplates($document);
        $templates["sections"]["footer"]["content"] = '
                    <footer class="dcpDocument__footer">
                         <strong>All right reserved &copy;</strong>
                    </footer>
                ';
        return $templates;
      }
    }
    

    Cela donnera la structure suivante :

    <html>
      <head>
        ...
      </head>
      <body>
        <div class="Smart Element">
          <div class="dcpDocument">
            <header class="dcpDocument__header">...</header>
            <nav class="dcpDocument__menu">...</nav>
            <section class="dcpDocument__body">...</section>
            <footer class="dcpDocument__footer">
              <strong>All right reserved &copy;</strong>
            </footer>
          </div>
        </div>
      </body>
    </html>
    

    # Variables des templates

    Il est possible d'utiliser des variables liées au Smart Element dans les templates.

    # Variables client

    Les variables sur les propriétés et les Smart Fields du Smart Element sont utilisables dans les templates :

    # Propriétés

    Clef Définition
    {{document.properties.id}} Identifiant du Smart Element
    {{document.properties.name}} Nom logique du Smart Element
    {{document.properties.initid}} Identifiant de la lignée du Smart Element
    {{document.properties.icon}} Url de l'icône du Smart Element
    {{document.properties.title}} Titre du Smart Element
    {{document.properties.family.title}} Titre de la structure du Smart Element
    {{document.properties.family.id}} Identifiant de la structure du Smart Element
    {{document.properties.family.icon}} Icône de la structure du Smart Element
    {{document.properties.isReadMode}} (booléen) Indique si le rendu de Smart Element est en mode consultation
    {{document.properties.isWriteMode}} (booléen) Indique si le rendu de Smart Element est en mode modification

    # Smart Fields

    Clef Définition
    {{document.attributes.fieldid.label}} Libellé du Smart Field "fieldid"
    {{document.attributes.fieldid.attributeValue.value}} Valeur brute
    {{document.attributes.fieldid.attributeValue.displayValue}} valeur affichable
    {{document.attributes.fieldid.attributeValue.specialProperty}} Autres propriétés
    {{{document.attributes.fieldid.htmlContent}}} Contenu (HTML) formaté de la valeur (Attention aux triple accolades)
    {{{document.attributes.fieldid.htmlView}}} Contenu (HTML) formaté de la valeur avec le libellé (non applicable au type tab ni aux attributs contenu dans un tableau) (Attention aux triple accolades)

    Exemple : Remplacement de l'entête

    <h1>Voici le Smart Element : "{{document.properties.title}}"</h1>
    {{> menu}}
    {{> content}}
    {{> footer}}
    

    Exemple : Affichage du cadre my_firstframe

    {{>header}}
    {{> menu}}
    <h1>Voici un cadre</h1>
    {{{document.attributes.my_firstframe.htmlView}}}
    
    {{> footer}}
    

    Ces variables sont remplacées sur le client lors du rendu du Smart Element.

    # Variables serveur

    Le template est aussi analysé par le serveur. Les variables notées entre double crochets sont des variables qui sont remplacées par le contrôleur avant d'être envoyé sur le client.

    Les clefs disponibles côté serveur sont celles gérées par le contrôleur.

    L'ensemble des clefs ne sont pas les mêmes que celle côté client. En particulier, les clefs de rendu HTML (htmlContent, htmlView) ne sont pas disponibles.

    Exemple : Remplacement de l'entête côté serveur

    <h1>[[#i18n]]my::This my document[[/i18n]] : "[[document.properties.title]]"</h1>
    {{> menu}} {{> content}} {{> footer}}
    

    ← getEtag getContextController →