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 autocomplete modifier accept an enum #165

Merged
merged 4 commits into from
Dec 31, 2024
Merged
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
31 changes: 24 additions & 7 deletions Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift
Original file line number Diff line number Diff line change
@@ -171,28 +171,45 @@ extension AutocapitalizeAttribute where Self: EmptyNode {
}
}

/// The protocol provides the element with the autocomplete handler.
/// A type that provides the `autocomplete` modifier.
@_documentation(visibility: internal)
public protocol AutocompleteAttribute: Attribute {

/// The function represents the html-attribute 'autocomplete'.
/// Specify an auto completion.
///
/// ```html
/// <tag autocomplete="" />
/// ```swift
/// Input()
/// .autocomplete(.off)
/// ```
///
/// - Parameter value: The value to be expected
///
/// - Returns: The element
func autocomplete(_ value: Values.Completion) -> Self

/// Specify an auto completion.
///
/// ```swift
/// Input()
/// .autocomplete([.organization, .organizationTitle])
/// ```
func hasCompletion(_ value: Bool) -> Self
///
/// - Parameter values: The values to be expected
///
/// - Returns: The element
func autocomplete(_ values: OrderedSet<Values.Completion>) -> Self
}

extension AutocompleteAttribute where Self: ContentNode {

internal func mutate(autocomplete value: Bool) -> Self {
internal func mutate(autocomplete value: String) -> Self {
return self.mutate(key: "autocomplete", value: value)
}
}

extension AutocompleteAttribute where Self: EmptyNode {

internal func mutate(autocomplete value: Bool) -> Self {
internal func mutate(autocomplete value: String) -> Self {
return self.mutate(key: "autocomplete", value: value)
}
}
16 changes: 15 additions & 1 deletion Sources/HTMLKit/Abstraction/Elements/BodyElements.swift
Original file line number Diff line number Diff line change
@@ -17816,8 +17816,22 @@ extension Form: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttributes, A
return mutate(action: value)
}

@available(*, deprecated, message: "The autocomplete attribute is actually a enum attribute. You should use autocomplete(_:) instead.")
public func hasCompletion(_ value: Bool) -> Form {
return mutate(autocomplete: value)

if value {
return mutate(autocomplete: "on")
}

return mutate(autocomplete: "off")
}

public func autocomplete(_ value: Values.Completion) -> Form {
return mutate(autocomplete: value.rawValue)
}

public func autocomplete(_ values: OrderedSet<Values.Completion>) -> Form {
return mutate(autocomplete: values.map { $0.rawValue }.joined(separator: " "))
}

public func encoding(_ value: Values.Encoding) -> Form {
48 changes: 45 additions & 3 deletions Sources/HTMLKit/Abstraction/Elements/FormElements.swift
Original file line number Diff line number Diff line change
@@ -181,8 +181,22 @@ extension Input: GlobalAttributes, GlobalEventAttributes, AcceptAttribute, Alter
return mutate(alternate: value)
}

@available(*, deprecated, message: "The autocomplete attribute is actually a enum attribute. You should use autocomplete(_:) instead.")
public func hasCompletion(_ value: Bool) -> Input {
return mutate(autocomplete: value)

if value {
return mutate(autocomplete: "on")
}

return mutate(autocomplete: "off")
}

public func autocomplete(_ value: Values.Completion) -> Input {
return mutate(autocomplete: value.rawValue)
}

public func autocomplete(_ values: OrderedSet<Values.Completion>) -> Input {
return mutate(autocomplete: values.map { $0.rawValue }.joined(separator: " "))
}

public func checked() -> Input {
@@ -806,8 +820,22 @@ extension Select: GlobalAttributes, GlobalEventAttributes, AutocompleteAttribute
return self
}

@available(*, deprecated, message: "The autocomplete attribute is actually a enum attribute. You should use autocomplete(_:) instead.")
public func hasCompletion(_ value: Bool) -> Select {
return mutate(autocomplete: value)

if value {
return mutate(autocomplete: "on")
}

return mutate(autocomplete: "off")
}

public func autocomplete(_ value: Values.Completion) -> Select {
return mutate(autocomplete: value.rawValue)
}

public func autocomplete(_ values: OrderedSet<Values.Completion>) -> Select {
return mutate(autocomplete: values.map { $0.rawValue }.joined(separator: " "))
}

public func disabled() -> Select {
@@ -1051,8 +1079,22 @@ extension TextArea: GlobalAttributes, GlobalEventAttributes, GlobalAriaAttribute
return self
}

@available(*, deprecated, message: "The autocomplete attribute is actually a enum attribute. You should use autocomplete(_:) instead.")
public func hasCompletion(_ value: Bool) -> TextArea {
return mutate(autocomplete: value)

if value {
return mutate(autocomplete: "on")
}

return mutate(autocomplete: "off")
}

public func autocomplete(_ value: Values.Completion) -> TextArea {
return mutate(autocomplete: value.rawValue)
}

public func autocomplete(_ values: OrderedSet<Values.Completion>) -> TextArea {
return mutate(autocomplete: values.map { $0.rawValue }.joined(separator: " "))
}

public func columns(_ size: Int) -> TextArea {
174 changes: 174 additions & 0 deletions Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@
If you about to add something to the file, stick to the official documentation to keep the code consistent.
*/

import Collections

/// A namespace for several types of attribute values.
public enum Values {

@@ -1014,4 +1016,176 @@ public enum Values {
/// Displays a keyboard optimized for URL input.
case url
}

/// A enumeration of potential completion settings
///
/// ```swift
/// Select {
/// }
/// .autocomplete([.organization, .organizationTitle])
/// ```
public enum Completion: String {

/// Enables completion
case on

/// Disables completion
case off

/// Expects a name
case name

/// Expects a prefix like Mr, Ms, Dr
case honorificPrefix = "honorific-prefix"

/// Expects the first name
case givenName = "given-name"

/// Expects a middle name
case additionalName = "additional-name"

/// Expects the last name
case familyName = "family-name"

/// Expects a degree
case honorificSuffix = "honorific-suffix"

/// Expects a screen name
case nickname

/// Expects a username
case username

/// Expects a new password
case newPassword = "new-password"

/// Expects the current password
case currentPassword = "current-password"

/// Expects a company name
case organization

/// Expects a job title
case organizationTitle = "organization-title"

/// Expects a one time code
case oneTimeCode = "one-time-code"

/// Expects a address
case streetAddress = "street-address"

/// Expects a address
case addressLine1 = "address-line1"

/// Expects a address
case addressLine2 = "address-line2"

/// Expects a address
case addressLine3 = "address-line3"

/// Expects a country code
case country = "country"

/// Expects the country name
case countryName = "country-name"

/// Expects a postal code
case postalCode = "postal-code"

/// Expects shipping information
case shipping

/// Expects billing information
case billing

/// Expects the full name for payment
case paymentName = "cc-name"

/// Expects the first name for payment
case paymentGivenName = "cc-given-name"

/// Expects the middle name for payment
case paymentAdditionalName = "cc-additional-name"

/// Expects the last name for payment
case paymentFamilyName = "cc-family-name"

/// Expects the credit card number for payment
case paymentNumber = "cc-number"

/// Expects the experiation date for payment
case paymentExpiry = "cc-expiry"

/// Expects the experiation month for payment
case paymentExpiryMonth = "cc-expiry-month"

/// Expects the experiation year for payment
case paymentExpiryYear = "cc-expiry-year"

/// Expects the credit security code
case paymentSecurityCode = "cc-csc"

/// Expects a payment type
case paymentType = "cc-type"

/// Expects a transaction currency
case transactionCurrency = "transaction-currency"

/// Expects the amount for payment
case transactionAmount = "transaction-amount"

/// Expects a perferred language
case language

/// Expects a birthday date
case birthday = "bday"

/// Expects the day detail of the birthday date
case birthdayDay = "bday-day"

/// Expects the month detail of the birthday date
case birthdayMonth = "bday-month"

/// Expects the year detail of the birthday date
case birthdayYear = "bday-year"

/// Expects a gender detail
case sex

/// Expects a photo
case photo

/// Expects a phone number
case phone = "tel"

/// Expects the country code of the phone number
case phoneCountryCode = "tel-country-code"

/// Expects a phone number without the country code
case phoneNational = "tel-national"

/// Expects the area code of the phone number
case phoneAreaCode = "tel-area-code"

/// Expects a phone number without the country and area code
case phoneLocal = "tel-local"

/// Expects the local prefix of the phone number
case phoneLocalPrefix = "tel-local-prefix"

/// Expects the local suffix of the phone number
case phoneLocalSuffix = "tel-local-suffix"

/// Phone internal extension code
case phoneExtension = "tel-extension"

/// Expects a url
case url

/// Expects an email address
case email

/// Expects a url for instant messaging
case messagingProtocol = "impp"
}
}
2 changes: 1 addition & 1 deletion Sources/HTMLKit/Framework/Rendering/Features.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// An option set of features.
public struct Features: OptionSet {
public struct Features: Swift.OptionSet {

public var rawValue: Int

18 changes: 14 additions & 4 deletions Tests/HTMLKitTests/AttributesTests.swift
Original file line number Diff line number Diff line change
@@ -158,8 +158,12 @@ final class AttributesTests: XCTestCase {
return self.mutate(async: "async")
}

func hasCompletion(_ value: Bool) -> Tag {
return self.mutate(autocomplete: value)
func autocomplete(_ value: Values.Completion) -> Tag {
return mutate(autocomplete: value.rawValue)
}

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

func autoplay() -> Tag {
@@ -1047,12 +1051,18 @@ final class AttributesTests: XCTestCase {
func testCompleteAttribute() throws {

let view = TestView {
Tag {}.hasCompletion(true)
Tag {}.autocomplete(.on)
Tag {}.autocomplete(.off)
Tag {}.autocomplete([.organization, .organizationTitle])
Tag {}.autocomplete([.birthday, .birthday])
}

XCTAssertEqual(try renderer.render(view: view),
"""
<tag autocomplete="true"></tag>
<tag autocomplete="on"></tag>\
<tag autocomplete="off"></tag>\
<tag autocomplete="organization organization-title"></tag>\
<tag autocomplete="bday"></tag>
"""
)
}