summaryrefslogtreecommitdiff
path: root/config/vim/autoload/emmet/lang/html.vim
diff options
context:
space:
mode:
Diffstat (limited to 'config/vim/autoload/emmet/lang/html.vim')
-rw-r--r--config/vim/autoload/emmet/lang/html.vim1036
1 files changed, 1036 insertions, 0 deletions
diff --git a/config/vim/autoload/emmet/lang/html.vim b/config/vim/autoload/emmet/lang/html.vim
new file mode 100644
index 0000000..fad887a
--- /dev/null
+++ b/config/vim/autoload/emmet/lang/html.vim
@@ -0,0 +1,1036 @@
+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