Home > Software engineering >  Vue plugin misbehaving when used with Pug
Vue plugin misbehaving when used with Pug

Time:09-28

I'm using a Vue plugin vue-masked-input for masking some inputs on my site. By default the plugin works fine and as expected, but when running the same code with Pug, I ran into issues.

Working code:

<template>
  <masked-input v-model="phone_number"mask="\ \1 (111) 111-1111" placeholder-char="_" placeholder=" 1 (555) 555-5555" type="tel" />
</template>

Expected result.

Doesn't work:

<template lang="pug">
  masked-input(v-model='phone_number' mask='\ \1 (111) 111-1111' placeholder-char='_' placeholder=' 1 (555) 555-5555' type='tel')
</template>

Incorrect result.

I've been using Pug for quite some time now and have never encountered any issue like this. Can anybody help me out?

CodePudding user response:

Explanation of the problem

The Pug code in your question doesn't result in the same HTML as your "Working code." (At least in vanilla Pug; not sure when using Pug and Vue together, but I would guess that Vue uses the same Pug.)

Most code blocks on pugjs.org are editable (e.g. on the Attributes page). You can copy-paste your Pug code to one of the editable code blocks there to see the end result:

<!-- Your "Working code" -->
<masked-input
  v-model="phone_number"
  mask="\ \1 (111) 111-1111"
  placeholder-char="_"
  placeholder=" 1 (555) 555-5555"
  type="tel"
/>

<!-- The HTML code generated from the Pug code -->
<masked-input
  v-model="phone_number"
  mask="  (111) 111-1111"
  placeholder-char="_"
  placeholder=" 1 (555) 555-5555"
  type="tel"
></masked-input>

Differences:

  • The masked-input tag is not self-closing.
  • \ is converted to .
  • \1 is converted to \u0001 (Unicode control character "Start of Heading").
    • The character is not visible on the code block above, and it's anyway stripped away when editing this answer.
    • The character is shown as a red dot on pugjs.org.

Screenshot from pugjs.org (I used the browser's dev tools to modify the code block on the right to span multiple lines for demonstration purposes):

The invalid Pug code copy-pasted to pugjs.org, showing also the invalid HTML code generated from the Pug code.

If you copy-paste the mask attribute's value from pugjs.org to vue-masked-input's demo (to the left input under the heading "Your own mask"), you'll get the same result as in your second screenshot. This confirms that the problem is most likely in the incorrect value of the mask attribute.

The fix

Two changes are needed to the Pug code to fix the HTML:

  • Make the masked-input self-closing by appending a slash: masked-input()masked-input()/.
  • Escape the backslashes with additional backslashes:
    • \ \\
    • \1\\1

Like so:

<template lang="pug">
  masked-input(
    v-model='phone_number'
    mask='\\ \\1 (111) 111-1111'
    placeholder-char='_'
    placeholder=' 1 (555) 555-5555'
    type='tel'
  )/
</template>

You can also put the Pug code on a single line, but placing it on multiple lines improves readability.

Result (identical to your "Working code"):

<masked-input
  v-model="phone_number"
  mask="\ \1 (111) 111-1111"
  placeholder-char="_"
  placeholder=" 1 (555) 555-5555"
  type="tel"
/>
  • Related