Components

Components are files that you can pull into a Template. You can pass data and content to them, and they help you organize blocks of markup that you use often.

Syntax

To create a Component, simply create an HTML file with a <content> tag:

<!-- src/components/example.html -->
<content></content>

The <content> tag is where content passed to the Component will be output.

To use a Component in a Template, you can use the <component> tag:

<component src="src/components/example.html">
  This text will replace the `content` tag in the Component.
</component>

Configuration

You can define where you keep your Components and what markup they use.

Attribute

Use a custom attribute name:

module.exports = {
  build: {
    components: {
      attribute: 'href',
    }
  }
}

You can now use it like this:

<component href="src/components/example.html">
  Content to pass inside component...
</component>

Tag

Use a custom tag name:

module.exports = {
  build: {
    components: {
      tag: 'module',
    }
  }
}

You can now use it like this:

<module src="src/components/example.html">
  Content to pass inside component...
</module>

Root

By default, when using a Component you have to reference its path relative to your project root (like we did above).

However, you can customize this path:

module.exports = {
  build: {
    components: {
      root: 'src/components',
    }
  }
}

Now you can reference them relative to that root path, and write less code:

<component src="example.html">
  Content to pass inside component...
</component>

Example

Let's create a VML background image Component, to which we can pass data about the image, and the HTML to be overlayed on top of it.

We might imagine something like this:

<!--[if mso]>
<v:image src="{{ page.image.url || 'https://via.placeholder.com/600x400' }}" xmlns:v="urn:schemas-microsoft-com:vml" style="width:{{ page.image.width || 600 }}px;height:{{ page.image.height || 400 }}px;" />
<v:rect fill="false" stroke="false" style="position:absolute;width:{{ page.image.width || 600 }}px;height:{{ page.image.height || 400 }}px;">
<v:textbox inset="0,0,0,0"><div><![endif]-->
<content></content>
<!--[if mso]></div></v:textbox></v:rect><![endif]-->

The content of the Component or, in our case, the HTML to be overlayed, will be output in place of the <content> tag.

The variables that we are referencing from the page object are currently undefined, so we let's create them in Front Matter:

---
image:
  url: https://example.com/image.jpg
  width: 600
  height: 400
---

<extends src="src/layouts/main.html">
  <block name="template">
    <component src="src/components/my-component.html">
      <div>
        Overlayed HTML!
      </div>
    </component>
  </block>
</extends>

Result:

<!--[if mso]>
<v:image src="https://example.com/image.jpg" xmlns:v="urn:schemas-microsoft-com:vml" style="width:600px;height:400px;" />
<v:rect fill="false" stroke="false" style="position:absolute;width:600px;height:400px;">
<v:textbox inset="0,0,0,0"><div><![endif]-->
  <div>
    Overlayed HTML!
  </div>
<!--[if mso]></div></v:textbox></v:rect><![endif]-->

Variables

When creating a Component, you have access to global variables:

<!-- src/components/example.html -->
<div>
  A 'global' variable: {{ page.env }}
</div>

You can also manually provide data to the Component, in the form of a JSON string that you pass inside a locals attribute:

<extends src="src/layouts/main.html">
  <block name="template">
    <component src="src/components/vmlbg.html" locals='{"foo": "bar"}'>
      <div>
        Foo is {{ foo }}
      </div>
    </component>
  </block>
</extends>

Of course, you can use both approaches at the same time.

Ignoring

Ignoring expressions inside a Component is a bit different.

To ignore a single expression:

@@{{ foo }}

To ignore a code block:

<raw>
  @{{ foo }}
</raw>