├── .gitignore ├── LICENSE ├── Makefile ├── ftdetect └── svelte.vim ├── ftplugin └── svelte.vim ├── indent └── svelte.vim ├── readme.md ├── syntax └── svelte.vim ├── syntax_checkers └── svelte │ └── eslint.vim └── test ├── test_html_tag_names.vader ├── test_indent.vader ├── test_syntax.vader └── vimrc /.gitignore: -------------------------------------------------------------------------------- 1 | /pack 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Robert burner Schadek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: dependencies 2 | vim -u test/vimrc -c 'Vader! test/*.vader' 3 | 4 | test-nvim: dependencies 5 | VADER_OUTPUT_FILE=/dev/stderr nvim -u test/vimrc -c 'Vader! test/*.vader' --headless 6 | 7 | dependencies = \ 8 | 'junegunn/vader.vim' \ 9 | 'cakebaker/scss-syntax.vim' \ 10 | 'digitaltoad/vim-pug' \ 11 | 'groenewege/vim-less' \ 12 | 'kchmck/vim-coffee-script' \ 13 | 'leafgarland/typescript-vim' \ 14 | 'slm-lang/vim-slm' \ 15 | 'wavded/vim-stylus' \ 16 | 'scrooloose/nerdcommenter' 17 | 18 | dependencies: 19 | test -L pack/testing/start/vim-svelte && exit 0; \ 20 | mkdir -p pack/testing/start; \ 21 | cd pack/testing/start; \ 22 | for repo in $(dependencies); do git clone https://github.com/$$repo.git; done; \ 23 | ln -s ../../.. vim-svelte 24 | 25 | clean: 26 | rm -rf pack 27 | 28 | .PHONY: test test-nvim dependencies clean 29 | -------------------------------------------------------------------------------- /ftdetect/svelte.vim: -------------------------------------------------------------------------------- 1 | au BufNewFile,BufRead *.svelte setf svelte 2 | -------------------------------------------------------------------------------- /ftplugin/svelte.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin 2 | " Language: svlete.js 3 | " Maintainer: Robert burner Schadek 4 | " Author: Robert burner Schadek 5 | 6 | if exists('b:did_ftplugin') 7 | finish 8 | endif 9 | 10 | runtime! ftplugin/html.vim 11 | 12 | setlocal suffixesadd+=.svelte 13 | 14 | if !exists('g:no_plugin_maps') && !exists('g:no_svelte_maps') 15 | nnoremap [[ :call search('^<\(template\script\style\)', 'bW') 16 | nnoremap ]] :call search('^<\(template\script\style\)', 'W') 17 | nnoremap [] :call search('^script\style\)', 'bW') 18 | nnoremap ][ :call search('^script\style\)', 'W') 19 | endif 20 | -------------------------------------------------------------------------------- /indent/svelte.vim: -------------------------------------------------------------------------------- 1 | " Vim indent file 2 | " Language: svelte.js 3 | " Maintainer: Robert burner Schadek 4 | " Author: Robert burner Schadek 5 | 6 | if exists('b:did_indent') 7 | finish 8 | endif 9 | 10 | function! s:get_indentexpr(language) 11 | unlet! b:did_indent 12 | execute 'runtime! indent/' . a:language . '.vim' 13 | return &indentexpr 14 | endfunction 15 | 16 | " The order is important here, tags without attributes go last. 17 | " HTML is left out, it will be used when there is no match. 18 | let s:languages = [ 19 | \ { 'name': 'css', 'pairs': [''] }, 20 | \ { 'name': 'javascript', 'pairs': [''] }, 21 | \ ] 22 | 23 | for s:language in s:languages 24 | " Set 'indentexpr' if the user has an indent file installed for the language 25 | if strlen(globpath(&rtp, 'indent/'. s:language.name .'.vim')) 26 | let s:language.indentexpr = s:get_indentexpr(s:language.name) 27 | endif 28 | endfor 29 | 30 | let s:html_indent = s:get_indentexpr('html') 31 | 32 | let b:did_indent = 1 33 | 34 | setlocal indentexpr=GetVueIndent() 35 | 36 | if exists('*GetSvelteIndent') 37 | finish 38 | endif 39 | 40 | function! GetSvelteIndent() 41 | for language in s:languages 42 | let opening_tag_line = searchpair(language.pairs[0], '', language.pairs[1], 'bWr') 43 | 44 | if opening_tag_line 45 | execute 'let indent = ' . get(language, 'indentexpr', -1) 46 | break 47 | endif 48 | endfor 49 | 50 | if exists('l:indent') 51 | if (opening_tag_line == prevnonblank(v:lnum - 1) || opening_tag_line == v:lnum) 52 | \ || getline(v:lnum) =~ '\v^\s*\" 13 | unlet! b:current_syntax 14 | 15 | "" 16 | " Get the pattern for a HTML {name} attribute with {value}. 17 | function! s:attr(name, value) 18 | return a:name . '=\("\|''\)[^\1]*' . a:value . '[^\1]*\1' 19 | endfunction 20 | 21 | "" 22 | " Check whether a syntax file for a given {language} exists. 23 | function! s:syntax_available(language) 24 | return !empty(globpath(&runtimepath, 'syntax/' . a:language . '.vim')) 25 | endfunction 26 | 27 | "" 28 | " Register {language} for a given {tag}. If [attr_override] is given and not 29 | " empty, it will be used for the attribute pattern. 30 | function! s:register_language(language, tag, ...) 31 | let attr_override = a:0 ? a:1 : '' 32 | let attr = !empty(attr_override) ? attr_override : s:attr('lang', a:language) 33 | 34 | if s:syntax_available(a:language) 35 | execute 'syntax include @' . a:language . ' syntax/' . a:language . '.vim' 36 | unlet! b:current_syntax 37 | execute 'syntax region svelte_' . a:language 38 | \ 'keepend' 39 | \ 'start=/<' . a:tag . '\>\_[^>]*' . attr . '\_[^>]*>/' 40 | \ 'end=""me=s-1' 41 | \ 'contains=@' . a:language . ',svelteSurroundingTag' 42 | \ 'fold' 43 | endif 44 | endfunction 45 | 46 | if !exists("g:svelte_disable_pre_processors") || !g:svelte_disable_pre_processors 47 | call s:register_language('less', 'style') 48 | call s:register_language('pug', 'template', s:attr('lang', '\%(pug\|jade\)')) 49 | call s:register_language('slm', 'template') 50 | call s:register_language('handlebars', 'template') 51 | call s:register_language('haml', 'template') 52 | call s:register_language('typescript', 'script', '\%(lang=\("\|''\)[^\1]*\(ts\|typescript\)[^\1]*\1\|ts\)') 53 | call s:register_language('coffee', 'script') 54 | call s:register_language('stylus', 'style') 55 | call s:register_language('sass', 'style') 56 | call s:register_language('scss', 'style') 57 | endif 58 | 59 | syn region svelteSurroundingTag contained start=+<\(script\|style\)+ end=+>+ fold contains=htmlTagN,htmlString,htmlArg,htmlValue,htmlTagError,htmlEvent 60 | syn keyword htmlSpecialTagName contained template 61 | syn keyword htmlArg contained scoped ts 62 | syn match htmlArg "[@v:][-:.0-9_a-z]*\>" contained 63 | 64 | let b:current_syntax = "svelte" 65 | -------------------------------------------------------------------------------- /syntax_checkers/svelte/eslint.vim: -------------------------------------------------------------------------------- 1 | " Vue configuration for Syntastic 2 | 3 | if exists('g:loaded_syntastic_svelte_eslint_checker') 4 | finish 5 | endif 6 | 7 | let g:loaded_syntastic_svelte_eslint_checker = 1 8 | 9 | runtime! syntax_checkers/javascript/eslint.vim 10 | 11 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 12 | \ 'filetype': 'svelte', 13 | \ 'name': 'eslint', 14 | \ 'redirect': 'javascript/eslint' 15 | \ }) 16 | -------------------------------------------------------------------------------- /test/test_html_tag_names.vader: -------------------------------------------------------------------------------- 1 | Given svelte (Arbitrary HTML tag names): 2 | 3 | 4 | 5 |

6 | 7 | 8 | Execute (The valid combinations get highlighted, since Vue does not enforce the W3C rules for custom tag names): 9 | AssertEqual 'htmlTagName', SyntaxOf('list') 10 | AssertEqual 'htmlTagName', SyntaxOf('FormItem') 11 | AssertEqual 'htmlTagName', SyntaxOf('form-item') 12 | AssertEqual 'htmlTagName', SyntaxOf('h1') 13 | AssertEqual 'htmlTagName', SyntaxOf('foo:bar') 14 | -------------------------------------------------------------------------------- /test/test_indent.vader: -------------------------------------------------------------------------------- 1 | # 2 | # HTML 3 | # 4 | Given vue (An unindented html template): 5 |
6 | Hello 7 |
8 | 9 | Do (Indent the whole buffer): 10 | gg=G 11 | 12 | Expect (The html template got indented): 13 |
14 | Hello 15 |
16 | 17 | # 18 | # JavaScript 19 | # 20 | Given vue (An unindented JavaScript region): 21 | 30 | 31 | Do (Indent the whole buffer): 32 | gg=G 33 | 34 | Expect vue (The JavaScript region got indented): 35 | 44 | 45 | # 46 | # CSS 47 | # 48 | Given vue (An unindented css region): 49 | 54 | 55 | Do (Indent the whole buffer): 56 | gg=G 57 | 58 | Expect vue (The css region got indented): 59 | 64 | -------------------------------------------------------------------------------- /test/test_syntax.vader: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # JavaScript 4 | # 5 | Given svelte: 6 | 9 | 10 | Execute: 11 | AssertEqual 'javaScriptLineComment', SyntaxAt(2, 1) 12 | AssertEqual 'htmlScriptTag', SyntaxAt(1, 1) 13 | 14 | 15 | Given svelte (Script tag with misc. attributes and newline): 16 | 21 | 22 | Execute: 23 | AssertEqual 'javaScriptLineComment', SyntaxAt(4, 1) 24 | AssertEqual 'htmlArg', SyntaxAt(2, 9) 25 | AssertEqual 'htmlScriptTag', SyntaxAt(1, 1) 26 | 27 | # 28 | # CSS 29 | # 30 | Given svelte (CSS region without lang attribute): 31 | 34 | 35 | Execute: 36 | AssertEqual 'cssComment', SyntaxAt(2, 1) 37 | AssertEqual 'htmlTag', SyntaxAt(1, 1) 38 | -------------------------------------------------------------------------------- /test/vimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | let &packpath = expand(':p:h:h') 4 | 5 | " Remove first and last entry from runtimepath, to prevent loading plugins from ~/.vim 6 | let &runtimepath = substitute(&runtimepath, '\v^.{-},(.*),.*$', '\1', '') 7 | 8 | filetype plugin indent on 9 | syntax on 10 | 11 | set expandtab 12 | set shiftwidth=2 13 | set softtabstop=2 14 | --------------------------------------------------------------------------------