Home > Blockchain >  Vim unexpectedly sources javascript indent filetype plugin on editing html files
Vim unexpectedly sources javascript indent filetype plugin on editing html files

Time:05-24

TL;DR: vim seems to be sourcing both indent/javascript.vim and indent/html.vim on editing html files; is this intentional or a bug? How can I make html files only source html.vim?


Recently I found out that vim seems to be using indent filetype plugins for both javascript and html on editing html files, and I've done some testing based on this behaviour on minimal vim configurations.

Here is my one-line .vimrc:

filetype plugin indent on

Inside my .vim directory:

~ % tree .vim
.vim
└── indent
    ├── html.vim
    └── javascript.vim

1 directory, 2 files

Where:

~ % cat .vim/indent/javascript.vim
setlocal formatprg=js-beautify
let g:testvar_js="js testvar"
let g:testvar="testvar defined in javascript.vim"

and

~ % cat .vim/indent/html.vim      
setlocal formatprg=html-beautify
let g:testvar_html="html testvar"
let g:testvar="testvar defined in html.vim"

Then I open up a new, empty vim buffer with vim foo.html, and tested with some commands:

:set filetype?
  filetype=html
:set formatprg?
  formatprg=js-beautify
:echo g:testvar
testvar defined in javascript.vim
:echo g:testvar_html
html testvar
:echo g:testvar_js
js testvar

As if vim sources both indent filetype plugins, with indent/html.vim first and then indent/javascript.vim.

Therefore, my questions are:

  • Did I make any silly mistakes?
  • If no, then is this an intentional design, a bug, or is that vim has nothing to do with this at all?
  • Is there a way to make vim only source on html.vim when editing html files?

Some additional information that might be helpful:

  • I'm on vim 8.2, macOS arm64, using Terminal.app
  • Neovim exhibits the same behaviour; actually that's where I first note it
  • This behaviour does not occur for ftplugin/, only indent/
  • javascript files are not affected by indent/html.vim: variables defined in indent/html.vim are all undefined in a javascript buffer
  • formatprg of html files is always js-beautify on open, regardless of if there are any javascript code pieces or <script> tags inside that html file
  • An indent/css.vim will not be involved at all when editing html - I've tested
  • js-beautify and html-beautify are two separate executables (repository is here)
    bin % ls -n js-beautify
    lrwxr-xr-x  1 501  80  53 Apr 19 17:59 js-beautify -> ../lib/node_modules/js-beautify/js/bin/js-beautify.js
    bin % ls -n html-beautify
    lrwxr-xr-x  1 501  80  55 Apr 19 17:59 html-beautify -> ../lib/node_modules/js-beautify/js/bin/html-beautify.js
    

If you want me to do some additional tests or need more information, just shout.

Many thanks

CodePudding user response:

Here is a perfectly valid HTML sample:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Sample</title>
        <script>
            console.log('Hello, World!');
        </script>
        <style>
            body {
                background: orange;
            }
        </style>
    </head>
    <body>
        <h1>Sample</h1>
    </body>
 </html>

You will notice it has a tiny bit of embedded JavaScript in it, which is a good enough reason for $VIMRUNTIME/indent/html.vim to source $VIMRUNTIME/indent/javascript.vim. After all, the javascript indent script is supposed to know how to indent JavaScript, so why not use it in a html buffer that can contain embedded JavaScript?

FWIW, here is the snippet responsible for that behaviour:

if !exists('*GetJavascriptIndent')
  runtime! indent/javascript.vim
endif

Note that the maintainers of $VIMRUNTIME/indent/html.vim chose the external route for javascript and the internal one for css. Maybe because $VIMRUNTIME/indent/css.vim didn't fit the bill? I don't know and, frankly, I don't think it matters.

Now, let's go through your mistakes…

  • Filetype-specific scripts (indent, syntax, ftplugins) are sourced in this order:

    1. ~/.vim/indent/<filetype>.vim,
    2. $VIMRUNTIME/indent/<filetype>.vim
    3. ~/.vim/after/indent/<filetype>.vim

    If you are not very careful, stuff you put in an earlier script might be overwritten when a later script is sourced. For that reason, it makes a lot more sense to put your own stuff in scripts under after/.

  • The following lines have nothing to do in indent scripts:

    setlocal formatprg=js-beautify
    setlocal formatprg=html-beautify
    

    They are supposed to be in ftplugins:

    " after/ftplugin/javascript.vim
    setlocal formatprg=js-beautify
    
    " after/ftplugin/html.vim
    setlocal formatprg=html-beautify
    

So…

Did I make any silly mistakes?

Yes, see above.

If no, then is this an intentional design, a bug, or is that vim has nothing to do with this at all?

Well yes, this is an intentional design that works pretty well. It only caused problems because you misused it.

Is there a way to make vim only source on html.vim when editing html files?

  • indent/html.vim? Yes, it certainly is possible but why would you want to do that?
  • ftplugin/html.vim? It already works the way you want and it is the right place for the things you mistakenly put in indent/html.vim to begin with.
  • Related