LoginSignup
13
8

More than 5 years have passed since last update.

マークアップフレームワーク!?elm-markup触ってみた

Posted at

elm-markupelm-uiの作者が作ったカスタマイズできるマークアップのパーサーです
ちょっと可能性を感じてしまったので触ってみました

まずはデモアプリを用意したので

| Counter

と入れてきてください

こんな感じにカウンターが表示されるはずです

image.png

ちなみにこのカウンターは普通に動きます。(複数個置いても状態は共有されてるので一緒にカウントされます)

こんな感じに独自コンポーネントをマークアップを書くだけで表示する力がelm-markupにはあります!

何でおもしろいと思っているのか

  • JAM stack的な流れに乗りたい
  • ノベルエンジンとかシナリオ作成に使えそう

何はともあれ型を見よと神もおっしゃられておる

type Block data

type Document result

document : (child -> result) -> Block child -> Document result

parse :
    Document result
    -> String
    -> Result (List (DeadEnd Context Problem)) result

Document型はdocumentでBlockから上げないと作れません。なので自分でカスタマイズする際はBlock型を使って、できたDocumentをparseに食わします

Document型はパーサーを表しているような?こういう方式のことをなんていうかわからないので、誰か知ってたら教えてください

Document result

resultは結果の型です
これが型変数だということはelm-markupでパースした結果はどんな型にでもできるということです!

マークダウンは普通、HTMLになるだけですがelm-markupでは任意の型に変換できます

今回のサンプルではDocument (Model -> Element Msg)型にしています
parse結果にModelを入れれるのでサンプルのように動的なカウンターが埋め込めるわけですね

Block a

Mark.boolとかstring, intのような基本的なものが用意されてます
(BlockというかParserな気がするんですが)

Mark.blockがカスタマイズできるやつです

| MyBlock
    body

こんな感じのマークアップを

Mark.block "MyBlock" Mark.string

これでパースできます。これはBlock Stringになるので適宜mapしてください

| Hogeがブロックなんですが、型のBlockとは意味の範囲が違うので気を付けましょう。型のほうはParser型みたいな感じです

Record

上の例じゃおもしろくないのでレコードの例を見てみます
マークダウンみたいに画像表示用のブロックを作りましょう

| Image
    src = http://placekitten/200/500
    description = A super cute kitten.

Imageブロックにsrcとdescriptionのデータが足されています。これを使ってimgタグを作りましょう

Mark.record2 "Image"
    (\src description ->
        Html.img [ Html.Attribute.src src, Html.Attribute.alt description ] []
    )
    (Mark.field "src" Mark.string)
    (Mark.field "description" Mark.string)

Mark.recordNを使うとフィールドを渡すことができるようになります

名前付き引数を渡せる感じになりますね

マークアップ上は順不同で書けます。つまりsrcとdescriptionはどっちを先に書いてもいいです
インデントはスペース4です。elm-markupはインデントにはセンシティブなので気を付けましょう

リストもマークアップできます

- いわゆるこれ
- マークダウンで一番使うやつ
    - 当者調べです
    - ネストもします
- elm-markupでもできます
nested :
    { item : Block item
    , start : Block icon
    }
    -> Block (List (Nested ( icon, List item )))

type Nested item
    = Nested
          { content : item
          , children : List (Nested item)
          }

中身のパーサー(item)と先頭要素のパーサー(start)を渡したらパースできるみたいですね。
まだ試してないです

Mark.text

Mark.textが本文を主にパースしてくれます

text :
    { view : Text -> rendered
    , inlines : List (Inline rendered)
    , replacements : List Replacement
    }
    -> Block (List rendered)

textは何も設定しなくても*itaric*, ~strike~, *bold*がパースされてstyleとして渡されます

type Text
    = Text (List Style) String

type Style
    = Bold
    | Italic
    | Strike

Text型を自分が欲しい型に変換すればいいです

replacementsは文字を他の文字に置き換えます
inlinesは大事なインラインブロック記法の定義になります

インラインブロック

マークダウンでよく使う記法第2位のリンクはインラインブロックで定義できます

{link| with a link to a web-comic. |url=http://www.poorlydrawnlines.com/comic/website-bird/}

これをパースします。|で分かれていて最初がブロックの名前、次が本文、最後がパラメータ、といった形になります

Mark.inline "link"
    (\txt url ->
        Html.a [ Html.Attriutes.href url ] (List.map renderText txt)
    )
    |> Mark.inlineText
    |> Mark.inlineString "url"

実は試してないので挙動はよくわかってないです。3分割じゃなくて任意の数な気はしますね
inlineIntとかはないので受けれるのはStringだけのようです。ちょっと謎ですね

組み合わせ

あとは今まででてきたものを組み合わせましょう

oneof

oneOf : List (Block a) -> Block a

これはよくあるやつですね
最初に成功したBlockを使います

startWith

startWith : (start -> rest -> result) -> Block start -> Block rest -> Block result

必ずTitleブロックから始まる文書とかに使えます。

manyOf

manyOf : List (Block a) -> Block (List a)

Many blocks that are all at the same indentation level.

という説明しか書いてないですが、manyOfは絶対に使う関数です!
今まで出てきたBlockは1行しか読み込みません。複数行の文章を扱いたいときはmanyOfBlock (List a)にしてもらわなきゃいけません。このListが行にあたります

行が固定値の場合はstartWithを行数分つなげればできますが、あんまりないと思うので必ずmanyOfを使うことになると思います

注意:manyOf [ manyOf [], ... ]このように直接ネストするとエラーになるかもしれません。また原因分かったら追記かなんかします

Mark.multilineを動かすとElmアプリケーション全体が止まります。たぶん。
たぶん無限ループしてると思うんですがよくわかりません。
どのみち存在意義はあんまりないので使わなければいいと思います

終わり

自分でも何を書いたらいいかわかんなかったんですけど、elm-markupがおもしろいと思ったので書きました
今後はいきなりノベルエンジンなるものを作ってみよう!とかいうと挫折するので小さめに作れる題材を考えたいと思います

13
8
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
13
8