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.

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.

mixin myMixin(foo string, bar string = "baz", foobar = "foozbaz", fooz = nil)
  p 
    > #{foo}, #{bar}, #{foobar}
    if fooz != nil
      > , #{fooz}
div: +myMixin(foo="abc", foobar="def")

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.

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:

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:

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>

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 _.

mixin foo()
  p: block _
div
  +foo()
    block _ This is the content of the block.

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

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

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


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.

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

Defaults and Checking If a Block Exists

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

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

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.

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

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

mixin leftRight()
  div(style="display: flex; justify-content: space-between;")
    div: block left
    if block right
      div: block right
+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

The &-Operator

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

mixin andPlaceholder()
  p(&&): block _
div
  +foo()
    &.foo.bar
    block _ Content

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.

mixin beam(verb="Beam")
  > #{verb} me up,#[ ]
  block _ Scotty
  > !
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}

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 #.

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

Last updated