Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 63 additions & 8 deletions Sources/Elementary/Core/Html+Attributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,72 @@ extension HTMLAttribute {
}
}

public struct _AttributedElement<Content: HTML>: HTML {
public protocol _Attributed {
var _attributes: _AttributeStorage { get set }
}

extension HTML where Self: _Attributed {
/// Adds the specified attribute to the element.
/// - Parameters:
/// - attribute: The attribute to add to the element.
/// - condition: If set to false, the attribute will not be added.
/// - Returns: A new element with the specified attribute added.
@inlinable
public func attributes(_ attribute: HTMLAttribute<Tag>, when condition: Bool = true) -> Self {
if condition {
var element = self
element._attributes.append(_AttributeStorage(attribute))
return element
} else {
return self
}
}

/// Adds the specified attributes to the element.
/// - Parameters:
/// - attributes: The attributes to add to the element.
/// - condition: If set to false, the attributes will not be added.
/// - Returns: A new element with the specified attributes added.
@inlinable
public func attributes(_ attributes: HTMLAttribute<Tag>..., when condition: Bool = true) -> Self {
self.attributes(contentsOf: attributes, when: condition)
}

/// Adds the specified attributes to the element.
/// - Parameters:
/// - attributes: The attributes to add to the element as an array.
/// - condition: If set to false, the attributes will not be added.
/// - Returns: A new element with the specified attributes added.
@inlinable
public func attributes(contentsOf attributes: [HTMLAttribute<Tag>], when condition: Bool = true) -> Self {
if condition {
var element = self
element._attributes.append(_AttributeStorage(attributes))
return element
} else {
return self
}
}
}

public struct _AttributedElement<Content: HTML>: HTML, _Attributed {
public typealias Body = Never
public typealias Tag = Content.Tag

public var content: Content
public var attributes: _AttributeStorage

@available(*, renamed: "_attributes")
public var attributes: _AttributeStorage {
_read { yield _attributes }
_modify { yield &_attributes }
}

public var _attributes: _AttributeStorage

@usableFromInline
init(content: Content, attributes: _AttributeStorage) {
self.content = content
self.attributes = attributes
self._attributes = attributes
}

@inlinable
Expand All @@ -82,7 +137,7 @@ public struct _AttributedElement<Content: HTML>: HTML {
into renderer: inout Renderer,
with context: consuming _RenderingContext
) {
context.prependAttributes(html.attributes)
context.prependAttributes(html._attributes)
Content._render(html.content, into: &renderer, with: context)
}

Expand All @@ -93,7 +148,7 @@ public struct _AttributedElement<Content: HTML>: HTML {
into renderer: inout Renderer,
with context: consuming _RenderingContext
) async throws {
context.prependAttributes(html.attributes)
context.prependAttributes(html._attributes)
try await Content._render(html.content, into: &renderer, with: context)
}
}
Expand All @@ -106,7 +161,7 @@ public extension HTML where Tag: HTMLTrait.Attributes.Global {
/// - attribute: The attribute to add to the element.
/// - condition: If set to false, the attribute will not be added.
/// - Returns: A new element with the specified attribute added.
@inlinable
@inlinable @_disfavoredOverload
func attributes(_ attribute: HTMLAttribute<Tag>, when condition: Bool = true) -> _AttributedElement<Self> {
if condition {
return _AttributedElement(content: self, attributes: .init(attribute))
Expand All @@ -120,7 +175,7 @@ public extension HTML where Tag: HTMLTrait.Attributes.Global {
/// - attributes: The attributes to add to the element.
/// - condition: If set to false, the attributes will not be added.
/// - Returns: A new element with the specified attributes added.
@inlinable
@inlinable @_disfavoredOverload
func attributes(_ attributes: HTMLAttribute<Tag>..., when condition: Bool = true) -> _AttributedElement<Self> {
_AttributedElement(content: self, attributes: .init(condition ? attributes : []))
}
Expand All @@ -130,7 +185,7 @@ public extension HTML where Tag: HTMLTrait.Attributes.Global {
/// - attributes: The attributes to add to the element as an array.
/// - condition: If set to false, the attributes will not be added.
/// - Returns: A new element with the specified attributes added.
@inlinable
@inlinable @_disfavoredOverload
func attributes(contentsOf attributes: [HTMLAttribute<Tag>], when condition: Bool = true) -> _AttributedElement<Self> {
_AttributedElement(content: self, attributes: .init(condition ? attributes : []))
}
Expand Down
21 changes: 11 additions & 10 deletions Sources/Elementary/Core/Html+Elements.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// An HTML element that can contain content.
public struct HTMLElement<Tag: HTMLTagDefinition, Content: HTML>: HTML where Tag: HTMLTrait.Paired {
public struct HTMLElement<Tag: HTMLTagDefinition, Content: HTML>: HTML, _Attributed where Tag: HTMLTrait.Paired {
/// The type of the HTML tag this element represents.
public typealias Tag = Tag
public typealias Body = Never
Expand All @@ -14,7 +14,7 @@ public struct HTMLElement<Tag: HTMLTagDefinition, Content: HTML>: HTML where Tag
/// - Parameter content: The content of the element.
@inlinable
public init(@HTMLBuilder content: () -> Content) {
_attributes = .init()
self._attributes = .init()
self.content = content()
}

Expand All @@ -24,7 +24,7 @@ public struct HTMLElement<Tag: HTMLTagDefinition, Content: HTML>: HTML where Tag
/// - content: The content of the element.
@inlinable
public init(_ attribute: HTMLAttribute<Tag>, @HTMLBuilder content: () -> Content) {
_attributes = .init(attribute)
self._attributes = .init(attribute)
self.content = content()
}

Expand All @@ -34,7 +34,7 @@ public struct HTMLElement<Tag: HTMLTagDefinition, Content: HTML>: HTML where Tag
/// - content: The content of the element.
@inlinable
public init(_ attributes: HTMLAttribute<Tag>..., @HTMLBuilder content: () -> Content) {
_attributes = .init(attributes)
self._attributes = .init(attributes)
self.content = content()
}

Expand All @@ -44,7 +44,7 @@ public struct HTMLElement<Tag: HTMLTagDefinition, Content: HTML>: HTML where Tag
/// - content: The content of the element.
@inlinable
public init(attributes: [HTMLAttribute<Tag>], @HTMLBuilder content: () -> Content) {
_attributes = .init(attributes)
self._attributes = .init(attributes)
self.content = content()
}

Expand Down Expand Up @@ -79,36 +79,37 @@ public struct HTMLElement<Tag: HTMLTagDefinition, Content: HTML>: HTML where Tag
}

/// An HTML element that does not contain content.
public struct HTMLVoidElement<Tag: HTMLTagDefinition>: HTML where Tag: HTMLTrait.Unpaired {
public struct HTMLVoidElement<Tag: HTMLTagDefinition>: HTML, _Attributed where Tag: HTMLTrait.Unpaired {
/// The type of the HTML tag this element represents.
public typealias Tag = Tag

public var _attributes: _AttributeStorage

/// Creates a new HTML void element.
@inlinable
public init() {
_attributes = .init()
self._attributes = .init()
}

/// Creates a new HTML void element with the specified attribute.
/// - Parameter attribute: The attribute to apply to the element.
@inlinable
public init(_ attribute: HTMLAttribute<Tag>) {
_attributes = .init(attribute)
self._attributes = .init(attribute)
}

/// Creates a new HTML void element with the specified attributes.
/// - Parameter attributes: The attributes to apply to the element.
@inlinable
public init(_ attributes: HTMLAttribute<Tag>...) {
_attributes = .init(attributes)
self._attributes = .init(attributes)
}

/// Creates a new HTML void element with the specified attributes.
/// - Parameter attributes: The attributes to apply to the element as an array.
@inlinable
public init(attributes: [HTMLAttribute<Tag>]) {
_attributes = .init(attributes)
self._attributes = .init(attributes)
}

@inlinable
Expand Down
Loading
Loading