diff --git a/Sources/HTMLKit/Abstraction/Attributes/VectorAttributes.swift b/Sources/HTMLKit/Abstraction/Attributes/VectorAttributes.swift
index 5b3739bb..7b6e5956 100644
--- a/Sources/HTMLKit/Abstraction/Attributes/VectorAttributes.swift
+++ b/Sources/HTMLKit/Abstraction/Attributes/VectorAttributes.swift
@@ -256,13 +256,47 @@ public protocol PositionPointAttribute: Attribute {
/// Vector {
/// Rectangle {
/// }
- /// .positionPoint((50, 50))
+ /// .position(x: 50, y: 50)
/// }
/// ```
- /// - Parameter point: The coodinates to position the shape.
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to position the shape.
+ /// - y: The vertical coordinate to position the shape
///
/// - Returns: The element
- func positionPoint(_ point: (Int, Int)) -> Self
+ func position(x: Int, y: Int) -> Self
+
+ /// Set the position of the shape.
+ ///
+ /// ```Swift
+ /// Vector {
+ /// Rectangle {
+ /// }
+ /// .position(x: 50.0, y: 50.0)
+ /// }
+ /// ```
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to position the shape.
+ /// - y: The vertical coordinate to position the shape
+ ///
+ /// - Returns: The element
+ func position(x: Double, y: Double) -> Self
+
+ /// Set the position of the shape.
+ ///
+ /// ```Swift
+ /// Vector {
+ /// Rectangle {
+ /// }
+ /// .position(UnitPoint(x: 50, y: 50))
+ /// }
+ /// ```
+ /// - Parameter point: The coordinates to position the shape.
+ ///
+ /// - Returns: The element
+ func position(_ point: UnitPoint) -> Self
}
extension PositionPointAttribute where Self: ContentNode {
@@ -283,6 +317,14 @@ extension PositionPointAttribute where Self: ContentNode {
return .init(attributes: attributes, content: content)
}
+
+ internal func mutate(x value: String) -> Self {
+ return self.mutate(key: "x", value: value)
+ }
+
+ internal func mutate(y value: String) -> Self {
+ return self.mutate(key: "y", value: value)
+ }
}
/// A type that provides the `radiusPoint` modifier.
@@ -295,13 +337,47 @@ public protocol RadiusPointAttribute: Attribute {
/// Vector {
/// Rectangle {
/// }
- /// .radiusPoint((10, 10))
+ /// .radius(x: 50, y: 50)
/// }
/// ```
- /// - Parameter point: The radius to apply to all corners.
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to round off corner.
+ /// - y: The vertical coordinate to round off corner.
+ ///
+ /// - Returns: The element
+ func radius(x: Int, y: Int) -> Self
+
+ /// Apply a corner radius to the shape.
+ ///
+ /// ```swift
+ /// Vector {
+ /// Rectangle {
+ /// }
+ /// .radius(x: 50, y: 50)
+ /// }
+ /// ```
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to round off corner.
+ /// - y: The vertical coordinate to round off corner.
///
/// - Returns: The element
- func radiusPoint(_ point: (Int, Int)) -> Self
+ func radius(x: Double, y: Double) -> Self
+
+ /// Apply a corner radius to the shape.
+ ///
+ /// ```swift
+ /// Vector {
+ /// Rectangle {
+ /// }
+ /// .radius(UnitPoint: (x: 50, y: 50))
+ /// }
+ /// ```
+ /// - Parameter point: The radius to round off corners.
+ ///
+ /// - Returns: The element
+ func radius(_ point: UnitPoint) -> Self
}
extension RadiusPointAttribute where Self: ContentNode {
@@ -322,6 +398,14 @@ extension RadiusPointAttribute where Self: ContentNode {
return .init(attributes: attributes, content: content)
}
+
+ internal func mutate(rx value: String) -> Self {
+ return self.mutate(key: "rx", value: value)
+ }
+
+ internal func mutate(ry value: String) -> Self {
+ return self.mutate(key: "ry", value: value)
+ }
}
/// A type that provides the `centerPoint` modifier.
@@ -334,13 +418,49 @@ public protocol CenterPointAttribute: Attribute {
/// Vector {
/// Circle {
/// }
- /// .centerPoint((50, 50))
+ /// .center(x: 50, y: 50)
+ /// }
+ /// ```
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to use as the center.
+ /// - y: The vertical coordinate to use as the center.
+ ///
+ /// - Returns: The element
+
+ func center(x: Int, y: Int) -> Self
+
+ /// Set the center point of the shape.
+ ///
+ /// ```swift
+ /// Vector {
+ /// Circle {
+ /// }
+ /// .center(x: 50.0, y: 50.0)
+ /// }
+ /// ```
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to use as the center.
+ /// - y: The vertical coordinate to use as the center.
+ ///
+ /// - Returns: The element
+ func center(x: Double, y: Double) -> Self
+
+
+ /// Set the center point of the shape.
+ ///
+ /// ```swift
+ /// Vector {
+ /// Circle {
+ /// }
+ /// .center(UnitPoint(x: 50, y: 50))
/// }
/// ```
/// - Parameter point: The coordinates to use as the center.
///
/// - Returns: The element
- func centerPoint(_ point: (Int, Int)) -> Self
+ func center(_ point: UnitPoint) -> Self
}
extension CenterPointAttribute where Self: ContentNode {
@@ -361,6 +481,14 @@ extension CenterPointAttribute where Self: ContentNode {
return .init(attributes: attributes, content: content)
}
+
+ internal func mutate(cx value: String) -> Self {
+ return self.mutate(key: "cx", value: value)
+ }
+
+ internal func mutate(cy value: String) -> Self {
+ return self.mutate(key: "cy", value: value)
+ }
}
/// A type that provides the `viewBox` modifier.
@@ -368,17 +496,38 @@ extension CenterPointAttribute where Self: ContentNode {
public protocol ViewBoxAttribute: Attribute {
/// Set the view box for the vector.
- ///
+ ///
/// ```swift
/// Vector {
/// }
- /// .viewBox("0 0 400 200")
+ /// .viewBox(x: 0, y: 0, width: 400, height: 200")
/// ```
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to use for the origin.
+ /// - y: The vertical coordinate to use for the origin.
+ /// - width: The width of the viewport
+ /// - height: The height of the viewport
+ ///
+ /// - Returns: The element
+ func viewBox(x: Int, y: Int, width: Int, height: Int) -> Self
+
+ /// Set the view box for the vector.
///
- /// - Parameter value: The bounds used to define the viewport.
- ///
+ /// ```swift
+ /// Vector {
+ /// }
+ /// .viewBox(x: 0.0, y: 0.0, width: 400.0, height: 200.0")
+ /// ```
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to use for the origin.
+ /// - y: The vertical coordinate to use for the origin.
+ /// - width: The width of the viewport
+ /// - height: The height of the viewport
+ ///
/// - Returns: The element
- func viewBox(_ value: String) -> Self
+ func viewBox(x: Double, y: Double, width: Double, height: Double) -> Self
}
extension ViewBoxAttribute where Self: ContentNode {
diff --git a/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift b/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift
index fe639c93..a285d160 100644
--- a/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift
+++ b/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift
@@ -22520,10 +22520,19 @@ extension Vector: GlobalVectorAttributes, WidthAttribute, HeightAttribute, ViewB
return self.mutate(style: value)
}
+ @available(*, deprecated, message: "Use the viewBox(x:y:width:height:) modifier instead.")
public func viewBox(_ value: String) -> Vector {
return self.mutate(viewbox: value)
}
+ public func viewBox(x: Int, y: Int, width: Int, height: Int) -> Vector {
+ return self.mutate(viewbox: "\(x) \(y) \(width) \(height)")
+ }
+
+ public func viewBox(x: Double, y: Double, width: Double, height: Double) -> Vector {
+ return self.mutate(viewbox: "\(x) \(y) \(width) \(height)")
+ }
+
public func fill(_ value: String) -> Vector {
return self.mutate(fill: value)
}
diff --git a/Sources/HTMLKit/Abstraction/Elements/VectorElements.swift b/Sources/HTMLKit/Abstraction/Elements/VectorElements.swift
index 05ee4324..6d2d67ec 100644
--- a/Sources/HTMLKit/Abstraction/Elements/VectorElements.swift
+++ b/Sources/HTMLKit/Abstraction/Elements/VectorElements.swift
@@ -87,10 +87,23 @@ extension Circle: GlobalVectorAttributes, CenterPointAttribute, RadiusAttribute
return self.mutate(strokewidth: size)
}
+ @available(*, deprecated, message: "Use the center(x:y:) modifier instead.")
public func centerPoint(_ point: (Int, Int)) -> Circle {
return self.mutate(centerpoint: point)
}
+ public func center(x: Int, y: Int) -> Circle {
+ return self.mutate(cx: "\(x)").mutate(cy: "\(y)")
+ }
+
+ public func center(x: Double, y: Double) -> Circle {
+ return self.mutate(cx: "\(x)").mutate(cy: "\(y)")
+ }
+
+ public func center(_ point: UnitPoint) -> Circle {
+ return self.mutate(cx: point.x).mutate(cy: point.y)
+ }
+
public func radius(_ size: Int) -> Circle {
return self.mutate(radius: size)
}
@@ -169,8 +182,8 @@ public struct Rectangle: ContentNode, VectorElement {
}
}
-extension Rectangle: GlobalVectorAttributes, WidthAttribute, HeightAttribute, RadiusPointAttribute {
-
+extension Rectangle: GlobalVectorAttributes, WidthAttribute, HeightAttribute, RadiusPointAttribute, PositionPointAttribute {
+
public func id(_ value: String) -> Rectangle {
return self.mutate(id: value)
}
@@ -199,10 +212,40 @@ extension Rectangle: GlobalVectorAttributes, WidthAttribute, HeightAttribute, Ra
return self.mutate(strokewidth: size)
}
+ @available(*, deprecated, message: "Use the radius(x:y:) modifier instead.")
public func radiusPoint(_ point: (Int, Int)) -> Rectangle {
return self.mutate(radiuspoint: point)
}
+ public func radius(x: Int, y: Int) -> Rectangle {
+ return self.mutate(rx: "\(x)").mutate(ry: "\(y)")
+ }
+
+ public func radius(x: Double, y: Double) -> Rectangle {
+ return self.mutate(rx: "\(x)").mutate(ry: "\(y)")
+ }
+
+ public func radius(_ point: UnitPoint) -> Rectangle {
+ return self.mutate(rx: point.x).mutate(ry: point.y)
+ }
+
+ @available(*, deprecated, message: "Use the position(x:y:) modifier instead.")
+ public func positionPoint(_ point: (Int, Int)) -> Rectangle {
+ return self.mutate(positionpoint: point)
+ }
+
+ public func position(x: Int, y: Int) -> Rectangle {
+ return self.mutate(x: "\(x)").mutate(y: "\(y)")
+ }
+
+ public func position(x: Double, y: Double) -> Rectangle {
+ return self.mutate(x: "\(x)").mutate(y: "\(y)")
+ }
+
+ public func position(_ point: UnitPoint) -> Rectangle {
+ return self.mutate(x: point.x).mutate(y: point.y)
+ }
+
public func width(_ size: Int) -> Rectangle {
return self.mutate(width: size)
}
@@ -315,14 +358,40 @@ extension Ellipse: GlobalVectorAttributes, CenterPointAttribute, RadiusPointAttr
return self.mutate(strokewidth: size)
}
+ @available(*, deprecated, message: "Use the center(x:y:) modifier instead.")
public func centerPoint(_ point: (Int, Int)) -> Ellipse {
return self.mutate(centerpoint: point)
}
+ public func center(x: Int, y: Int) -> Ellipse {
+ return self.mutate(cx: "\(x)").mutate(cy: "\(y)")
+ }
+
+ public func center(x: Double, y: Double) -> Ellipse {
+ return self.mutate(cx: "\(x)").mutate(cy: "\(y)")
+ }
+
+ public func center(_ point: UnitPoint) -> Ellipse {
+ return self.mutate(cx: point.x).mutate(cy: point.y)
+ }
+
+ @available(*, deprecated, message: "Use the radius(x:y:) modifier instead.")
public func radiusPoint(_ point: (Int, Int)) -> Ellipse {
return self.mutate(radiuspoint: point)
}
+ public func radius(x: Int, y: Int) -> Ellipse {
+ return self.mutate(rx: "\(x)").mutate(ry: "\(y)")
+ }
+
+ public func radius(x: Double, y: Double) -> Ellipse {
+ return self.mutate(rx: "\(x)").mutate(ry: "\(y)")
+ }
+
+ public func radius(_ point: UnitPoint) -> Ellipse {
+ return self.mutate(rx: point.x).mutate(ry: point.y)
+ }
+
public func fillOpacity(_ value: Double) -> Ellipse {
return self.mutate(fillopacity: value)
}
@@ -926,7 +995,7 @@ public struct Use: ContentNode, VectorElement {
}
}
-extension Use: GlobalVectorAttributes, ReferenceAttribute, WidthAttribute, HeightAttribute {
+extension Use: GlobalVectorAttributes, ReferenceAttribute, WidthAttribute, HeightAttribute, PositionPointAttribute {
public func id(_ value: String) -> Use {
return self.mutate(id: value)
@@ -940,6 +1009,23 @@ extension Use: GlobalVectorAttributes, ReferenceAttribute, WidthAttribute, Heigh
return self.mutate(href: value)
}
+ @available(*, deprecated, message: "Use the position(x:y:) modifier instead.")
+ public func positionPoint(_ point: (Int, Int)) -> Use {
+ return self.mutate(positionpoint: point)
+ }
+
+ public func position(x: Int, y: Int) -> Use {
+ return self.mutate(x: "\(x)").mutate(y: "\(y)")
+ }
+
+ public func position(x: Double, y: Double) -> Use {
+ return self.mutate(x: "\(x)").mutate(y: "\(y)")
+ }
+
+ public func position(_ point: UnitPoint) -> Use {
+ return self.mutate(x: point.x).mutate(y: point.y)
+ }
+
public func width(_ size: Int) -> Use {
return self.mutate(width: size)
}
diff --git a/Sources/HTMLKit/Abstraction/Types/UnitPoint.swift b/Sources/HTMLKit/Abstraction/Types/UnitPoint.swift
new file mode 100644
index 00000000..349b4c84
--- /dev/null
+++ b/Sources/HTMLKit/Abstraction/Types/UnitPoint.swift
@@ -0,0 +1,58 @@
+public struct UnitPoint {
+
+ /// A enumeration of potential point formats
+ public enum PointFormat {
+
+ /// Indicates an absolute value.
+ case absolute
+
+ /// Indicates an relative value.
+ case relative
+ }
+
+ /// The horizontal position of the point
+ internal var x: String
+
+ /// The vertical position of the point
+ internal var y: String
+
+ /// Create a point.
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to place the point.
+ /// - y: The vertical coordinate to place the point.
+ /// - format: Whether the coordinates should be relative.
+ public init(x: Double, y: Double, format: PointFormat = .absolute) {
+
+ if case format = .relative {
+
+ self.x = "\(x)%"
+ self.y = "\(y)%"
+
+ } else {
+
+ self.x = "\(x)"
+ self.y = "\(y)"
+ }
+ }
+
+ /// Create a point.
+ ///
+ /// - Parameters:
+ /// - x: The horizontal coordinate to place the point.
+ /// - y: The vertical coordinate to place the point.
+ /// - format: Whether the coordinates should be relative.
+ public init(x: Int, y: Int, format: PointFormat = .absolute) {
+
+ if case format = .relative {
+
+ self.x = "\(x)%"
+ self.y = "\(y)%"
+
+ } else {
+
+ self.x = "\(x)"
+ self.y = "\(y)"
+ }
+ }
+}
diff --git a/Tests/HTMLKitTests/AttributesTests.swift b/Tests/HTMLKitTests/AttributesTests.swift
index 8d273769..053bab59 100644
--- a/Tests/HTMLKitTests/AttributesTests.swift
+++ b/Tests/HTMLKitTests/AttributesTests.swift
@@ -619,18 +619,62 @@ final class AttributesTests: XCTestCase {
return self.mutate(positionpoint: point)
}
+ func position(x: Int, y: Int) -> Tag {
+ return self.mutate(x: "\(x)").mutate(y: "\(y)")
+ }
+
+ func position(x: Double, y: Double) -> Tag {
+ return self.mutate(x: "\(x)").mutate(y: "\(y)")
+ }
+
+ func position(_ point: UnitPoint) -> Tag {
+ return self.mutate(x: point.x).mutate(y: point.y)
+ }
+
func radiusPoint(_ point: (Int, Int)) -> Tag {
return self.mutate(radiuspoint: point)
}
+ func radius(x: Int, y: Int) -> Tag {
+ return self.mutate(rx: "\(x)").mutate(ry: "\(y)")
+ }
+
+ func radius(x: Double, y: Double) -> Tag {
+ return self.mutate(rx: "\(x)").mutate(ry: "\(y)")
+ }
+
+ func radius(_ point: HTMLKit.UnitPoint) -> Tag {
+ return self.mutate(rx: point.x).mutate(ry: point.y)
+ }
+
func centerPoint(_ point: (Int, Int)) -> Tag {
return self.mutate(centerpoint: point)
}
+ func center(x: Int, y: Int) -> Tag {
+ return self.mutate(cx: "\(x)").mutate(cy: "\(y)")
+ }
+
+ func center(x: Double, y: Double) -> Tag {
+ return self.mutate(cx: "\(x)").mutate(cy: "\(y)")
+ }
+
+ func center(_ point: UnitPoint) -> Tag {
+ return self.mutate(cx: point.x).mutate(cy: point.y)
+ }
+
func viewBox(_ value: String) -> Tag {
return self.mutate(viewbox: value)
}
+ func viewBox(x: Int, y: Int, width: Int, height: Int) -> Tag {
+ return self.mutate(viewbox: "\(x) \(y) \(width) \(height)")
+ }
+
+ func viewBox(x: Double, y: Double, width: Double, height: Double) -> Tag {
+ return self.mutate(viewbox: "\(x) \(y) \(width) \(height)")
+ }
+
func namespace(_ value: String) -> Tag {
return self.mutate(namespace: value)
}
@@ -2891,15 +2935,21 @@ final class AttributesTests: XCTestCase {
)
}
- func testPositionPointAttribute() throws {
+ func testPositionAttribute() throws {
let view = TestView {
- Tag {}.positionPoint((10,10))
+ Tag {}.position(x: 50, y: 50)
+ Tag {}.position(x: 50.0, y: 50.0)
+ Tag {}.position(UnitPoint(x: 50.0, y: 50.0))
+ Tag {}.position(UnitPoint(x: 50, y: 50, format: .relative))
}
XCTAssertEqual(try renderer.render(view: view),
"""
-
+ \
+ \
+ \
+
"""
)
}
@@ -2907,12 +2957,18 @@ final class AttributesTests: XCTestCase {
func testRadiusPointAttribute() throws {
let view = TestView {
- Tag {}.radiusPoint((10,10))
+ Tag {}.radius(x: 10, y: 10)
+ Tag {}.radius(x: 10.0, y: 10.0)
+ Tag {}.radius(UnitPoint(x: 10.0, y: 10.0))
+ Tag {}.radius(UnitPoint(x: 10, y: 10, format: .relative))
}
XCTAssertEqual(try renderer.render(view: view),
"""
-
+ \
+ \
+ \
+
"""
)
}
@@ -2920,12 +2976,18 @@ final class AttributesTests: XCTestCase {
func testCenterPointAttribute() throws {
let view = TestView {
- Tag {}.centerPoint((10,10))
+ Tag {}.center(x: 10, y: 10)
+ Tag {}.center(x: 10.0, y: 10.0)
+ Tag {}.center(UnitPoint(x: 10.0, y: 10.0))
+ Tag {}.center(UnitPoint(x: 10, y: 10, format: .relative))
}
XCTAssertEqual(try renderer.render(view: view),
"""
-
+ \
+ \
+ \
+
"""
)
}
@@ -2933,12 +2995,14 @@ final class AttributesTests: XCTestCase {
func testViewBoxAttribute() throws {
let view = TestView {
- Tag {}.viewBox("0 0 100 100")
+ Tag {}.viewBox(x: 0, y: 0, width: 100, height: 100)
+ Tag {}.viewBox(x: 0, y: 0, width: 100.0, height: 100.0)
}
XCTAssertEqual(try renderer.render(view: view),
"""
-
+ \
+
"""
)
}