Vue.jsのカスタムディレクティブ作って公開した話

f:id:ao_kiken:20191204113028p:plain この記事はBASE Advent Calendar 2019の6日目の記事です

devblog.thebase.in

どうもこんにちは、Frontend Groupの青木です

BASEではVue.js+TypeScriptを採用したフロントエンド開発を行っています

今回のブログでは、私が業務で直面したちょっとした課題を、Vue.jsのカスタムディレクティブを実装して解決し、npmのパッケージとして公開した話をします

何を作ったか

vue-remove-whitespace - npm

spanやaなどのinline要素内での改行による意図しないスペースを削除するVue.jsのカスタムディレクティブを作りました

挙動としては

<p v-remove-whitespace>
  お問い合わせは
  <a href="#">こちらから</a>
  お願いします
</p>

というvueのtemplateが、レンダリングされる際には

<p>お問い合わせは<a href="#">こちらから</a>お願いします</p>

となります

ディレクティブの指定がある場合と無い場合では、

お問い合わせはこちらからお願いします
お問い合わせは こちらから お願いします

のような見かけ上の違いが生じます

この程度の文字数であれば、最初から改行を含めなければいいのでは?と思うところですが、各要素のattribute属性やイベント修飾子、propsなど入力するものが増えたりすると、改行したくなったりすることもあり、解決できるものを作ろうと思いました

npmのpackageとして公開するまでにしたこと

調べている過程で、vue-focusというライブラリの開発構成がシンプルそうでいいなと思い、構成をforkして、機能実装を済ませ、初回のリリースを終えました

テストの実装と、TypeScriptの開発環境で使いやすくする

公開して満足してしまい、追加で開発しようと思っていたことができていなかったのですが、今回のアドベントカレンダーを機会に、テストの実装とTypeScriptの開発環境で使いやすくしてみました

テストを実装するまでにしたこと

import { removeWhitespace } from '../index'

export default {
  directives: { removeWhitespace },
  template: `
      <div v-remove-whitespace>
          <span>1</span>
          <span>2</span>
          <span>3</span>
          <span>4</span>
          <span>5</span>
      </div>
  `,
}
import { mount } from '@vue/test-utils'
import InlineElementWithLineBreak from './InlineElementWithLineBreak'

describe('InlineElementWithLineBreak', () => {
  const wrapper = mount(InlineElementWithLineBreak)
  it('renders the correct markup', () => {
    expect(wrapper.html()).toBe('<div><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span></div>')
  })
})

簡単なテストですが、期待通りに動いていることが確認できました🎉

TypeScriptの開発環境で使いやすくするためにしたこと

  • index.d.tsを書く

https://github.com/aokiken/vue-remove-whitespace/blob/master/index.d.ts

import { DirectiveOptions } from 'vue'

export const version: string
export const removeWhitespace: DirectiveOptions
export const mixin: {
    directives: {
        [key: string]: DirectiveOptions,
    },
}
  • package.jsonにtypesを追記する

https://github.com/aokiken/vue-remove-whitespace/blob/master/package.json#L61 f:id:ao_kiken:20191204113426p:plain

これらを追記したおかげで、TypeScriptのプロジェクトでも、型情報が参照できるようになりました🎉

最後に

今回のnpm公開は、実装の過程でコンパクトな機能が出来たので、これなら公開できそうと思ったことと、 まずはやってみよう という思いから挑戦してみました

おまけ1: いくつか対応策はあった

閉じタグの>を改行すればスペースは入らない

<div>
  <span>1</span
  ><span>2</span
  ><span>3</span
  ><span>4</span
  ><span>5</span>
</div>

開始タグの<tag以下を改行すればスペースは入らない

<div>
  <span
  >1</span><span
  >2</span><span
  >3</span><span
  >4</span
  ><span
  >5</span>
</div>

コメントアウトを挟めばスペースは入らない

<div>
   <span>1</span><!--
--><span>2</span><!--
--><span>3</span><!--
--><span>4</span><!--
--><span>5</span>
</div>

おまけ2: cssで工夫するとスペースや改行が入り込む

https://codepen.io/aokiken/pen/vYBLMyv 気にならなければ良い気もしている

おまけ3: 英語では困らない

そもそも単語区切りでスペースが入るので、困らないのか、と実装してて気がつきました 逆に、日本語、中国語、タイ語などの言語では有効そう

明日はService Devマネージャーの菊地さんと人事の米田さんです!