diff --git a/Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift b/Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift index 84382bf1..c33bf45c 100644 --- a/Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift +++ b/Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift @@ -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 - /// + /// ```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) -> 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) } } diff --git a/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift b/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift index 8e72e497..b7278831 100644 --- a/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift +++ b/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift @@ -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) -> Form { + return mutate(autocomplete: values.map { $0.rawValue }.joined(separator: " ")) } public func encoding(_ value: Values.Encoding) -> Form { diff --git a/Sources/HTMLKit/Abstraction/Elements/FormElements.swift b/Sources/HTMLKit/Abstraction/Elements/FormElements.swift index fd830dec..46e79e2a 100644 --- a/Sources/HTMLKit/Abstraction/Elements/FormElements.swift +++ b/Sources/HTMLKit/Abstraction/Elements/FormElements.swift @@ -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) -> 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) -> 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) -> TextArea { + return mutate(autocomplete: values.map { $0.rawValue }.joined(separator: " ")) } public func columns(_ size: Int) -> TextArea { diff --git a/Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift b/Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift index f9277b0d..6657f9eb 100644 --- a/Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift +++ b/Sources/HTMLKit/Abstraction/Tokens/ValueTokens.swift @@ -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" + } } diff --git a/Sources/HTMLKit/Framework/Rendering/Features.swift b/Sources/HTMLKit/Framework/Rendering/Features.swift index 780ea9e2..fc40de09 100644 --- a/Sources/HTMLKit/Framework/Rendering/Features.swift +++ b/Sources/HTMLKit/Framework/Rendering/Features.swift @@ -1,5 +1,5 @@ /// An option set of features. -public struct Features: OptionSet { +public struct Features: Swift.OptionSet { public var rawValue: Int diff --git a/Tests/HTMLKitTests/AttributesTests.swift b/Tests/HTMLKitTests/AttributesTests.swift index 5dea41a1..49b4c143 100644 --- a/Tests/HTMLKitTests/AttributesTests.swift +++ b/Tests/HTMLKitTests/AttributesTests.swift @@ -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) -> 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), """ - + \ + \ + \ + """ ) }