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 [![vim-svelte](https://github.com/evanleck/vim-svelte/actions/workflows/main.yml/badge.svg)](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=""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