😢
MarkdownとGo言語だけでWebアプリ作ってみた
goだけでアプリつくりたいなーと思い、HTMLやCSSを使わずにWebアプリをつくれないか試してみました!
自由度やデザインなどある程度制限がありますが、仮アプリとしてはほどほどに使える状態にはなったと思います。
ソースコードはこちら (HikaruEgashira/simple-server - GitHub)
<!-- pages/user.md -->
# Welcome
{{ text }}
[home](/)
今回やる内容
- HTML部分をMarkdownに置き換えたWebアプリの作成
- フォームに名前を入力したら、userページでユーザー名を表示するシンプルなアプリ
- サーバーサイドフレームワークとしてginを用います。多分一番有名なので
方針
- MarkdownをHTML(正式にはmustache HTML)に変換
- mustache HTMLから表示するHTMLを生成
- 描画
普通のアプローチと比較すると
手順1が増えただけなので、やり方さえつかめばいろいろな応用ができます。
初期構築
Go moduleを利用します。
go mod init github.com/xxxxx/yyyyy
go get -u github.com/gin-gonic/gin # Goフレームワーク
go get -u github.com/russross/blackfriday # MarkdownをHTMLに変換するライブラリ
go get -u github.com/cbroglie/mustache # Markdownで変数を入れるのに使う
階層構造はこんな感じ。
- controller ... ページごとの処理を行う
- lib ... MarkdownからHTMLを生成し描画するライブラリを作成
- pages ... 描画するMarkdown
- template ... htmlが書いてあるけど、コピペで大丈夫
- usecase ... ロジック置き場
simple-server ❯❯❯ tree .
.
├── go.mod
├── go.sum
├── main.go
├── controller
│ ├── index.go
│ └── user.go
├── lib
│ └── lib.go
├── pages
│ ├── index.md
│ └── user.md
├── template
│ └── md.html
└── usecase
└── hello.go
MarkdownをGitHubのデザインにするためのレイアウトの作成
コピペで動きます。
github-markdown-cssというライブラリを用いてCSSを触らずに見た目を整えています。
{{define "md"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Markdown Server</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/4.0.0/github-markdown.min.css" integrity="sha512-Oy18vBnbSJkXTndr2n6lDMO5NN31UljR8e/ICzVPrGpSud4Gkckb8yUpqhKuUNoE+o9gAb4O/rAxxw1ojyUVzg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}
</style>
</head>
<body>
<div class="markdown-body">
{{.}}
</div>
</body>
</html>
{{end}}
Markdownのページを作成
フォームにだけHTMLを使いますのでここだけ調べる必要がありそうです。
<!-- pages/index.md -->
# simple-server
### 名前を入力
<form
action="user"
method="GET"
>
<input type="text" name="name" placeholder="type username">
<input type="submit" value="go">
</form>
値を埋め込むときはmustache形式で書くようにしました。
{{ }}
の中に変数名を書くだけです。
<!-- pages/user.md -->
# Welcome
{{ text }}
[home](/)
MarkdownをHTMLに変換するRender関数の作成
第二引数にパス。それ以降の引数でMarkdown上に埋め込みたいデータを入力するライブラリを作成します。
// lib/lib.go
package lib
import (
"html/template"
"io"
"io/ioutil"
"github.com/cbroglie/mustache"
"github.com/russross/blackfriday"
)
func Render(w io.Writer, path string, context ...interface{}) {
md, _ := ioutil.ReadFile(path + ".md")
// 1. MarkdownをHTML(正式にはmustache HTML)に変換
mustacheHtml := string(blackfriday.Run(md))
// 2. mustache HTMLから表示するHTMLを生成
html, _ := mustache.Render(mustacheHtml, context...)
// 3. 描画
tmpl := template.Must(template.ParseFiles("template/md.html"))
tmpl.ExecuteTemplate(w, "md", template.HTML(html))
}
// 使い方
// pages/userにtextが埋め込まれたHTMLを返す
lib.Render(c.Writer, "pages/user", map[string]string{"text": text})
ginでルーティング
main関数ではginを利用してルーティングを行います。
シンプルですね。
// main.go
package main
import (
"github.com/xxxxx/yyyyy/controller"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/", controller.IndexHandler)
router.GET("/user", controller.UserHandler)
router.Run(":8080")
}
Controllerの作成
静的なページを返すだけなら一行でおっけー
// controller/index.go
package controller
import (
"github.com/xxxxx/yyyyy/lib"
"github.com/gin-gonic/gin"
)
func IndexHandler(c *gin.Context) {
lib.Render(c.Writer, "pages/index")
}
値を埋め込むときは、引数に渡してあげます。
// controller/user.go
package controller
import (
"github.com/xxxxx/yyyyy/lib"
"github.com/xxxxx/yyyyy/usecase"
"github.com/gin-gonic/gin"
)
func UserHandler(c *gin.Context) {
name := c.Query("name")
text := usecase.Hello(name)
lib.Render(c.Writer, "pages/user", map[string]string{"text": text})
}
こんな感じにHTMLを使わずに画面部分を作成することができました!
まとめ
本格的なアプリになるとこれだけだと難しいのですが、まずはデモアプリをつくるところから始めてみましょう!
実際にサーバーサイドだけのデモアプリからアプリ化までもっていった実例(自分)があるので紹介します。
Discussion
このマークダウンではソースコードはシンタックスハイライトで表示されますか?