Special Keys

The following special JSON keys provide additional logic when processing the data file.

_dataUrl

Deprecated.

Location of a file to be included in the JSON object. Although _dataUrl is still supported, new code should use _include.

_delegate

Inserts any selected template into a wrapper template’s delegated placeholder. Applicable in top-level data files /styleguide/_wrapper.json. This key promotes modular development, because it incorporates different types of referred templates into a top-level referring template. A typical scenario is building a referring template with a header, body, and footer, and delegating the contents of the body to an arbitrary referred template.

The following example illustrates the effect of _delegate.

Step 1: Create Article Template

Create a modular template /styleguide/article/Article.hbs containing an article’s headline and body.

<div class="Article">
    <div class="Article-headline">
        {{articleHeadline}}
    </div>
    <div class="Article-body">
        {{articleBody}}
    </div>
</div>

The previous snippet is designed to be referenced by other templates: there are no <html>, <head>, and <body> tags, all of which are provided by the more complete wrapper template.

Step 2: Create Article Data File

Create a data file /styleguide/article/Article.json that populates the template Article.hbs with mock data.

{
  "_template": "/styleguide/article/Article.hbs",
  "articleHeadline": "New Mexico Headed for Real Estate Bubble",
  "articleBody": "Real estate agents throughout northern New Mexico are reporting brisk sales of property even though a meteor is predicted to flatten the area in the year 2035."
}

Step 3: Create Wrapper Template

Create a template /styleguide/page/Page.hbs that serves as a wrapper template. At runtime, Styleguide wraps all selected templates inside this template.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
   <head>
       <title>{{pageHeader}}</title>
       <link href="/styleguide/All.min.css" type="text/css" rel="stylesheet" />
   </head>

   <body>
       <div class="Page">
           <div class="Page-header">
               {{pageHeader}}
           </div>
           {{pageBody}}
           <div class="Page-footer">
               {{pageFooter}}
           </div>
       </div>
   </body>
</html>

In the previous snippet, line 13 has a placeholder pageBody. At runtime, Styleguide replaces this placeholder with the hydrated template selected in the Styleguide GUI. (When your Styleguide project is integrated with a parent project such as Brightspot, the backend implements interfaces to populate this placeholder with the appropriate child View.)

Step 4: Create Wrapper Data File

Create a data file /styleguide/_wrapper.json that hydrates the wrapper template Page.hbs with mock data and includes a delegate instruction.

1
2
3
4
5
6
7
8
{
  "_template": "/styleguide/page/Page.hbs",
  "pageHeader": "Extraterrestrial Times",
  "pageBody": {
    "_delegate": true
  },
  "pageFooter": "Area 51, Edwards Air Force Base"
}

In the previous snippet, lines 4–6 insert any selected template into the wrapper template’s {{pageBody}} placeholder.

Note

You can prevent a template from being wrapped inside a wrapper template. For details, see _wrapper.

Step 5: Add Styling

This step is optional.

Create a styling file /styleguide/article/Article.less that generates the CSS selectors.

.Page {
  font-family: sans-serif;

  &-header {
    font-size: 18px;
    margin-bottom: 1.0em;
  }

  &-footer {
    font-size: 18px;
    margin-top: 1.5em;
  }

}

.Article {
  &-headline {
    font-size: 24px;
    margin-bottom: 0.5em;
  }

  &-body {
    font-size: 18px;
    font-family: serif;
  }

}
/* Ensure this file ends with a blank line */

Next, create a file /styleguide/All.less that imports the styling file.

@import 'article/Article';
/* Ensure this file ends with a blank line */

Step 6: Run Styleguide

If the Styleguide server isn’t running, in the root directory /styleguide/ enter gulp styleguide.

Runtime Analysis

The sequence of events at runtime are as follows:

  1. User clicks a template in the Styleguide GUI, such as Article.
  2. Check for existence of the file /styleguide/_wrapper.json.
  3. If the file exists, retrieve associated wrapper template from the key _template, in this case Page.hbs.
  4. Hydrate the retrieved wrapper template with explicit values from /styleguide/_wrapper.json.
  5. Open the data file associated with the selected template Article, in this case Article.json.
  6. Retrieve the associated template from the key _template, in this case Article.hbs.
  7. Hydrate Article.hbs with values from its data file Article.json.
  8. Place the hydrated template Article.hbs into the placeholder {{pageBody}} inside the wrapper template.
../../_images/delegate-key.svg

_image

If true, indicates that the backend retrieves image attributes, such as height, width, and possibly other attributes listed in The img Element, from /styleguide/_config.json.

1
2
3
4
5
6
{
  "_template": "/absolute/path/to/Image.hbs",
  "image": {
    "_image": true
  }
}

In the previous snippet—

  • Line 2 indicates the template file is Image.hbs.

  • Line 3 indicates the Model element to be laid out is image.

  • Line 4 indicates the following:

    • When building a parent project that incorporates Styleguide, the generated Java View interface specifies a method that returns the image’s attributes as a Map<String, ?>.
    • The map’s keys and values are retrieved from /styleguide/_config.json. You place in this file all the traditional image attributes such as width and height. In addition, Styleguide automatically inserts into the map a key src that specifies the image’s URL.
    • The backend ViewModel implementing the View’s method retrieves the keys and values using the ImageSize.getAttributes() method.

    The following code samples illustrate the processing logic for configuring and retrieving the image attributes. The following snippet is an example of specifying image attributes in /styleguide/_config.json.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
  "imageSizes": {
    "tiny": {
      "width": 50,
      "height": 50,
      "srcset": ["2x"]
    },
    "small": {
      "width": 300,
      "height": 200,
      "srcset": ["2x"]
    }
  },
  "imageSizeContexts": {
    "Image.hbs": {
      "image": "tiny"
    }
  }
}

In the previous snippet—

  • Lines 15–17 specify that when rendering the field image using the template Image.hbs, the corresponding image attributes come from the object labeled imageSizes.tiny.
  • Lines 3–7 provide the image attributes for tiny.

Backend ViewModels extract the image data by implementing the ImageView interface. The following snippet is an example of an automatically generated interface based on the previous Styleguide JSON file.

1
2
3
4
5
6
public interface ImageView extends PageViewMainField {

    default Map<String, ?> getImage() {
    }

}

The following snippet is an example of a ViewModel retrieving image attributes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package content.article;

import com.psddev.cms.image.ImageSize;
import java.util.Map;

public class ImageViewModel extends ViewModel<Image> implements ImageView {

    @Override
    public Map<String, ?> getImage() {
        return ImageSize.getAttributes(model.getImage());
    }

}

In the previous snippet, line 10 retrieves the following items in an object named image:

  • The URL for the image, saved in the map’s src key.
  • The other attributes stored in the JSON file using the following logic:
    1. At runtime, determine the template file. In this case, Styleguide knows the template is Image.hbs.
    2. Open the file /styleguide/_config.json, and look up the value for ImageSizeContexts.Image.hbs.image. In this case the value is tiny.
    3. Using the retrieved value from step 2, look up the image attributes under imageSizes.tiny, and store those attributes in an object named image.

When rendering the View, the backend uses the properties in image to lay out the image.

_include

Location of a referenced data file to be included in this one. This key promotes the reuse of existing templates and data files.

Example 1: Referencing One Template from Another

The following steps provide an example of using _include to reference an author template from an article template.

Step 1: Create Author Template

Create a modular template AuthorInfo.hbs containing the author’s name and bio.

<div>
    {{authorName}}
</div>
<div>
    {{authorBio}}
</div>

The previous snippet is designed to be referenced by other templates: there are no <html>, <head>, and <body> tags, all of which are provided by the more complete referencing template.

Step 2: Create Author Data File

Create a data file AuthorInfo.json that populates the template AuthorInfo.hbs with mock data.

{
  "_template": "/absolute/path/to/AuthorInfo.hbs",
  "authorName": "{{name()}}",
  "authorBio": "{{words(10)}}"
}

Step 3: Create Article Template

Create a template Article.hbs for an article that references the author template.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
   <head>
       <title>{{headline}}</title>
   </head>

   <body>
       <div>
           {{headline}}
       </div>
       <div>
           {{body}}
       </div>
       {{authorInfo}}
   </body>
</html>

In the previous snippet, line 14 has a placeholder authorInfo. Styleguide replaces this placeholder with the template for author info using the data file created in the following step. Furthermore, this snippet is a complete HTML file: it contains the <html>, <head>, and <body> tags.

Step 4: Create Article Data File

Create a data file Article.json that populates the template Article.hbs with mock data and also contains a reference to the data file AuthorInfo.json.

1
2
3
4
5
6
7
8
{
  "_template": "/absolute/path/to/Article.hbs",
  "headline": "{{words(4)}}",
  "body": "{{paragraphs(1, 2, 10)}}",
  "authorInfo": {
    "_include": "AuthorInfo.json"
  }
}

At runtime, lines 5–7 perform the following:

  1. Open the file AuthorInfo.json.
  2. Retrieve the value for the key _template, which is AuthorInfo.hbs.
  3. In the article template Article.hbs, replace the placeholder authorInfo with the contents of the template AuthorInfo.hbs.
  4. Populate all placeholders with mock data from the data files Article.json and AuthorInfo.json.

At the end of these steps, Styleguide produces the complete page.

<!DOCTYPE html>
<html>
    <head>
        <title>Omri ka co uk</title>
    </head>

    <body>
        <div>
            Omri ka co uk
        </div>
        <div>
            <p>Awma uze lucfaw siwgicgev wugtuwdob gulnoj apevema gitjifo div dabawibep. Wasef je kim joh fa kohwodvo fabege koni tezwib binsifzen.</p>
        </div>
        <div>
            Frank Stanley
        </div>
        <div>
            Lohadmi pe voku lumowwi ha Eddie Silva odro da ed uwaeme
        </div>

    </body>
</html>

Example 2: Referencing One Template from Another Multiple Times

Example 1: Referencing One Template from Another describes how to reference one template from another a single time. You can use the _repeat key to include a template multiple times.

1
2
3
4
5
6
7
8
9
{
  "_template": "/absolute/path/to/Article.hbs",
  "headline": "{{words(4)}}",
  "body": "{{paragraphs(1, 2, 10)}}",
  "authorInfo": {
    "_include": "AuthorInfo.json"
    "_repeat": [ 3, 4 ]
  }
}

In the previous snippet, line 7 indicates that Styleguide includes AuthorInfo.json 3–4 times. For more information about repeated includes, see _repeat.

Example 3: Including an Element From a JSON Array

There are times when you may want to organize similar template components into a single data file. The following snippet, named AuthenticationForms.json, contains variations for the prompt on an authentication page: register, log in, and forgot password.

[
  {
    "_template": "/absolute/path/to/RegistrationForm.hbs",
    "body": "<p>Register</p>"
  },
  {
    "_template": "/absolute/path/to/LoginForm.hbs",
    "body": "<p>Log in</p>"
  },
  {
    "_template": "/absolute/path/to/ForgotPassword.hbs",
    "body": "<p>Forgot password</p>"
  }
]

The previous snippet is a JSON array of three elements. You can refer to one of these elements in a parent data file.

1
2
3
4
5
6
{
  "main": {
    "_include": "/absolute/path/to/AuthenticationForms.json",
    "_key": 1
  }
}

In the previous snippet—

  • Line 3 refers to the file containing a JSON array.
  • Line 4 refers to the index within the JSON array to include. In this case, Styleguide includes the second element in the array, corresponding to the log-in form.

For more information about including elements from a JSON array, see _key.

Example 4: Including a Random Element From a JSON Array

There are times when you may want to display different layouts of the same content type. The following snippet, named AdTypes.json, contains variations for ad layout: one with text only, the other with text and an image.

[
  {
    "_template": "/styleguide/content/random/TextOnly.hbs",
    "body": "{{words(10)}}"
  },
  {
    "_template": "/styleguide/content/random/TextAndImage.hbs",
    "body": "{{words(10)}}",
    "image": "{{image(100,100)}}"
  }
]

The previous snippet is a JSON array of two elements, and at runtime Styleguide can randomly select one of them to display.

1
2
3
4
5
6
{
  "main": {
    "_include": "/absolute/path/to/AdTypes.json",
    "_random": true
  }
}

In the previous snippet—

  • Line 3 refers to the file containing a JSON array.
  • Line 4 instructs Styleguide to randomly draw one of the layouts from the referred data file and include it in the parent file.

_key

When present with an _include key that points to a file containing a JSON array, specifies which element within the array to use. Indexing of _include arrays starts at zero.

{
  "main": {
    "_include": "/absolute/path/to/ArticleBodies.json",
    "_key": 0
  }
}

In the previous snippet, Styleguide examines the array in the file ArticleBodies.json, and uses the first element to generate child Views for main. If there is no _key element, then Styleguide imports the entire included file.

For another example, see the snippet under Example 3: Including an Element From a JSON Array.

_random

Randomly selects which element within an array to use for generating a View. Applies when all of the following are true:

  • Present with an _include key.
  • _include points to a file containing a JSON array.
  • _random is set to true.
{
  "main": {
    "_include": "/absolute/path/to/ArticleBodies.json",
    "_random": true
  }
}

In the previous snippet, Styleguide examines the array in the file ArticleBodies.json, and randomly selects one of the elements to generate child Views for main.

For another example, see the snippet under Example 4: Including a Random Element From a JSON Array.

_repeat

Number of times a JSON object referenced by _include is repeated. This entry has two forms:

  • Repeating a fixed number of time: "_repeat": 1
  • Repeating a random number of times between x and y: "_repeat": [ x, y ]

For an example, see the snippet under Example 2: Referencing One Template from Another Multiple Times.

_template

Path to the corresponding template. Your data file must have either a _template or a _view key.

As a best practice, use a full path from the Styleguide root to the template file. If there is a _delegate key that includes other templates, the full path ensures Styleguide can find those included templates.

{
  "_template": "/styleguide/page/Page.hbs",
}

_view

Fully qualified class name that outputs a JSON object instead of HTML in the preview. Use _view instead of _template when the output for the View should be directly serialized to JSON. Your data file must have either a _template or a _view key.

_wrapper

When false, the associated template is not wrapped inside a wrapper template. For example, suppose you have a data file /styleguide/_wrapper.json as follows:

1
2
3
4
5
6
7
8
{
  "_template": "/absolute/path/to/Page.hbs",
  "pageHeader": "Extraterrestrial Times",
  "pageBody": {
    "_delegate": true
  },
  "pageFooter": "Area 51, Edwards Air Force Base"
}

In the previous snippet, lines 4–6 indicate that any template selected in the Styleguide GUI is hydrated and inserted into the wrapping template’s {{pageBody}} placeholder. (For a detailed explanation, see _delegate.) However, if a template’s data file has the key _wrapper set to false, Styleguide displays the selected template without the wrapping.

1
2
3
4
5
6
{
  "_template": "/absolute/path/to/Article.hbs",
  "_wrapper": false,
  "articleHeadline": "New Mexico Headed for Real Estate Bubble",
  "articleBody": "Real estate agents throughout northern New Mexico are reporting brisk sales of property even though a meteor is predicted to flatten the area in the year 2035."
}

In the previous snippet, line 3 prevents Article.hbs from being wrapped inside a top-level template.