@@ -31,39 +31,103 @@ public enum Translate: String {
3131 case no
3232}
3333
34+ private extension String {
3435
36+ /// turns a list of class values (separated by a space" into an array of strings
37+ var classArray : [ String ] {
38+ split ( separator: " " ) . map { String ( $0) }
39+ }
40+ }
41+
42+ private extension Array where Element == String {
43+
44+ var classString : String {
45+ filter { !$0. isEmpty } . joined ( separator: " " )
46+ }
47+ }
3548
3649public extension Tag {
3750
38- /// Specifies a shortcut key to activate/focus an element
39- func accesskey( _ value: Character ) -> Self {
40- attribute ( " accesskey " , String ( value) )
51+ // MARK: - class management
52+
53+ /// find an existing class attribute and return the value as an array of strings or an empty array
54+ private var classArray : [ String ] {
55+ node. attributes. first { $0. key == " class " } ? . value? . classArray ?? [ ]
4156 }
4257
4358 /// Specifies one classname for an element (refers to a class in a style sheet)
4459 func `class`( _ value: String ? , _ condition: Bool = true ) -> Self {
45- let values = value? . split ( separator: " " ) . map { String ( $0) } ?? [ ]
46- let existing = node. attributes. first { $0. key == " class " } ? . value? . split ( separator: " " ) . map { String ( $0) } ?? [ ]
47- let newValues = existing + values
48-
49- var newValue : String ? = nil
50- if !newValues. isEmpty {
51- newValue = newValues. joined ( separator: " " )
52- }
53- return attribute ( " class " , newValue, condition)
60+ attribute ( " class " , value, condition)
5461 }
5562
5663 /// Specifies multiple classnames for an element (refers to a class in a style sheet)
5764 func `class`( _ values: [ String ] , _ condition: Bool = true ) -> Self {
5865 /// @NOTE: explicit true flag is needed, otherwise Swift won't know which function to call...
59- `class` ( values. filter { !$0 . isEmpty } . joined ( separator : " " ) , condition)
66+ `class` ( values. classString , condition)
6067 }
6168
6269 /// Specifies multiple classnames for an element (refers to a class in a style sheet)
6370 func `class`( _ values: String ... ) -> Self {
6471 `class` ( values)
6572 }
6673
74+ /// Adds a single value to the class list if the condition is true
75+ ///
76+ /// Note: If the value is empty or nil it won't be added to the list
77+ ///
78+ func `class`( add value: String ? , _ condition: Bool = true ) -> Self {
79+ guard let value = value else {
80+ return self
81+ }
82+ return `class` ( add: [ value] , condition)
83+ }
84+
85+ /// Adds an array of values to the class list if the condition is true
86+ ///
87+ /// Note: If the value is empty it won't be added to the list
88+ ///
89+ func `class`( add values: [ String ] , _ condition: Bool = true ) -> Self {
90+ let newValues = classArray + values. filter { !$0. isEmpty }
91+
92+ var newValue : String ? = nil
93+ if !newValues. isEmpty {
94+ newValue = newValues. classString
95+ }
96+ return `class` ( newValue, condition)
97+ }
98+
99+ /// Removes a given class values if the condition is true
100+ func `class`( remove value: String ? , _ condition: Bool = true ) -> Self {
101+ guard let value = value else {
102+ return self
103+ }
104+ return `class` ( remove: [ value] , condition)
105+ }
106+
107+ /// Removes an array of class values if the condition is true
108+ func `class`( remove values: [ String ] , _ condition: Bool = true ) -> Self {
109+ let newClasses = classArray. filter { !values. contains ( $0) }
110+ return `class` ( newClasses, condition)
111+ }
112+
113+ /// toggles a single class value
114+ func `class`( toggle value: String ? , _ condition: Bool = true ) -> Self {
115+ guard let value = value else {
116+ return self
117+ }
118+ if classArray. contains ( value) {
119+ return `class` ( remove: value, condition)
120+ }
121+ return `class` ( add: value, condition)
122+ }
123+
124+ // MARK: - other global attributes
125+
126+ /// Specifies a shortcut key to activate/focus an element
127+ func accesskey( _ value: Character ) -> Self {
128+ attribute ( " accesskey " , String ( value) )
129+ }
130+
67131 /// Specifies whether the content of an element is editable or not
68132 func contenteditable( _ value: Bool ) -> Self {
69133 attribute ( " contenteditable " , String ( value) )
0 commit comments