├── after ├── ftplugin │ ├── jsx.vim │ └── tsx.vim ├── syntax │ ├── jsx.vim │ └── tsx.vim └── indent │ ├── tsx.vim │ └── jsx.vim ├── ftdetect ├── typescript.vim └── javascript.vim └── README.md /after/ftplugin/jsx.vim: -------------------------------------------------------------------------------- 1 | if exists('loaded_matchit') 2 | let b:match_ignorecase = 0 3 | let s:jsx_match_words = '<\([a-zA-Z0-9.]\+\)\(>\|$\|\s\):<\/\1>' 4 | 5 | if !exists('b:loaded_jsx_match_words') 6 | let b:loaded_jsx_match_words = 0 7 | endif 8 | 9 | if b:loaded_jsx_match_words == 0 10 | let b:match_words = exists('b:match_words') 11 | \ ? b:match_words . ',' . s:jsx_match_words 12 | \ : s:jsx_match_words 13 | endif 14 | 15 | let b:loaded_jsx_match_words = 1 16 | endif 17 | 18 | setlocal suffixesadd+=.jsx 19 | -------------------------------------------------------------------------------- /after/ftplugin/tsx.vim: -------------------------------------------------------------------------------- 1 | " modified from html.vim 2 | if exists('loaded_matchit') 3 | let b:match_ignorecase = 0 4 | let s:tsx_match_words = '<\([a-zA-Z0-9.]\+\)\(>\|$\|\s\):<\/\1>' 5 | 6 | if !exists('b:loaded_tsx_match_words') 7 | let b:loaded_tsx_match_words = 0 8 | endif 9 | 10 | if b:loaded_tsx_match_words == 0 11 | let b:match_words = exists('b:match_words') 12 | \ ? b:match_words . ',' . s:tsx_match_words 13 | \ : s:tsx_match_words 14 | endif 15 | 16 | let b:loaded_tsx_match_words = 1 17 | endif 18 | 19 | setlocal suffixesadd+=.tsx 20 | -------------------------------------------------------------------------------- /ftdetect/typescript.vim: -------------------------------------------------------------------------------- 1 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vim ftdetect file 3 | " 4 | " Language: TSX (TypeScript) 5 | " 6 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 7 | 8 | let s:tsx_pragma_pattern = '\%^\_s*\/\*\*\%(\_.\%(\*\/\)\@!\)*@tsx\_.\{-}\*\/' 9 | 10 | " if g:tsx_check_react_import == 1 11 | " parse the first line of ts file (skipping comments). When it has a 'react' 12 | " importation, we guess the user writes tsx 13 | " endif 14 | let s:tsx_prevalent_pattern = 15 | \ '\v\C%^\_s*%(%(//.*\_$|/\*\_.{-}\*/)@>\_s*)*%(import\s+\k+\s+from\s+|%(\l+\s+)=\k+\s*\=\s*require\s*\(\s*)[`"'']react>' 16 | 17 | " Whether to set the TSX filetype on *.ts files. 18 | fu! EnableTSX() 19 | " Whether the .tsx extension is required. 20 | if !exists('g:tsx_ext_required') 21 | let g:tsx_ext_required = 0 22 | endif 23 | 24 | " Whether the @tsx pragma is required. 25 | if !exists('g:tsx_pragma_required') 26 | let g:tsx_pragma_required = 0 27 | endif 28 | 29 | if g:tsx_pragma_required && !exists('b:tsx_ext_found') 30 | " Look for the @tsx pragma. It must be included in a docblock comment 31 | " before anything else in the file (except whitespace). 32 | let b:tsx_pragma_found = search(s:tsx_pragma_pattern, 'npw') 33 | endif 34 | 35 | if g:tsx_pragma_required && !b:tsx_pragma_found | return 0 | endif 36 | if g:tsx_ext_required && !exists('b:tsx_ext_found') && 37 | \ !(get(g:,'tsx_check_react_import') && search(s:tsx_prevalent_pattern, 'nw')) 38 | return 0 39 | endif 40 | return 1 41 | endfu 42 | 43 | augroup typescript_tsx_syntax_detection 44 | autocmd! 45 | autocmd BufNewFile,BufRead *.tsx let b:tsx_ext_found = 1 46 | autocmd BufNewFile,BufRead *.tsx set filetype=typescript.tsx 47 | autocmd BufNewFile,BufRead *.ts 48 | \ if EnableTSX() | set filetype=typescript.tsx | endif 49 | augroup END 50 | -------------------------------------------------------------------------------- /ftdetect/javascript.vim: -------------------------------------------------------------------------------- 1 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vim ftdetect file 3 | " 4 | " Language: JSX (JavaScript) 5 | " Maintainer: Max Wang 6 | " 7 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 8 | 9 | let s:jsx_pragma_pattern = '\%^\_s*\/\*\*\%(\_.\%(\*\/\)\@!\)*@jsx\_.\{-}\*\/' 10 | 11 | " if g:jsx_check_react_import == 1 12 | " parse the first line of js file (skipping comments). When it has a 'react' 13 | " importation, we guess the user writes jsx 14 | " endif 15 | let s:jsx_prevalent_pattern = 16 | \ '\v\C%^\_s*%(%(//.*\_$|/\*\_.{-}\*/)@>\_s*)*%(import\s+\k+\s+from\s+|%(\l+\s+)=\k+\s*\=\s*require\s*\(\s*)[`"'']react>' 17 | 18 | " Whether to set the JSX filetype on *.js files. 19 | fu! EnableJSX() 20 | " Whether the .jsx extension is required. 21 | if !exists('g:jsx_ext_required') 22 | let g:jsx_ext_required = 0 23 | endif 24 | 25 | " Whether the @jsx pragma is required. 26 | if !exists('g:jsx_pragma_required') 27 | let g:jsx_pragma_required = 0 28 | endif 29 | 30 | if g:jsx_pragma_required && !exists('b:jsx_ext_found') 31 | " Look for the @jsx pragma. It must be included in a docblock comment 32 | " before anything else in the file (except whitespace). 33 | let b:jsx_pragma_found = search(s:jsx_pragma_pattern, 'npw') 34 | endif 35 | 36 | if g:jsx_pragma_required && !b:jsx_pragma_found | return 0 | endif 37 | if g:jsx_ext_required && !exists('b:jsx_ext_found') && 38 | \ !(get(g:,'jsx_check_react_import') && search(s:jsx_prevalent_pattern, 'nw')) 39 | return 0 40 | endif 41 | return 1 42 | endfu 43 | 44 | augroup javascript_jsx_syntax_detection 45 | autocmd! 46 | autocmd BufNewFile,BufRead *.jsx let b:jsx_ext_found = 1 47 | autocmd BufNewFile,BufRead *.jsx set filetype=javascript.jsx 48 | autocmd BufNewFile,BufRead *.js 49 | \ if EnableJSX() | set filetype=javascript.jsx | endif 50 | augroup END 51 | -------------------------------------------------------------------------------- /after/syntax/jsx.vim: -------------------------------------------------------------------------------- 1 | " Prologue; load in XML syntax. 2 | if exists('b:current_syntax') 3 | let s:current_syntax=b:current_syntax 4 | unlet b:current_syntax 5 | endif 6 | syn include @XMLSyntax syntax/xml.vim 7 | if exists('s:current_syntax') 8 | let b:current_syntax=s:current_syntax 9 | endif 10 | 11 | " Officially, vim-jsx depends on the pangloss/vim-javascript syntax package 12 | " (and is tested against it exclusively). However, in practice, we make some 13 | " effort towards compatibility with other packages. 14 | " 15 | " These are the plugin-to-syntax-element correspondences: 16 | " 17 | " - pangloss/vim-javascript: jsBlock, jsExpression 18 | " - jelera/vim-javascript-syntax: javascriptBlock 19 | " - othree/yajs.vim: javascriptNoReserved 20 | 21 | 22 | " JSX attributes should color as JS. Note the trivial end pattern; we let 23 | " jsBlock take care of ending the region. 24 | syn region xmlString contained start=+{+ end=++ contains=jsBlock,javascriptBlock 25 | 26 | " JSX comments inside XML tag should color as comment. Note the trivial end pattern; we let 27 | " jsComment take care of ending the region. 28 | syn region xmlString contained start=+//+ end=++ contains=jsComment 29 | 30 | " JSX child blocks behave just like JSX attributes, except that (a) they are 31 | " syntactically distinct, and (b) they need the syn-extend argument, or else 32 | " nested XML end-tag patterns may end the outer jsxRegion. 33 | syn region jsxChild contained start=+{+ end=++ contains=jsBlock,javascriptBlock 34 | \ extend 35 | 36 | " Highlight JSX regions as XML; recursively match. 37 | " 38 | " Note that we prohibit JSX tags from having a < or word character immediately 39 | " preceding it, to avoid conflicts with, respectively, the left shift operator 40 | " and generic Flow type annotations (http://flowtype.org/). 41 | syn region jsxRegion 42 | \ contains=@Spell,@XMLSyntax,jsxRegion,jsxChild,jsBlock,javascriptBlock 43 | \ start=+\%(<\|\w\)\@[:,]\@!\)\([^>]*>(\)\@!+ 44 | \ skip=++ 45 | \ end=++ 46 | \ end=+/>+ 47 | \ keepend 48 | \ extend 49 | 50 | " Shorthand fragment support 51 | " 52 | " Note that since the main jsxRegion contains @XMLSyntax, we cannot simply 53 | " adjust the regex above since @XMLSyntax will highlight the opening `<` as an 54 | " XMLError. Instead we create a new group with the same name that does not 55 | " include @XMLSyntax and instead uses matchgroup to get the same highlighting. 56 | syn region jsxRegion 57 | \ contains=@Spell,jsxRegion,jsxChild,jsBlock,javascriptBlock 58 | \ matchgroup=xmlTag 59 | \ start=/<>/ 60 | \ end=/<\/>/ 61 | \ keepend 62 | \ extend 63 | 64 | " Add jsxRegion to the lowest-level JS syntax cluster. 65 | syn cluster jsExpression add=jsxRegion 66 | 67 | " Allow jsxRegion to contain reserved words. 68 | syn cluster javascriptNoReserved add=jsxRegion 69 | -------------------------------------------------------------------------------- /after/syntax/tsx.vim: -------------------------------------------------------------------------------- 1 | " Prologue; load in XML syntax. 2 | if exists('b:current_syntax') 3 | let s:current_syntax=b:current_syntax 4 | unlet b:current_syntax 5 | endif 6 | syn include @XMLSyntax syntax/xml.vim 7 | if exists('s:current_syntax') 8 | let b:current_syntax=s:current_syntax 9 | endif 10 | 11 | " Officially, vim-jsx depends on the amadeus/vim-typescript syntax package 12 | " (and is tested against it exclusively). These are the 13 | " plugin-to-syntax-element correspondences: 14 | " 15 | " - amadeus/vim-typescript: tsBlock, tsExpression 16 | 17 | 18 | " JSX attributes should color as JS. Note the trivial end pattern; we let 19 | " tsBlock take care of ending the region. 20 | syn region xmlString contained start=+{+ end=++ contains=tsBlock,javascriptBlock 21 | 22 | " JSX comments inside XML tag should color as comment. Note the trivial end pattern; we let 23 | " tsComment take care of ending the region. 24 | syn region xmlString contained start=+//+ end=++ contains=tsComment 25 | syn region xmlString contained start=+/\*+ end=++ contains=tsComment fold extend keepend 26 | 27 | " JSX child blocks behave just like JSX attributes, except that (a) they are 28 | " syntactically distinct, and (b) they need the syn-extend argument, or else 29 | " nested XML end-tag patterns may end the outer tsxRegion. 30 | syn region tsxChild contained start=+{+ end=++ contains=tsBlock,javascriptBlock 31 | \ extend 32 | 33 | " Highlight JSX regions as XML; recursively match. 34 | " 35 | " Note that we prohibit JSX tags from having a < or word character immediately 36 | " preceding it, to avoid conflicts with, respectively, the left shift operator 37 | " and generic TSC type annotations (http://flowtype.org/). 38 | syn region tsxRegion 39 | \ contains=@Spell,@XMLSyntax,tsxRegion,tsxChild,tsBlock,javascriptBlock 40 | \ start=+\%(<\|\w\)\@[:,]\@!\)\([^>]*>(\)\@!+ 41 | \ skip=++ 42 | \ end=++ 43 | \ end=+/>+ 44 | \ keepend 45 | \ extend 46 | 47 | syn match xmlTagName +\%(<\|"']\++ contained contains=xmlNamespace,xmlAttribPunct,@xmlTagHook nextgroup=tsTSCGeneric display 48 | 49 | " Shorthand fragment support 50 | " 51 | " Note that since the main tsxRegion contains @XMLSyntax, we cannot simply 52 | " adjust the regex above since @XMLSyntax will highlight the opening `<` as an 53 | " XMLError. Instead we create a new group with the same name that does not 54 | " include @XMLSyntax and instead uses matchgroup to get the same highlighting. 55 | syn region tsxRegion 56 | \ contains=@Spell,tsxRegion,tsxChild,tsBlock,javascriptBlock 57 | \ matchgroup=xmlTag 58 | \ start=/<>/ 59 | \ end=/<\/>/ 60 | \ keepend 61 | \ extend 62 | 63 | " Add tsxRegion to the lowest-level JS syntax cluster. 64 | syn cluster tsExpression add=tsxRegion 65 | 66 | " Allow tsxRegion to contain reserved words. 67 | syn cluster javascriptNoReserved add=tsxRegion 68 | -------------------------------------------------------------------------------- /after/indent/tsx.vim: -------------------------------------------------------------------------------- 1 | " Save the current JavaScript indentexpr. 2 | let b:tsx_js_indentexpr = &indentexpr 3 | 4 | " Prologue; load in XML indentation. 5 | if exists('b:did_indent') 6 | let s:did_indent=b:did_indent 7 | unlet b:did_indent 8 | endif 9 | exe 'runtime! indent/xml.vim' 10 | if exists('s:did_indent') 11 | let b:did_indent=s:did_indent 12 | endif 13 | 14 | setlocal indentexpr=GetJsxIndent() 15 | 16 | " JS indentkeys 17 | setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e 18 | " XML indentkeys 19 | setlocal indentkeys+=*,<>>,<<>,/ 20 | 21 | " Multiline end tag regex (line beginning with '>' or '/>') 22 | let s:endtag = '^\s*\/\?>\s*;\=' 23 | 24 | " Get all syntax types at the beginning of a given line. 25 | fu! SynSOL(lnum) 26 | return map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') 27 | endfu 28 | 29 | " Get all syntax types at the end of a given line. 30 | fu! SynEOL(lnum) 31 | let lnum = prevnonblank(a:lnum) 32 | let col = strlen(getline(lnum)) 33 | return map(synstack(lnum, col), 'synIDattr(v:val, "name")') 34 | endfu 35 | 36 | " Check if a syntax attribute is XMLish. 37 | fu! SynAttrXMLish(synattr) 38 | return a:synattr =~ "^xml" || a:synattr =~ "^tsx" 39 | endfu 40 | 41 | " Check if a synstack is XMLish (i.e., has an XMLish last attribute). 42 | fu! SynXMLish(syns) 43 | return SynAttrXMLish(get(a:syns, -1)) 44 | endfu 45 | 46 | " Check if a synstack denotes the end of a JSX block. 47 | fu! SynJSXBlockEnd(syns) 48 | return get(a:syns, -1) =~ '\%(ts\|javascript\)Braces' && 49 | \ SynAttrXMLish(get(a:syns, -2)) 50 | endfu 51 | 52 | " Determine how many tsxRegions deep a synstack is. 53 | fu! SynJSXDepth(syns) 54 | return len(filter(copy(a:syns), 'v:val ==# "tsxRegion"')) 55 | endfu 56 | 57 | " Check whether `cursyn' continues the same tsxRegion as `prevsyn'. 58 | fu! SynJSXContinues(cursyn, prevsyn) 59 | let curdepth = SynJSXDepth(a:cursyn) 60 | let prevdepth = SynJSXDepth(a:prevsyn) 61 | 62 | " In most places, we expect the nesting depths to be the same between any 63 | " two consecutive positions within a tsxRegion (e.g., between a parent and 64 | " child node, between two JSX attributes, etc.). The exception is between 65 | " sibling nodes, where after a completed element (with depth N), we return 66 | " to the parent's nesting (depth N - 1). This case is easily detected, 67 | " since it is the only time when the top syntax element in the synstack is 68 | " tsxRegion---specifically, the tsxRegion corresponding to the parent. 69 | return prevdepth == curdepth || 70 | \ (prevdepth == curdepth + 1 && get(a:cursyn, -1) ==# 'tsxRegion') 71 | endfu 72 | 73 | " Cleverly mix JS and XML indentation. 74 | fu! GetJsxIndent() 75 | let cursyn = SynSOL(v:lnum) 76 | let prevsyn = SynEOL(v:lnum - 1) 77 | 78 | " Use XML indenting iff: 79 | " - the syntax at the end of the previous line was either JSX or was the 80 | " closing brace of a tsBlock whose parent syntax was JSX; and 81 | " - the current line continues the same tsxRegion as the previous line. 82 | if (SynXMLish(prevsyn) || SynJSXBlockEnd(prevsyn)) && 83 | \ SynJSXContinues(cursyn, prevsyn) 84 | let ind = XmlIndentGet(v:lnum, 0) 85 | 86 | " Align '/>' and '>' with '<' for multiline tags. 87 | if getline(v:lnum) =~? s:endtag 88 | let ind = ind - &sw 89 | endif 90 | 91 | " Then correct the indentation of any JSX following '/>' or '>'. 92 | if getline(v:lnum - 1) =~? s:endtag 93 | let ind = ind + &sw 94 | endif 95 | else 96 | if len(b:tsx_js_indentexpr) 97 | " Invoke the base JS package's custom indenter. (For vim-javascript, 98 | " e.g., this will be GetJavascriptIndent().) 99 | let ind = eval(b:tsx_js_indentexpr) 100 | else 101 | let ind = cindent(v:lnum) 102 | endif 103 | endif 104 | 105 | return ind 106 | endfu 107 | -------------------------------------------------------------------------------- /after/indent/jsx.vim: -------------------------------------------------------------------------------- 1 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vim indent file 3 | " 4 | " Language: JSX (JavaScript) 5 | " Maintainer: Max Wang 6 | " 7 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 8 | 9 | " Save the current JavaScript indentexpr. 10 | let b:jsx_js_indentexpr = &indentexpr 11 | 12 | " Prologue; load in XML indentation. 13 | if exists('b:did_indent') 14 | let s:did_indent=b:did_indent 15 | unlet b:did_indent 16 | endif 17 | exe 'runtime! indent/xml.vim' 18 | if exists('s:did_indent') 19 | let b:did_indent=s:did_indent 20 | endif 21 | 22 | setlocal indentexpr=GetJsxIndent() 23 | 24 | " JS indentkeys 25 | setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e 26 | " XML indentkeys 27 | setlocal indentkeys+=*,<>>,<<>,/ 28 | 29 | " Multiline end tag regex (line beginning with '>' or '/>') 30 | let s:endtag = '^\s*\/\?>\s*;\=' 31 | 32 | " Get all syntax types at the beginning of a given line. 33 | fu! SynSOL(lnum) 34 | return map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') 35 | endfu 36 | 37 | " Get all syntax types at the end of a given line. 38 | fu! SynEOL(lnum) 39 | let lnum = prevnonblank(a:lnum) 40 | let col = strlen(getline(lnum)) 41 | return map(synstack(lnum, col), 'synIDattr(v:val, "name")') 42 | endfu 43 | 44 | " Check if a syntax attribute is XMLish. 45 | fu! SynAttrXMLish(synattr) 46 | return a:synattr =~ "^xml" || a:synattr =~ "^jsx" 47 | endfu 48 | 49 | " Check if a synstack is XMLish (i.e., has an XMLish last attribute). 50 | fu! SynXMLish(syns) 51 | return SynAttrXMLish(get(a:syns, -1)) 52 | endfu 53 | 54 | " Check if a synstack denotes the end of a JSX block. 55 | fu! SynJSXBlockEnd(syns) 56 | return get(a:syns, -1) =~ '\%(js\|javascript\)Braces' && 57 | \ SynAttrXMLish(get(a:syns, -2)) 58 | endfu 59 | 60 | " Determine how many jsxRegions deep a synstack is. 61 | fu! SynJSXDepth(syns) 62 | return len(filter(copy(a:syns), 'v:val ==# "jsxRegion"')) 63 | endfu 64 | 65 | " Check whether `cursyn' continues the same jsxRegion as `prevsyn'. 66 | fu! SynJSXContinues(cursyn, prevsyn) 67 | let curdepth = SynJSXDepth(a:cursyn) 68 | let prevdepth = SynJSXDepth(a:prevsyn) 69 | 70 | " In most places, we expect the nesting depths to be the same between any 71 | " two consecutive positions within a jsxRegion (e.g., between a parent and 72 | " child node, between two JSX attributes, etc.). The exception is between 73 | " sibling nodes, where after a completed element (with depth N), we return 74 | " to the parent's nesting (depth N - 1). This case is easily detected, 75 | " since it is the only time when the top syntax element in the synstack is 76 | " jsxRegion---specifically, the jsxRegion corresponding to the parent. 77 | return prevdepth == curdepth || 78 | \ (prevdepth == curdepth + 1 && get(a:cursyn, -1) ==# 'jsxRegion') 79 | endfu 80 | 81 | " Cleverly mix JS and XML indentation. 82 | fu! GetJsxIndent() 83 | let cursyn = SynSOL(v:lnum) 84 | let prevsyn = SynEOL(v:lnum - 1) 85 | 86 | " Use XML indenting iff: 87 | " - the syntax at the end of the previous line was either JSX or was the 88 | " closing brace of a jsBlock whose parent syntax was JSX; and 89 | " - the current line continues the same jsxRegion as the previous line. 90 | if (SynXMLish(prevsyn) || SynJSXBlockEnd(prevsyn)) && 91 | \ SynJSXContinues(cursyn, prevsyn) 92 | let ind = XmlIndentGet(v:lnum, 0) 93 | 94 | " Align '/>' and '>' with '<' for multiline tags. 95 | if getline(v:lnum) =~? s:endtag 96 | let ind = ind - &sw 97 | endif 98 | 99 | " Then correct the indentation of any JSX following '/>' or '>'. 100 | if getline(v:lnum - 1) =~? s:endtag 101 | let ind = ind + &sw 102 | endif 103 | else 104 | if len(b:jsx_js_indentexpr) 105 | " Invoke the base JS package's custom indenter. (For vim-javascript, 106 | " e.g., this will be GetJavascriptIndent().) 107 | let ind = eval(b:jsx_js_indentexpr) 108 | else 109 | let ind = cindent(v:lnum) 110 | endif 111 | endif 112 | 113 | return ind 114 | endfu 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vim-jsx 2 | ======= 3 | 4 | **NOTE:** This repo is a fork of [mxw/vim-jsx](https://github.com/mxw/vim-jsx). 5 | While I normally do not like making a fork of such a commonly used plugin, it 6 | appears to have been abandoned with no activity over the last seven+ months. 7 | Notably in this fork, I have added support for the new shorthand fragment 8 | syntax, as well as manually cherry-picked in a few open PRs from mxw/vim-jsx. 9 | 10 | **NOTE 2:** While it's not required, I also recommend installing 11 | [amadeus/vim-xml](https://github.com/amadeus/vim-xml). It's a fork of the 12 | built in xml syntax plugin that fixes a few bugs (like the final boolean prop 13 | in a JSX statement or the closing xml tag not matching the opening one). 14 | 15 | --------------- 16 | 17 | Syntax highlighting and indenting for JSX. JSX is a JavaScript syntax 18 | transformer which translates inline XML document fragments into JavaScript 19 | objects. It was developed by Facebook alongside [React][1]. 20 | 21 | vim-jsx is _not_ a JavaScript syntax package, so in order to use it, you will 22 | also need to choose a base JS highlighter. [pangloss/vim-javascript][2] is the 23 | recommended package---it is vim-jsx's "official" dependency, and the only 24 | package against which it is regularly tested. However, vim-jsx makes a best 25 | effort to support other JavaScript syntax packages, including: 26 | - [pangloss/vim-javascript](https://github.com/pangloss/vim-javascript) 27 | - [jelera/vim-javascript-syntax](https://github.com/jelera/vim-javascript-syntax) 28 | - [othree/yajs](https://github.com/othree/yajs.vim) 29 | 30 | Notably, the system vim JavaScript syntax is _not_ supported, due to its 31 | over-simplicity. However, the system XML syntax package is an implicit 32 | dependency. 33 | 34 | Vim support for inline XML in JS is remarkably similar to the same for PHP, 35 | which you can find [here][3]. 36 | 37 | Troubleshooting 38 | --------------- 39 | 40 | If you're experiencing incorrect highlighting or indenting in your JSX code, 41 | please file a GitHub issue which includes the following: 42 | 43 | - A brief affirmation that you've read the README and have installed one of the 44 | supported dependencies (and the name of the one you're using). 45 | 46 | - A minimal ~/.vimrc which repros the issue you're having, as well as both a 47 | paste and a screenshot of the issue (a paste alone is insufficient, since it 48 | doesn't illustrate the specific highlighting or indenting problem). To 49 | obtain a minimal ~/.vimrc, simply bisect your ~/.vimrc by adding `finish` at 50 | various points in the file. (You can likewise bisect your included plugins 51 | by selectively including only half of them, then a quarter, etc.). 52 | 53 | Most of the issues filed result from failures to install vim-javascript or 54 | conflicts with existing JS syntax or indent files---so failing to indicate that 55 | you've ruled those issues out may result in your issue being closed with 56 | minimal comment. 57 | 58 | (Please feel free to disregard all this for feature requests.) 59 | 60 | Usage 61 | ----- 62 | 63 | By default, JSX syntax highlighting and indenting will be enabled for 64 | files with the `.js` and `.jsx` extension. If you would like JSX only in `.jsx` files, add 65 | 66 | ```viml 67 | let g:jsx_ext_required = 1 68 | ``` 69 | 70 | to your .vimrc or somewhere in your include path. If you wish to restrict JSX 71 | to files with the pre-v0.12 `@jsx React.DOM` pragma, add 72 | 73 | ```viml 74 | let g:jsx_pragma_required = 1 75 | ``` 76 | 77 | to your .vimrc or somewhere in your include path. 78 | 79 | Frequently Asked Questions 80 | -------------------------- 81 | 82 | - _How come syntax highlighting doesn't work at all?_ 83 | 84 | This is the only question I'll answer with another question---Which do you 85 | think is more likely: (a) this package fails completely and utterly in serving 86 | its most fundamental purpose, or (b) user error? 87 | 88 | - _Why are my end tags colored differently than my start tags?_ 89 | 90 | vim-jsx is basically the glue that holds JavaScript and XML syntax packages 91 | together in blissful harmony. This means that any XML syntax defaults carry 92 | over to the XML portions of vim, and it's common for many colorschemes to 93 | highlight start and end tags differently due to the system XML syntax defaults. 94 | 95 | - _Syntax highlighting seems to work, but breaks highlighting and indenting 96 | further down in the file. What's wrong?_ 97 | 98 | This often results from trying to enable XML folding in one's `~/.vimrc` (i.e., 99 | via `let g:xml_syntax_folding = 1`). vim-jsx does not support syntax folding, 100 | and is not tested with either JavaScript or XML folding enabled. 101 | 102 | Installation 103 | ------------ 104 | 105 | ### vim-plug 106 | 107 | The recommended installation method is via [vim-plug][6]---just add the following lines to 108 | your `~/.vimrc`: 109 | 110 | Plug 'pangloss/vim-javascript' 111 | Plug 'mxw/vim-jsx' 112 | 113 | To install from within vim, use the commands below. 114 | 115 | :so ~/.vimrc 116 | :PlugInstall 117 | 118 | ### Pathogen 119 | 120 | You can also add vim-jsx using [Pathogen][4]. Then simply execute 121 | 122 | git clone https://github.com/mxw/vim-jsx.git ~/.vim/bundle/vim-jsx 123 | 124 | (You can install [vim-javascript][2] in an analogous manner.) 125 | 126 | ### Vundle 127 | 128 | You can also add vim-jsx using [Vundle][5]---just add the following lines to 129 | your `~/.vimrc`: 130 | 131 | Plugin 'pangloss/vim-javascript' 132 | Plugin 'mxw/vim-jsx' 133 | 134 | To install from within vim, use the commands below. 135 | 136 | :so ~/.vimrc 137 | :PluginInstall 138 | 139 | Alternatively, use the command below to install the plugins from the command 140 | line. 141 | 142 | vim +PluginInstall +qall 143 | 144 | ### Manual Installation 145 | 146 | If you have no `~/.vim/after` directory, you can download the tarball or zip 147 | and copy the contents to `~/.vim`. 148 | 149 | If you have existing `~/.vim/after` files, copy the syntax and indent files 150 | directly into their respective destinations. If you have existing after syntax 151 | or indent files for Javascript, you'll probably want to do something like 152 | 153 | mkdir -p ~/.vim/after/syntax/javascript 154 | cp path/to/vim-jsx/after/syntax/jsx.vim ~/.vim/after/syntax/javascript/jsx.vim 155 | mkdir -p ~/.vim/after/indent/javascript 156 | cp path/to/vim-jsx/after/indent/jsx.vim ~/.vim/after/indent/javascript/jsx.vim 157 | 158 | 159 | [1]: http://facebook.github.io/react/ "React" 160 | [2]: https://github.com/pangloss/vim-javascript "pangloss: vim-javascript" 161 | [3]: https://github.com/mxw/vim-xhp "mxw: vim-xhp" 162 | [4]: https://github.com/tpope/vim-pathogen "tpope: vim-pathogen" 163 | [5]: https://github.com/VundleVim/Vundle.vim "VundleVim: Vundle.vim" 164 | [6]: https://github.com/junegunn/vim-plug "vim-plug" 165 | --------------------------------------------------------------------------------