Skip to content

Commit

Permalink
Make Node.div API based on a protocol
Browse files Browse the repository at this point in the history
Base the `Node.div` API on a new `HTMLDividableContext` protocol,
which enables that API to be shared between `HTML.BodyContext`
and `HTML.DescriptionListContext`. While this does come with a minor
downside of now requiring an explicit context whenever a `div` node
is created as a stand-alone value (when using `Node.div` directly, without
defining any child nodes within it), in practice that should be very rare, as
`div` nodes are most likely placed within a known context (such as within
a `body` node, or another node that inherits `HTML.BodyContext` from its
parent).
  • Loading branch information
JohnSundell committed Apr 7, 2023
1 parent e1e9270 commit 47f5df2
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 22 deletions.
6 changes: 4 additions & 2 deletions Sources/Plot/API/HTML.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public extension HTML {
/// The context within an HTML document's `<head>` element.
enum HeadContext: HTMLContext, HTMLScriptableContext {}
/// The context within an HTML document's `<body>` element.
class BodyContext: HTMLStylableContext, HTMLScriptableContext, HTMLImageContainerContext {}
class BodyContext: HTMLStylableContext, HTMLScriptableContext, HTMLImageContainerContext, HTMLDividableContext {}
/// The context within an HTML `<a>` element.
final class AnchorContext: BodyContext, HTMLLinkableContext {}
/// The context within an HTML `<audio>` element.
Expand All @@ -99,7 +99,7 @@ public extension HTML {
/// The context within an HTML `<datalist>` element.
enum DataListContext: HTMLOptionListContext {}
/// The context within an HTML `<dl>` element.
enum DescriptionListContext: HTMLStylableContext {}
enum DescriptionListContext: HTMLStylableContext, HTMLDividableContext {}
/// The context within an HTML `<details>` element.
final class DetailsContext: BodyContext {}
/// The context within an HTML `<embed>` element.
Expand Down Expand Up @@ -153,6 +153,8 @@ public protocol HTMLContext {}
/// Context shared among all HTML elements that can have their dimensions
/// (width and height) specified through attributes, such as `<video>`.
public protocol HTMLDimensionContext: HTMLContext {}
/// Context shared among all HTML elements can be divided using `<div>` elements.
public protocol HTMLDividableContext: HTMLContext {}
/// Context shared among all HTML elements that can contain an `<img>` element.
public protocol HTMLImageContainerContext: HTMLContext {}
/// Context shared among all HTML elements that act as some form
Expand Down
2 changes: 1 addition & 1 deletion Sources/Plot/API/HTMLComponents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public enum ElementDefinitions {
/// Definition for the `<button>` element.
public enum Button: ElementDefinition { public static var wrapper = Node.button }
/// Definition for the `<div>` element.
public enum Div: ElementDefinition { public static var wrapper = Node.div }
public enum Div: ElementDefinition { public static var wrapper = Node<HTML.BodyContext>.div }
/// Definition for the `<fieldset>` element.
public enum FieldSet: ElementDefinition { public static var wrapper = Node.fieldset }
/// Definition for the `<footer>` element.
Expand Down
25 changes: 8 additions & 17 deletions Sources/Plot/API/HTMLElements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,6 @@ public extension Node where Context: HTML.BodyContext {
.element(named: "details", nodes: nodes)
}

/// Add a `<div>` HTML element within the current context.
/// - parameter nodes: The element's attributes and child elements.
static func div(_ nodes: Node<HTML.BodyContext>...) -> Node {
.element(named: "div", nodes: nodes)
}

/// Add a `<dl>` HTML element within the current context.
/// - parameter nodes: The element's attributes and child elements.
static func dl(_ nodes: Node<HTML.DescriptionListContext>...) -> Node {
Expand Down Expand Up @@ -432,17 +426,6 @@ public extension Node where Context == HTML.DescriptionListContext {
}
}

public extension Node where Context == HTML.DescriptionListContext {
// The `<div>` element wraps a group, that is part of a term-description group in a description list (`<dl>` element).
//
// This is allowed according to the HTML spec: // https://html.spec.whatwg.org/multipage/grouping-content.html#the-dl-element
//
/// - parameter nodes: The element's attributes and child elements (`<dl>` or `<dd>` elements).
static func div(_ nodes: Node<HTML.DescriptionListContext>...) -> Node {
.element(named: "div", nodes: nodes)
}
}

public extension Node where Context: HTMLOptionListContext {
/// Add an `<option>` HTML element within the current context.
/// - parameter nodes: The element's attributes.
Expand Down Expand Up @@ -534,3 +517,11 @@ public extension Node where Context: HTMLScriptableContext {
.element(named: "script", nodes: nodes)
}
}

public extension Node where Context: HTMLDividableContext {
/// Add a `<div>` HTML element within the current context.
/// - parameter nodes: The element's attributes and child elements.
static func div(_ nodes: Node<Context>...) -> Node {
.element(named: "div", nodes: nodes)
}
}
4 changes: 2 additions & 2 deletions Tests/PlotTests/HTMLComponentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ final class HTMLComponentTests: XCTestCase {
}

func testAddingClassToNode() {
let html = Node.div().class("hello").render()
XCTAssertEqual(html, #"<div class="hello"></div>"#)
let html = Node.div(.p()).class("hello").render()
XCTAssertEqual(html, #"<div class="hello"><p></p></div>"#)
}

func testEnvironmentValuesDoNotApplyToSiblings() {
Expand Down

0 comments on commit 47f5df2

Please sign in to comment.