Skip to content

ajaygandecha/stitch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stitch

This project explores the creation of a DSL (domain-specific language) for rendering HTML in Swift, inspired by the declarative syntax of SwiftUI.

Usage

Components

The core UI primitive of Stitch is the Component, which is loosely analogous to the SwiftUI View. Components specify a body, which contains the UI. UI construction is declarative. Stitch components can be constructed out of any standard HTML element or any other custom Stitch element. An example of a simple home page is shown below:

struct HomePage: Component {
    
    var body: some Component {
        Div {
            H1("Hello, world!")
                .className("font-bold")
            Br()
            P {
                "This is "
                Span("SUPER cool.")
            }
            AnotherComponent()
        }
    }
}

Currently, components are renderable, which produces raw HTML as output:

struct SmallPage: Component {

  var body: some Component {
    Div {
      P {
        "I am "
        Span("renderable!")
          .className("font-bold")
      }
    }
  }
}

SmallPage().render()
// Outputs:
// <div><p>I am <span class="font-bold">renderable!</span></p></div>

The vision for the Stitch components is that they would eventually support reactivity, including states (@State), handling side effects (@Effect), more complex querying (@Query) and event handling.

Conditional rendering is supported, like so:

struct ConditionalRendering: Component {

  var body: some Component {
    Div {
      if myCondition {
        P("It's true!")
      } else {
        P("It's false...")
      }
    }
  }
}

SmallPage().render()
// Outputs:
// <div><p>It's true!</p></div>

Building out HTML with loops is also supported, like so:

struct IterableRendering: Component {

  var items = ["one", "two", "three"]
    
  var body: some Component {
    Div {
      for item in items {
        P(item)
      }
    }
  }
}

SmallPage().render()
// Outputs:
// <div><p>one</p><p>two</p><p>three</p></div>

Elements

All standard HTML elements exist in Stitch. There are two ways of creating elements:

  1. If an element is a one-liner (only contains text or no content), then a text constructor can be used:
Br()
P("Hello, world!")
H1("I 💛 Swift")
  1. If an element composes other elements or contains a more complex body, the body (@ComponentBuilder) constructor can be used:
Div {
  P("Wow")
  P {
    "This is "
    Span("EPIC")
    "!"
  }
}

Strings and elements can be mixed and matched in the same body.

Applying Attributes

Currently, attributes to elements are applied using modifiers, in a similar way to how modifiers are applied to SwiftUI views. For example, to apply a class to a paragraph (P), you would use the .className() modifier. Here is an example (using Tailwind-esque styling):

P("Hello, world!")
  .className("text-muted-foreground")

Some HTML elements have required inputs. These are passed as parameters:

Video(src: "/..path")

In the future, HTML elements in Stitch will be modified so that some non-required inputs for certain elements are passed in parameters where it is applicable.

The @ComponentBuilder Attribute

The core functionality for Stitch's declarative view creation is @ComponentBuilder, which is inspired by SwiftUI's @ViewBuilder. @ComponentBuilder is built on top of result builders, one of my favorite features in Swift.

With the help of Swift's function builder, @ComponentBuilder can support blocks with multiple components, conditional rendering (with if and if-else), and views built with for-loops. There is also a helper GroupComponent to help with managing groupings of components.

The full @ComponentBuilder functionality can be found here.

About

Exploration for creating an HTML DSL for Swift, inspired by SwiftUI.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages