Skip to content

Commit edfa388

Browse files
authored
Introduce the abbreviated attribute (#216)
* Introduce the abbreviated attribute * Add conformance to the element * Add a code example
1 parent c731bc0 commit edfa388

3 files changed

Lines changed: 104 additions & 2 deletions

File tree

Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4159,3 +4159,66 @@ extension PopoverTargetAttribute where Self: EmptyNode {
41594159
return self.mutate(key: "popovertargetaction", value: value)
41604160
}
41614161
}
4162+
4163+
/// A type that provides the `abbreviated` modifier.
4164+
@_documentation(visibility: internal)
4165+
public protocol AbbreviatedAttribute: Attribute {
4166+
4167+
/// Announce a brief alternate label.
4168+
///
4169+
/// ```
4170+
/// HeaderCell {
4171+
/// "Lorem ipsum..."
4172+
/// }
4173+
/// .abbreviated("Lorem Ipsum")
4174+
/// ```
4175+
///
4176+
/// - Parameter value: The alternate label to describe the content.
4177+
///
4178+
/// - Returns: The element
4179+
func abbreviated(_ value: String) -> Self
4180+
4181+
/// Announce a brief localized alternate label.
4182+
///
4183+
/// ```
4184+
/// HeaderCell {
4185+
/// "Lorem ipsum..."
4186+
/// }
4187+
/// .abbreviated("Lorem Ipsum")
4188+
/// ```
4189+
///
4190+
/// - Parameters:
4191+
/// - localizedKey: The string key to be translated.
4192+
/// - tableName: The translation table to look in.
4193+
///
4194+
/// - Returns: The element
4195+
func abbreviated(_ localizedKey: LocalizedStringKey, tableName: String?) -> Self
4196+
4197+
/// Announce a brief alternate label without localization.
4198+
///
4199+
/// ```
4200+
/// HeaderCell {
4201+
/// "Lorem ipsum..."
4202+
/// }
4203+
/// .abbreviated(verbatim: "Lorem Ipsum")
4204+
/// ```
4205+
///
4206+
/// - Parameter value: The alternate label to describe the content.
4207+
///
4208+
/// - Returns: The element
4209+
func abbreviated(verbatim value: String) -> Self
4210+
}
4211+
4212+
extension AbbreviatedAttribute where Self: ContentNode {
4213+
4214+
internal func mutate(abbr value: AttributeData) -> Self {
4215+
return self.mutate(key: "abbr", value: value)
4216+
}
4217+
}
4218+
4219+
extension AbbreviatedAttribute where Self: EmptyNode {
4220+
4221+
internal func mutate(abbr value: AttributeData) -> Self {
4222+
return self.mutate(key: "abbr", value: value)
4223+
}
4224+
}

Sources/HTMLKit/Abstraction/Elements/TableElements.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3984,7 +3984,7 @@ public struct HeaderCell: ContentNode, TableElement {
39843984
}
39853985
}
39863986

3987-
extension HeaderCell: GlobalAttributes, GlobalEventAttributes, GlobalAccessibilityAttributes, ColumnSpanAttribute, RowSpanAttribute, HeadersAttribute, ScopeAttribute, ColumnIndexAccessibilityAttribute {
3987+
extension HeaderCell: GlobalAttributes, GlobalEventAttributes, GlobalAccessibilityAttributes, ColumnSpanAttribute, RowSpanAttribute, HeadersAttribute, ScopeAttribute, ColumnIndexAccessibilityAttribute, AbbreviatedAttribute {
39883988

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

4194+
@_disfavoredOverload
4195+
public func abbreviated(_ value: String) -> HeaderCell {
4196+
return mutate(abbr: .init(value, context: .tainted(.html)))
4197+
}
4198+
4199+
public func abbreviated(_ localizedKey: LocalizedStringKey, tableName: String? = nil) -> HeaderCell {
4200+
return mutate(abbr: .init(LocalizedString(key: localizedKey, table: tableName), context: .tainted(.html)))
4201+
}
4202+
4203+
public func abbreviated(verbatim value: String) -> HeaderCell {
4204+
return mutate(abbr: .init(value, context: .tainted(.html)))
4205+
}
4206+
41944207
public func custom(key: String, value: String, context: EscapeContext = .tainted(.html)) -> HeaderCell {
41954208
return mutate(key: key, value: .init(value, context: context))
41964209
}

Tests/HTMLKitTests/AttributesTests.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class AttributesTests: XCTestCase {
1515
@ContentBuilder<Content> var body: Content
1616
}
1717

18-
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
18+
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
1919

2020
struct Tag: ContentNode, GlobalElement, AllAttributes {
2121

@@ -1172,6 +1172,19 @@ final class AttributesTests: XCTestCase {
11721172

11731173
return self
11741174
}
1175+
1176+
@_disfavoredOverload
1177+
func abbreviated(_ value: String) -> Tag {
1178+
return self.mutate(abbr: .init(value, context: .tainted(.html)))
1179+
}
1180+
1181+
func abbreviated(_ localizedKey: HTMLKit.LocalizedStringKey, tableName: String? = nil) -> Tag {
1182+
return self.mutate(abbr: .init(LocalizedString(key: localizedKey, table: tableName), context: .tainted(.html)))
1183+
}
1184+
1185+
func abbreviated(verbatim value: String) -> Tag {
1186+
return self.mutate(abbr: .init(value, context: .tainted(.html)))
1187+
}
11751188
}
11761189

11771190
var renderer = Renderer()
@@ -3811,4 +3824,17 @@ final class AttributesTests: XCTestCase {
38113824
"""
38123825
)
38133826
}
3827+
3828+
func testAbbreviatedAttribute() throws {
3829+
3830+
let view = TestView {
3831+
Tag {}.abbreviated("HTML")
3832+
}
3833+
3834+
XCTAssertEqual(try renderer.render(view: view),
3835+
"""
3836+
<tag abbr="HTML"></tag>
3837+
"""
3838+
)
3839+
}
38143840
}

0 commit comments

Comments
 (0)