Skip to content

Commit

Permalink
Make the sandbox modifier accept an enum (#167)
Browse files Browse the repository at this point in the history
* Make the sandbox modifier accept an enum

* Assign the sandbox attribute to the inlineframe element
  • Loading branch information
mattesmohr authored Dec 31, 2024
1 parent d3dcaa6 commit 44b4722
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 6 deletions.
33 changes: 29 additions & 4 deletions Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2191,16 +2191,41 @@ extension RowSpanAttribute where Self: EmptyNode {
}
}

/// The protocol provides the element with the sandbox handler.
/// A type that provides the `sandbox` modifier.
///
/// > Note: Currently, this protocol is only applicable to `InlineFrame`.
@_documentation(visibility: internal)
public protocol SandboxAttribute: Attribute {

/// The function represents the html-attribute 'sandbox'.
/// Define the permissions for the element.
///
/// ```html
/// <tag sandbox />
/// ```swift
/// InlineFrame {
/// }
/// .source("https://...")
/// .sandbox()
/// ```
func sandbox() -> Self

/// Define the permissions for the element.
///
/// ```swift
/// InlineFrame {
/// }
/// .source("https://...")
/// .sandbox(.allowDownloads)
/// ```
func sandbox(_ value: Values.Permission) -> Self

/// Define the permissions for the element.
///
/// ```swift
/// InlineFrame {
/// }
/// .source("https://...")
/// .sandbox([.allowDownloads, .allowPopups])
/// ```
func sandbox(_ values: OrderedSet<Values.Permission>) -> Self
}

extension SandboxAttribute where Self: ContentNode {
Expand Down
14 changes: 13 additions & 1 deletion Sources/HTMLKit/Abstraction/Elements/BodyElements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15956,7 +15956,7 @@ public struct InlineFrame: ContentNode, HtmlElement, BodyElement, FormElement, F
}
}

extension InlineFrame: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, SourceAttribute, NameAttribute, WidthAttribute, HeightAttribute, ReferrerPolicyAttribute & LoadingAttribute {
extension InlineFrame: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, SourceAttribute, NameAttribute, WidthAttribute, HeightAttribute, ReferrerPolicyAttribute & LoadingAttribute & SandboxAttribute {

public func accessKey(_ value: Character) -> InlineFrame {
return mutate(accesskey: value)
Expand Down Expand Up @@ -16085,6 +16085,18 @@ extension InlineFrame: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttrib
return self
}

public func sandbox() -> InlineFrame {
return mutate(sandbox: "sandbox")
}

public func sandbox(_ value: Values.Permission) -> InlineFrame {
return mutate(sandbox: value.rawValue)
}

public func sandbox(_ values: OrderedCollections.OrderedSet<Values.Permission>) -> InlineFrame {
return mutate(sandbox: values.map { $0.rawValue }.joined(separator: " "))
}

public func source(_ value: String) -> InlineFrame {
return mutate(source: value)
}
Expand Down
46 changes: 46 additions & 0 deletions Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1188,4 +1188,50 @@ public enum Values {
/// Expects a url for instant messaging
case messagingProtocol = "impp"
}

/// A enumeration of extra permission
///
/// ```swift
/// InlineFrame {
/// }
/// .sandbox([.allowDownloads, .allowForms])
/// ```
public enum Permission: String {

/// Permits downloads
case allowDownloads = "allow-downloads"

/// Permits form submissions within the content
case allowForms = "allow-forms"

/// Permits to open modals
case allowModals = "allow-modals"

/// Permits to lock the screen orientation
case allowOrientationLock = "allow-orientation-lock"

/// Permits the use of the pointer lock API
case allowPointerLock = "allow-pointer-lock"

/// Permits to open popups
case allowPopups = "allow-popups"

/// Permits popups to open new windows without inheriting the sandboxing
case allowPopupsToEscapeSandbox = "allow-popups-to-escape-sandbox"

/// Permits to start a presentation session
case allowPresentation = "allow-presentation"

/// Permits the content to be treated as being from the same origin
case allowSameOrigin = "allow-same-origin"

/// Permits script execution
case allowScripts = "allow-scripts"

/// Permits the content to navigate its top-level browsing context
case allowTopNavigation = "allow-top-navigation"

/// Permits the content to navigate its top-level browsing context, but only if initiated by user
case allowTopNavigationByUserActivation = "allow-top-navigation-by-user-activation"
}
}
14 changes: 13 additions & 1 deletion Tests/HTMLKitTests/AttributesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,14 @@ final class AttributesTests: XCTestCase {
return self.mutate(sandbox: "sandbox")
}

func sandbox(_ value: Values.Permission) -> Tag {
return self.mutate(sandbox: value.rawValue)
}

func sandbox(_ values: OrderedSet<Values.Permission>) -> Tag {
return self.mutate(sandbox: values.map { $0.rawValue }.joined(separator: " "))
}

func scope(_ value: Values.Scope) -> Tag {
return self.mutate(scope: value.rawValue)
}
Expand Down Expand Up @@ -1834,11 +1842,15 @@ final class AttributesTests: XCTestCase {

let view = TestView {
Tag {}.sandbox()
Tag {}.sandbox(.allowDownloads)
Tag {}.sandbox([.allowDownloads, .allowForms])
}

XCTAssertEqual(try renderer.render(view: view),
"""
<tag sandbox="sandbox"></tag>
<tag sandbox="sandbox"></tag>\
<tag sandbox="allow-downloads"></tag>\
<tag sandbox="allow-downloads allow-forms"></tag>
"""
)
}
Expand Down

0 comments on commit 44b4722

Please sign in to comment.