@@ -88,11 +88,11 @@ private extension HTMLElement {
8888 break
8989 case " event " :
9090 key = " on " + key_element. memberAccess!. declName. baseName. text
91- if var ( literalValue , returnType ) : ( String , LiteralReturnType ) = parse_literal_value ( context: context, elementType: elementType, key: key, argument: function. arguments. last!) {
92- if returnType == . string {
93- literalValue . escapeHTML ( escapeAttributes: true )
91+ if var result : ( String , LiteralReturnType ) = parse_literal_value ( context: context, elementType: elementType, key: key, argument: function. arguments. last!) {
92+ if result . 1 == . string {
93+ result . 0 . escapeHTML ( escapeAttributes: true )
9494 }
95- value = literalValue
95+ value = result . 0
9696 } else {
9797 unallowed_expression ( context: context, node: function. arguments. last!)
9898 return [ ]
@@ -164,13 +164,13 @@ private extension HTMLElement {
164164
165165 static func parse_attribute( context: some MacroExpansionContext , elementType: HTMLElementType , key: String , argument: LabeledExprSyntax ) -> String ? {
166166 let expression : ExprSyntax = argument. expression
167- if var ( string , returnType ) : ( String , LiteralReturnType ) = parse_literal_value ( context: context, elementType: elementType, key: key, argument: argument) {
168- switch returnType {
169- case . boolean: return string . elementsEqual ( " true " ) ? " " : nil
167+ if var result : ( String , LiteralReturnType ) = parse_literal_value ( context: context, elementType: elementType, key: key, argument: argument) {
168+ switch result . 1 {
169+ case . boolean: return result . 0 . elementsEqual ( " true " ) ? " " : nil
170170 case . string:
171- string . escapeHTML ( escapeAttributes: true )
172- return string
173- case . interpolation: return string
171+ result . 0 . escapeHTML ( escapeAttributes: true )
172+ return result . 0
173+ case . interpolation: return result . 0
174174 }
175175 }
176176 func member( _ value: String ) -> String {
@@ -215,22 +215,13 @@ private extension HTMLElement {
215215 if function. calledExpression. as ( DeclReferenceExprSyntax . self) ? . baseName. text == " StaticString " {
216216 return ( function. arguments. first!. expression. stringLiteral!. string, . string)
217217 }
218- return ( " \\ ( \( function) ) " , . interpolation)
218+ return ( " \( function) " , . interpolation)
219219 }
220220 }
221221 if let member: MemberAccessExprSyntax = expression. memberAccess {
222222 let decl : String = member. declName. baseName. text
223223 if let _: ExprSyntax = member. base {
224- /*if let integer:String = base.integerLiteral?.literal.text {
225- switch decl {
226- case "description":
227- return (integer, .integer)
228- default:
229- return (integer, .interpolation)
230- }
231- } else {*/
232- return ( " \\ ( \( member) ) " , . interpolation)
233- //}
224+ return ( " \( member) " , . interpolation)
234225 } else {
235226 return ( HTMLElementAttribute . Extra. htmlValue ( enumName: enumName ( elementType: elementType, key: key) , for: decl) , . string)
236227 }
@@ -268,18 +259,18 @@ private extension HTMLElement {
268259 let interpolation : [ ExpressionSegmentSyntax ] = expression. stringLiteral? . segments. compactMap ( { $0. as ( ExpressionSegmentSyntax . self) } ) ?? [ ]
269260 var remaining_interpolation : Int = interpolation. count
270261 for expr in interpolation {
271- string = flatten_interpolation ( remaining_interpolation: & remaining_interpolation, expr: expr)
262+ string = flatten_interpolation ( context : context , remaining_interpolation: & remaining_interpolation, expr: expr)
272263 }
273264 if returnType == . interpolation || remaining_interpolation > 0 {
274265 if !string. contains ( " \\ ( " ) {
275266 string = " \\ ( " + string + " ) "
267+ warn_interpolation ( context: context, node: expression)
276268 }
277269 returnType = . interpolation
278- context. diagnose ( Diagnostic ( node: expression, message: DiagnosticMsg ( id: " unsafeInterpolation " , message: " Interpolation may introduce raw HTML. " , severity: . warning) ) )
279270 }
280271 return ( string, returnType)
281272 }
282- static func flatten_interpolation( remaining_interpolation: inout Int , expr: ExpressionSegmentSyntax ) -> String {
273+ static func flatten_interpolation( context : some MacroExpansionContext , remaining_interpolation: inout Int , expr: ExpressionSegmentSyntax ) -> String {
283274 let expression : ExprSyntax = expr. expressions. first!. expression
284275 var string : String = " \( expr) "
285276 if let stringLiteral: StringLiteralExprSyntax = expression. stringLiteral {
@@ -288,24 +279,39 @@ private extension HTMLElement {
288279 remaining_interpolation = 0
289280 string = segments. map ( { $0. as ( StringSegmentSyntax . self) !. content. text } ) . joined ( )
290281 } else {
291- var values : [ String ] = [ ]
282+ string = " "
292283 for segment in segments {
293284 if let literal: String = segment. as ( StringSegmentSyntax . self) ? . content. text {
294- values . append ( literal)
285+ string += literal
295286 } else if let interpolation: ExpressionSegmentSyntax = segment. as ( ExpressionSegmentSyntax . self) {
296- values. append ( flatten_interpolation ( remaining_interpolation: & remaining_interpolation, expr: interpolation) )
287+ let flattened : String = flatten_interpolation ( context: context, remaining_interpolation: & remaining_interpolation, expr: interpolation)
288+ if " \( interpolation) " == flattened {
289+ //string += "\\(\"\(flattened)\".escapingHTML(escapeAttributes: true))"
290+ string += " \( flattened) "
291+ warn_interpolation ( context: context, node: interpolation)
292+ } else {
293+ string += flattened
294+ }
297295 } else {
298- values. append ( " \( segment) " )
296+ //string += "\\(\"\(segment)\".escapingHTML(escapeAttributes: true))"
297+ warn_interpolation ( context: context, node: segment)
298+ string += " \( segment) "
299299 }
300300 }
301- string = values. joined ( )
302301 }
303302 } else if let fix: String = expression. integerLiteral? . literal. text ?? expression. floatLiteral? . literal. text {
304- remaining_interpolation -= string. ranges ( of: " \( expr) " ) . count
305- string. replace ( " \( expr) " , with: fix)
303+ let target : String = " \( expr) "
304+ remaining_interpolation -= string. ranges ( of: target) . count
305+ string. replace ( target, with: fix)
306+ } else {
307+ //string = "\\(\"\(string)\".escapingHTML(escapeAttributes: true))"
308+ warn_interpolation ( context: context, node: expr)
306309 }
307310 return string
308311 }
312+ static func warn_interpolation( context: some MacroExpansionContext , node: some SyntaxProtocol ) {
313+ context. diagnose ( Diagnostic ( node: node, message: DiagnosticMsg ( id: " unsafeInterpolation " , message: " Interpolation may introduce raw HTML. " , severity: . warning) ) )
314+ }
309315}
310316
311317enum LiteralReturnType {
0 commit comments