Artifact
dc0e431a31a900f7a0a5d0d091b5eb0ddda65f540ab0453990225e978fb31ddf:
import makeElement from './../common/util/dom/make-element'
import setInnerHTML from './../common/util/dom/set-inner-HTML'
import $ from './../common/util/dom/$'
import {
IE_VERSION,
RE_SPECIAL_TAGS,
RE_SPECIAL_TAGS_NO_OPTION
} from './../common/global-variables'
/*
Includes hacks needed for the Internet Explorer version 9 and below
See: http://kangax.github.io/compat-table/es5/#ie8
http://codeplanet.io/dropping-ie8/
*/
const
reHasYield = /<yield\b/i,
reYieldAll = /<yield\s*(?:\/>|>([\S\s]*?)<\/yield\s*>|>)/ig,
reYieldSrc = /<yield\s+to=['"]([^'">]*)['"]\s*>([\S\s]*?)<\/yield\s*>/ig,
reYieldDest = /<yield\s+from=['"]?([-\w]+)['"]?\s*(?:\/>|>([\S\s]*?)<\/yield\s*>)/ig,
rootEls = { tr: 'tbody', th: 'tr', td: 'tr', col: 'colgroup' },
tblTags = IE_VERSION && IE_VERSION < 10 ? RE_SPECIAL_TAGS : RE_SPECIAL_TAGS_NO_OPTION,
GENERIC = 'div',
SVG = 'svg'
/*
Creates the root element for table or select child elements:
tr/th/td/thead/tfoot/tbody/caption/col/colgroup/option/optgroup
*/
function specialTags(el, tmpl, tagName) {
let
select = tagName[0] === 'o',
parent = select ? 'select>' : 'table>'
// trim() is important here, this ensures we don't have artifacts,
// so we can check if we have only one element inside the parent
el.innerHTML = '<' + parent + tmpl.trim() + '</' + parent
parent = el.firstChild
// returns the immediate parent if tr/th/td/col is the only element, if not
// returns the whole tree, as this can include additional elements
/* istanbul ignore next */
if (select) {
parent.selectedIndex = -1 // for IE9, compatible w/current riot behavior
} else {
// avoids insertion of cointainer inside container (ex: tbody inside tbody)
const tname = rootEls[tagName]
if (tname && parent.childElementCount === 1) parent = $(tname, parent)
}
return parent
}
/*
Replace the yield tag from any tag template with the innerHTML of the
original tag in the page
*/
function replaceYield(tmpl, html) {
// do nothing if no yield
if (!reHasYield.test(tmpl)) return tmpl
// be careful with #1343 - string on the source having `$1`
const src = {}
html = html && html.replace(reYieldSrc, function (_, ref, text) {
src[ref] = src[ref] || text // preserve first definition
return ''
}).trim()
return tmpl
.replace(reYieldDest, function (_, ref, def) { // yield with from - to attrs
return src[ref] || def || ''
})
.replace(reYieldAll, function (_, def) { // yield without any "from"
return html || def || ''
})
}
/**
* Creates a DOM element to wrap the given content. Normally an `DIV`, but can be
* also a `TABLE`, `SELECT`, `TBODY`, `TR`, or `COLGROUP` element.
*
* @param { String } tmpl - The template coming from the custom tag definition
* @param { String } html - HTML content that comes from the DOM element where you
* will mount the tag, mostly the original tag in the page
* @param { Boolean } isSvg - true if the root node is an svg
* @returns { HTMLElement } DOM element with _tmpl_ merged through `YIELD` with the _html_.
*/
export default function mkdom(tmpl, html, isSvg) {
const match = tmpl && tmpl.match(/^\s*<([-\w]+)/)
const tagName = match && match[1].toLowerCase()
let el = makeElement(isSvg ? SVG : GENERIC)
// replace all the yield tags with the tag inner html
tmpl = replaceYield(tmpl, html)
/* istanbul ignore next */
if (tblTags.test(tagName))
el = specialTags(el, tmpl, tagName)
else
setInnerHTML(el, tmpl, isSvg)
return el
}