例えば、
<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!