Create an HTML/XML generator in Swift (dynamicMemberLookup)

Overview

Create a DSL that generates HTML/XML in Swift using @dynamicMemberLookup. (I made)

SwiftPM

It is distributed in the form of Swift PM.

https://github.com/coe/MarkUpDynamic

Code example

HTML

Write Swift in the following form.

MarkUp()
    .html[MarkUp()
            .body[MarkUp()
                    .table[MarkUp()
                            .tr[MarkUp()
                                    .td[character: "one"]
                                    .td[character: "two"]
                            ]
                    ]
            ]
    ].generate()

If you write Swift code with the above structure, HTML text will be generated in the following form.

<html>
<body>
  <table>
    <tr>
      <td>one</td>
      <td>two</td>
    </tr>
  </table>
</body>
</html>

XML You can generate XML as well. Connect the recipe and the procedure with dot access.

MarkUp(doctype: #"<?xml version="1.0" encoding="UTF-8"?>"#)
    .recipe[MarkUp()
                .procedure[character: "Mix all ingredients together."]
                .procedure[character: "Place in the oven at 180 ° C and bake for 30 minutes."]
    ]
    .generate()

This will generate XML in the following form.

<?xml version="1.0" encoding="UTF-8"?>
<recipe>
    <procedure>Mix all ingredients together.</procedure>
    <procedure>Place in the oven at 180 ° C and bake for 30 minutes.</procedure>
</recipe>

How it works

We use @dynamicMemberLookup to generate these tags.

dynamicMemberLookup

dynamicMemberLookup is a feature added in Swift 4.2. When @dynamicMemberLookup is given, you can access with dots as if a proper paddy is implemented, and internally you will write the processing for dot access in the part ofsubscript (dynamicMember :).

In the case of the above code, subscript (dynamicMember :) works by accessing .html, .body, .recipe, etc., and the process to generate the tag is performed.

    public subscript(dynamicMember member: String) -> MarkUp {
        tagName(member)
    }
    
    public func tagName(_ tagName: String) -> MarkUp {
        queue.append(self)
        return MarkUp(tag: tagName,queue: queue)
    }

Recommended Posts

Create an HTML/XML generator in Swift (dynamicMemberLookup)
[Swift] Create UIButton class in code
Make an FPS counter in Swift
Find an approximation of cosx in Swift
Nuxt.js × Create an application in Rails API mode
[Swift] Create an image selection UI with PhotoKit
I got an error "undefined method` create'" in RSpec
Create UnsafeMutablePointer <UnsafeMutablePointer <Int8>?>! In Swift for C char ** hoge
Division becomes 0 in Swift
Create JSON in Java
[Rails] Create an application
Multidimensional array in Swift