patch 9.1.0551: filetype: htmlangular files are not properly detected

Problem:  filetype: htmlangular files are not properly detected
Solution: Use the new htmlangular filetype for angular files, because
          since angular v17, those are no longer valid HTML files.
          (Dennis van den Berg)

Since Angular 17, the new Control Flow Syntax is not valid HTML. This PR
adds a new filetype detection for the HTML templates of Angular.

It first checks the filename. The Angular convention is to use
*.component.html for the template. However, this is not mandatory.

If the filename does not match, it will check the contents of the file
if it contains:

  - One of the Control-Flow blocks: @if, @for, @switch, @defer
  - A structural directive: *ngIf, *ngFor, *ngSwitch, *ngTemplateOutlet
  - Builtin Angular elements: ng-template or ng-content
  - String interpolation: {{ something }}

This enables the Angular LSP to attach only to htmlangular filetypes, as
well as language parsers, such as tree-sitter.

closes: #15190

Signed-off-by: Dennis van den Berg <dennis.vandenberg@nedap.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Dennis van den Berg
2024-07-09 19:25:33 +02:00
committed by Christian Brabandt
parent 4a7a4a3675
commit 1ad194c0df
4 changed files with 69 additions and 3 deletions

View File

@ -402,14 +402,29 @@ export def FTharedoc()
endif
enddef
# Distinguish between HTML, XHTML and Django
# Distinguish between HTML, XHTML, Django and Angular
export def FThtml()
var n = 1
# Test if the filename follows the Angular component template convention
if expand('%:t') =~ '^.*\.component\.html$'
setf htmlangular
return
endif
while n < 40 && n <= line("$")
# Check for Angular
if getline(n) =~ '@\(if\|for\|defer\|switch\)\|\*\(ngIf\|ngFor\|ngSwitch\|ngTemplateOutlet\)\|ng-template\|ng-content\|{{.*}}'
setf htmlangular
return
endif
# Check for XHTML
if getline(n) =~ '\<DTD\s\+XHTML\s'
setf xhtml
return
endif
# Check for Django
if getline(n) =~ '{%\s*\(autoescape\|block\|comment\|csrf_token\|cycle\|debug\|extends\|filter\|firstof\|for\|if\|ifchanged\|include\|load\|lorem\|now\|query_string\|regroup\|resetcycle\|spaceless\|templatetag\|url\|verbatim\|widthratio\|with\)\>\|{#\s\+'
setf htmldjango
return

View File

@ -0,0 +1,12 @@
" Vim filetype plugin file
" Language: Angular HTML Template
" Maintainer: Dennis van den Berg <dennis@vdberg.dev>
" Last Change: 2024 Jul 8
" Only use this filetype plugin when no other was loaded.
if exists("b:did_ftplugin")
finish
endif
" Use HTML and Angular template ftplugins
runtime! ftplugin/html.vim

View File

@ -334,7 +334,8 @@ def s:GetFilenameChecks(): dict<list<string>>
hoon: ['file.hoon'],
hostconf: ['/etc/host.conf', 'any/etc/host.conf'],
hostsaccess: ['/etc/hosts.allow', '/etc/hosts.deny', 'any/etc/hosts.allow', 'any/etc/hosts.deny'],
html: ['file.html', 'file.htm', 'file.cshtml', 'file.component.html'],
html: ['file.html', 'file.htm', 'file.cshtml'],
htmlangular: ['file.component.html'],
htmlm4: ['file.html.m4'],
httest: ['file.htt', 'file.htb'],
hurl: ['file.hurl'],
@ -1046,7 +1047,8 @@ func Test_emptybuf_ftdetect()
call assert_equal('', &filetype)
filetype detect
call assert_equal('sh', &filetype)
close!
" close the swapfile
bw!
endfunc
" Test for ':filetype indent on' and ':filetype indent off' commands
@ -1570,6 +1572,41 @@ func Test_hook_file()
filetype off
endfunc
func Test_html_file()
filetype on
" HTML Angular
let content = ['@for (item of items; track item.name) {', ' <li> {{ item.name }}</li>', '} @empty {', ' <li> There are no items.</li>', '}']
call writefile(content, 'Xfile.html', 'D')
split Xfile.html
call assert_equal('htmlangular', &filetype)
bwipe!
" Django Template
let content = ['{% if foobar %}',
\ ' <ul>',
\ ' {% for question in list %}',
\ ' <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>',
\ ' {% endfor %}',
\ ' </ul>',
\ '{% else %}',
\ ' <p>No polls are available.</p>',
\ '{% endif %}']
call writefile(content, 'Xfile.html', 'D')
split Xfile.html
call assert_equal('htmldjango', &filetype)
bwipe!
" regular HTML
let content = ['<!DOCTYPE html>', '<html>', ' <head>Foobar</head>', ' <body>Content', ' </body>', '</html>']
call writefile(content, 'Xfile.html', 'D')
split Xfile.html
call assert_equal('html', &filetype)
bwipe!
filetype off
endfunc
func Test_m_file()
filetype on

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
551,
/**/
550,
/**/