@@ -88,11 +88,11 @@ private extension HTMLElement {
88
88
break
89
89
case " event " :
90
90
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 )
94
94
}
95
- value = literalValue
95
+ value = result . 0
96
96
} else {
97
97
unallowed_expression ( context: context, node: function. arguments. last!)
98
98
return [ ]
@@ -164,13 +164,13 @@ private extension HTMLElement {
164
164
165
165
static func parse_attribute( context: some MacroExpansionContext , elementType: HTMLElementType , key: String , argument: LabeledExprSyntax ) -> String ? {
166
166
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
170
170
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
174
174
}
175
175
}
176
176
func member( _ value: String ) -> String {
@@ -215,22 +215,13 @@ private extension HTMLElement {
215
215
if function. calledExpression. as ( DeclReferenceExprSyntax . self) ? . baseName. text == " StaticString " {
216
216
return ( function. arguments. first!. expression. stringLiteral!. string, . string)
217
217
}
218
- return ( " \\ ( \( function) ) " , . interpolation)
218
+ return ( " \( function) " , . interpolation)
219
219
}
220
220
}
221
221
if let member: MemberAccessExprSyntax = expression. memberAccess {
222
222
let decl : String = member. declName. baseName. text
223
223
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)
234
225
} else {
235
226
return ( HTMLElementAttribute . Extra. htmlValue ( enumName: enumName ( elementType: elementType, key: key) , for: decl) , . string)
236
227
}
@@ -268,18 +259,18 @@ private extension HTMLElement {
268
259
let interpolation : [ ExpressionSegmentSyntax ] = expression. stringLiteral? . segments. compactMap ( { $0. as ( ExpressionSegmentSyntax . self) } ) ?? [ ]
269
260
var remaining_interpolation : Int = interpolation. count
270
261
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)
272
263
}
273
264
if returnType == . interpolation || remaining_interpolation > 0 {
274
265
if !string. contains ( " \\ ( " ) {
275
266
string = " \\ ( " + string + " ) "
267
+ warn_interpolation ( context: context, node: expression)
276
268
}
277
269
returnType = . interpolation
278
- context. diagnose ( Diagnostic ( node: expression, message: DiagnosticMsg ( id: " unsafeInterpolation " , message: " Interpolation may introduce raw HTML. " , severity: . warning) ) )
279
270
}
280
271
return ( string, returnType)
281
272
}
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 {
283
274
let expression : ExprSyntax = expr. expressions. first!. expression
284
275
var string : String = " \( expr) "
285
276
if let stringLiteral: StringLiteralExprSyntax = expression. stringLiteral {
@@ -288,24 +279,39 @@ private extension HTMLElement {
288
279
remaining_interpolation = 0
289
280
string = segments. map ( { $0. as ( StringSegmentSyntax . self) !. content. text } ) . joined ( )
290
281
} else {
291
- var values : [ String ] = [ ]
282
+ string = " "
292
283
for segment in segments {
293
284
if let literal: String = segment. as ( StringSegmentSyntax . self) ? . content. text {
294
- values . append ( literal)
285
+ string += literal
295
286
} 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
+ }
297
295
} else {
298
- values. append ( " \( segment) " )
296
+ //string += "\\(\"\(segment)\".escapingHTML(escapeAttributes: true))"
297
+ warn_interpolation ( context: context, node: segment)
298
+ string += " \( segment) "
299
299
}
300
300
}
301
- string = values. joined ( )
302
301
}
303
302
} 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)
306
309
}
307
310
return string
308
311
}
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
+ }
309
315
}
310
316
311
317
enum LiteralReturnType {
0 commit comments