2019-05-24に更新

VuePress で Navbar のリンクが別タブで開かれないようにするためにデフォルト・テーマをちょっといじる

はじめに

ウェブアプリのドキュメントを、これまで GitBook でつくっていたのですが VuePress に乗り換えようとしています
Guide にあるみたいに既存のアプリケーションに docs フォルダをつくってそこで作業をするようにするとアプリケーションのコードとドキュメントが一体で管理できて嬉しいです

アプリケーションとドキュメントのナビゲーションに相互に行き来できるようリンクを用意します

あれ?ドキュメントからアプリに素直に戻ってくれないで、わざわざ別タブでアプリを開き直してくれてる、これはちょっと...

試してみてダメだったこと

Config Reference 見てたら markdown.externalLinks って section があって、デフォルトは { target: '_blank', rel: 'noopener noreferrer' } なんだそうです
これが原因だなとおもって config.js で

markdown: {
  externalLinks: {
  }
}

ってかんじに target: '_blank' その他諸々をまるまる消してみたのですがダメでした
名前の通り、これは markdown に対する設定みたい

default theme に手を入れる

Nav の link に対する設定はないかな?と思って Config Reference を穴が開くほど見るのですがめぼしいものがみつかりません
ないのならテーマに手を入れて nav の link に target='_blank' つけるのを止めるしかなさそうです

昨日今日 vuepress を触りはじめたばかりのニワカ者 にそんな事がかんたんに出来るものなのかという妥当な不安を感じますが、実はその心配は杞憂だったということをこの後の作業を通じて大観します

theme の eject

手を入れるために、まず以下のコマンドで default theme の定義ファイルを docs/theme の下に吐き出させます

vuepress eject docs

なお、ゴチャゴチャやってるうちに vuepress なんてコマンドありません とか言われてしまうようなややこしい環境になってしまってたら、package.json に vuepress の build コマンドを追加したのと同じ要領で eject コマンドを追加しておいて

  "scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs",
    "docs:eject": "vuepress eject docs"
  },

npm run docs:eject で実行するのもいいかもしれません、環境をさっさと修復すべきなのかもしれませんが

theme の下にできたファイルを見ていると NavLink.vue なんていうそれっぽい名前のファイルがあったので見てみると

template>

    class="nav-link"
    :to="link"
    v-if="!isExternal(link)"
    :exact="exact"
  >{{ item.text }}

    v-else
    :href="link"
    class="nav-link external"
    :target="isMailto(link) || isTel(link)? null : '_blank'"
    :rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'"
  >

みるからにコレですね ^^;

手の入れ方は以下の3通りが考えられます

  • :target を無条件に null にする
  • :target を null にする条件に isExternal(link) を追加する
  • :target を null にする条件に isAppTop(link) というのを新たにつくって追加し、アプリケーションに戻るパスだけ null にする

このどれでもうまくいく(実際にうまくいきました、戻るリンクに target='_blank' はつかなくなりました)のですが、最初のはちょっと気がさしますよね
2番めのはまだマシかと思いきや、実は isExternal の定義って util/index.js にあって

export const outboundRE = /^(https?:|mailto:|tel:)/

export function isExternal (path) {
  return outboundRE.test(path)
}

なので、2番めのロジックって実は最初のと全く同じになってしまうという ^^;;;

3番めのロジックは NavLink.vue の methods に

    isAppTop: function (path){
      return /^https?:\/\/pokectiveness2.netlify.com\//.test(path)
    }

みたいに(直書きでカッコ悪いですが ^^;;;)チェックを追加して、前述の template に追加します

    :target="isMailto(link) || isTel(link) || isAppTop(link) ? null : '_blank'"

感想

なぜ GItBook じゃなくて VuePress なのかにも 'and the theming system is, again, not Vue based' ってありましたけど、最初に読んだときは「だからなんなんだ ^^;;;」って心でツッコミいれながら読んでたんですけども、実際に自分で体験してみるとテーマの定義が Vue で読めるのって予想以上に嬉しいですね、ドキュメントとかなくてもコンポーネント見てると自然にわかってくる感じがとても気持ちいいです

それはそうとなんで vuepress は外部へのリンクをタブで開かせたがるんだろ?


Dr. Takeyuki Ueda

Je suis un Japonipais, experimants ingénieur logiciel de mobile et cloud. Ph.D en ingénierie.

Crieitは個人で開発中です。 興味がある方は是非記事の投稿をお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください!

ボードとは?

関連記事

コメント