6
2

More than 3 years have passed since last update.

SwiftUIっぽくHTMLを作成するライブラリを作ってみた

Last updated at Posted at 2021-07-21

例えば、

<ul>
  <li>ベーグル</li>
  <li>バゲット
    <ul>
      <li>パリジャン</li>
      <li>バタール</li>
    </ul>
  </li>
</ul>

のようなHTMLを、

ul.children {
    li.children { "ベーグル" }
    li.children {
        "バゲット"
        ul.children {
            li.children { "パリジャン" }
            li.children { "バタール" }
        }
    }
}

のようなSwiftで書けるライブラリを作成したのでご紹介です。

Swift Package Manager

MarkUpDynamic としてSwift Package Managerで配布しています。

使い方

MarkUp

MarkUpは、マークアップ文書を作成する際に最初に使うものになります。
MarkUpはdynamicMemberLookupを利用しているので、後述するElementをドットアクセスで生成することができます。

let m = MarkUp()

let ul: Element = m.ul
let li: Element = m.li

もし、ドットアクセスでは使えない、ハイフンなどを含むElementを使いたい場合は直接dynamicMemberを使ってElementの生成も可能です。

let m = MarkUp()

let ul = m[dynamicMember: "ul"]
let li = m[dynamicMember: "li"]

Element

Elementは、ひと組のタグを表しています。

Attributes

ElementはdynamicCallableに対応しているので、パラメータを割り当ててAttributeを含めることが可能です。

let m = MarkUp()
m.li(fuga: "hoge").children { "ベーグル" }.toString()
<li fuga="hoge">ベーグル</li>

ハイフンつきattribute名を付けたい場合は直接dynamicallyCallを使います。

let m = MarkUp()
m.form.dynamicallyCall(withKeywordArguments: ["accept-charset": "UTF-8"]).toString()
<form accept-charset="UTF-8"></form>

children

Elementの中に含めたいコンテンツをchildrenのメソッドで定義します。
childrenはresultBuilderに対応しているので、SwiftUIのように複数のContentを指定できます。
Contentは、Elementの他に、Stringも含まれます。

        let m = MarkUp()
        let ul: Element = m.ul
        let li: Element = m.li(attribute: "hoge")

        let htmlString = ul.children {
            "パンの種類"
            li.children { "ベーグル" }
            li.children { "バゲット" }
            li.children { "サンドイッチ" }
        }
        .toString()
<ul>パンの種類
  <li attribute="hoge">ベーグル</li>
  <li attribute="hoge">バゲット</li>
  <li attribute="hoge">サンドイッチ</li>
</ul>

閉じタグの省略

例えばHTMLにおけるmetaタグのような、閉じタグを省略しなければならない場合、doNotSpecifyEndTag()を指定します。

        let m = MarkUp()
        let html = m.html
        let head = m.head
        let meta = m.meta.doNotSpecifyEndTag()

        let htmlString = html.children {
            head.children {
                meta(charset: "UTF-8")
                meta(name: "description",
                       content: "Free Web tutorials")
                meta(name: "keywords",
                       content: "HTML, CSS, JavaScript")
                meta(name: "author",
                       content: "John Doe")
            }
        }
        .toString()
<html>
<head>
  <meta charset="UTF-8">
  <meta name="description" content="Free Web tutorials">
  <meta name="keywords" content="HTML, CSS, JavaScript">
  <meta name="author" content="John Doe">
</head>
</html>

使ってみる

HTML

        let m = MarkUp()
        let html = m.html
        let head = m.head
        let meta = m.meta.doNotSpecifyEndTag()
        let body = m.body
        let p = m.p

        let htmlString = html.children {
            head.children {
                meta(charset: "UTF-8")
                meta(name: "description",
                       content: "Free Web tutorials")
                meta(name: "keywords",
                       content: "HTML, CSS, JavaScript")
                meta(name: "author",
                       content: "John Doe")
            }
            body.children {
                p.children {
                    "All meta information goes inside the head section."
                }
            }
        }
        .toString()
<html>
<head>
  <meta charset="UTF-8">
  <meta name="description" content="Free Web tutorials">
  <meta name="keywords" content="HTML, CSS, JavaScript">
  <meta name="author" content="John Doe">
</head>
<body>
  <p>All meta information goes inside the head section.</p>
</body>
</html>

XML

同じくマークアップ言語のXMLも生成できます。
ドットアクセスなどで日本語も使えて面白いです。

        let m = MarkUp()

        let htmlString = m.書籍目録.children {
            m.書名(出版日: "2007-10-31").children { "XML入門" }
            m.著者.children { "筒井" }
            m.書名(出版日: "2017-10-31").children { "続・XML入門" }
            m.著者.children { "小松" }
        }
        .toString()
<書籍目録>
  <書名 出版日="2007-10-31">XML入門</書名>
  <著者>筒井</著者>
  <書名 出版日="2017-10-31">続・XML入門</書名>
  <著者>小松</著者>
</書籍目録>

まとめ

つかおう!resultBuilder!

6
2
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
6
2