diff --git a/Sources/HTMLKit/Abstraction/Attributes/ContentAttributes.swift b/Sources/HTMLKit/Abstraction/Attributes/ContentAttributes.swift
index 76c7d4b4..5f193626 100644
--- a/Sources/HTMLKit/Abstraction/Attributes/ContentAttributes.swift
+++ b/Sources/HTMLKit/Abstraction/Attributes/ContentAttributes.swift
@@ -4414,3 +4414,39 @@ extension ImageSizesAttribute where Self: EmptyNode {
return self.mutate(key: "imagesizes", value: value)
}
}
+
+/// A type that provides the `command` modifier.
+@_documentation(visibility: internal)
+public protocol CommandAttribute: Attribute {
+
+ /// Set an action to perform for the button element.
+ ///
+ /// - Parameters:
+ /// - action: The action to perform when triggered.
+ /// - target: The identifier of the target to invoke.
+ ///
+ /// - Returns: The element
+ func command(_ action: ActionCommand, for target: String) -> Self
+}
+
+extension CommandAttribute where Self: ContentNode {
+
+ internal func mutate(command value: AttributeData) -> Self {
+ return self.mutate(key: "command", value: value)
+ }
+
+ internal func mutate(commandfor value: AttributeData) -> Self {
+ return self.mutate(key: "commandfor", value: value)
+ }
+}
+
+extension CommandAttribute where Self: EmptyNode {
+
+ internal func mutate(command value: AttributeData) -> Self {
+ return self.mutate(key: "command", value: value)
+ }
+
+ internal func mutate(commandfor value: AttributeData) -> Self {
+ return self.mutate(key: "commandfor", value: value)
+ }
+}
diff --git a/Sources/HTMLKit/Abstraction/Elements/FormElements.swift b/Sources/HTMLKit/Abstraction/Elements/FormElements.swift
index e9d0b18a..4461c582 100644
--- a/Sources/HTMLKit/Abstraction/Elements/FormElements.swift
+++ b/Sources/HTMLKit/Abstraction/Elements/FormElements.swift
@@ -2293,7 +2293,7 @@ public struct Button: ContentNode, FormElement {
}
}
-extension Button: GlobalContentAttributes, GlobalEventAttributes, GlobalAccessibilityAttributes, DisabledAttribute, FormAttribute, FormActionAttribute, NameAttribute, TypeAttribute, ValueAttribute, PopoverTargetAttribute, PressedAccessibilityAttribute, SelectedAccessibilityAttribute, ExpandedAccessibilityAttribute {
+extension Button: GlobalContentAttributes, GlobalEventAttributes, GlobalAccessibilityAttributes, DisabledAttribute, FormAttribute, FormActionAttribute, NameAttribute, TypeAttribute, ValueAttribute, PopoverTargetAttribute, CommandAttribute, PressedAccessibilityAttribute, SelectedAccessibilityAttribute, ExpandedAccessibilityAttribute {
public func accessKey(_ value: Character) -> Button {
return mutate(accesskey: .init("\(value)", context: .trusted))
@@ -2514,6 +2514,10 @@ extension Button: GlobalContentAttributes, GlobalEventAttributes, GlobalAccessib
return copy
}
+ public func command(_ action: ActionCommand, for target: String) -> Button {
+ return mutate(command:.init(action.rawValue, context: .trusted)).mutate(commandfor: .init(target, context: .tainted(.html)))
+ }
+
public func custom(key: String, value: String, context: EscapeContext = .tainted(.html)) -> Button {
return mutate(key: key, value: .init(value, context: context))
}
diff --git a/Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift b/Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift
index 9d845e80..e2e59f5e 100644
--- a/Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift
+++ b/Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift
@@ -1,5 +1,34 @@
import Collections
+/// A command of a button element.
+///
+/// ```swift
+/// Button {
+/// "Lorem ipsum"
+/// }
+/// .command(.togglePopover, for: "id")
+/// ```
+public enum ActionCommand: String {
+
+ /// Toggles the popover element.
+ case togglePopover = "toggle-popover"
+
+ /// Shows the popover element.
+ case showPopover = "show-popover"
+
+ /// Hides the popover element.
+ case hidePopover = "hide-popover"
+
+ /// Closes the dialog element.
+ case closeDialog = "close"
+
+ /// Requests to close the dialog element.
+ case requestClose = "request-close"
+
+ /// Opens the dialog element.
+ case showModal = "show-modal"
+}
+
public enum Credential {
/// A credential mode for cross-origin requests.
diff --git a/Tests/HTMLKitTests/AttributesTests.swift b/Tests/HTMLKitTests/AttributesTests.swift
index 032b8caa..0eae355c 100644
--- a/Tests/HTMLKitTests/AttributesTests.swift
+++ b/Tests/HTMLKitTests/AttributesTests.swift
@@ -10,9 +10,9 @@ final class AttributesTests: XCTestCase {
@ContentBuilder var body: Content
}
- typealias AllAttributes = AccessKeyAttribute & AcceptAttribute & ActionAttribute & AlternateAttribute & AsynchronouslyAttribute & AutocapitalizeAttribute & AutocompleteAttribute & AutofocusAttribute & AutoplayAttribute & CharsetAttribute & CheckedAttribute & CiteAttribute & ClassAttribute & ColumnsAttribute & ColumnSpanAttribute & ContentAttribute & EditAttribute & ControlsAttribute & DataAttribute & DateTimeAttribute & DefaultAttribute & DeferAttribute & DirectionAttribute & DisabledAttribute & DownloadAttribute & DragAttribute & EncodingAttribute & EnterKeyAttribute & ForAttribute & FormAttribute & FormActionAttribute & EquivalentAttribute & HeadersAttribute & HeightAttribute & HiddenAttribute & HighAttribute & ReferenceAttribute & ReferenceLanguageAttribute & IdentifierAttribute & IsMapAttribute & InputModeAttribute & IsAttribute & ItemAttribute & ItemPropertyAttribute & KindAttribute & LabelAttribute & LanguageAttribute & ListAttribute & LoopAttribute & LowAttribute & MaximumValueAttribute & MaximumLengthAttribute & MediaAttribute & MethodAttribute & MinimumValueAttribute & MinimumLengthAttribute & MultipleAttribute & MutedAttribute & NameAttribute & NonceAttribute & NoValidateAttribute & OpenAttribute & OptimumAttribute & PatternAttribute & PartAttribute & PingAttribute & PlaceholderAttribute & PosterAttribute & PreloadAttribute & ReadOnlyAttribute & ReferrerPolicyAttribute & RelationshipAttribute & RequiredAttribute & ReversedAttribute & RoleAttribute & RowsAttribute & RowSpanAttribute & SandboxAttribute & ScopeAttribute & ShapeAttribute & SizeAttribute & SizesAttribute & SlotAttribute & SpanAttribute & SpellCheckAttribute & SourceAttribute & StartAttribute & StepAttribute & StyleAttribute & TabulatorAttribute & TargetAttribute & TitleAttribute & TranslateAttribute & TypeAttribute & ValueAttribute & WidthAttribute & WrapAttribute & PropertyAttribute & SelectedAttribute & WindowEventAttribute & FocusEventAttribute & PointerEventAttribute & MouseEventAttribute & WheelEventAttribute & InputEventAttribute & KeyboardEventAttribute & DragEventAttribute & ClipboardEventAttribute & SelectionEventAttribute & MediaEventAttribute & FormEventAttribute & DetailEventAttribute & AtomicAccessibilityAttribute & BusyAccessibilityAttribute & ControlsAccessibilityAttribute & CurrentAccessibilityAttribute & DescriptionsAccessibilityAttribute & DetailAccessibilityAttribute & DisabledAccessibilityAttribute & FlowAccessibilityAttribute & PopupAccessibilityAttribute & HiddenAccessibilityAttribute & InvalidAccessibilityAttribute & ShortcutsAccessibilityAttribute & LabelAccessibilityAttribute & LabelsAccessibilityAttribute & LiveAccessibilityAttribute & OwnsAccessibilityAttribute & MultilineAccessibilityAttribute & RowIndexAccessibilityAttribute & RelevantAccessibilityAttribute & RoleDescriptionAccessibilityAttribute & SortAccessibilityAttribute & OrientationAccessibilityAttribute & RequiredAccessibilityAttribute & ReadOnlyAccessibilityAttribute & ModalAccessibilityAttribute & LevelAccessibilityAttribute & HintAccessibilityAttribute & PositionAccessibilityAttribute & MultiselectAccessibilityAttribute & RowCountAccessibilityAttribute & ColumnIndexAccessibilityAttribute & ColumnCountAccessibilityAttribute & RowSpanAccessibilityAttribute & ColumnSpanAccessibilityAttribute & MaximumValueAccessibilityAttribute & MinimumValueAccessibilityAttribute & ValueAccessibilityAttribute & PressedAccessibilityAttribute & SelectedAccessibilityAttribute & CheckedAccessibilityAttribute & ExpandedAccessibilityAttribute & FocusedAccessibilityAttribute & CompletionAccessibilityAttribute & DrawAttribute & FillAttribute & StrokeAttribute & RadiusAttribute & PositionPointAttribute & RadiusPointAttribute & CenterPointAttribute & ViewBoxAttribute & NamespaceAttribute & PointsAttribute & ShadowRootModeAttribute & InertAttribute & FetchPriorityAttribute & LoadingAttribute & SourcesAttribute & DecodingAttribute & BlockingAttribute & PopoverAttribute & PopoverTargetAttribute & UseMapAttribute & PlaysInlineAttribute & IntegrityAttribute & AsAttribute & CrossOriginAttribute & SourceLanguageAttribute & SourceDocumentAttribute & AbbreviatedAttribute & ImageSourcesAttribute & ImageSizesAttribute
+ typealias AllAttributes = AccessKeyAttribute & AcceptAttribute & ActionAttribute & AlternateAttribute & AsynchronouslyAttribute & AutocapitalizeAttribute & AutocompleteAttribute & AutofocusAttribute & AutoplayAttribute & CharsetAttribute & CheckedAttribute & CiteAttribute & ClassAttribute & ColumnsAttribute & ColumnSpanAttribute & ContentAttribute & EditAttribute & ControlsAttribute & DataAttribute & DateTimeAttribute & DefaultAttribute & DeferAttribute & DirectionAttribute & DisabledAttribute & DownloadAttribute & DragAttribute & EncodingAttribute & EnterKeyAttribute & ForAttribute & FormAttribute & FormActionAttribute & EquivalentAttribute & HeadersAttribute & HeightAttribute & HiddenAttribute & HighAttribute & ReferenceAttribute & ReferenceLanguageAttribute & IdentifierAttribute & IsMapAttribute & InputModeAttribute & IsAttribute & ItemAttribute & ItemPropertyAttribute & KindAttribute & LabelAttribute & LanguageAttribute & ListAttribute & LoopAttribute & LowAttribute & MaximumValueAttribute & MaximumLengthAttribute & MediaAttribute & MethodAttribute & MinimumValueAttribute & MinimumLengthAttribute & MultipleAttribute & MutedAttribute & NameAttribute & NonceAttribute & NoValidateAttribute & OpenAttribute & OptimumAttribute & PatternAttribute & PartAttribute & PingAttribute & PlaceholderAttribute & PosterAttribute & PreloadAttribute & ReadOnlyAttribute & ReferrerPolicyAttribute & RelationshipAttribute & RequiredAttribute & ReversedAttribute & RoleAttribute & RowsAttribute & RowSpanAttribute & SandboxAttribute & ScopeAttribute & ShapeAttribute & SizeAttribute & SizesAttribute & SlotAttribute & SpanAttribute & SpellCheckAttribute & SourceAttribute & StartAttribute & StepAttribute & StyleAttribute & TabulatorAttribute & TargetAttribute & TitleAttribute & TranslateAttribute & TypeAttribute & ValueAttribute & WidthAttribute & WrapAttribute & PropertyAttribute & SelectedAttribute & WindowEventAttribute & FocusEventAttribute & PointerEventAttribute & MouseEventAttribute & WheelEventAttribute & InputEventAttribute & KeyboardEventAttribute & DragEventAttribute & ClipboardEventAttribute & SelectionEventAttribute & MediaEventAttribute & FormEventAttribute & DetailEventAttribute & AtomicAccessibilityAttribute & BusyAccessibilityAttribute & ControlsAccessibilityAttribute & CurrentAccessibilityAttribute & DescriptionsAccessibilityAttribute & DetailAccessibilityAttribute & DisabledAccessibilityAttribute & FlowAccessibilityAttribute & PopupAccessibilityAttribute & HiddenAccessibilityAttribute & InvalidAccessibilityAttribute & ShortcutsAccessibilityAttribute & LabelAccessibilityAttribute & LabelsAccessibilityAttribute & LiveAccessibilityAttribute & OwnsAccessibilityAttribute & MultilineAccessibilityAttribute & RowIndexAccessibilityAttribute & RelevantAccessibilityAttribute & RoleDescriptionAccessibilityAttribute & SortAccessibilityAttribute & OrientationAccessibilityAttribute & RequiredAccessibilityAttribute & ReadOnlyAccessibilityAttribute & ModalAccessibilityAttribute & LevelAccessibilityAttribute & HintAccessibilityAttribute & PositionAccessibilityAttribute & MultiselectAccessibilityAttribute & RowCountAccessibilityAttribute & ColumnIndexAccessibilityAttribute & ColumnCountAccessibilityAttribute & RowSpanAccessibilityAttribute & ColumnSpanAccessibilityAttribute & MaximumValueAccessibilityAttribute & MinimumValueAccessibilityAttribute & ValueAccessibilityAttribute & PressedAccessibilityAttribute & SelectedAccessibilityAttribute & CheckedAccessibilityAttribute & ExpandedAccessibilityAttribute & FocusedAccessibilityAttribute & CompletionAccessibilityAttribute & DrawAttribute & FillAttribute & StrokeAttribute & RadiusAttribute & PositionPointAttribute & RadiusPointAttribute & CenterPointAttribute & ViewBoxAttribute & NamespaceAttribute & PointsAttribute & ShadowRootModeAttribute & InertAttribute & FetchPriorityAttribute & LoadingAttribute & SourcesAttribute & DecodingAttribute & BlockingAttribute & PopoverAttribute & PopoverTargetAttribute & UseMapAttribute & PlaysInlineAttribute & IntegrityAttribute & AsAttribute & CrossOriginAttribute & SourceLanguageAttribute & SourceDocumentAttribute & AbbreviatedAttribute & ImageSourcesAttribute & ImageSizesAttribute & CommandAttribute
- struct Tag: ContentNode, GlobalElement, AllAttributes {
+ struct Tag: ContentNode, GlobalElement, AllAttributes {
var name: String { "tag" }
@@ -1226,6 +1226,10 @@ final class AttributesTests: XCTestCase {
func imageSizes(_ candidates: HTMLKit.SizeCandidate...) -> Tag {
return mutate(imagesizes: .init(EnumeratedList(values: candidates, separator: ", "), context: .tainted(.html)))
}
+
+ func command(_ action: ActionCommand, for target: String) -> Tag {
+ return mutate(command:.init(action.rawValue, context: .trusted)).mutate(commandfor: .init(target, context: .tainted(.html)))
+ }
}
var renderer = Renderer()
@@ -3939,4 +3943,17 @@ final class AttributesTests: XCTestCase {
"""
)
}
+
+ func testCommandAttribute() throws {
+
+ let view = TestView {
+ Tag {}.command(.hidePopover, for: "test")
+ }
+
+ XCTAssertEqual(try renderer.render(view: view),
+ """
+
+ """
+ )
+ }
}