dot/config/vim/autoload/emmet/lang/html.vim

1037 lines
34 KiB
VimL

let s:bx = '{\%("[^"]*"\|''[^'']*''\|\$#\|\${\w\+}\|\$\+\|{[^{]\+\|[^{}]\)\{-}}'
let s:mx = '\([+>]\|[<^]\+\)\{-}'
\ .'\((*\)\{-}'
\ .'\([@#.]\{-}[a-zA-Z_\!][a-zA-Z0-9:_\!\-$]*\|' . s:bx . '\|\[[^\]]\+\]\)'
\ .'\('
\ .'\%('
\ .'\%(#{[{}a-zA-Z0-9_\-\$]\+\|#[a-zA-Z0-9_\-\$]\+\)'
\ .'\|\%(\[\%(\[[^\]]*\]\|"[^"]*"\|[^"\[\]]*\)\+\]\)'
\ .'\|\%(\.{[{}a-zA-Z0-9_\-\$\.]\+\|\.[a-zA-Z0-9_\-\$]\+\)'
\ .'\)*'
\ .'\)'
\ .'\%(\(' . s:bx . '\+\)\)\{0,1}'
\ .'\%(\(@-\{0,1}[0-9]*\)\{0,1}\*\([0-9]\+\)\)\{0,1}'
\ .'\(\%()\%(\(@-\{0,1}[0-9]*\)\{0,1}\*[0-9]\+\)\{0,1}\)*\)'
function! emmet#lang#html#findTokens(str) abort
let str = a:str
let [pos, last_pos] = [0, 0]
while 1
let tag = matchstr(str, '<[a-zA-Z].\{-}>', pos)
if len(tag) == 0
break
endif
let pos = stridx(str, tag, pos) + len(tag)
endwhile
while 1
let tag = matchstr(str, '{%[^%]\{-}%}', pos)
if len(tag) == 0
break
endif
let pos = stridx(str, tag, pos) + len(tag)
endwhile
let last_pos = pos
while len(str) > 0
let white = matchstr(str, '^\s\+', pos)
if white != ''
let last_pos = pos + len(white)
let pos = last_pos
endif
let token = matchstr(str, s:mx, pos)
if token ==# ''
break
endif
let pos = stridx(str, token, pos) + len(token)
endwhile
let str = a:str[last_pos :-1]
if str =~# '^\w\+="[^"]*$'
return ''
endif
return str
endfunction
function! emmet#lang#html#parseIntoTree(abbr, type) abort
let abbr = a:abbr
let type = a:type
let settings = emmet#getSettings()
if !has_key(settings, type)
let type = 'html'
endif
if len(type) == 0 | let type = 'html' | endif
let indent = emmet#getIndentation(type)
let pmap = {
\'p': 'span',
\'ul': 'li',
\'ol': 'li',
\'table': 'tr',
\'tr': 'td',
\'tbody': 'tr',
\'thead': 'tr',
\'tfoot': 'tr',
\'colgroup': 'col',
\'select': 'option',
\'optgroup': 'option',
\'audio': 'source',
\'video': 'source',
\'object': 'param',
\'map': 'area'
\}
let inlineLevel = split('a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var',',')
let custom_expands = emmet#getResource(type, 'custom_expands', {})
if empty(custom_expands) && has_key(settings, 'custom_expands')
let custom_expands = settings['custom_expands']
endif
" try 'foo' to (foo-x)
let rabbr = emmet#getExpandos(type, abbr)
if rabbr == abbr
" try 'foo+(' to (foo-x)
let rabbr = substitute(abbr, '\%(+\|^\)\([a-zA-Z][a-zA-Z0-9+]\+\)+\([(){}>]\|$\)', '\="(".emmet#getExpandos(type, submatch(1)).")".submatch(2)', 'i')
endif
let abbr = rabbr
let root = emmet#newNode()
let root['variables'] = {}
let parent = root
let last = root
let pos = []
while len(abbr)
" parse line
let match = matchstr(abbr, s:mx)
let str = substitute(match, s:mx, '\0', 'ig')
let operator = substitute(match, s:mx, '\1', 'ig')
let block_start = substitute(match, s:mx, '\2', 'ig')
let tag_name = substitute(match, s:mx, '\3', 'ig')
let attributes = substitute(match, s:mx, '\4', 'ig')
let value = substitute(match, s:mx, '\5', 'ig')
let basevalue = substitute(match, s:mx, '\6', 'ig')
let multiplier = 0 + substitute(match, s:mx, '\7', 'ig')
let block_end = substitute(match, s:mx, '\8', 'ig')
let custom = ''
let important = 0
if len(str) == 0
break
endif
if tag_name =~# '^#'
let attributes = tag_name . attributes
let tag_name = ''
endif
if tag_name =~# '[^!]!$'
let tag_name = tag_name[:-2]
let important = 1
endif
if tag_name =~# '^\.'
let attributes = tag_name . attributes
let tag_name = ''
endif
if tag_name =~# '^\[.*\]$'
let attributes = tag_name . attributes
let tag_name = ''
endif
for k in keys(custom_expands)
if tag_name =~ k
let custom = tag_name
let tag_name = ''
break
endif
endfor
if empty(tag_name)
let pname = len(parent.child) > 0 ? parent.child[0].name : ''
if !empty(pname) && has_key(pmap, pname) && custom == ''
let tag_name = pmap[pname]
elseif !empty(pname) && index(inlineLevel, pname) > -1
let tag_name = 'span'
elseif len(custom) == 0
let tag_name = 'div'
elseif len(custom) != 0 && multiplier > 1
let tag_name = 'div'
else
let tag_name = custom
endif
endif
let basedirect = basevalue[1] ==# '-' ? -1 : 1
if basevalue != ''
let basevalue = 0 + abs(basevalue[1:])
else
let basevalue = 1
endif
if multiplier <= 0 | let multiplier = 1 | endif
" make default node
let current = emmet#newNode()
let current.name = tag_name
let current.important = important
" aliases
let aliases = emmet#getResource(type, 'aliases', {})
if has_key(aliases, tag_name)
let current.name = aliases[tag_name]
endif
let use_pipe_for_cursor = emmet#getResource(type, 'use_pipe_for_cursor', 1)
" snippets
let snippets = emmet#getResource(type, 'snippets', {})
if !empty(snippets)
let snippet_name = tag_name
if has_key(snippets, snippet_name)
let snippet = snippet_name
while has_key(snippets, snippet)
let snippet = snippets[snippet]
endwhile
if use_pipe_for_cursor
let snippet = substitute(snippet, '|', '${cursor}', 'g')
endif
" just redirect to expanding
if type == 'html' && snippet !~ '^\s*[{\[<]'
return emmet#lang#html#parseIntoTree(snippet, a:type)
endif
let lines = split(snippet, "\n", 1)
call map(lines, 'substitute(v:val, "\\( \\|\\t\\)", escape(indent, "\\\\"), "g")')
let current.snippet = join(lines, "\n")
let current.name = ''
endif
endif
for k in keys(custom_expands)
if tag_name =~# k
let snippet = '${' . (empty(custom) ? tag_name : custom) . '}'
let current.name = ''
let current.snippet = snippet
break
elseif custom =~# k
let snippet = '${' . custom . '}'
let current.snippet = '${' . custom . '}'
if current.name != ''
let snode = emmet#newNode()
let snode.snippet = snippet
let snode.parent = current
call add(current.child, snode)
else
let current.snippet = snippet
endif
break
endif
endfor
" default_attributes
let default_attributes = emmet#getResource(type, 'default_attributes', {})
if !empty(default_attributes)
for pat in [current.name, tag_name]
if has_key(default_attributes, pat)
if type(default_attributes[pat]) == 4
let a = default_attributes[pat]
let current.attrs_order += keys(a)
if use_pipe_for_cursor
for k in keys(a)
if type(a[k]) == 7
call remove(current.attr, k)
continue
endif
let current.attr[k] = len(a[k]) ? substitute(a[k], '|', '${cursor}', 'g') : '${cursor}'
endfor
else
for k in keys(a)
if type(a[k]) == 7
call remove(current.attr, k)
continue
endif
let current.attr[k] = a[k]
endfor
endif
else
for a in default_attributes[pat]
let current.attrs_order += keys(a)
if use_pipe_for_cursor
for k in keys(a)
if type(a[k]) == 7
call remove(current.attr, k)
continue
endif
let current.attr[k] = len(a[k]) ? substitute(a[k], '|', '${cursor}', 'g') : '${cursor}'
endfor
else
for k in keys(a)
if type(a[k]) == 7
call remove(current.attr, k)
continue
endif
let current.attr[k] = a[k]
endfor
endif
endfor
endif
if has_key(settings.html.default_attributes, current.name)
let current.name = substitute(current.name, ':.*$', '', '')
endif
break
endif
endfor
endif
" parse attributes
if len(attributes)
let attr = attributes
while len(attr)
let item = matchstr(attr, '\(\%(\%(#[{}a-zA-Z0-9_\-\$]\+\)\|\%(\[\%(\[[^\]]*\]\|"[^"]*"\|[^"\[\]]*\)\+\]\)\|\%(\.[{}a-zA-Z0-9_\-\$]\+\)*\)\)')
if g:emmet_debug > 1
echomsg 'attr=' . item
endif
if len(item) == 0
break
endif
if item[0] ==# '#'
let current.attr.id = item[1:]
let root['variables']['id'] = current.attr.id
endif
if item[0] ==# '.'
let current.attr.class = substitute(item[1:], '\.', ' ', 'g')
let root['variables']['class'] = current.attr.class
endif
if item[0] ==# '['
let atts = item[1:-2]
if matchstr(atts, '^\s*\zs[0-9a-zA-Z_\-:]\+\(="[^"]*"\|=''[^'']*''\|=[^ ''"]\+\)') ==# ''
let ks = []
if has_key(default_attributes, current.name)
let dfa = default_attributes[current.name]
let ks = type(dfa) == 3 ? len(dfa) > 0 ? keys(dfa[0]) : [] : keys(dfa)
endif
if len(ks) == 0 && has_key(default_attributes, current.name . ':src')
let dfa = default_attributes[current.name . ':src']
let ks = type(dfa) == 3 ? len(dfa) > 0 ? keys(dfa[0]) : [] : keys(dfa)
endif
if len(ks) > 0
let current.attr[ks[0]] = atts
elseif atts =~# '\.$'
let current.attr[atts[:-2]] = function('emmet#types#true')
else
let current.attr[atts] = ''
endif
else
while len(atts)
let amat = matchstr(atts, '^\s*\zs\([0-9a-zA-Z-:]\+\%(={{.\{-}}}\|="[^"]*"\|=''[^'']*''\|=[^ ''"]\+\|[^ ''"\]]*\)\{0,1}\)')
if len(amat) == 0
break
endif
let key = split(amat, '=')[0]
let Val = amat[len(key)+1:]
if key =~# '\.$' && Val ==# ''
let key = key[:-2]
unlet Val
let Val = function('emmet#types#true')
elseif Val =~# '^["'']'
let Val = Val[1:-2]
endif
let current.attr[key] = Val
if index(current.attrs_order, key) == -1
let current.attrs_order += [key]
endif
let atts = atts[stridx(atts, amat) + len(amat):]
unlet Val
endwhile
endif
endif
let attr = substitute(strpart(attr, len(item)), '^\s*', '', '')
endwhile
endif
" parse text
if tag_name =~# '^{.*}$'
let current.name = ''
let current.value = tag_name
else
let current.value = value
endif
let current.basedirect = basedirect
let current.basevalue = basevalue
let current.multiplier = multiplier
" parse step inside/outside
if !empty(last)
if operator =~# '>'
unlet! parent
let parent = last
let current.parent = last
let current.pos = last.pos + 1
else
let current.parent = parent
let current.pos = last.pos
endif
else
let current.parent = parent
let current.pos = 1
endif
if operator =~# '[<^]'
for c in range(len(operator))
let tmp = parent.parent
if empty(tmp)
break
endif
let parent = tmp
let current.parent = tmp
endfor
endif
call add(parent.child, current)
let last = current
" parse block
if block_start =~# '('
if operator =~# '>'
let last.pos += 1
endif
let last.block = 1
for n in range(len(block_start))
let pos += [last.pos]
endfor
endif
if block_end =~# ')'
for n in split(substitute(substitute(block_end, ' ', '', 'g'), ')', ',),', 'g'), ',')
if n ==# ')'
if len(pos) > 0 && last.pos >= pos[-1]
for c in range(last.pos - pos[-1])
let tmp = parent.parent
if !has_key(tmp, 'parent')
break
endif
let parent = tmp
endfor
if len(pos) > 0
call remove(pos, -1)
endif
let last = parent
let last.pos += 1
endif
elseif len(n)
let st = 0
for nc in range(len(last.child))
if last.child[nc].block
let st = nc
break
endif
endfor
let cl = last.child[st :]
let cls = []
for c in range(n[1:])
for cc in cl
if cc.multiplier > 1
let cc.basedirect = c + 1
else
let cc.basevalue = c + 1
endif
endfor
let cls += deepcopy(cl)
endfor
if st > 0
let last.child = last.child[:st-1] + cls
else
let last.child = cls
endif
endif
endfor
endif
let abbr = abbr[stridx(abbr, match) + len(match):]
if abbr == '/'
let current.empty = 1
endif
if g:emmet_debug > 1
echomsg 'str='.str
echomsg 'block_start='.block_start
echomsg 'tag_name='.tag_name
echomsg 'operator='.operator
echomsg 'attributes='.attributes
echomsg 'value='.value
echomsg 'basevalue='.basevalue
echomsg 'multiplier='.multiplier
echomsg 'block_end='.block_end
echomsg 'abbr='.abbr
echomsg 'pos='.string(pos)
echomsg '---'
endif
endwhile
return root
endfunction
function! s:dollar_add(base,no) abort
if a:base > 0
return a:base + a:no - 1
elseif a:base < 0
return a:base - a:no + 1
else
return a:no
endif
endfunction
function! emmet#lang#html#toString(settings, current, type, inline, filters, itemno, indent) abort
let settings = a:settings
let current = a:current
let type = a:type
let inline = a:inline
let filters = a:filters
let itemno = a:itemno
let indent = a:indent
let dollar_expr = emmet#getResource(type, 'dollar_expr', 1)
let q = emmet#getResource(type, 'quote_char', '"')
let ct = emmet#getResource(type, 'comment_type', 'both')
let an = emmet#getResource(type, 'attribute_name', {})
let empty_elements = emmet#getResource(type, 'empty_elements', settings.html.empty_elements)
let empty_element_suffix = emmet#getResource(type, 'empty_element_suffix', settings.html.empty_element_suffix)
if emmet#useFilter(filters, 'haml')
return emmet#lang#haml#toString(settings, current, type, inline, filters, itemno, indent)
endif
if emmet#useFilter(filters, 'slim')
return emmet#lang#slim#toString(settings, current, type, inline, filters, itemno, indent)
endif
let comment = ''
let current_name = current.name
if dollar_expr
let current_name = substitute(current_name, '\$$', itemno+1, '')
endif
let str = ''
if len(current_name) == 0
let text = current.value[1:-2]
if dollar_expr
" TODO: regexp engine specified
let nr = itemno + 1
if exists('&regexpengine')
let text = substitute(text, '\%#=1\%(\\\)\@\<!\(\$\+\)\(@-\?[0-9]\+\)\{0,1}\([^{#]\|$\)', '\=printf("%0".len(submatch(1))."d",s:dollar_add(submatch(2)[1:],nr)).submatch(3)', 'g')
else
let text = substitute(text, '\%(\\\)\@\<!\(\$\+\)\(@-\?[0-9]\+\)\{0,1}\([^{#]\|$\)', '\=printf("%0".len(submatch(1))."d",s:dollar_add(submatch(2)[1:],nr).submatch(3)', 'g')
endif
let text = substitute(text, '\${nr}', "\n", 'g')
let text = substitute(text, '\\\$', '$', 'g')
endif
return text
endif
if len(current_name) > 0
let str .= '<' . current_name
endif
for attr in emmet#util#unique(current.attrs_order + keys(current.attr))
if !has_key(current.attr, attr)
continue
endif
let Val = current.attr[attr]
if type(Val) == 2 && Val == function('emmet#types#true')
unlet Val
let Val = 'true'
if g:emmet_html5
let str .= ' ' . attr
else
let str .= ' ' . attr . '=' . q . attr . q
endif
if emmet#useFilter(filters, 'c')
if attr ==# 'id' | let comment .= '#' . Val | endif
if attr ==# 'class' | let comment .= '.' . Val | endif
endif
else
if dollar_expr
while Val =~# '\$\([^#{]\|$\)'
" TODO: regexp engine specified
if exists('&regexpengine')
let Val = substitute(Val, '\%#=1\(\$\+\)\([^{#]\|$\)', '\=printf("%0".len(submatch(1))."d", itemno+1).submatch(2)', 'g')
else
let Val = substitute(Val, '\(\$\+\)\([^{#]\|$\)', '\=printf("%0".len(submatch(1))."d", itemno+1).submatch(2)', 'g')
endif
endwhile
let attr = substitute(attr, '\$$', itemno+1, '')
endif
if attr ==# 'class' && emmet#useFilter(filters, 'bem')
let vals = split(Val, '\s\+')
let Val = ''
let lead = ''
for _val in vals
if len(Val) > 0
let Val .= ' '
endif
if _val =~# '^_'
if has_key(current.parent.attr, 'class')
let lead = current.parent.attr["class"]
if _val =~# '^__'
let Val .= lead . _val
else
let Val .= lead . ' ' . lead . _val
endif
else
let lead = split(vals[0], '_')[0]
let Val .= lead . _val
endif
elseif _val =~# '^-'
for l in split(_val, '_')
if len(Val) > 0
let Val .= ' '
endif
let l = substitute(l, '^-', '__', '')
if len(lead) == 0
let pattr = current.parent.attr
if has_key(pattr, 'class')
let lead = split(pattr['class'], '\s\+')[0]
endif
endif
let Val .= lead . l
let lead .= l . '_'
endfor
else
let Val .= _val
endif
endfor
endif
if has_key(an, attr)
let attr = an[attr]
endif
if emmet#isExtends(type, 'jsx') && Val =~ '^{.*}$'
let str .= ' ' . attr . '=' . Val
else
let str .= ' ' . attr . '=' . q . Val . q
endif
if emmet#useFilter(filters, 'c')
if attr ==# 'id' | let comment .= '#' . Val | endif
if attr ==# 'class' | let comment .= '.' . Val | endif
endif
endif
unlet Val
endfor
if len(comment) > 0 && ct ==# 'both'
let str = '<!-- ' . comment . " -->\n" . str
endif
if current.empty
let str .= ' />'
elseif stridx(','.empty_elements.',', ','.current_name.',') != -1
let str .= empty_element_suffix
else
let str .= '>'
let text = current.value[1:-2]
if dollar_expr
" TODO: regexp engine specified
let nr = itemno + 1
if exists('&regexpengine')
let text = substitute(text, '\%#=1\%(\\\)\@\<!\(\$\+\)\(@-\?[0-9]\+\)\{0,1}\([^{#]\|$\)', '\=printf("%0".len(submatch(1))."d",s:dollar_add(submatch(2)[1:],nr)).submatch(3)', 'g')
else
let text = substitute(text, '\%(\\\)\@\<!\(\$\+\)\(@-\?[0-9]\+\)\{0,1}\([^{#]\|$\)', '\=printf("%0".len(submatch(1))."d",s:dollar_add(submatch(2)[1:],nr)).submatch(3)', 'g')
endif
let text = substitute(text, '\${nr}', "\n", 'g')
let text = substitute(text, '\\\$', '$', 'g')
if text != ''
let str = substitute(str, '\("\zs$#\ze"\|\s\zs\$#"\|"\$#\ze\s\)', text, 'g')
endif
endif
let str .= text
let nc = len(current.child)
let dr = 0
if nc > 0
for n in range(nc)
let child = current.child[n]
if child.multiplier > 1 || (child.multiplier == 1 && len(child.child) > 0 && stridx(','.settings.html.inline_elements.',', ','.current_name.',') == -1) || settings.html.block_all_childless
let str .= "\n" . indent
let dr = 1
elseif len(current_name) > 0 && stridx(','.settings.html.inline_elements.',', ','.current_name.',') == -1
if nc > 1 || (len(child.name) > 0 && stridx(','.settings.html.inline_elements.',', ','.child.name.',') == -1)
let str .= "\n" . indent
let dr = 1
elseif current.multiplier == 1 && nc == 1 && len(child.name) == 0
let str .= "\n" . indent
let dr = 1
endif
endif
let inner = emmet#toString(child, type, 0, filters, itemno, indent)
let inner = substitute(inner, "^\n", '', 'g')
let inner = substitute(inner, "\n", "\n" . escape(indent, '\'), 'g')
let inner = substitute(inner, "\n" . escape(indent, '\') . '$', '', 'g')
let str .= inner
endfor
else
if settings.html.indent_blockelement && len(current_name) > 0 && stridx(','.settings.html.inline_elements.',', ','.current_name.',') == -1 || settings.html.block_all_childless
let str .= "\n" . indent . '${cursor}' . "\n"
else
let str .= '${cursor}'
endif
endif
if dr
let str .= "\n"
endif
let str .= '</' . current_name . '>'
endif
if len(comment) > 0
if ct ==# 'lastonly'
let str .= '<!-- ' . comment . ' -->'
else
let str .= "\n<!-- /" . comment . ' -->'
endif
endif
if len(current_name) > 0 && current.multiplier > 0 || stridx(','.settings.html.block_elements.',', ','.current_name.',') != -1
let str .= "\n"
endif
return str
endfunction
function! emmet#lang#html#imageSize() abort
let img_region = emmet#util#searchRegion('<img\s', '>')
if !emmet#util#regionIsValid(img_region) || !emmet#util#cursorInRegion(img_region)
return
endif
let content = emmet#util#getContent(img_region)
if content !~# '^<img[^><]\+>$'
return
endif
let current = emmet#lang#html#parseTag(content)
if empty(current) || !has_key(current.attr, 'src')
return
endif
let fn = current.attr.src
if fn =~# '^\s*$'
return
elseif fn !~# '^\(/\|http\)'
let fn = simplify(expand('%:h') . '/' . fn)
endif
let [width, height] = emmet#util#getImageSize(fn)
if width == -1 && height == -1
return
endif
let current.attr.width = width
let current.attr.height = height
let current.attrs_order += ['width', 'height']
let html = substitute(emmet#toString(current, 'html', 1), '\n', '', '')
let html = substitute(html, '\${cursor}', '', '')
call emmet#util#setContent(img_region, html)
endfunction
function! emmet#lang#html#imageEncode() abort
let img_region = emmet#util#searchRegion('<img\s', '>')
if !emmet#util#regionIsValid(img_region) || !emmet#util#cursorInRegion(img_region)
return
endif
let content = emmet#util#getContent(img_region)
if content !~# '^<img[^><]\+>$'
return
endif
let current = emmet#lang#html#parseTag(content)
if empty(current) || !has_key(current.attr, 'src')
return
endif
let fn = current.attr.src
if fn =~# '^\s*$'
return
elseif fn !~# '^\(/\|http\)'
let fn = simplify(expand('%:h') . '/' . fn)
endif
let encoded = emmet#util#imageEncodeDecode(fn, 0)
let current.attr.src = encoded
let content = substitute(emmet#toString(current, 'html', 1), '\n', '', '')
let content = substitute(content, '\${cursor}', '', '')
call emmet#util#setContent(img_region, content)
endfunction
function! emmet#lang#html#parseTag(tag) abort
let current = emmet#newNode()
let mx = '<\([a-zA-Z][a-zA-Z0-9]*\)\(\%(\s[a-zA-Z][a-zA-Z0-9]\+=\?\%([^"'' \t]\+\|"[^"]\{-}"\|''[^'']\{-}''\)\s*\)*\)\(/\{0,1}\)>'
let match = matchstr(a:tag, mx)
let current.name = substitute(match, mx, '\1', 'i')
let attrs = substitute(match, mx, '\2', 'i')
let mx = '\([a-zA-Z0-9]\+\)\(\(=[^"'' \t]\+\)\|="\([^"]\{-}\)"\|=''\([^'']\{-}\)''\)\?'
while len(attrs) > 0
let match = matchstr(attrs, mx)
if len(match) == 0
break
endif
let attr_match = matchlist(match, mx)
let name = attr_match[1]
if len(attr_match[2])
let Val = len(attr_match[3]) ? attr_match[3] : attr_match[4]
else
let Val = function('emmet#types#true')
endif
let current.attr[name] = Val
let current.attrs_order += [name]
let attrs = attrs[stridx(attrs, match) + len(match):]
endwhile
return current
endfunction
function! emmet#lang#html#toggleComment() abort
let orgpos = getpos('.')
let curpos = getpos('.')
let mx = '<\%#[^>]*>'
while 1
let block = emmet#util#searchRegion('<!--', '-->')
if emmet#util#regionIsValid(block)
let block[1][1] += 2
let content = emmet#util#getContent(block)
let content = substitute(content, '^<!--\s\(.*\)\s-->$', '\1', '')
call emmet#util#setContent(block, content)
silent! call setpos('.', orgpos)
return
endif
let block = emmet#util#searchRegion('<[^>]', '>')
if !emmet#util#regionIsValid(block)
let pos1 = searchpos('<', 'bcW')
if pos1[0] == 0 && pos1[1] == 0
return
endif
let curpos = getpos('.')
continue
endif
let pos1 = block[0]
let pos2 = block[1]
let content = emmet#util#getContent(block)
let tag_name = matchstr(content, '^<\zs/\{0,1}[^ \r\n>]\+')
if tag_name[0] ==# '/'
call setpos('.', [0, pos1[0], pos1[1], 0])
let pos2 = searchpairpos('<'. tag_name[1:] . '\>[^/>]*>', '', '</' . tag_name[1:] . '>', 'bnW')
let pos1 = searchpos('>', 'cneW')
let block = [pos2, pos1]
elseif tag_name =~# '/$'
if !emmet#util#pointInRegion(orgpos[1:2], block)
" it's broken tree
call setpos('.', orgpos)
let block = emmet#util#searchRegion('>', '<')
let content = '><!-- ' . emmet#util#getContent(block)[1:-2] . ' --><'
call emmet#util#setContent(block, content)
silent! call setpos('.', orgpos)
return
endif
else
call setpos('.', [0, pos2[0], pos2[1], 0])
let pos3 = searchpairpos('<'. tag_name . '\>[^/>]*>', '', '</' . tag_name . '>', 'nW')
if pos3 == [0, 0]
let block = [pos1, pos2]
else
call setpos('.', [0, pos3[0], pos3[1], 0])
let pos2 = searchpos('>', 'neW')
let block = [pos1, pos2]
endif
endif
if !emmet#util#regionIsValid(block)
silent! call setpos('.', orgpos)
return
endif
if emmet#util#pointInRegion(curpos[1:2], block)
let content = '<!-- ' . emmet#util#getContent(block) . ' -->'
call emmet#util#setContent(block, content)
silent! call setpos('.', orgpos)
return
endif
endwhile
endfunction
function! emmet#lang#html#balanceTag(flag) range abort
let vblock = emmet#util#getVisualBlock()
let curpos = emmet#util#getcurpos()
let settings = emmet#getSettings()
if a:flag > 0
let mx = '<\([a-zA-Z][a-zA-Z0-9:_\-]*\)[^>]*'
let last = curpos[1:2]
while 1
let pos1 = searchpos(mx, 'bW')
let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx)
let tag_name = matchstr(content, '^<\zs[a-zA-Z0-9:_\-]*\ze')
if stridx(','.settings.html.empty_elements.',', ','.tag_name.',') != -1
let pos2 = searchpos('>', 'nW')
else
let pos2 = searchpairpos('<' . tag_name . '[^>]*>', '', '</'. tag_name . '\zs>', 'nW')
endif
let block = [pos1, pos2]
if pos1 == [0, 0]
break
endif
if emmet#util#pointInRegion(last, block) && emmet#util#regionIsValid(block)
call emmet#util#selectRegion(block)
return
endif
if pos1 == last
break
endif
let last = pos1
endwhile
else
let mx = '<\([a-zA-Z][a-zA-Z0-9:_\-]*\)[^>]*>'
while 1
let pos1 = searchpos(mx, 'W')
if pos1 == [0, 0] || pos1 == curpos[1:2]
let pos1 = searchpos('>\zs', 'W')
let pos2 = searchpos('.\ze<', 'W')
let block = [pos1, pos2]
if emmet#util#regionIsValid(block)
call emmet#util#selectRegion(block)
return
endif
endif
let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx)
let tag_name = matchstr(content, '^<\zs[a-zA-Z0-9:_\-]*\ze')
if stridx(','.settings.html.empty_elements.',', ','.tag_name.',') != -1
let pos2 = searchpos('>', 'nW')
else
let pos2 = searchpairpos('<' . tag_name . '[^>]*>', '', '</'. tag_name . '\zs>', 'nW')
endif
let block = [pos1, pos2]
if pos1 == [0, 0]
break
endif
if emmet#util#regionIsValid(block)
call emmet#util#selectRegion(block)
return
endif
endwhile
endif
call setpos('.', curpos)
endfunction
function! emmet#lang#html#moveNextPrevItem(flag) abort
silent! exe "normal \<esc>"
let mx = '\%([0-9a-zA-Z-:]\+\%(="[^"]*"\|=''[^'']*''\|[^ ''">\]]*\)\{0,1}\)'
let pos = searchpos('\s'.mx.'\zs', '')
if pos != [0,0]
call feedkeys('v?\s\zs'.mx."\<cr>", '')
endif
return ''
endfunction
function! emmet#lang#html#moveNextPrev(flag) abort
let pos = search('\%(</\w\+\)\@<!\zs><\/\|\(""\)\|^\(\s*\)$', a:flag ? 'Wpb' : 'Wp')
if pos == 3
startinsert!
elseif pos != 0
silent! normal! l
startinsert
endif
return ''
endfunction
function! emmet#lang#html#splitJoinTag() abort
let curpos = emmet#util#getcurpos()
let mx = '<\(/\{0,1}[a-zA-Z][-a-zA-Z0-9:_\-]*\)\%(\%(\s[a-zA-Z][a-zA-Z0-9]\+=\%([^"'' \t]\+\|"[^"]\{-}"\|''[^'']\{-}''\)\s*\)*\)\s*\%(/\{0,1}\)>'
while 1
let old = getpos('.')[1:2]
let pos1 = searchpos(mx, 'bcnW')
let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx)
let tag_name = substitute(content, '^<\(/\{0,1}[a-zA-Z][a-zA-Z0-9:_\-]*\).*$', '\1', '')
let block = [pos1, [pos1[0], pos1[1] + len(content) - 1]]
if content[-2:] ==# '/>' && emmet#util#cursorInRegion(block)
let content = substitute(content[:-3], '\s*$', '', '') . '></' . tag_name . '>'
call emmet#util#setContent(block, content)
call setpos('.', [0, block[0][0], block[0][1], 0])
return
endif
if tag_name[0] ==# '/'
let pos1 = searchpos('<' . tag_name[1:] . '[^a-zA-Z0-9]', 'bcnW')
call setpos('.', [0, pos1[0], pos1[1], 0])
let pos2 = searchpairpos('<'. tag_name[1:] . '\>[^/>]*>', '', '</' . tag_name[1:] . '>', 'W')
else
let pos2 = searchpairpos('<'. tag_name . '[^/>]*>', '', '</' . tag_name . '>', 'W')
endif
if pos2 == [0, 0]
return
endif
let pos2 = searchpos('>', 'neW')
let block = [pos1, pos2]
if emmet#util#pointInRegion(curpos[1:2], block)
let content = matchstr(content, mx)[:-2] . ' />'
call emmet#util#setContent(block, content)
call setpos('.', [0, block[0][0], block[0][1], 0])
return
endif
if block[0][0] > 0
call setpos('.', [0, block[0][0]-1, block[0][1], 0])
else
call setpos('.', curpos)
return
endif
if pos1 == old
call setpos('.', curpos)
return
endif
endwhile
endfunction
function! emmet#lang#html#removeTag() abort
let curpos = emmet#util#getcurpos()
let mx = '<\(/\{0,1}[a-zA-Z][-a-zA-Z0-9:_\-]*\)\%(\%(\s[a-zA-Z][a-zA-Z0-9]\+=\%([^"'' \t]\+\|"[^"]\{-}"\|''[^'']\{-}''\)\s*\)*\)\s*\%(/\{0,1}\)>'
let pos1 = searchpos(mx, 'bcnW')
let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx)
let tag_name = substitute(content, '^<\(/\{0,1}[a-zA-Z][a-zA-Z0-9:_\-]*\).*$', '\1', '')
let block = [pos1, [pos1[0], pos1[1] + len(content) - 1]]
if content[-2:] ==# '/>' && emmet#util#cursorInRegion(block)
call emmet#util#setContent(block, '')
call setpos('.', [0, block[0][0], block[0][1], 0])
return
endif
if tag_name[0] ==# '/'
let pos1 = searchpos('<' . tag_name[1:] . '[^a-zA-Z0-9]', 'bcnW')
call setpos('.', [0, pos1[0], pos1[1], 0])
let pos2 = searchpairpos('<'. tag_name[1:] . '\>[^/>]*>', '', '</' . tag_name[1:] . '>', 'W')
else
let pos2 = searchpairpos('<'. tag_name . '[^/>]*>', '', '</' . tag_name . '>', 'W')
endif
if pos2 == [0, 0]
return
endif
let pos2 = searchpos('>', 'neW')
let block = [pos1, pos2]
if emmet#util#pointInRegion(curpos[1:2], block)
call emmet#util#setContent(block, '')
call setpos('.', [0, block[0][0], block[0][1], 0])
return
endif
if block[0][0] > 0
call setpos('.', [0, block[0][0]-1, block[0][1], 0])
else
call setpos('.', curpos)
endif
endfunction
function! emmet#lang#html#mergeLines() abort
let curpos = emmet#util#getcurpos()
let settings = emmet#getSettings()
let mx = '<\([a-zA-Z][a-zA-Z0-9:_\-]*\)[^>]*>'
let last = curpos[1:2]
while 1
let pos1 = searchpos(mx, 'bcW')
let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx)
echomsg string(content)
let tag_name = matchstr(content, '^<\zs[a-zA-Z0-9:_\-]*\ze')
if stridx(','.settings.html.empty_elements.',', ','.tag_name.',') != -1
let pos2 = searchpos('>', 'nW')
else
let pos2 = searchpairpos('<' . tag_name . '[^>]*>', '', '</'. tag_name . '\zs>', 'nW')
endif
if pos1 == [0, 0] || pos2 == [0, 0]
call setpos('.', curpos)
return
endif
let block = [pos1, pos2]
if emmet#util#pointInRegion(last, block) && emmet#util#regionIsValid(block)
break
endif
if pos1 == last
call setpos('.', curpos)
return
endif
let last = pos1
endwhile
let content = emmet#util#getContent(block)
let mx = '<\(/\{0,1}[a-zA-Z][-a-zA-Z0-9:_\-]*\)\%(\%(\s[a-zA-Z][a-zA-Z0-9]\+=\%([^"'' \t]\+\|"[^"]\{-}"\|''[^'']\{-}''\)\s*\)*\)\s*\%(/\{0,1}\)>'
let content = join(map(split(content, mx . '\zs\s*'), 'trim(v:val)'), '')
call emmet#util#setContent(block, content)
if block[0][0] > 0
call setpos('.', [0, block[0][0], block[0][1], 0])
else
call setpos('.', curpos)
endif
endfunction