# Mixins

Mixins are like functions and allow you to reduce repetitive content.

## Naming

Mixins names should be written in `camelCase`. Use `UpperCamelCase` for exported mixins, more on that in the next chapter.

## Parameters

Unlike functions, mixins have unordered parameters that must be set by name. When defining the mixin you may set defaults for parameters that are optional. Required parameters must always have a type, the type of optional parameters will be inferred from the default value.

{% hint style="info" %}
Corgi may sometimes not be able to infer the type of an optional parameter by it's default expression. Don't worry, should that be the case, the corgi compiler will tell you.

In such cases it may be necessary for you to explicitly define the type, like for the `bar` parameter below.
{% endhint %}

```pug
mixin myMixin(foo string, bar string = "baz", foobar = "foozbaz", fooz = nil)
  p 
    > #{foo}, #{bar}, #{foobar}
    if fooz != nil
      > , #{fooz}
```

{% tabs %}
{% tab title="Corgi" %}

```pug
div: +myMixin(foo="abc", foobar="def")
```

{% endtab %}

{% tab title="HTML" %}

```markup
<div><p>abc, baz, def</p></div>
```

{% endtab %}
{% endtabs %}

You can use any expression to set a parameter including ternary and chain expressions.

When using a chain expression, the parameter will only be set if the chain expression passes its checks. When using a chain expression for a required parameter you must provide a default.

{% hint style="warning" %}
If you have parameters that accept URLs or srcset values, you should set their type to `woof.URL` or `woof.Srcset` to leverage corgi's contextual escaping.

Consider the following example to illustrate:

```pug
mixin foo(href string): a(href=href) foo

- a := "foo&bar"
+foo(href="/foo?a=#{a}")
// generates: <a href="/foo?a=foo&bar">foo</a>
```

This is probably not what you expected and can be solved by making `href`'s type `woof.URL`:

```pug
import "github.com/mavolin/corgi/woof"

mixin foo(href woof.URL): a(href=href) foo

- a := "foo&bar"
+foo(href="/foo?a=#{a}")
// generates: <a href="/foo?a=foo%26bar">foo</a>
```

{% endhint %}

## Blocks

Blocks allow you to define placeholders for longer content.

Each block is named. If you only have a single block, it is conventional to call it `_`.

```pug
mixin foo()
  p: block _
```

{% tabs %}
{% tab title="Corgi" %}

```pug
div
  +foo()
    block _ This is the content of the block.


```

{% endtab %}

{% tab title="HTML" %}

```markup
<div>
  <p>
            This is the content of the block.
  </p>
</div>
```

{% endtab %}
{% endtabs %}

You are not limited to just one block. If you want, you can use multiple of them.

```pug
mixin namedBlocks()
  div
    p: block myFirstBlock
    p: block myOtherBlock
```

{% tabs %}
{% tab title="Corgi" %}

```pug
div
  +namedBlocks()
    block myFirstBlock
      &.foo
      > This text will appear in the first <p>.

    block myOtherBlock
      > This text will appear in the second <p>.



```

{% endtab %}

{% tab title="HTML" %}

```markup
<div>
  <div>
    <p 
      class="foo">
        This text will appear in the first &lt;p>.
    </p>
    <p>
        This text will appear in the second &lt;p>.
    </p>
  </div>
</div>
```

{% endtab %}
{% endtabs %}

### Block Short Form

If you only want to fill the `_` block, then you can use one of the block short forms. All of the below examples are equivalent.

{% tabs %}
{% tab title="Corgi - Backslash" %}

```pug
div
  +foo()\
    > Beam me up, Scotty!
```

{% endtab %}

{% tab title="Corgi - Inline Text" %}

```pug
div
  +foo() Beam me up, Scotty!

```

{% endtab %}

{% tab title="Corgi - Block Expansion" %}

```pug
div
  +foo():> Beam me up, Scotty!

```

{% endtab %}

{% tab title="HTML" %}

```markup
<div>
  <p>Beam me up, Scotty!</p>
</div>
```

{% endtab %}
{% endtabs %}

### Defaults and Checking If a Block Exists

Just like parameters, you can also define defaults for blocks.

```pug
mixin withDefaults()
  p
    block _
      > Nothing to see here.
```

{% hint style="info" %}
Unlike parameters, there are no "required" blocks. If you don't define a default for a block, it is assumed that the default is simply nothing.
{% endhint %}

{% tabs %}
{% tab title="Corgi" %}

```pug
+withDefaults()
+withDefaults() A lot to see here.
```

{% endtab %}

{% tab title="HTML" %}

```markup
<p>Nothing to see here.</p>
<p>A lot to see here.</p>
```

{% endtab %}
{% endtabs %}

You can also use an `if block` conditional to check if a block exists.

```pug
mixin leftRight()
  div(style="display: flex; justify-content: space-between;")
    div: block left
    if block right
      div: block right
```

{% tabs %}
{% tab title="Corgi" %}

```pug
+leftRight()
  block left
    p Left only


+leftRight()
  // no block left
  block right
    p Right only


+leftRight()
  block left
    p Left...

  block right
    p ...and right


```

{% endtab %}

{% tab title="HTML" %}

```markup
<div style="display: flex; justify-content: space-between;">
  <div>
    <p>Left only</p>
  </div>
</div>
<div style="display: flex; justify-content: space-between;">
  <div></div>
  <div>
    <p>Right only</p>
  </div>
</div>
<div style="display: flex; justify-content: space-between;">
  <div>
    <p>Left...</p>
  </div>
  <div>
    <p>...and right</p>
  </div>
</div>
```

{% endtab %}
{% endtabs %}

## The `&`-Operator

You can also use the `&` operator inside the body of a mixin call to add attributes to elements with an &-placeholder:

```pug
mixin andPlaceholder()
  p(&&): block _
```

{% tabs %}
{% tab title="Corgi" %}

```pug
div
  +foo()
    &.foo.bar
    block _ Content


```

{% endtab %}

{% tab title="HTML" %}

```markup
<div>
  <p
    class="foo bar">
      Content
  </p>
</div>
```

{% endtab %}
{% endtabs %}

## Interpolation

Similar to expression interpolation, you can also interpolate mixins.

You can also fill the mixin's `_` block, if you add `[text]` in brackets, or an `{expression}` in braces.

```pug
mixin beam(verb="Beam")
  > #{verb} me up,#[ ]
  block _ Scotty
  > !
```

{% tabs %}
{% tab title="Corgi" %}

```pug
p And then he said: #+beam()
p And then he said: #+beam(verb="Fly")
p And then he said: #+beam()[Chekov]
- sulu := "Sulu"
p And then he said: +beam(){sulu}
```

{% endtab %}

{% tab title="HTML" %}

<pre class="language-markup"><code class="lang-markup"><strong>&#x3C;p>And then he said: Beam me up, Scotty!&#x3C;/p>
</strong>&#x3C;p>And then he said: Fly me up, Scotty!&#x3C;/p>
&#x3C;p>And then he said: Beam me up, Chekov!&#x3C;/p>

&#x3C;p>And then he said: Beam me up, Sulu!&#x3C;/p>
</code></pre>

{% endtab %}
{% endtabs %}

## Mixins As Attribute Values

Mixins that only generate text (and no elements, or attributes) can be used as values for attributes.

The syntax is the same as for interpolated mixins, minus the leading `#`.

{% tabs %}
{% tab title="Corgi" %}

```pug
img(src="beam-me-up.webp", alt=+beam(verb="Fly")[Chekov])
```

{% endtab %}

{% tab title="HTML" %}

```markup
<img src="beam-me-up.webp" alt="Fly me up, Chekov!">
```

{% endtab %}
{% endtabs %}
