LoginSignup
0
3

More than 3 years have passed since last update.

【Vue.js】HTMLかけない人でも静的ファイルを読み込んでいい感じの記事を書けるようにする

Last updated at Posted at 2020-02-24

HTMLかけない人でも静的ファイルを読み込んでいい感じの記事を書けるようにする

動機

  • HTMLかけない人でもいい感じの記事やテキストページを書けるようにしたい
  • HTMLかける人でもテキストページくらいは労力減らして書けるようにしたい
  • 利用者自身で好きに編集できるようにしたい
  • 内容をDBに保存したりとかAPI連携するとか考えたくない
  • 管理画面ちゃんと作るのめんどくさい

実現したもの

  • Markdown使う
  • .mdの静的ファイルを読み込むようにしたのでファイル上書きすれば更新可能

デモ

mdsampleGif - Google Chrome 2020-02-24 22-18-03.gif

インポートしてるmdファイルの中身

  • markdown.md
# 見出し1
## 見出し2
 `くつしたねこ`, `ハチワレねこ`, または `ジト目ねこ`
+ 哺乳類
  - ねこ
    * メインクーン
    + ノルウェージャンフォレストキャット
    - サバンナキャット
+ Very cute!

好きな柄順

1. 長さの違う靴下
2. 長さがだいたい同じ靴下
3. 全部


:smile:
> 猫
>> ねこ
> > > 🐈

\```
ねこ
ねこ
ねこ
\```


| 種類 | 詳細 |
| ------| -----------|
| メインクーン | かわいい |
| ノルウェージャンフォレストキャット | かわいい|
| サバンナキャット | かわいい |

## Links

[wiki:ネコ](https://ja.wikipedia.org/wiki/%E3%83%8D%E3%82%B3)

[ホバーで説明が出るリンク](https://ja.wikipedia.org/wiki/%E3%83%8D%E3%82%B3 "ねこかわいい")



![ねこ](./img/cat1.jpg)


 19^th^
- H~2~O

++Inserted text++

==Marked text==


Footnotes

Footnote 1 link[^first].

Footnote 2 link[^second].

Inline footnote^[Text of inline footnote] definition.

Duplicated footnote reference[^second].

[^first]: Footnote **can have markup**

    and multiple paragraphs.

[^second]: Footnote text.


### Abbreviations

This is HTML abbreviation example.

It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on.

* [HTML]: Hyper Text Markup Language

画像はpublicのフォルダ配下に配置する。
今回はpublicの下にimgフォルダを作って画像を置いているので
http://localhost:8080/img/cat1.jpg
で画像にアクセスできる

実装

使ったもの

Vue.js
vue-markdown
 VuiCLI3を使ってるので
 npm install --save vue-markdown @vue/cli でインストールした
axios

階層

MarkdownSmaple
  ┠ public
  ┃  ┠ markdown.md  --importするmarkdownのファイル
  ┃  ┠ img
  ┃  ┗  ┗ cat1.jpg  --markdown内で使う画像ファイル
  ┠ src
  ┃  ┠ main.js
  ┃  ┠ assets
  ┃  ┠ components
  ┃  ┃ ┠ Markdown.vue
  ┃  ┃ ┠ md.css   --markdown用のcss
  ┗  ┗ ┗ md_table.css  --markdown用(table)のcss

コード

  • main.js

axiosを使えるようにする

import Vue from 'vue'
import App from './App.vue'
import axios from 'axios' //追加

Vue.config.productionTip = false
Vue.prototype.$axios = axios //追加

new Vue({
  render: h => h(App)
}).$mount('#app')

  • Markdown.vue
<template>
  <div>
    <v-row id="md">
      <v-col>
        <vue-markdown :source="source"></vue-markdown>
      </v-col>
    </v-row>
  </div>
</template>

<script>

import VueMarkdown from "vue-markdown";
export default {
  components: {
    VueMarkdown
  },
  data() {
    return { source: "" };
  },
  mounted: function() {
   /* publicのフォルダに置いたmdファイルを取得する
      public配下はbuildするとroot直下として扱われる
   assetsフォルダの下に置くと読み込まれないので注意 */
    this.$axios
      .get("./markdown.md")
      .then(response => (this.source = response.data));
  }
};
</script>
<style>
/* cssファイルをインポート */
@import "./md.css";
@import "./md_table.css";
#md {
  position: relative;
  left: 5%;
}
</style>
  • md.css

ここのcssを一部改修した
cssを変更すればデザインも変わるのでいい感じにしよう

@import url(http://fonts.googleapis.com/css?family=Ubuntu:bold);
@import url(http://fonts.googleapis.com/css?family=Vollkorn);


html { 
  font-size: 100%; 
  overflow-y: scroll; 
  -webkit-text-size-adjust: 100%; 
      -ms-text-size-adjust: 100%; 
}

body {
  max-width:42em;
  padding:1em;
  margin:auto;
  color:#444;
  line-height:1.5em;
  font-family:Vollkorn, Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif;
  font-size:12px;
  background:#fefefe;
}

a { 
  color: #337ab7; 
  text-decoration:none;
}

a:visited { color: #0b0080; }
a:hover   { color: #06e; }
a:active  { color:#faa700; }
a:focus   { outline: thin dotted; }
a:hover, a:active { outline: 0; }

::-moz-selection{ background: rgba(255,255,0,0.3); color: #000}
::selection{      background: rgba(255,255,0,0.3); color: #000}

a::-moz-selection{ background: rgba(255,255,0,0.3); color: #0645ad}
a::selection{      background: rgba(255,255,0,0.3); color: #0645ad}

p {
  margin: 1em 0;
}

img {
  max-width: 100%;
}

h1,h2,h3,h4,h5,h6 {
  font-family: 'Ubuntu';
  font-weight:normal;
  color:#111;
  line-height:1em;
}
h4, h5, h6 { font-weight: bold; }
h1 { font-size:2.5em; }
h2 { font-size:2em; }
h3 { font-size:1.5em; }
h4 { font-size:1.2em; }
h5 { font-size:1em; }
h6 { font-size:0.9em; }

blockquote {
  padding-left: 3em;
  margin: 0;
  color: #666666;
  border-left: 0.5em #EEE solid;
}

hr {
  padding: 0; 
  margin: 1em 0; 
  display: block; 
  height: 2px; 
  border: 0; 
  border-top: 1px solid #aaa;
  border-bottom: 1px solid #eee; 
}

pre, kbd, samp { 
  color: #000; 
  font-family: monospace, monospace; 
  _font-family: 'courier new', monospace; 
  font-size: 0.98em; 

}
 code{ 
    padding: 2px 4px;
    font-size: 90%; 
    color: #c7254e; 
    background-color: #f9f2f4;
    border-radius: 4px;
    font-family: monospace, monospace; 
    _font-family: 'courier new', monospace; 
    font-size: 0.98em; 

  }

pre { 
  white-space: pre; 
  white-space: pre-wrap; 
  word-wrap: break-word; 
  color: #333;
  background-color: #f5f5f5;
  border: 1px solid #ccc;
  border-radius: 4px;
}

pre code {
    padding: 0;
    font-size: inherit;
    color: inherit;
    white-space: pre-wrap;
    background-color: transparent;
    border-radius: 0;
}

b, strong { 
  font-weight: bold; 
}

dfn { font-style: italic; }

ins { color: #000;  text-decoration: underline; }

mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }

sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sup { top: -0.5em; }
sub { bottom: -0.25em; }

ul, ol { margin: 1em 0; padding: 0 0 0 2em; }
li p:last-child { margin:0 }
dd { margin: 0 0 0 2em; }

img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }



@media only screen and (min-width: 480px) {
  body {
    max-width: 100%;
    font-size: 14px;
  }
}

@media only screen and (min-width: 768px) {
  body {
    max-width:42em;
    font-size: 16px;
  }
}

@media print {
  * { background: transparent !important; color: black !important; filter:none !important; -ms-filter: none !important; }
  body{font-size:12pt; max-width:100%;}
  a, a:visited { text-decoration: underline; }
  hr { height: 1px; border:0; border-bottom:1px solid black; }
  a[href]:after { content: " (" attr(href) ")"; }
  abbr[title]:after { content: " (" attr(title) ")"; }
  .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
  pre, blockquote { border: 1px solid #999; padding-right: 1em; page-break-inside: avoid; }
  tr, img { page-break-inside: avoid; }
  img { max-width: 100% !important; }
  @page { margin: 0.5cm; }
  p, h2, h3 { orphans: 3; widows: 3; }
  h2, h3 { page-break-after: avoid; }
}
  • md_table.css

長かったので外に出しただけ

table {
    border-spacing: 0;
    border-collapse: collapse;
  }

  td, th {
    padding: 0
  }
  thead {
    display: table-header-group
  }
  .table {
    width: 100%;
    max-width: 100%;
    margin-bottom: 20px
  }

  .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th {
    padding: 8px;
    line-height: 1.42857143;
    vertical-align: top;
    border-top: 1px solid #ddd
  }

  .table>thead>tr>th {
    vertical-align: bottom;
    border-bottom: 2px solid #ddd
  }

  .table>caption+thead>tr:first-child>td, .table>caption+thead>tr:first-child>th, .table>colgroup+thead>tr:first-child>td, .table>colgroup+thead>tr:first-child>th, .table>thead:first-child>tr:first-child>td, .table>thead:first-child>tr:first-child>th {
    border-top: 0
  }

  .table>tbody+tbody {
    border-top: 2px solid #ddd
  }

  .table .table {
    background-color: #fff
  }

  .table-condensed>tbody>tr>td, .table-condensed>tbody>tr>th, .table-condensed>tfoot>tr>td, .table-condensed>tfoot>tr>th, .table-condensed>thead>tr>td, .table-condensed>thead>tr>th {
    padding: 5px
  }

  .table-bordered {
    border: 1px solid #ddd
  }

  .table-bordered>tbody>tr>td, .table-bordered>tbody>tr>th, .table-bordered>tfoot>tr>td, .table-bordered>tfoot>tr>th, .table-bordered>thead>tr>td, .table-bordered>thead>tr>th {
    border: 1px solid #ddd
  }

  .table-bordered>thead>tr>td, .table-bordered>thead>tr>th {
    border-bottom-width: 2px
  }

  .table-striped>tbody>tr:nth-of-type(odd) {
    background-color: #f9f9f9
  }

  .table-hover>tbody>tr:hover {
    background-color: #f5f5f5
  }

  table col[class*=col-] {
    position: static;
    display: table-column;
    float: none
  }

  table td[class*=col-], table th[class*=col-] {
    position: static;
    display: table-cell;
    float: none
  }

  .table>tbody>tr.active>td, .table>tbody>tr.active>th, .table>tbody>tr>td.active, .table>tbody>tr>th.active, .table>tfoot>tr.active>td, .table>tfoot>tr.active>th, .table>tfoot>tr>td.active, .table>tfoot>tr>th.active, .table>thead>tr.active>td, .table>thead>tr.active>th, .table>thead>tr>td.active, .table>thead>tr>th.active {
    background-color: #f5f5f5
  }

  .table-hover>tbody>tr.active:hover>td, .table-hover>tbody>tr.active:hover>th, .table-hover>tbody>tr:hover>.active, .table-hover>tbody>tr>td.active:hover, .table-hover>tbody>tr>th.active:hover {
    background-color: #e8e8e8
  }

  .table>tbody>tr.success>td, .table>tbody>tr.success>th, .table>tbody>tr>td.success, .table>tbody>tr>th.success, .table>tfoot>tr.success>td, .table>tfoot>tr.success>th, .table>tfoot>tr>td.success, .table>tfoot>tr>th.success, .table>thead>tr.success>td, .table>thead>tr.success>th, .table>thead>tr>td.success, .table>thead>tr>th.success {
    background-color: #dff0d8
  }

  .table-hover>tbody>tr.success:hover>td, .table-hover>tbody>tr.success:hover>th, .table-hover>tbody>tr:hover>.success, .table-hover>tbody>tr>td.success:hover, .table-hover>tbody>tr>th.success:hover {
    background-color: #d0e9c6
  }

  .table>tbody>tr.info>td, .table>tbody>tr.info>th, .table>tbody>tr>td.info, .table>tbody>tr>th.info, .table>tfoot>tr.info>td, .table>tfoot>tr.info>th, .table>tfoot>tr>td.info, .table>tfoot>tr>th.info, .table>thead>tr.info>td, .table>thead>tr.info>th, .table>thead>tr>td.info, .table>thead>tr>th.info {
    background-color: #d9edf7
  }

  .table-hover>tbody>tr.info:hover>td, .table-hover>tbody>tr.info:hover>th, .table-hover>tbody>tr:hover>.info, .table-hover>tbody>tr>td.info:hover, .table-hover>tbody>tr>th.info:hover {
    background-color: #c4e3f3
  }

  .table>tbody>tr.warning>td, .table>tbody>tr.warning>th, .table>tbody>tr>td.warning, .table>tbody>tr>th.warning, .table>tfoot>tr.warning>td, .table>tfoot>tr.warning>th, .table>tfoot>tr>td.warning, .table>tfoot>tr>th.warning, .table>thead>tr.warning>td, .table>thead>tr.warning>th, .table>thead>tr>td.warning, .table>thead>tr>th.warning {
    background-color: #fcf8e3
  }

  .table-hover>tbody>tr.warning:hover>td, .table-hover>tbody>tr.warning:hover>th, .table-hover>tbody>tr:hover>.warning, .table-hover>tbody>tr>td.warning:hover, .table-hover>tbody>tr>th.warning:hover {
    background-color: #faf2cc
  }

  .table>tbody>tr.danger>td, .table>tbody>tr.danger>th, .table>tbody>tr>td.danger, .table>tbody>tr>th.danger, .table>tfoot>tr.danger>td, .table>tfoot>tr.danger>th, .table>tfoot>tr>td.danger, .table>tfoot>tr>th.danger, .table>thead>tr.danger>td, .table>thead>tr.danger>th, .table>thead>tr>td.danger, .table>thead>tr>th.danger {
    background-color: #f2dede
  }

  .table-hover>tbody>tr.danger:hover>td, .table-hover>tbody>tr.danger:hover>th, .table-hover>tbody>tr:hover>.danger, .table-hover>tbody>tr>td.danger:hover, .table-hover>tbody>tr>th.danger:hover {
    background-color: #ebcccc
  }

  .table-responsive {
    min-height: .01%;
    overflow-x: auto
  }

まとめ

利用規約とか軽い日記とか労力かけたくないけど見栄えよくしたい場合にいいと思います。
HTMLかけなくてもコマンド使えればなんとかなる
コマンド使えない人も使えるようにするなら管理画面作ってあげたほうがいいけど、静的ファイル更新するだけなのでそこまで難しくなさそう

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3