From 65725c89fbaa3e2e9ecc631910edc2f1edfe5965 Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 14 Dec 2024 17:26:18 -0500 Subject: [PATCH 1/2] Adds new alt attribute to produce alt text for images --- Sources/Elementary/HtmlAttributes.swift | 6 +++ .../AttributeRenderingTests.swift | 49 ++++++++++++------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Sources/Elementary/HtmlAttributes.swift b/Sources/Elementary/HtmlAttributes.swift index 18a2e00..32ff5b7 100644 --- a/Sources/Elementary/HtmlAttributes.swift +++ b/Sources/Elementary/HtmlAttributes.swift @@ -357,6 +357,12 @@ public extension HTMLAttributeValue { } } +public extension HTMLAttribute where Tag == HTMLTag.img { + static func alt(_ value: String) -> Self { + HTMLAttribute(name: "alt", value: value) + } +} + public extension HTMLAttribute where Tag: HTMLTrait.Attributes.autocomplete { static func autocomplete(_ value: HTMLAttributeValue.AutoComplete) -> Self { HTMLAttribute(name: "autocomplete", value: value.rawValue) diff --git a/Tests/ElementaryTests/AttributeRenderingTests.swift b/Tests/ElementaryTests/AttributeRenderingTests.swift index af4946d..5f9451b 100644 --- a/Tests/ElementaryTests/AttributeRenderingTests.swift +++ b/Tests/ElementaryTests/AttributeRenderingTests.swift @@ -8,56 +8,56 @@ final class AttributeRenderingTests: XCTestCase { #"

"# ) } - + func testRendersAttributes() async throws { try await HTMLAssertEqual( p(.id("foo"), .class("foo"), .hidden) {}, #""# ) } - + func testEscapesAttributeValues() async throws { try await HTMLAssertEqual( p(.id("foo\""), .class("&foo<>")) {}, #"

"# ) } - + func testRendersAppliedAttributes() async throws { try await HTMLAssertEqual( p {}.attributes(.id("foo"), .class("bar")), #"

"# ) } - + func testKeepsAttributeOrder() async throws { try await HTMLAssertEqual( p(.id("1")) { "yo" }.attributes(.class("2")).attributes(.lang("de-AT")), #"

yo

"# ) } - + func testAppliesConditionalAttributes() async throws { try await HTMLAssertEqual( img(.id("1")).attributes(.class("2"), .id("no"), when: false).attributes(.style("2"), when: true), #""# ) } - + func testMergesClassAndStyleByDefault() async throws { try await HTMLAssertEqual( p(.class("first")) {}.attributes(.class("second"), .style("style1")).attributes(.style("style2")), #"

"# ) } - + func testOverridesByDefault() async throws { try await HTMLAssertEqual( br(.id("foo")).attributes(.hidden, .id("bar")).attributes(.id("baz")), #""# ) } - + func testRespectsCustomMergeMode() async throws { try await HTMLAssertEqual( br(.id("1"), .data("bar", value: "baz")) @@ -67,67 +67,82 @@ final class AttributeRenderingTests: XCTestCase { #"
"# ) } - + func testRendersMouseEventAttribute() async throws { try await HTMLAssertEqual( p(.on(.click, "doIt()")) {}, #"

"# ) } - + func testRendersKeyboardEventAttribute() async throws { try await HTMLAssertEqual( p(.on(.keydown, "doIt()")) {}, #"

"# ) } - + func testRendersFormEventAttribute() async throws { try await HTMLAssertEqual( p(.on(.blur, "doIt()")) {}, #"

"# ) } - + func testRendersMetaCharset() async throws { try await HTMLAssertEqual( meta(.charset(.utf8)), #""# ) } - + func testRendersRequired() async throws { try await HTMLAssertEqual( input(.type(.text), .required), #""# ) } - + func testRendersAttributesArray() async throws { try await HTMLAssertEqual( p(attributes: [.id("foo"), .class("foo"), .hidden]) {}, #""# ) } - + func testRendersAttributesArrayOnVoidElement() async throws { try await HTMLAssertEqual( input(attributes: [.type(.text), .required]), #""# ) } - + func testRendersAppliedConditionalAttributesArray() async throws { try await HTMLAssertEqual( img(.id("1")).attributes(contentsOf: [.class("2"), .id("no")], when: false).attributes(contentsOf: [.style("2")], when: true), #""# ) } - + func testRendersWidthAndHeightAttributes() async throws { try await HTMLAssertEqual( img(.width(100), .height(200)), #""# ) } + + func testRendersAltForImg() async throws { + try await HTMLAssertEqual( + img(.src("/path/to/dog.jpeg"), .alt("A happy dog"), .width(200), .height(200)), + #"A happy dog"# + ) + } + + func testAltFailsForNonImg() async throws { +// Un-comment to confirm non-img elements won't take an `alt` attr +// try await HTMLAssertEqual( +// div(.alt("A happy dog")), +// #"
Date: Mon, 16 Dec 2024 09:49:35 +0100 Subject: [PATCH 2/2] removed non-test and formatting --- .../AttributeRenderingTests.swift | 44 ++++++++----------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/Tests/ElementaryTests/AttributeRenderingTests.swift b/Tests/ElementaryTests/AttributeRenderingTests.swift index 5f9451b..ac36d08 100644 --- a/Tests/ElementaryTests/AttributeRenderingTests.swift +++ b/Tests/ElementaryTests/AttributeRenderingTests.swift @@ -8,56 +8,56 @@ final class AttributeRenderingTests: XCTestCase { #"

"# ) } - + func testRendersAttributes() async throws { try await HTMLAssertEqual( p(.id("foo"), .class("foo"), .hidden) {}, #""# ) } - + func testEscapesAttributeValues() async throws { try await HTMLAssertEqual( p(.id("foo\""), .class("&foo<>")) {}, #"

"# ) } - + func testRendersAppliedAttributes() async throws { try await HTMLAssertEqual( p {}.attributes(.id("foo"), .class("bar")), #"

"# ) } - + func testKeepsAttributeOrder() async throws { try await HTMLAssertEqual( p(.id("1")) { "yo" }.attributes(.class("2")).attributes(.lang("de-AT")), #"

yo

"# ) } - + func testAppliesConditionalAttributes() async throws { try await HTMLAssertEqual( img(.id("1")).attributes(.class("2"), .id("no"), when: false).attributes(.style("2"), when: true), #""# ) } - + func testMergesClassAndStyleByDefault() async throws { try await HTMLAssertEqual( p(.class("first")) {}.attributes(.class("second"), .style("style1")).attributes(.style("style2")), #"

"# ) } - + func testOverridesByDefault() async throws { try await HTMLAssertEqual( br(.id("foo")).attributes(.hidden, .id("bar")).attributes(.id("baz")), #""# ) } - + func testRespectsCustomMergeMode() async throws { try await HTMLAssertEqual( br(.id("1"), .data("bar", value: "baz")) @@ -67,82 +67,74 @@ final class AttributeRenderingTests: XCTestCase { #"
"# ) } - + func testRendersMouseEventAttribute() async throws { try await HTMLAssertEqual( p(.on(.click, "doIt()")) {}, #"

"# ) } - + func testRendersKeyboardEventAttribute() async throws { try await HTMLAssertEqual( p(.on(.keydown, "doIt()")) {}, #"

"# ) } - + func testRendersFormEventAttribute() async throws { try await HTMLAssertEqual( p(.on(.blur, "doIt()")) {}, #"

"# ) } - + func testRendersMetaCharset() async throws { try await HTMLAssertEqual( meta(.charset(.utf8)), #""# ) } - + func testRendersRequired() async throws { try await HTMLAssertEqual( input(.type(.text), .required), #""# ) } - + func testRendersAttributesArray() async throws { try await HTMLAssertEqual( p(attributes: [.id("foo"), .class("foo"), .hidden]) {}, #""# ) } - + func testRendersAttributesArrayOnVoidElement() async throws { try await HTMLAssertEqual( input(attributes: [.type(.text), .required]), #""# ) } - + func testRendersAppliedConditionalAttributesArray() async throws { try await HTMLAssertEqual( img(.id("1")).attributes(contentsOf: [.class("2"), .id("no")], when: false).attributes(contentsOf: [.style("2")], when: true), #""# ) } - + func testRendersWidthAndHeightAttributes() async throws { try await HTMLAssertEqual( img(.width(100), .height(200)), #""# ) } - + func testRendersAltForImg() async throws { try await HTMLAssertEqual( img(.src("/path/to/dog.jpeg"), .alt("A happy dog"), .width(200), .height(200)), #"A happy dog"# ) } - - func testAltFailsForNonImg() async throws { -// Un-comment to confirm non-img elements won't take an `alt` attr -// try await HTMLAssertEqual( -// div(.alt("A happy dog")), -// #"