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
63 changes: 63 additions & 0 deletions Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4159,3 +4159,66 @@ extension PopoverTargetAttribute where Self: EmptyNode {
return self.mutate(key: "popovertargetaction", value: value)
}
}

/// A type that provides the `abbreviated` modifier.
@_documentation(visibility: internal)
public protocol AbbreviatedAttribute: Attribute {

/// Announce a brief alternate label.
///
/// ```
/// HeaderCell {
/// "Lorem ipsum..."
/// }
/// .abbreviated("Lorem Ipsum")
/// ```
///
/// - Parameter value: The alternate label to describe the content.
///
/// - Returns: The element
func abbreviated(_ value: String) -> Self

/// Announce a brief localized alternate label.
///
/// ```
/// HeaderCell {
/// "Lorem ipsum..."
/// }
/// .abbreviated("Lorem Ipsum")
/// ```
///
/// - Parameters:
/// - localizedKey: The string key to be translated.
/// - tableName: The translation table to look in.
///
/// - Returns: The element
func abbreviated(_ localizedKey: LocalizedStringKey, tableName: String?) -> Self

/// Announce a brief alternate label without localization.
///
/// ```
/// HeaderCell {
/// "Lorem ipsum..."
/// }
/// .abbreviated(verbatim: "Lorem Ipsum")
/// ```
///
/// - Parameter value: The alternate label to describe the content.
///
/// - Returns: The element
func abbreviated(verbatim value: String) -> Self
}

extension AbbreviatedAttribute where Self: ContentNode {

internal func mutate(abbr value: AttributeData) -> Self {
return self.mutate(key: "abbr", value: value)
}
}

extension AbbreviatedAttribute where Self: EmptyNode {

internal func mutate(abbr value: AttributeData) -> Self {
return self.mutate(key: "abbr", value: value)
}
}
15 changes: 14 additions & 1 deletion Sources/HTMLKit/Abstraction/Elements/TableElements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3984,7 +3984,7 @@ public struct HeaderCell: ContentNode, TableElement {
}
}

extension HeaderCell: GlobalAttributes, GlobalEventAttributes, GlobalAccessibilityAttributes, ColumnSpanAttribute, RowSpanAttribute, HeadersAttribute, ScopeAttribute, ColumnIndexAccessibilityAttribute {
extension HeaderCell: GlobalAttributes, GlobalEventAttributes, GlobalAccessibilityAttributes, ColumnSpanAttribute, RowSpanAttribute, HeadersAttribute, ScopeAttribute, ColumnIndexAccessibilityAttribute, AbbreviatedAttribute {

public func accessKey(_ value: Character) -> HeaderCell {
return mutate(accesskey: .init("\(value)", context: .trusted))
Expand Down Expand Up @@ -4191,6 +4191,19 @@ extension HeaderCell: GlobalAttributes, GlobalEventAttributes, GlobalAccessibili
return mutate(popover: .init(value.rawValue, context: .trusted))
}

@_disfavoredOverload
public func abbreviated(_ value: String) -> HeaderCell {
return mutate(abbr: .init(value, context: .tainted(.html)))
}

public func abbreviated(_ localizedKey: LocalizedStringKey, tableName: String? = nil) -> HeaderCell {
return mutate(abbr: .init(LocalizedString(key: localizedKey, table: tableName), context: .tainted(.html)))
}

public func abbreviated(verbatim value: String) -> HeaderCell {
return mutate(abbr: .init(value, context: .tainted(.html)))
}

public func custom(key: String, value: String, context: EscapeContext = .tainted(.html)) -> HeaderCell {
return mutate(key: key, value: .init(value, context: context))
}
Expand Down
28 changes: 27 additions & 1 deletion Tests/HTMLKitTests/AttributesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class AttributesTests: XCTestCase {
@ContentBuilder<Content> 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 & SourceSetAttribute & DecodingAttribute & BlockingAttribute & PopoverAttribute & PopoverTargetAttribute & UseMapAttribute & PlaysInlineAttribute & IntegrityAttribute & AsAttribute & CrossOriginAttribute & SourceLanguageAttribute & SourceDocumentAttribute
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 & SourceSetAttribute & DecodingAttribute & BlockingAttribute & PopoverAttribute & PopoverTargetAttribute & UseMapAttribute & PlaysInlineAttribute & IntegrityAttribute & AsAttribute & CrossOriginAttribute & SourceLanguageAttribute & SourceDocumentAttribute & AbbreviatedAttribute

struct Tag: ContentNode, GlobalElement, AllAttributes {

Expand Down Expand Up @@ -1172,6 +1172,19 @@ final class AttributesTests: XCTestCase {

return self
}

@_disfavoredOverload
func abbreviated(_ value: String) -> Tag {
return self.mutate(abbr: .init(value, context: .tainted(.html)))
}

func abbreviated(_ localizedKey: HTMLKit.LocalizedStringKey, tableName: String? = nil) -> Tag {
return self.mutate(abbr: .init(LocalizedString(key: localizedKey, table: tableName), context: .tainted(.html)))
}

func abbreviated(verbatim value: String) -> Tag {
return self.mutate(abbr: .init(value, context: .tainted(.html)))
}
}

var renderer = Renderer()
Expand Down Expand Up @@ -3811,4 +3824,17 @@ final class AttributesTests: XCTestCase {
"""
)
}

func testAbbreviatedAttribute() throws {

let view = TestView {
Tag {}.abbreviated("HTML")
}

XCTAssertEqual(try renderer.render(view: view),
"""
<tag abbr="HTML"></tag>
"""
)
}
}
Loading