vuepressでカレンダー埋め込みを実装

vuepress は、vue.js のコンポーネントを入れることができるとのことで、早速カレンダーを導入した。

ライブラリは、vue-calendarである。 UI は以下の感じで、markdown に直接 <BlogCalendar /> を埋め込むことで下のようなカレンダーが表示される。

実装としては以下の手順を踏めばおーけー

私の実装手順

  1. .vuepress/public配下にカレンダー用のvueファイルを作成する。
  2. .vuepress/enhanceApp.jsに作成したvueファイルを登録する。
  3. 予定表をまとめたjsonファイルを.vuepress/public配下に作成する。

追加したソースコードは以下。

  • BlogCalendar.vue
<template>
  <div>
    <component
      v-if="calendar"
      :is="calendar"
      is-expanded
      :attributes="attrs"
    ></component>
  </div>
</template>

<script>
import schedule from "../public/schedule.json";

export default {
  name: "BlogCalendar",
  data() {
    return {
      attrs: this.getSchedule(),
      calendar: null,
    };
  },
  mounted() {
    import("v-calendar").then((module) => {
      this.calendar = module.Calendar;
    });
  },
  methods: {
    getSchedule: () => {
      return schedule.map((e) => {
        return {
          highlight: {
            animated: true,
            height: "1.8rem",
            backgroundColor: "red",
            borderColor: null,
            borderWidth: "1px",
            borderStyle: "solid",
            borderRadius: "1.8rem",
            opacity: 1,
          },
          dates: new Date(e.year, e.month - 1, e.day),
          popover: {
            label: e.label,
          },
        };
      });
    },
  },
};
</script>

<style scoped>
.cell-content {
  text-align: left;
  width: 70px;
  height: 50px;
  font-size: 50%;
  /* border: 1px solid #efefef; */
}
.cell-content-line {
  border-bottom: 1px solid #efefef;
}
</style>
  • enhanceApp.js
import { BlogCalendar } from "./components/BlogCalendar.vue";

export default ({ Vue, options, router, siteData }) => {
  Vue.component("BlogCalendar", BlogCalendar);
  Vue.config.productionTip = false;
};
  • schedule.json
[
  {
    "year": 2020,
    "month": 5,
    "day": 6,
    "label": "誕生日"
  },
  {
    "year": 2020,
    "month": 5,
    "day": 24,
    "label": "映画鑑賞2本"
  }
]

注意点としては、v-calendarは SSR に対応してないこと。
vuepress の build は全て SSR なため、単に import しただけだと build がこける。

これを防ぐために、v-calendarはクライアント側で動的に compornent が呼ばれるようにしなければならない。 このやり方については、Using Vue in Markdownに詳しく書いてある。

作って思ったのが、わざわざ markdown に埋め込ませる必要はなかったかなと笑

2020/5/5 FooQoo