Skip to content

Commit 198746b

Browse files
authored
Introduce the crossorigin attribute (#193)
* Introduce the crossorigin attribute * Add conformance to the elements * Include a code example
1 parent d758039 commit 198746b

File tree

5 files changed

+96
-6
lines changed

5 files changed

+96
-6
lines changed

Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,38 @@ extension CoordinatesAttribute where Self: EmptyNode {
756756
}
757757
}
758758

759+
/// A type that provides the `crossOrigin` modifier
760+
@_documentation(visibility: internal)
761+
public protocol CrossOriginAttribute: Attribute {
762+
763+
/// Control the credential mode for cross-origin requests.
764+
///
765+
/// ```swift
766+
/// Script {
767+
/// }
768+
/// .crossOrigin(.anonymous)
769+
/// ```
770+
///
771+
/// - Parameter value: The mode to use.
772+
///
773+
/// - Returns: The element
774+
func crossOrigin(_ value: Credential.Mode) -> Self
775+
}
776+
777+
extension CrossOriginAttribute where Self: ContentNode {
778+
779+
internal func mutate(crossorigin value: String) -> Self {
780+
return self.mutate(key: "crossorigin", value: value)
781+
}
782+
}
783+
784+
extension CrossOriginAttribute where Self: EmptyNode {
785+
786+
internal func mutate(crossorigin value: String) -> Self {
787+
return self.mutate(key: "crossorigin", value: value)
788+
}
789+
}
790+
759791
/// A type that provides the `data` modifier.
760792
@_documentation(visibility: internal)
761793
public protocol DataAttribute: Attribute{

Sources/HTMLKit/Abstraction/Elements/BodyElements.swift

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17148,7 +17148,7 @@ public struct Image: EmptyNode, HtmlElement, BodyElement, FormElement, FigureEle
1714817148
}
1714917149
}
1715017150

17151-
extension Image: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, AlternateAttribute, SourceAttribute, SizesAttribute, WidthAttribute, HeightAttribute, ReferrerPolicyAttribute, FetchPriorityAttribute & LoadingAttribute & SourceSetAttribute & DecodingAttribute & IsMapAttribute & UseMapAttribute {
17151+
extension Image: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, AlternateAttribute, SourceAttribute, SizesAttribute, WidthAttribute, HeightAttribute, ReferrerPolicyAttribute, FetchPriorityAttribute & LoadingAttribute & SourceSetAttribute & DecodingAttribute & IsMapAttribute & UseMapAttribute, CrossOriginAttribute {
1715217152

1715317153
public func accessKey(_ value: Character) -> Image {
1715417154
return mutate(accesskey: value)
@@ -17165,6 +17165,10 @@ extension Image: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes,
1716517165
public func `class`(_ value: String) -> Image {
1716617166
return mutate(class: value)
1716717167
}
17168+
17169+
public func crossOrigin(_ value: Credential.Mode) -> Image {
17170+
return mutate(crossorigin: value.rawValue)
17171+
}
1716817172

1716917173
public func isEditable(_ value: Bool) -> Image {
1717017174
return mutate(contenteditable: value)
@@ -18502,7 +18506,7 @@ public struct Video: ContentNode, HtmlElement, BodyElement, FormElement, FigureE
1850218506
}
1850318507
}
1850418508

18505-
extension Video: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, SourceAttribute, AutoplayAttribute, LoopAttribute, MutedAttribute, ControlsAttribute, WidthAttribute, HeightAttribute, PreloadAttribute, PlaysInlineAttribute {
18509+
extension Video: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, SourceAttribute, AutoplayAttribute, LoopAttribute, MutedAttribute, ControlsAttribute, WidthAttribute, HeightAttribute, PreloadAttribute, PlaysInlineAttribute, CrossOriginAttribute {
1850618510

1850718511
public func accessKey(_ value: Character) -> Video {
1850818512
return mutate(accesskey: value)
@@ -18715,6 +18719,10 @@ extension Video: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes,
1871518719
return self
1871618720
}
1871718721

18722+
public func crossOrigin(_ value: Credential.Mode) -> Video {
18723+
return mutate(crossorigin: value.rawValue)
18724+
}
18725+
1871818726
public func custom(key: String, value: Any) -> Video {
1871918727
return mutate(key: key, value: value)
1872018728
}
@@ -18866,7 +18874,7 @@ public struct Audio: ContentNode, HtmlElement, BodyElement, FormElement, FigureE
1886618874
}
1886718875
}
1886818876

18869-
extension Audio: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, SourceAttribute, AutoplayAttribute, LoopAttribute, MutedAttribute, ControlsAttribute, PreloadAttribute {
18877+
extension Audio: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, SourceAttribute, AutoplayAttribute, LoopAttribute, MutedAttribute, ControlsAttribute, PreloadAttribute, CrossOriginAttribute {
1887018878

1887118879
public func accessKey(_ value: Character) -> Audio {
1887218880
return mutate(accesskey: value)
@@ -18883,6 +18891,10 @@ extension Audio: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes,
1888318891
public func `class`(_ value: String) -> Audio {
1888418892
return mutate(class: value)
1888518893
}
18894+
18895+
public func crossOrigin(_ value: Credential.Mode) -> Audio {
18896+
return mutate(crossorigin: value.rawValue)
18897+
}
1888618898

1888718899
public func isEditable(_ value: Bool) -> Audio {
1888818900
return mutate(contenteditable: value)
@@ -21718,7 +21730,7 @@ public struct Script: ContentNode, HeadElement, BodyElement, FormElement, Figure
2171821730
}
2171921731
}
2172021732

21721-
extension Script: GlobalAttributes, GlobalEventAttributes, AsynchronouslyAttribute, ReferrerPolicyAttribute, SourceAttribute, TypeAttribute, FetchPriorityAttribute, BlockingAttribute, IntegrityAttribute, DeferAttribute {
21733+
extension Script: GlobalAttributes, GlobalEventAttributes, AsynchronouslyAttribute, ReferrerPolicyAttribute, SourceAttribute, TypeAttribute, FetchPriorityAttribute, BlockingAttribute, IntegrityAttribute, DeferAttribute, CrossOriginAttribute {
2172221734

2172321735
public func accessKey(_ value: Character) -> Script {
2172421736
return mutate(accesskey: value)
@@ -21735,6 +21747,10 @@ extension Script: GlobalAttributes, GlobalEventAttributes, AsynchronouslyAttribu
2173521747
public func `class`(_ value: String) -> Script {
2173621748
return mutate(class: value)
2173721749
}
21750+
21751+
public func crossOrigin(_ value: Credential.Mode) -> Script {
21752+
return mutate(crossorigin: value.rawValue)
21753+
}
2173821754

2173921755
public func isEditable(_ value: Bool) -> Script {
2174021756
return mutate(contenteditable: value)

Sources/HTMLKit/Abstraction/Elements/HeadElements.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ public struct Link: EmptyNode, HeadElement, BodyElement {
990990
}
991991
}
992992

993-
extension Link: GlobalAttributes, GlobalEventAttributes, ReferenceAttribute, ReferenceLanguageAttribute, MediaAttribute, ReferrerPolicyAttribute, RelationshipAttribute, SizesAttribute, TypeAttribute, FetchPriorityAttribute, BlockingAttribute, FormEventAttribute, IntegrityAttribute, AsAttribute {
993+
extension Link: GlobalAttributes, GlobalEventAttributes, ReferenceAttribute, ReferenceLanguageAttribute, MediaAttribute, ReferrerPolicyAttribute, RelationshipAttribute, SizesAttribute, TypeAttribute, FetchPriorityAttribute, BlockingAttribute, FormEventAttribute, IntegrityAttribute, AsAttribute, CrossOriginAttribute {
994994

995995
public func accessKey(_ value: Character) -> Link {
996996
return mutate(accesskey: value)
@@ -1011,6 +1011,10 @@ extension Link: GlobalAttributes, GlobalEventAttributes, ReferenceAttribute, Ref
10111011
public func `class`(_ value: String) -> Link {
10121012
return mutate(class: value)
10131013
}
1014+
1015+
public func crossOrigin(_ value: Credential.Mode) -> Link {
1016+
return mutate(crossorigin: value.rawValue)
1017+
}
10141018

10151019
public func isEditable(_ value: Bool) -> Link {
10161020
return mutate(contenteditable: value)

Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
import Collections
22

3+
public enum Credential {
4+
5+
/// A credential mode for cross-origin requests.
6+
///
7+
/// ```swift
8+
/// Link()
9+
///     .reference("https://...")
10+
///     .crossOrigin(.useCredentials)
11+
/// ```
12+
public enum Mode: String {
13+
14+
/// Requests without credentials.
15+
case anonymous
16+
17+
/// Send credentials with the request.
18+
case useCredentials = "use-credentials"
19+
}
20+
}
21+
322
/// A namespace for several types of attribute values.
423
public enum Values {
524

Tests/HTMLKitTests/AttributesTests.swift

Lines changed: 20 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 & CoordinatesAttribute & DataAttribute & DateTimeAttribute & DefaultAttribute & DeferAttribute & DirectionAttribute & DisabledAttribute & DownloadAttribute & DragAttribute & EncodingAttribute & EnterKeyHintAttribute & ForAttribute & FormAttribute & FormActionAttribute & EquivalentAttribute & HeaderAttribute & HeightAttribute & HiddenAttribute & HighAttribute & ReferenceAttribute & ReferenceLanguageAttribute & IdentifierAttribute & IsMapAttribute & InputModeAttribute & IsAttribute & ItemAttribute & ItemIdAttribute & ItemPropertyAttribute & ItemReferenceAttribute & ItemScopeAttribute & ItemTypeAttribute & 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 & ReadyOnlyAttribute & 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 & AriaAtomicAttribute & AriaBusyAttribute & AriaControlsAttribute & AriaCurrentAttribute & AriaDescribedAttribute & AriaDetailsAttribute & AriaDisabledAttribute & AriaErrorMessageAttribute & AriaFlowToAttribute & AriaPopupAttribute & AriaHiddenAttribute & AriaInvalidAttribute & AriaShortcutsAttribute & AriaLabelAttribute & AriaLabeledAttribute & AriaLiveAttribute & AriaOwnsAttribute & AriaRelevantAttribute & AriaRoleDescriptionAttribute & DrawAttribute & FillAttribute & FillOpacityAttribute & StrokeAttribute & StrokeWidthAttribute & StrokeOpacityAttribute & StrokeLineCapAttribute & StrokeLineJoinAttribute & RadiusAttribute & PositionPointAttribute & RadiusPointAttribute & CenterPointAttribute & ViewBoxAttribute & NamespaceAttribute & PointsAttribute & ShadowRootModeAttribute & InertAttribute & FetchPriorityAttribute & LoadingAttribute & SourceSetAttribute & DecodingAttribute & BlockingAttribute & PopoverAttribute & PopoverTargetAttribute & PopoverActionAttribute & UseMapAttribute & PlaysInlineAttribute & IntegrityAttribute & AsAttribute
18+
typealias AllAttributes = AccessKeyAttribute & AcceptAttribute & ActionAttribute & AlternateAttribute & AsynchronouslyAttribute & AutocapitalizeAttribute & AutocompleteAttribute & AutofocusAttribute & AutoplayAttribute & CharsetAttribute & CheckedAttribute & CiteAttribute & ClassAttribute & ColumnsAttribute & ColumnSpanAttribute & ContentAttribute & EditAttribute & ControlsAttribute & CoordinatesAttribute & DataAttribute & DateTimeAttribute & DefaultAttribute & DeferAttribute & DirectionAttribute & DisabledAttribute & DownloadAttribute & DragAttribute & EncodingAttribute & EnterKeyHintAttribute & ForAttribute & FormAttribute & FormActionAttribute & EquivalentAttribute & HeaderAttribute & HeightAttribute & HiddenAttribute & HighAttribute & ReferenceAttribute & ReferenceLanguageAttribute & IdentifierAttribute & IsMapAttribute & InputModeAttribute & IsAttribute & ItemAttribute & ItemIdAttribute & ItemPropertyAttribute & ItemReferenceAttribute & ItemScopeAttribute & ItemTypeAttribute & 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 & ReadyOnlyAttribute & 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 & AriaAtomicAttribute & AriaBusyAttribute & AriaControlsAttribute & AriaCurrentAttribute & AriaDescribedAttribute & AriaDetailsAttribute & AriaDisabledAttribute & AriaErrorMessageAttribute & AriaFlowToAttribute & AriaPopupAttribute & AriaHiddenAttribute & AriaInvalidAttribute & AriaShortcutsAttribute & AriaLabelAttribute & AriaLabeledAttribute & AriaLiveAttribute & AriaOwnsAttribute & AriaRelevantAttribute & AriaRoleDescriptionAttribute & DrawAttribute & FillAttribute & FillOpacityAttribute & StrokeAttribute & StrokeWidthAttribute & StrokeOpacityAttribute & StrokeLineCapAttribute & StrokeLineJoinAttribute & RadiusAttribute & PositionPointAttribute & RadiusPointAttribute & CenterPointAttribute & ViewBoxAttribute & NamespaceAttribute & PointsAttribute & ShadowRootModeAttribute & InertAttribute & FetchPriorityAttribute & LoadingAttribute & SourceSetAttribute & DecodingAttribute & BlockingAttribute & PopoverAttribute & PopoverTargetAttribute & PopoverActionAttribute & UseMapAttribute & PlaysInlineAttribute & IntegrityAttribute & AsAttribute & CrossOriginAttribute
1919

2020
struct Tag: ContentNode, GlobalElement, AllAttributes {
2121

@@ -699,6 +699,10 @@ final class AttributesTests: XCTestCase {
699699
return self.mutate(integrity: hashes.joined(separator: " "))
700700
}
701701

702+
func crossOrigin(_ value: Credential.Mode) -> Tag {
703+
return self.mutate(crossorigin: value.rawValue)
704+
}
705+
702706
func on(event: Events.Window, _ value: String) -> Tag {
703707
return self.mutate(key: event.rawValue, value: value)
704708
}
@@ -2320,6 +2324,21 @@ final class AttributesTests: XCTestCase {
23202324
)
23212325
}
23222326

2327+
func testCrossOriginAttribute() throws {
2328+
2329+
let view = TestView {
2330+
Tag {}.crossOrigin(.anonymous)
2331+
Tag {}.crossOrigin(.useCredentials)
2332+
}
2333+
2334+
XCTAssertEqual(try renderer.render(view: view),
2335+
"""
2336+
<tag crossorigin="anonymous"></tag>\
2337+
<tag crossorigin="use-credentials"></tag>
2338+
"""
2339+
)
2340+
}
2341+
23232342
func testCustomAttribute() throws {
23242343

23252344
let view = TestView {

0 commit comments

Comments
 (0)