Skip to content

Commit

Permalink
Renamed all Html to HTML to follow guidelines (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
sliemeobn authored Jun 21, 2024
1 parent abc623d commit bcec5a1
Show file tree
Hide file tree
Showing 20 changed files with 465 additions and 465 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Hummingbird

extension MainLayout: ResponseGenerator {}

extension Html {
extension HTML {
func response(from request: Request, context: some RequestContext) throws -> Response {
.init(
status: .ok,
Expand Down
22 changes: 11 additions & 11 deletions Examples/HummingbirdDemo/Sources/App/Pages.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import Elementary

struct MainLayout<Body: Html>: HtmlDocument {
struct MainLayout<Body: HTML>: HTMLDocument {
var title: String
@HtmlBuilder var pageContent: Body
@HTMLBuilder var pageContent: Body

var head: some Html {
var head: some HTML {
meta(.name(.viewport), .content("width=device-width, initial-scale=1.0"))
HtmlComment("Do not use this in production, use the tailwind CLI to generate a production build from your swift files.")
HTMLComment("Do not use this in production, use the tailwind CLI to generate a production build from your swift files.")
script(.src("https://cdn.tailwindcss.com")) {}
}

var body: some Html {
var body: some HTML {
div(.class("flex flex-col min-h-screen items-center font-mono bg-zinc-300")) {
div(.class("bg-zinc-50 m-12 p-12 rounded-lg shadow-md gap-4")) {
h1(.class("text-3xl pb-6 mx-auto")) { title }
Expand All @@ -22,8 +22,8 @@ struct MainLayout<Body: Html>: HtmlDocument {
}
}

struct WelcomePage: Html {
var content: some Html {
struct WelcomePage: HTML {
var content: some HTML {
div(.class("flex flex-col gap-4")) {
p {
"This is a simple example of using "
Expand All @@ -45,11 +45,11 @@ struct WelcomePage: Html {
}
}

struct GreetingPage: Html {
struct GreetingPage: HTML {
var name: String
var greetingCount: Int

var content: some Html {
var content: some HTML {
if greetingCount < 1 {
p(.class("text-red-500")) {
"No greetings to show."
Expand All @@ -70,11 +70,11 @@ struct GreetingPage: Html {
// example of using modifier-like methods to apply styling
extension input {
// making the return type specify the input tag allows to chain attributes for it
func roundedTextbox() -> some Html<HtmlTag.input> {
func roundedTextbox() -> some HTML<HTMLTag.input> {
attributes(.class("rounded-lg p-2 border border-gray-300"))
}

func primaryButton() -> some Html<HtmlTag.input> {
func primaryButton() -> some HTML<HTMLTag.input> {
attributes(
.class("rounded-lg p-2 bg-orange-500 text-white font-semibold shadow-sm"),
.class("hover:bg-orange-600 hover:shadow-xl")
Expand Down
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
🚧 Work In Progress 🚧 - don't bet your future on it just yet ;)

```swift
struct MainPage: HtmlDocument {
struct MainPage: HTMLDocument {
var title: String = "Elementary"

var head: some Html {
var head: some HTML {
meta(.name(.description), .content("Typesafe HTML in modern Swift"))
}

var body: some Html {
var body: some HTML {
main {
h1 { "Features" }

Expand All @@ -32,10 +32,10 @@ struct MainPage: HtmlDocument {
}
}

struct FeatureList: Html {
struct FeatureList: HTML {
var features: [String]

var content: some Html {
var content: some HTML {
ul {
for feature in features {
li { feature }
Expand All @@ -59,8 +59,8 @@ Any element can be rendered individually, ideal for [htmx](https://htmx.org/).
let html = div(.class("pretty")) { "Hello" }.render()
// <div class="pretty">Hello</div>

let fragment = FeatureList(features: ["Anything conforming to Html can be rendered"]).render()
// <ul><li>Anything conforming to Html can be rendered</li></ul>
let fragment = FeatureList(features: ["Anything conforming to HTML can be rendered"]).render()
// <ul><li>Anything conforming to HTML can be rendered</li></ul>
```

Optionally you can render formatted output, or stream the rendered HTML without collecting it in a string first.
Expand Down Expand Up @@ -93,11 +93,11 @@ By design, it does not come with a layout engine, reactive state tracking, or bu
Structure your HTML with a SwiftUI-inspired composition API.

```swift
struct List: Html {
struct List: HTML {
var items: [String]
var importantIndex: Int

var content: some Html {
var content: some HTML {
// conditional rendering
if items.isEmpty {
p { "No items" }
Expand All @@ -113,11 +113,11 @@ struct List: Html {
}
}

struct ListItem: Html {
struct ListItem: HTML {
var text: String
var isimportant: Bool = false

var content: some Html {
var content: some HTML {
// conditional attributes
li { text }
.attributes(.class("important"), when: isimportant)
Expand Down Expand Up @@ -154,11 +154,11 @@ div {
By exposing the tag type of `content`, attributes will fall through and be applied correctly.

```swift
struct Button: Html {
struct Button: HTML {
var text: String

// by exposing the HtmlTag type information...
var content: some Html<HtmlTag.input> {
// by exposing the HTMLTag type information...
var content: some HTML<HTMLTag.input> {
input(.type(.button), .value(text))
}
}
Expand Down Expand Up @@ -198,5 +198,5 @@ My main motivation for Elementary was to create an experience like these, but
## Future directions

- Try out a **_hummingbird + elementary + htmx + tailwind_** stack for fully-featured web apps (without too much client javascript or wasm)
- Experiment with an `AsyncHtml` type, that can include `await` in bodies and stream html and an async sequence
- Experiment with an `AsyncHTML` type, that can include `await` in bodies and stream html and an async sequence
- Experiment with embedded swift for wasm and bolt a lean state tracking/reconciler for reactive DOM manipulation on top
4 changes: 2 additions & 2 deletions Sources/Elementary/Core/AttributeStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ enum AttributeStorage {
self = .none
}

init(_ attribute: HtmlAttribute<some HtmlTagDefinition>) {
init(_ attribute: HTMLAttribute<some HTMLTagDefinition>) {
self = .single(attribute.htmlAttribute)
}

init(_ attributes: [HtmlAttribute<some HtmlTagDefinition>]) {
init(_ attributes: [HTMLAttribute<some HTMLTagDefinition>]) {
switch attributes.count {
case 0: self = .none
case 1: self = .single(attributes[0].htmlAttribute)
Expand Down
28 changes: 14 additions & 14 deletions Sources/Elementary/Core/CoreModel.swift
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
public protocol Html<Tag> {
associatedtype Tag: HtmlTagDefinition = Content.Tag
associatedtype Content: Html = Never
public protocol HTML<Tag> {
associatedtype Tag: HTMLTagDefinition = Content.Tag
associatedtype Content: HTML = Never

@HtmlBuilder var content: Content { get }
@HTMLBuilder var content: Content { get }

@_spi(Rendering)
static func _render<Renderer: _HtmlRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext)
static func _render<Renderer: _HTMLRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext)
}

public protocol HtmlTagDefinition {
public protocol HTMLTagDefinition {
static var name: String { get }

@_spi(Rendering)
static var _rendersInline: Bool { get }
}

extension Never: HtmlTagDefinition {
public static var name: String { fatalError("HtmlTag.name was called on Never") }
extension Never: HTMLTagDefinition {
public static var name: String { fatalError("HTMLTag.name was called on Never") }
}

public struct _RenderingContext {
Expand All @@ -26,7 +26,7 @@ public struct _RenderingContext {
}

// TODO: think about this interface... seems not ideal
public enum _HtmlRenderToken {
public enum _HTMLRenderToken {
public enum RenderingType {
case block
case inline
Expand All @@ -41,17 +41,17 @@ public enum _HtmlRenderToken {
case comment(String)
}

public protocol _HtmlRendering {
mutating func appendToken(_ token: consuming _HtmlRenderToken)
public protocol _HTMLRendering {
mutating func appendToken(_ token: consuming _HTMLRenderToken)
}

public extension Html {
static func _render<Renderer: _HtmlRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
public extension HTML {
static func _render<Renderer: _HTMLRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
Content._render(html.content, into: &renderer, with: context)
}
}

public extension HtmlTagDefinition {
public extension HTMLTagDefinition {
@_spi(Rendering)
static var _rendersInline: Bool { false }
}
24 changes: 12 additions & 12 deletions Sources/Elementary/Core/Html+Attributes.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public struct HtmlAttribute<Tag: HtmlTagDefinition> {
public struct HTMLAttribute<Tag: HTMLTagDefinition> {
var htmlAttribute: StoredAttribute

init(name: String, value: String?, mergeMode: StoredAttribute.MergeMode = .replaceValue) {
Expand All @@ -9,50 +9,50 @@ public struct HtmlAttribute<Tag: HtmlTagDefinition> {
public var value: String? { htmlAttribute.value }
}

public struct _AttributedElement<Content: Html>: Html {
public struct _AttributedElement<Content: HTML>: HTML {
public var content: Content

var attributes: AttributeStorage

@_spi(Rendering)
public static func _render<Renderer: _HtmlRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
public static func _render<Renderer: _HTMLRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
context.prependAttributes(html.attributes)
Content._render(html.content, into: &renderer, with: context)
}
}

public extension HtmlElement {
init(_ attribute: HtmlAttribute<Tag>, @HtmlBuilder content: () -> Content) {
public extension HTMLElement {
init(_ attribute: HTMLAttribute<Tag>, @HTMLBuilder content: () -> Content) {
attributes = .init(attribute)
self.content = content()
}

init(_ attributes: HtmlAttribute<Tag>..., @HtmlBuilder content: () -> Content) {
init(_ attributes: HTMLAttribute<Tag>..., @HTMLBuilder content: () -> Content) {
self.attributes = .init(attributes)
self.content = content()
}
}

public extension HtmlVoidElement {
init(_ attribute: HtmlAttribute<Tag>) {
public extension HTMLVoidElement {
init(_ attribute: HTMLAttribute<Tag>) {
attributes = .init(attribute)
}

init(_ attributes: HtmlAttribute<Tag>...) {
init(_ attributes: HTMLAttribute<Tag>...) {
self.attributes = .init(attributes)
}
}

public extension Html where Tag: HtmlTrait.Attributes.Global {
func attributes(_ attribute: HtmlAttribute<Tag>, when condition: Bool = true) -> _AttributedElement<Self> {
public extension HTML where Tag: HTMLTrait.Attributes.Global {
func attributes(_ attribute: HTMLAttribute<Tag>, when condition: Bool = true) -> _AttributedElement<Self> {
if condition {
return _AttributedElement(content: self, attributes: .init(attribute))
} else {
return _AttributedElement(content: self, attributes: .init())
}
}

func attributes(_ attributes: HtmlAttribute<Tag>..., when condition: Bool = true) -> _AttributedElement<Self> {
func attributes(_ attributes: HTMLAttribute<Tag>..., when condition: Bool = true) -> _AttributedElement<Self> {
_AttributedElement(content: self, attributes: .init(condition ? attributes : []))
}
}
Expand Down
28 changes: 14 additions & 14 deletions Sources/Elementary/Core/Html+Elements.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
public struct HtmlElement<Tag: HtmlTagDefinition, Content: Html>: Html where Tag: HtmlTrait.Paired {
public struct HTMLElement<Tag: HTMLTagDefinition, Content: HTML>: HTML where Tag: HTMLTrait.Paired {
public typealias Tag = Tag
@HtmlBuilder public var content: Content
@HTMLBuilder public var content: Content
var attributes: AttributeStorage

public init(@HtmlBuilder content: () -> Content) {
public init(@HTMLBuilder content: () -> Content) {
attributes = .init()
self.content = content()
}

@_spi(Rendering)
public static func _render<Renderer: _HtmlRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
public static func _render<Renderer: _HTMLRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
html.attributes.append(context.attributes)
renderer.appendStartTag(Tag.name, attributes: html.attributes.flattened(), isUnpaired: false, renderType: Tag.renderingType)

Expand All @@ -19,7 +19,7 @@ public struct HtmlElement<Tag: HtmlTagDefinition, Content: Html>: Html where Tag
}
}

public struct HtmlVoidElement<Tag: HtmlTagDefinition>: Html where Tag: HtmlTrait.Unpaired {
public struct HTMLVoidElement<Tag: HTMLTagDefinition>: HTML where Tag: HTMLTrait.Unpaired {
public typealias Tag = Tag
var attributes: AttributeStorage

Expand All @@ -28,43 +28,43 @@ public struct HtmlVoidElement<Tag: HtmlTagDefinition>: Html where Tag: HtmlTrait
}

@_spi(Rendering)
public static func _render<Renderer: _HtmlRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
public static func _render<Renderer: _HTMLRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
html.attributes.append(context.attributes)
renderer.appendStartTag(Tag.name, attributes: html.attributes.flattened(), isUnpaired: true, renderType: Tag.renderingType)
}
}

public struct HtmlComment: Html {
public struct HTMLComment: HTML {
public var text: String

public init(_ text: String) {
self.text = text
}

@_spi(Rendering)
public static func _render<Renderer: _HtmlRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
public static func _render<Renderer: _HTMLRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
context.assertNoAttributes(self)
renderer.appendToken(.comment(html.text))
}
}

public struct HtmlRaw: Html {
public struct HTMLRaw: HTML {
public var text: String

public init(_ text: String) {
self.text = text
}

@_spi(Rendering)
public static func _render<Renderer: _HtmlRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
public static func _render<Renderer: _HTMLRendering>(_ html: consuming Self, into renderer: inout Renderer, with context: consuming _RenderingContext) {
context.assertNoAttributes(self)
renderer.appendToken(.raw(html.text))
}
}

private extension _HtmlRendering {
private extension _HTMLRendering {
// TODO: maybe we could get by without allocating attribute lists and iterate them in somehow
mutating func appendStartTag(_ tagName: String, attributes: [StoredAttribute], isUnpaired: Bool, renderType: _HtmlRenderToken.RenderingType) {
mutating func appendStartTag(_ tagName: String, attributes: [StoredAttribute], isUnpaired: Bool, renderType: _HTMLRenderToken.RenderingType) {
appendToken(.startTagOpen(tagName, type: renderType))
for attribute in attributes {
appendToken(.attribute(name: attribute.name, value: attribute.value))
Expand All @@ -73,8 +73,8 @@ private extension _HtmlRendering {
}
}

extension HtmlTagDefinition {
static var renderingType: _HtmlRenderToken.RenderingType {
extension HTMLTagDefinition {
static var renderingType: _HTMLRenderToken.RenderingType {
_rendersInline ? .inline : .block
}
}
Loading

0 comments on commit bcec5a1

Please sign in to comment.