Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the sandbox modifier accept an enum #167

Merged
merged 2 commits into from
Dec 31, 2024
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
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
Loading