⌨️

[Vue3 + Vite + ElementPlus]質問に答えるだけでマークダウン形式に変換してくれるアプリを作った

2022/03/12に公開

目的

質問に答えていくだけで、質問項目と入力値をマークダウン形式で出力してくれるアプリを作りたい
質問内容は自分でテンプレートとして作れるようにする

技術スタック

アプリケーション

  • Vue 3.0
  • Vuex 4
  • Vue-router 4
  • Vite
  • Scss
  • Element Plus

ホスティング

  • Amazon S3
  • Amazon CloudFront

作った物

全体像.gif

↓こちらから利用できます。
https://d2yiqmlxenm8oa.cloudfront.net

Githubはこちらで公開しています。
https://github.com/yuya8696/templator

使い方

  1. 「新規テンプレート」ボタンをクリックしてテンプレート作成画面を開きます。
  2. 任意の質問と入力形式(テキスト形式、テキストエリア形式、日付形式、etc)を選び、テンプレート作成します。
  3. 作成したテンプレートの質問項目に回答を入力し、「作成」ボタンをクリックします。
  4. 質問と入力内容がマークダウン形式で表示されるので、コピーして使います。

大変だったこと

ViteとElementPlusの組み合わせにハマった

単純にVite環境でElementPlusをインストールしてもエラーで動かなかった

→→追加のプラグインをインストールして、公式ドキュメントの「On-demand Import」に記載の設定をvite.config.jsに書いたら動いた

yarn add -D unplugin-vue-components unplugin-auto-import

https://element-plus.org/en-US/guide/quickstart.html#vite

Vuexに保存した情報がブラウザ更新で消えちゃう

せっかくテンプレートを作ってもVuexの使用上リロードすると消えてしまう。このためにわざわざDB用意するのも骨が折れるな、、

→→Vuexの情報をローカルステイトに保存する!便利なプラグイン「vuex-persistedstate」を利用
こんな感じで作ったstoreにimport, exportするだけでstoreの値をローカルステイトに保存してくれる

store/index.js
import { createStore } from "vuex";

// ローカルストレージへの保存
import createPersistedState from "vuex-persistedstate";

import { reactive } from "vue";

const state = reactive({
// 省略
});

const mutations = {
// 省略
};

const actions = {
// 省略
};

export default createStore({
  state,
  actions,
  mutations,
  // ローカルストレージへの保存
  plugins: [ 
    createPersistedState({
      key: "template",
    }),
  ],
});

マークダウンの改行を再現する

Vueの変数に格納したテキストエリアの内容をそのままマークダウン形式で出力しても、改行コードが反映されなかった。

→→マークダウン形式でも改行されるように、「改行コード」を「改行コード + スペース2つ」にゴリ押し変換した

src/pages/top.vue
const onClickCreate = (template) => {
  dialogTextarea.value = "";
  dialogContents.title = template.name.templateName;
  for (let item of template.contents) {
    if (item.type === "heading") {
      dialogTextarea.value += `# ${item.label} \n`;
    } else if (item.type === "textarea") {
      // テキスト内で改行がある場合は、スペース2つと改行コードに変換
      dialogTextarea.value += `- ${item.label}:  \n${item.value.replace(
        /\n/g,
        "  \n"
      )} \n`;
    } else {
      dialogTextarea.value += `- ${item.label}${item.value} \n`;
    }
  }
  dialogVisible.value = true;
};

<input type="text">に入力してEnterを押すと画面がリロードされる。(リロードされるんでその他の入力値が消える)

質問項目をFormで作っている場合、Formの中に<input type="text">が1つだけあると、input要素に入力した後Enterをクリックすると勝手にSubmitされてしまうらしい。
今回Formの中でSubmitに相当するボタンは書いてないので、Submitされると勝手にブラウザリロードされ、入力項目が全部消えちゃうという罠にはまった。

→→Element PlusのForm要素<el-form>にSubmitしないよう@submit.preventを加える

-        <el-form label-position="top" class="create__card__header">
+        <el-form
+          @submit.prevent
+          label-position="top"
+          class="create__card__header"
+        >

Discussion