Repository: evanleck/vim-svelte
Branch: main
Commit: f6df955ad865
Files: 11
Total size: 23.3 KB
Directory structure:
gitextract_itkqry4z/
├── .github/
│ └── workflows/
│ └── main.yml
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── ftdetect/
│ └── svelte.vim
├── ftplugin/
│ └── svelte.vim
├── indent/
│ └── svelte.vim
├── syntax/
│ └── svelte.vim
└── test/
├── indent.vader
└── vimrc
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/main.yml
================================================
name: vim-svelte
on: [push, pull_request]
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
neovim: [true, false]
runs-on: ${{ matrix.os }}
steps:
- name: Set up vim
uses: rhysd/action-setup-vim@v1
with:
version: stable
neovim: ${{ matrix.neovim }}
- name: Checkout vim-svelte
uses: actions/checkout@v2
- name: Checkout html5
uses: actions/checkout@v2
with:
repository: othree/html5.vim
path: html5.vim
- name: Checkout vader
uses: actions/checkout@v2
with:
repository: junegunn/vader.vim
path: vader.vim
- name: Checkout vim-javascript
uses: actions/checkout@v2
with:
repository: pangloss/vim-javascript
path: vim-javascript
- name: Test
run: vim --nofork --clean -u test/vimrc -c 'Vader! test/*.vader'
================================================
FILE: .gitignore
================================================
html5.vim
vader.vim
vim-javascript
================================================
FILE: LICENSE
================================================
BSD 3-Clause License
Copyright (c) 2022, Evan Lecklider
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: Makefile
================================================
test: html5.vim vader.vim vim-javascript
vim --nofork --clean -u test/vimrc -c 'Vader! test/*.vader'
.PHONY: test
vader.vim:
git clone git@github.com:junegunn/vader.vim.git
vim-javascript:
git clone git@github.com:pangloss/vim-javascript.git vim-javascript
html5.vim:
git clone git@github.com:othree/html5.vim.git html5.vim
clean:
rm -rf html5.vim vader.vim vim-javascript
.PHONY: clean
================================================
FILE: README.md
================================================
# vim-svelte
[](https://github.com/evanleck/vim-svelte/actions/workflows/main.yml)
Vim syntax highlighting and indentation for [Svelte 3][svelte] components.
This is mostly just HTML syntax highlighting with some keywords added and all
expressions inside of `{` and `}` highlighted as JavaScript.
Highlighting includes:
- HTML attributes with a colon like `on:click` or `transition:fade` highlighted
as `Keyword`.
- `#if`, `/if`, `:else`, and `:else if` highlighted as `Conditional`.
- `#await`, `/await`, `:catch`, `:then`, and `@html` highlighted as `Keyword`.
- `#each` and `/each` highlighted as `Repeat`.
## Dependencies
1. [pangloss/vim-javascript][vim-javascript] for JavaScript syntax highlighting.
2. [othree/html5.vim][html5-vim] for HTML indent.
Both of those dependencies are included in [sheerun/vim-polyglot][vim-polyglot]
so if you're already using that then you should be set.
## Installation
The simplest way to install vim-svelte is via a package manager like
[Pathogen][pathogen], [Vundle][vundle], [NeoBundle][neobundle],
[Plug][vim-plug], or [minpac][minpac].
For example, using minpac:
```vimscript
call minpac#add('othree/html5.vim')
call minpac#add('pangloss/vim-javascript')
call minpac#add('evanleck/vim-svelte')
```
Or using Plug:
```vimscript
Plug 'othree/html5.vim'
Plug 'pangloss/vim-javascript'
Plug 'evanleck/vim-svelte', {'branch': 'main'}
```
vim-svelte works just fine with Vim 8's native package loading as well.
## Options
To disable indentation within `
```
### Customizing the list of preprocessed languages
In addition to enabling the built-in preprocessors, you can add your own
preprocessors that this plugin will detect using the
`g:svelte_preprocessor_tags` variable. It should be a list of dictionaries with
at least a `name` and a `tag` attribute. You can optionally include an `as`
attribute which maps to the syntax you'd like to use within the tag.
Here's an example:
```vim
let g:svelte_preprocessor_tags = [
\ { 'name': 'postcss', 'tag': 'style', 'as': 'scss' }
\ ]
" You still need to enable these preprocessors as well.
let g:svelte_preprocessors = ['postcss']
```
This would highlight `', 'bW') && previous_line =~ ';$' && current_line !~ '}'
return previous_line_indent
endif
" "/await" or ":catch" or ":then"
if current_line =~ '^\s*{\s*\/await' || current_line =~ '^\s*{\s*:\(catch\|then\)'
let await_start = searchpair('{\s*#await\>', '', '{\s*\/await\>', 'bW')
if await_start
return indent(await_start)
endif
endif
" "/each"
if current_line =~ '^\s*{\s*\/each'
let each_start = searchpair('{\s*#each\>', '', '{\s*\/each\>', 'bW')
if each_start
return indent(each_start)
endif
endif
" "/if"
if current_line =~ '^\s*{\s*\/if'
let if_start = searchpair('{\s*#if\>', '', '{\s*\/if\>', 'bW')
if if_start
return indent(if_start)
endif
endif
" ":else" is tricky because it can match an opening "#each" _or_ an opening
" "#if", so we try to be smart and look for the closest of the two.
if current_line =~ '^\s*{\s*:else'
let if_start = searchpair('{\s*#if\>', '', '{\s*\/if\>', 'bW')
" If it's an "else if" then we know to look for an "#if"
if current_line =~ '^\s*{\s*:else if' && if_start
return indent(if_start)
else
" The greater line number will be closer to the cursor position because
" we're searching backward.
return indent(max([if_start, searchpair('{\s*#each\>', '', '{\s*\/each\>', 'bW')]))
endif
endif
" "#if" or "#each"
if previous_line =~ '^\s*{\s*#\(if\|each\|await\)'
return previous_line_indent + shiftwidth()
endif
" ":else" or ":then"
if previous_line =~ '^\s*{\s*:\(else\|catch\|then\)'
return previous_line_indent + shiftwidth()
endif
" Custom element juggling for abnormal self-closing tags (),
" capitalized component tags (), and custom svelte tags
" ().
if synID(previous_line_number, match(previous_line, '\S') + 1, 0) == hlID('htmlTag')
\ && synID(current_line_number, match(current_line, '\S') + 1, 0) != hlID('htmlEndTag')
let indents_match = indent == previous_line_indent
let previous_closes = previous_line =~ '/>$'
if indents_match && !previous_closes && previous_line =~ '<\(\u\|\l\+:\l\+\)'
return previous_line_indent + shiftwidth()
elseif !indents_match && previous_closes
return previous_line_indent
endif
endif
return indent
endfunction
================================================
FILE: syntax/svelte.vim
================================================
" Vim syntax file
" Language: Svelte 3 (HTML/JavaScript)
" Author: Evan Lecklider
" Maintainer: Evan Lecklide
" Depends: pangloss/vim-javascript
" URL: https://github.com/evanleck/vim-svelte
"
" Like vim-jsx, this depends on the pangloss/vim-javascript syntax package (and
" is tested against it exclusively). If you're using vim-polyglot, then you're
" all set.
if exists("b:current_syntax")
finish
endif
" Read HTML to begin with.
runtime! syntax/html.vim
unlet! b:current_syntax
" Expand HTML tag names to include mixed case, periods, and colons.
syntax match htmlTagName contained "\<[a-zA-Z:\.]*\>"
" Special attributes that include some kind of binding e.g. "on:click",
" "bind:something", etc.
syntax match svelteKeyword "\<[a-z]\+:[a-zA-Z|]\+=" contained containedin=htmlTag
" The "slot" attribute has special meaning.
syntax keyword svelteKeyword slot contained containedin=htmlTag
" According to vim-jsx, you can let jsBlock take care of ending the region.
" https://github.com/mxw/vim-jsx/blob/master/after/syntax/jsx.vim
syntax region svelteExpression start="{" end="" contains=javaScriptEmbed,jsBlock,javascriptBlock containedin=htmlString,htmlTag,htmlArg,htmlValue,htmlH1,htmlH2,htmlH3,htmlH4,htmlH5,htmlH6,htmlHead,htmlTitle,htmlBoldItalicUnderline,htmlUnderlineBold,htmlUnderlineItalicBold,htmlUnderlineBoldItalic,htmlItalicUnderline,htmlItalicBold,htmlItalicBoldUnderline,htmlItalicUnderlineBold,htmlLink,htmlLeadingSpace,htmlBold,htmlBoldUnderline,htmlBoldItalic,htmlBoldUnderlineItalic,htmlUnderline,htmlUnderlineItalic,htmlItalic,htmlStrike,javaScript
" Block conditionals.
syntax match svelteConditional "#if" contained containedin=jsBlock,javascriptBlock
syntax match svelteConditional "/if" contained containedin=jsBlock,javascriptBlock
syntax match svelteConditional ":else if" contained containedin=jsBlock,javascriptBlock
syntax match svelteConditional ":else" contained containedin=jsBlock,javascriptBlock
" Block keywords.
syntax match svelteKeyword "#await" contained containedin=jsBlock,javascriptBlock
syntax match svelteKeyword "/await" contained containedin=jsBlock,javascriptBlock
syntax match svelteKeyword ":catch" contained containedin=jsBlock,javascriptBlock
syntax match svelteKeyword ":then" contained containedin=jsBlock,javascriptBlock
" Inline keywords.
syntax match svelteKeyword "@html" contained containedin=jsBlock,javascriptBlock
syntax match svelteKeyword "@debug" contained containedin=jsBlock,javascriptBlock
" Repeat functions.
syntax match svelteRepeat "#each" contained containedin=jsBlock,javascriptBlock
syntax match svelteRepeat "/each" contained containedin=jsBlock,javascriptBlock
highlight def link svelteConditional Conditional
highlight def link svelteKeyword Keyword
highlight def link svelteRepeat Repeat
" Preprocessed languages that aren't supported out of the box by Svelte require
" additional syntax files to be pulled in and can slow Vim down a bit. For that
" reason, preprocessed languages must be enabled manually. Note that some may
" require additional plugins that contain the actual syntax definitions.
"
" Heavily cribbed from https://github.com/posva/vim-vue and largely completed by
" @davidroeca (thank you!).
" A syntax should be registered if there's a valid syntax definition known to
" Vim and it is enabled for the Svelte plugin.
function! s:enabled(language)
" Check whether a syntax file for {language} exists
let s:syntax_name = get(a:language, 'as', a:language.name)
if empty(globpath(&runtimepath, 'syntax/' . s:syntax_name . '.vim'))
return 0
endif
" If g:svelte_preprocessors is set, check for it there, otherwise return 0.
if exists('g:svelte_preprocessors') && type(g:svelte_preprocessors) == v:t_list
return index(g:svelte_preprocessors, a:language.name) != -1
else
return 0
endif
endfunction
" Default tag definitions.
let s:languages = [
\ { 'name': 'less', 'tag': 'style' },
\ { 'name': 'scss', 'tag': 'style' },
\ { 'name': 'sass', 'tag': 'style' },
\ { 'name': 'stylus', 'tag': 'style' },
\ { 'name': 'typescript', 'tag': 'script' },
\ ]
" Add global tag definitions to our defaults.
if exists('g:svelte_preprocessor_tags') && type(g:svelte_preprocessor_tags) == v:t_list
let s:languages += g:svelte_preprocessor_tags
endif
for s:language in s:languages
let s:attr = '\(lang\|type\)=\("\|''\)[^\2]*' . s:language.name . '[^\2]*\2'
let s:start = '<' . s:language.tag . '\>\_[^>]*' . s:attr . '\_[^>]*>'
if s:enabled(s:language)
execute 'syntax include @' . s:language.name . ' syntax/' . get(s:language, 'as', s:language.name) . '.vim'
unlet! b:current_syntax
execute 'syntax region svelte_' . s:language.name
\ 'keepend'
\ 'start=/' . s:start . '/'
\ 'end="' . s:language.tag . '>"me=s-1'
\ 'contains=@' . s:language.name . ',svelteSurroundingTag'
\ 'fold'
endif
endfor
syntax region svelteSurroundingTag contained start=+<\(script\|style\|template\)+ end=+>+ fold contains=htmlTagN,htmlString,htmlArg,htmlValue,htmlTagError,htmlEvent
" Cybernetically enhanced web apps.
let b:current_syntax = "svelte"
" Sync from start because of the wacky nesting.
syntax sync fromstart
================================================
FILE: test/indent.vader
================================================
Given svelte (an open tag right after a close tag):
{#if something}
{/if}
Do (indent the whole buffer):
gg=G
Expect svelte (matching indentation of the opening and closing tags):
{#if something}
{/if}
Given svelte (a svelte: tag):
Foo
Do (indent the whole buffer):
gg=G
Expect svelte (an indented svelte: tag):
Foo
Given svelte (a sequence of self-closing tags):
Do (indent the whole buffer):
gg=G
Expect svelte (an indented sequence of self-closing tags):
Given svelte (a mix of self-closing and normal custom tags):
Do (indent the whole buffer):
gg=G
Expect svelte (an indented mix of self-closing and normal custom tags):
Given svelte (a combination of normal and capitalize tags):
Do (indent the whole buffer):
gg=G
Expect svelte (indented block):
Given svelte (namespaced tags):
Do (indent the whole buffer):
gg=G
Expect svelte (indented block):
Given svelte (outdented style tag):
Do (indent the whole buffer):
gg=G
Expect svelte (indented style tag):
Given svelte (uneven script tag #1):
Do (indent the whole buffer):
gg=G
Expect svelte (indented script tag):
Given svelte (uneven script tag #2):
Do (indent the whole buffer):
gg=G
Expect svelte (indented script tag):
Execute (turn off script indenting):
let g:svelte_indent_script = 0
Given svelte (an indented script tag):
Do (indent the whole buffer):
gg=G
Expect svelte (an outdented script tag):
Execute (reset script indenting):
unlet g:svelte_indent_script
Execute (turn off style indenting):
let g:svelte_indent_style = 0
Given svelte (an indented style tag):
Do (indent the whole buffer):
gg=G
Expect svelte (an outdented style tag):
Execute (reset style indenting):
unlet g:svelte_indent_style
================================================
FILE: test/vimrc
================================================
set nocompatible
filetype off
set runtimepath^=html5.vim
set runtimepath^=vader.vim
set runtimepath^=vim-javascript
set runtimepath^=.
set expandtab
set shiftwidth=2
set softtabstop=2
set tabstop=2
filetype plugin indent on
syntax enable