getgrit / gritql

GritQL is a query language for searching, linting, and modifying code.
https://docs.grit.io/
MIT License
2.98k stars 70 forks source link

Bug | angular self closing tags with *ngIf #67

Closed scr2em closed 6 months ago

scr2em commented 6 months ago

Hi,

I want to try GritQL to transform all possible elements to be self closed. I've checked https://app.grit.io/studio?preset=prefer_self_closing_tag_jsx&key=OR1LvWpzVk9vLiS6tgCZ9

but it seems like it's stripping *, any advice ?

     <ion-spinner *ngIf="isLoading" color="white"></ion-spinner>
image
morgante commented 6 months ago

Thanks for the report. The problem is this isn't actually valid JSX according to our parser: (ngIf= isn't valid). Do you have more context on the file you're trying to rewrite? A full file would help - I'm guessing this actually needs to be parsed with an HTML parser.

morgante commented 6 months ago

Here's a workaround that avoids looking at the props directly:

engine marzano(0.1)
language js

// The 'pattern' keyword is used to define custom named patterns at the top of this Grit snippet.
// We use separate patterns for matching different groups of html tags to aid readability.
pattern html_headings() { or { "h1" , "h2" , "h3" , "h4" , "h5" , "h6", "title" } }
pattern html_containers() { or { "div" , "section" , "article" , "nav" , "main" , "aside" , "footer" , "header" , "hgroup" } }
pattern html_block_text() { or { "address" , "blockquote" , "dl" , "dt" , "dd" , "ul" , "ol" , "li" , "figcaption" , "figure" , "p" , "pre" } }
pattern html_inline_text() { or { "a" , "b" , "span" , "abbr" , "bdi" , "bdo" , "cite" , "code" , "data" , "dfn" , "em" , "i" , "kbd" , "mark" , "q" , "ruby" , "rp" , "rt" , "rtc" , "s" , "samp" , "small" , "strong" , "sub" , "sup" , "time" , "u" , "var" , "small" , "del" , "ins" } }
pattern html_tables() { or { "table" , "tbody" , "thead" , "tfoot" , "tr" , "th" , "td" , "caption" , "optgroup" } }
pattern html_forms() { or { "form" , "button" , "label" , "fieldset" , "legend" , "select" , "datalist" , "option" , "textarea" , "progress" , "output" , "meter" } }
pattern html_web_components() { or { "content" , "element" , "shadow" , "slot" , "template" } }
pattern html_interactive() { or { "dialog" , "details" , "summary" , "menu" , "menuitem" } }
// Finally, the pattern HTMLTagsWithPair() is defined as the disjunction of all the above defined patterns
pattern html_tags_pair() { or { html_headings() , html_containers() , html_block_text() , html_inline_text() , html_tables() , html_forms() , html_web_components(), html_interactive() } }

jsx_element($children, $open_tag)
where {
    $open_tag <: jsx_opening_element($name),
    $open_tag <: r"(.+)>"($stuff),
    $children <: r"\s*",
    // $name must NOT match one of the html_tags_pair defined at the top of the file
    $name <: not html_tags_pair()
} => `$stuff />`

Playground: https://app.grit.io/studio?preset=prefer_self_closing_tag_jsx&key=OR1LvWpzVk9vLiS6tgCZ9

scr2em commented 6 months ago

@morgante it's an html file in an angular application

<div class="flex" (click)="handleClick()">
    <ion-icon *ngIf="!isLoading" name="search-outline" color="white"></ion-icon>
    <ion-spinner *ngIf="isLoading" color="white"></ion-spinner>
</div>

in angular, we can use *ngIf, *ngFor and *ngSwitch. it's also valid as [ngIf]= https://angular.io/api/common/NgIf

Playground: https://app.grit.io/studio?preset=prefer_self_closing_tag_jsx&key=OR1LvWpzVk9vLiS6tgCZ9

morgante commented 6 months ago

Got it. We don't support HTML today (only JSX): https://github.com/getgrit/gritql/issues/68

It is close enough that with error recovery we can do some things, but a proper parser will be needed to make it reliable.

scr2em commented 6 months ago

@morgante Thanks, I'll watch #68

morgante commented 6 months ago

@scr2em Did you try the workaround I pasted? It should work, at least for the case you shared.

scr2em commented 6 months ago

@morgante Yes, It worked great. I found that there is another syntax in the repo:

 <app-dialog #ref> </app-dialog>

and it was able to transform it correctly too.

I really appreciate your help. I fell in love with GritQL <3