# vue-pug-loader

A Webpack loader that compiles [pug](https://pugjs.org) templates into HTML specifically for use in Vue component templates. Forked from [pug-plain-loader](https://npmjs.com/package/pug-plain-loader), added [vue-pug-plugin](https://npmjs.com/package/vue-pug-plugin) to convert native pug syntax into an AST that Vue will understand. 

If you want first class pug support in Vue component templates, and you don't use Webpack/Laravel Mix, use [vue-pug-plugin](https://npmjs.com/package/vue-pug-plugin) instead.

The motivation for this fork is to add first-class pug syntax support in the context of Vue component templates. Instead of writing an ugly mish-mash of pug _and_ Vue syntax in your component, eg:

```pug
<template lang="pug">
ul
  li(v-for="item in items")
    a(v-if="item.type == 'link'" :href="item.url") some link title: {{item.title}}
    p(v-else) {{item.content}}
</template>

<script> 
  // ...Vue component JS
```

With `vue-pug-loader` you can rely on the proper, first-class native pug syntax for iteration and conditionals, as well as var interpolation, eg:

```pug
<template lang="pug">
ul
  for item in items
    li
      if item.type == 'link'
        a(:href="item.url") some link title: #{item.title}
      else
        p= item.content
</template>

<script>
  // ...Vue component JS
```

Note that since pug natively allows `for` and `if`/`else if`/`else` blocks with multiple children inside them, but Vue's approach of attaching control logic to individual elements is necessarily singular, if your native pug blocks have multiple children, a `template` tag will be inserted to transparently make it Vue-friendly, eg:

```pug
if foo == 1
  h1 Hello
  p It's foo!
```

Gets translated to:

```pug
template(v-if="foo == 1")
  h1 Hello
  p It's foo!
```

## Installation

Note `pug` is a peer dependency, so make sure to install both:

``` sh
npm install -D vue-pug-loader pug
```

## Usage

This loader is mostly intended to be used alongside `vue-loader` v15+, since it now requires using webpack loaders to handle template preprocessors.

If you are only using this loader for templating in single-file Vue components, simply configure it with:

``` js
{
  module: {
    rules: [
      {
        test: /\.pug$/,
        loader: 'vue-pug-loader'
      }
    ]
  }
}
```

This will apply this loader to all `<template lang="pug">` blocks in your Vue components.

If you also intend to import `.pug` files as HTML strings in JavaScript for use outside of Vue single file components, you will need to chain `raw-loader` after either `vue-pug-loader` (if you still want to transform the pug syntax into Vue syntax) _or_ [pug-plain-loader](https://npmjs.com/package/pug-plain-loader) (if you dont want to transform pug syntax into Vue syntax). Note however adding `raw-loader` would break the output for Vue components, so you need to have two rules, one of them excluding Vue components:

``` js
{
  module: {
    rules: [
      {
        test: /\.pug$/,
        oneOf: [
          // this applies to pug imports inside JavaScript
          {
            exclude: /\.vue$/,
            use: ['raw-loader', 'pug-plain-loader']
          },
          // this applies to <template lang="pug"> in Vue components
          {
            use: ['vue-pug-loader']
          }
        ]
      }
    ]
  }
}
```

## Using with Laravel Mix

You can use `vue-pug-loader` in [Laravel Mix](https://laravel-mix.com/) by passing the relevant Webpack rules to Mix's `webpackConfig` method, eg:

``` js
.webpackConfig({
  module: {
    rules: [
      {
        test: /\.pug$/,
        loader: 'vue-pug-loader',
      }
    ],
  }
})
```

## Vue variable interpolation

You can continue to use Vue-style variable interpolation syntax (eg `{{ foo }}`) if you wish, but you may also prefer to use pug interpolation syntax instead.

If you prefer to stick with native pug interpolation syntax, any instance of pug [buffered code](https://pugjs.org/language/code.html#buffered-code) will get be automatically converted to Vue antlers syntax. For example:

```pug
p= foo
```

Will become:

```pug
p {{foo}}
```

This also applies to pug [string interpolation](https://pugjs.org/language/interpolation.html), for example:

```pug
p some normal text #{foo} hey there
```

Will become:

```pug
p some normal text {{foo}} hey there
```

Note that for Vue _attribute_ variables you should continue to wrap them in string literals, eg:

```pug
//- correct
a(:href="someVueVar + '.com'")

//- incorrect
a(:href=someVueVar + '.com')
```

If you use [unbuffered](https://pugjs.org/language/code.html#unbuffered-code) code, that will not be transformed, instead it will be left in the code for _compile-time_. If you want to output a variable from that unbuffered code in your pug template at _compile-time_, you can use [unescaped buffered code](https://pugjs.org/language/code.html#unescaped-buffered-code) and [unescaped string interpolation](https://pugjs.org/language/interpolation.html#string-interpolation-unescaped). For example:

```pug
- var unbuffered = 'foo'

p!= unbuffered // <--- will insert 'foo' at compile-time, not dynamically via Vue client-side
```

The majority of the time when using pug inside a Vue template, you only really care about _Vue_ data/variables, hence why the more common pug buffered/escaped symbols are transformed into the Vue antlers syntax

## Loops & Vue iteration keys

As expected, you can manually specify the `:key` attribute on the child of a `for` block. For example:

```pug
for item, i in items
  p(:key="i") foo
```

However, if you use `key` as the loop index variable name, `:key="key"` will automatically be inserted on the looping element. For example:

```pug
for item, key in items
  p foo
```

Will translate to:

```pug
p(v-for="(item, key) in items" :key="key") foo
```

Any other loop index variable name (eg `for item, index...`, `for item, i...` etc) will not add the `:key` attribute to the looping element.

Importantly, if a native pug `for` block has multiple children, since a `template` wrapper will be automatically inserted, if you are using [Vue 3](https://v3.vuejs.org/guide/migration/key-attribute.html#with-template-v-for) and need to attach a `:key` attribute to the inserted `template` looping element, you should also use `key` as the name of the loop index variable. For example:

```pug
for item, key in items
  p foo
  p bar
```

Will translate to:

```pug
template(v-for="(item, key) in items" :key="key") 
  p foo
  p bar
```

If you are using Vue 2 and a pug `for` block has multiple children, you cannot add `:key` to a `template` tag, in which case you should not rely on this automatic behaviour. Instead, manually add the `:key` attribute to each child element, or use your own wrapper element with something like `:key="index"` specified. [See here](https://v3.vuejs.org/guide/migration/key-attribute.html#with-template-v-for) for more information on the difference between Vue 2/3 and the handling of the `:key` attribute on `template` tags

## Options

See [Pug compiler options](https://pugjs.org/api/reference.html#options).

The `doctype` option is set to `html` by default, since most Vue templates are HTML fragments without explicit doctype.

An additional option `data` can be used to pass locals for the template, although this is typically not recommended when using in Vue components.
