webapp.vendor.js.riot+compiler.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of leshan-bsserver-demo Show documentation
Show all versions of leshan-bsserver-demo Show documentation
A LWM2M bootstrap demonstration server running an embedded Jetty server
/* Riot v3.13.2, @license MIT */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.riot = factory());
}(this, (function () { 'use strict';
/**
* Shorter and fast way to select a single node in the DOM
* @param { String } selector - unique dom selector
* @param { Object } ctx - DOM node where the target of our search will is located
* @returns { Object } dom node found
*/
function $(selector, ctx) {
return (ctx || document).querySelector(selector)
}
var
// be aware, internal usage
// ATTENTION: prefix the global dynamic variables with `__`
// tags instances cache
__TAGS_CACHE = [],
// tags implementation cache
__TAG_IMPL = {},
YIELD_TAG = 'yield',
/**
* Const
*/
GLOBAL_MIXIN = '__global_mixin',
// riot specific prefixes or attributes
ATTRS_PREFIX = 'riot-',
// Riot Directives
REF_DIRECTIVES = ['ref', 'data-ref'],
IS_DIRECTIVE = 'data-is',
CONDITIONAL_DIRECTIVE = 'if',
LOOP_DIRECTIVE = 'each',
LOOP_NO_REORDER_DIRECTIVE = 'no-reorder',
SHOW_DIRECTIVE = 'show',
HIDE_DIRECTIVE = 'hide',
KEY_DIRECTIVE = 'key',
RIOT_EVENTS_KEY = '__riot-events__',
// for typeof == '' comparisons
T_STRING = 'string',
T_OBJECT = 'object',
T_UNDEF = 'undefined',
T_FUNCTION = 'function',
XLINK_NS = 'http://www.w3.org/1999/xlink',
SVG_NS = 'http://www.w3.org/2000/svg',
XLINK_REGEX = /^xlink:(\w+)/,
WIN = typeof window === T_UNDEF ? /* istanbul ignore next */ undefined : window,
// special native tags that cannot be treated like the others
RE_SPECIAL_TAGS = /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?|opt(?:ion|group))$/,
RE_SPECIAL_TAGS_NO_OPTION = /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?)$/,
RE_EVENTS_PREFIX = /^on/,
RE_HTML_ATTRS = /([-\w]+) ?= ?(?:"([^"]*)|'([^']*)|({[^}]*}))/g,
// some DOM attributes must be normalized
CASE_SENSITIVE_ATTRIBUTES = {
'viewbox': 'viewBox',
'preserveaspectratio': 'preserveAspectRatio'
},
/**
* Matches boolean HTML attributes in the riot tag definition.
* With a long list like this, a regex is faster than `[].indexOf` in most browsers.
* @const {RegExp}
* @see [attributes.md](https://github.com/riot/compiler/blob/dev/doc/attributes.md)
*/
RE_BOOL_ATTRS = /^(?:disabled|checked|readonly|required|allowfullscreen|auto(?:focus|play)|compact|controls|default|formnovalidate|hidden|ismap|itemscope|loop|multiple|muted|no(?:resize|shade|validate|wrap)?|open|reversed|seamless|selected|sortable|truespeed|typemustmatch)$/,
// version# for IE 8-11, 0 for others
IE_VERSION = (WIN && WIN.document || /* istanbul ignore next */ {}).documentMode | 0;
/**
* Create a generic DOM node
* @param { String } name - name of the DOM node we want to create
* @returns { Object } DOM node just created
*/
function makeElement(name) {
return name === 'svg' ? document.createElementNS(SVG_NS, name) : document.createElement(name)
}
/**
* Set any DOM attribute
* @param { Object } dom - DOM node we want to update
* @param { String } name - name of the property we want to set
* @param { String } val - value of the property we want to set
*/
function setAttribute(dom, name, val) {
var xlink = XLINK_REGEX.exec(name);
if (xlink && xlink[1])
{ dom.setAttributeNS(XLINK_NS, xlink[1], val); }
else
{ dom.setAttribute(name, val); }
}
var styleNode;
// Create cache and shortcut to the correct property
var cssTextProp;
var byName = {};
var needsInject = false;
// skip the following code on the server
if (WIN) {
styleNode = ((function () {
// create a new style element with the correct type
var newNode = makeElement('style');
// replace any user node or insert the new one into the head
var userNode = $('style[type=riot]');
setAttribute(newNode, 'type', 'text/css');
/* istanbul ignore next */
if (userNode) {
if (userNode.id) { newNode.id = userNode.id; }
userNode.parentNode.replaceChild(newNode, userNode);
} else { document.head.appendChild(newNode); }
return newNode
}))();
cssTextProp = styleNode.styleSheet;
}
/**
* Object that will be used to inject and manage the css of every tag instance
*/
var styleManager = {
styleNode: styleNode,
/**
* Save a tag style to be later injected into DOM
* @param { String } css - css string
* @param { String } name - if it's passed we will map the css to a tagname
*/
add: function add(css, name) {
byName[name] = css;
needsInject = true;
},
/**
* Inject all previously saved tag styles into DOM
* innerHTML seems slow: http://jsperf.com/riot-insert-style
*/
inject: function inject() {
if (!WIN || !needsInject) { return }
needsInject = false;
var style = Object.keys(byName)
.map(function (k) { return byName[k]; })
.join('\n');
/* istanbul ignore next */
if (cssTextProp) { cssTextProp.cssText = style; }
else { styleNode.innerHTML = style; }
},
/**
* Remove a tag style of injected DOM later.
* @param {String} name a registered tagname
*/
remove: function remove(name) {
delete byName[name];
needsInject = true;
}
};
/**
* The riot template engine
* @version v3.0.8
*/
/* istanbul ignore next */
var skipRegex = (function () { //eslint-disable-line no-unused-vars
var beforeReChars = '[{(,;:?=|&!^~>%*/';
var beforeReWords = [
'case',
'default',
'do',
'else',
'in',
'instanceof',
'prefix',
'return',
'typeof',
'void',
'yield'
];
var wordsLastChar = beforeReWords.reduce(function (s, w) {
return s + w.slice(-1)
}, '');
var RE_REGEX = /^\/(?=[^*>/])[^[/\\]*(?:(?:\\.|\[(?:\\.|[^\]\\]*)*\])[^[\\/]*)*?\/[gimuy]*/;
var RE_VN_CHAR = /[$\w]/;
function prev (code, pos) {
while (--pos >= 0 && /\s/.test(code[pos])){ }
return pos
}
function _skipRegex (code, start) {
var re = /.*/g;
var pos = re.lastIndex = start++;
var match = re.exec(code)[0].match(RE_REGEX);
if (match) {
var next = pos + match[0].length;
pos = prev(code, pos);
var c = code[pos];
if (pos < 0 || ~beforeReChars.indexOf(c)) {
return next
}
if (c === '.') {
if (code[pos - 1] === '.') {
start = next;
}
} else if (c === '+' || c === '-') {
if (code[--pos] !== c ||
(pos = prev(code, pos)) < 0 ||
!RE_VN_CHAR.test(code[pos])) {
start = next;
}
} else if (~wordsLastChar.indexOf(c)) {
var end = pos + 1;
while (--pos >= 0 && RE_VN_CHAR.test(code[pos])){ }
if (~beforeReWords.indexOf(code.slice(pos + 1, end))) {
start = next;
}
}
}
return start
}
return _skipRegex
})();
/**
* riot.util.brackets
*
* - `brackets ` - Returns a string or regex based on its parameter
* - `brackets.set` - Change the current riot brackets
*
* @module
*/
/* global riot */
/* istanbul ignore next */
var brackets = (function (UNDEF) {
var
REGLOB = 'g',
R_MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g,
R_STRINGS = /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|`[^`\\]*(?:\\[\S\s][^`\\]*)*`/g,
S_QBLOCKS = R_STRINGS.source + '|' +
/(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source + '|' +
/\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?([^<]\/)[gim]*/.source,
UNSUPPORTED = RegExp('[\\' + 'x00-\\x1F<>a-zA-Z0-9\'",;\\\\]'),
NEED_ESCAPE = /(?=[[\]()*+?.^$|])/g,
S_QBLOCK2 = R_STRINGS.source + '|' + /(\/)(?![*\/])/.source,
FINDBRACES = {
'(': RegExp('([()])|' + S_QBLOCK2, REGLOB),
'[': RegExp('([[\\]])|' + S_QBLOCK2, REGLOB),
'{': RegExp('([{}])|' + S_QBLOCK2, REGLOB)
},
DEFAULT = '{ }';
var _pairs = [
'{', '}',
'{', '}',
/{[^}]*}/,
/\\([{}])/g,
/\\({)|{/g,
RegExp('\\\\(})|([[({])|(})|' + S_QBLOCK2, REGLOB),
DEFAULT,
/^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/,
/(^|[^\\]){=[\S\s]*?}/
];
var
cachedBrackets = UNDEF,
_regex,
_cache = [],
_settings;
function _loopback (re) { return re }
function _rewrite (re, bp) {
if (!bp) { bp = _cache; }
return new RegExp(
re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : ''
)
}
function _create (pair) {
if (pair === DEFAULT) { return _pairs }
var arr = pair.split(' ');
if (arr.length !== 2 || UNSUPPORTED.test(pair)) {
throw new Error('Unsupported brackets "' + pair + '"')
}
arr = arr.concat(pair.replace(NEED_ESCAPE, '\\').split(' '));
arr[4] = _rewrite(arr[1].length > 1 ? /{[\S\s]*?}/ : _pairs[4], arr);
arr[5] = _rewrite(pair.length > 3 ? /\\({|})/g : _pairs[5], arr);
arr[6] = _rewrite(_pairs[6], arr);
arr[7] = RegExp('\\\\(' + arr[3] + ')|([[({])|(' + arr[3] + ')|' + S_QBLOCK2, REGLOB);
arr[8] = pair;
return arr
}
function _brackets (reOrIdx) {
return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _cache[reOrIdx]
}
_brackets.split = function split (str, tmpl, _bp) {
// istanbul ignore next: _bp is for the compiler
if (!_bp) { _bp = _cache; }
var
parts = [],
match,
isexpr,
start,
pos,
re = _bp[6];
var qblocks = [];
var prevStr = '';
var mark, lastIndex;
isexpr = start = re.lastIndex = 0;
while ((match = re.exec(str))) {
lastIndex = re.lastIndex;
pos = match.index;
if (isexpr) {
if (match[2]) {
var ch = match[2];
var rech = FINDBRACES[ch];
var ix = 1;
rech.lastIndex = lastIndex;
while ((match = rech.exec(str))) {
if (match[1]) {
if (match[1] === ch) { ++ix; }
else if (!--ix) { break }
} else {
rech.lastIndex = pushQBlock(match.index, rech.lastIndex, match[2]);
}
}
re.lastIndex = ix ? str.length : rech.lastIndex;
continue
}
if (!match[3]) {
re.lastIndex = pushQBlock(pos, lastIndex, match[4]);
continue
}
}
if (!match[1]) {
unescapeStr(str.slice(start, pos));
start = re.lastIndex;
re = _bp[6 + (isexpr ^= 1)];
re.lastIndex = start;
}
}
if (str && start < str.length) {
unescapeStr(str.slice(start));
}
parts.qblocks = qblocks;
return parts
function unescapeStr (s) {
if (prevStr) {
s = prevStr + s;
prevStr = '';
}
if (tmpl || isexpr) {
parts.push(s && s.replace(_bp[5], '$1'));
} else {
parts.push(s);
}
}
function pushQBlock(_pos, _lastIndex, slash) { //eslint-disable-line
if (slash) {
_lastIndex = skipRegex(str, _pos);
}
if (tmpl && _lastIndex > _pos + 2) {
mark = '\u2057' + qblocks.length + '~';
qblocks.push(str.slice(_pos, _lastIndex));
prevStr += str.slice(start, _pos) + mark;
start = _lastIndex;
}
return _lastIndex
}
};
_brackets.hasExpr = function hasExpr (str) {
return _cache[4].test(str)
};
_brackets.loopKeys = function loopKeys (expr) {
var m = expr.match(_cache[9]);
return m
? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] }
: { val: expr.trim() }
};
_brackets.array = function array (pair) {
return pair ? _create(pair) : _cache
};
function _reset (pair) {
if ((pair || (pair = DEFAULT)) !== _cache[8]) {
_cache = _create(pair);
_regex = pair === DEFAULT ? _loopback : _rewrite;
_cache[9] = _regex(_pairs[9]);
}
cachedBrackets = pair;
}
function _setSettings (o) {
var b;
o = o || {};
b = o.brackets;
Object.defineProperty(o, 'brackets', {
set: _reset,
get: function () { return cachedBrackets },
enumerable: true
});
_settings = o;
_reset(b);
}
Object.defineProperty(_brackets, 'settings', {
set: _setSettings,
get: function () { return _settings }
});
/* istanbul ignore next: in the browser riot is always in the scope */
_brackets.settings = typeof riot !== 'undefined' && riot.settings || {};
_brackets.set = _reset;
_brackets.skipRegex = skipRegex;
_brackets.R_STRINGS = R_STRINGS;
_brackets.R_MLCOMMS = R_MLCOMMS;
_brackets.S_QBLOCKS = S_QBLOCKS;
_brackets.S_QBLOCK2 = S_QBLOCK2;
return _brackets
})();
/**
* @module tmpl
*
* tmpl - Root function, returns the template value, render with data
* tmpl.hasExpr - Test the existence of a expression inside a string
* tmpl.loopKeys - Get the keys for an 'each' loop (used by `_each`)
*/
/* istanbul ignore next */
var tmpl = (function () {
var _cache = {};
function _tmpl (str, data) {
if (!str) { return str }
return (_cache[str] || (_cache[str] = _create(str))).call(
data, _logErr.bind({
data: data,
tmpl: str
})
)
}
_tmpl.hasExpr = brackets.hasExpr;
_tmpl.loopKeys = brackets.loopKeys;
// istanbul ignore next
_tmpl.clearCache = function () { _cache = {}; };
_tmpl.errorHandler = null;
function _logErr (err, ctx) {
err.riotData = {
tagName: ctx && ctx.__ && ctx.__.tagName,
_riot_id: ctx && ctx._riot_id //eslint-disable-line camelcase
};
if (_tmpl.errorHandler) { _tmpl.errorHandler(err); }
else if (
typeof console !== 'undefined' &&
typeof console.error === 'function'
) {
console.error(err.message);
console.log('<%s> %s', err.riotData.tagName || 'Unknown tag', this.tmpl); // eslint-disable-line
console.log(this.data); // eslint-disable-line
}
}
function _create (str) {
var expr = _getTmpl(str);
if (expr.slice(0, 11) !== 'try{return ') { expr = 'return ' + expr; }
return new Function('E', expr + ';') // eslint-disable-line no-new-func
}
var RE_DQUOTE = /\u2057/g;
var RE_QBMARK = /\u2057(\d+)~/g;
function _getTmpl (str) {
var parts = brackets.split(str.replace(RE_DQUOTE, '"'), 1);
var qstr = parts.qblocks;
var expr;
if (parts.length > 2 || parts[0]) {
var i, j, list = [];
for (i = j = 0; i < parts.length; ++i) {
expr = parts[i];
if (expr && (expr = i & 1
? _parseExpr(expr, 1, qstr)
: '"' + expr
.replace(/\\/g, '\\\\')
.replace(/\r\n?|\n/g, '\\n')
.replace(/"/g, '\\"') +
'"'
)) { list[j++] = expr; }
}
expr = j < 2 ? list[0]
: '[' + list.join(',') + '].join("")';
} else {
expr = _parseExpr(parts[1], 0, qstr);
}
if (qstr.length) {
expr = expr.replace(RE_QBMARK, function (_, pos) {
return qstr[pos]
.replace(/\r/g, '\\r')
.replace(/\n/g, '\\n')
});
}
return expr
}
var RE_CSNAME = /^(?:(-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*)|\u2057(\d+)~):/;
var
RE_BREND = {
'(': /[()]/g,
'[': /[[\]]/g,
'{': /[{}]/g
};
function _parseExpr (expr, asText, qstr) {
expr = expr
.replace(/\s+/g, ' ').trim()
.replace(/\ ?([[\({},?\.:])\ ?/g, '$1');
if (expr) {
var
list = [],
cnt = 0,
match;
while (expr &&
(match = expr.match(RE_CSNAME)) &&
!match.index
) {
var
key,
jsb,
re = /,|([[{(])|$/g;
expr = RegExp.rightContext;
key = match[2] ? qstr[match[2]].slice(1, -1).trim().replace(/\s+/g, ' ') : match[1];
while (jsb = (match = re.exec(expr))[1]) { skipBraces(jsb, re); }
jsb = expr.slice(0, match.index);
expr = RegExp.rightContext;
list[cnt++] = _wrapExpr(jsb, 1, key);
}
expr = !cnt ? _wrapExpr(expr, asText)
: cnt > 1 ? '[' + list.join(',') + '].join(" ").trim()' : list[0];
}
return expr
function skipBraces (ch, re) {
var
mm,
lv = 1,
ir = RE_BREND[ch];
ir.lastIndex = re.lastIndex;
while (mm = ir.exec(expr)) {
if (mm[0] === ch) { ++lv; }
else if (!--lv) { break }
}
re.lastIndex = lv ? expr.length : ir.lastIndex;
}
}
// istanbul ignore next: not both
var // eslint-disable-next-line max-len
JS_CONTEXT = '"in this?this:' + (typeof window !== 'object' ? 'global' : 'window') + ').',
JS_VARNAME = /[,{][\$\w]+(?=:)|(^ *|[^$\w\.{])(?!(?:typeof|true|false|null|undefined|in|instanceof|is(?:Finite|NaN)|void|NaN|new|Date|RegExp|Math)(?![$\w]))([$_A-Za-z][$\w]*)/g,
JS_NOPROPS = /^(?=(\.[$\w]+))\1(?:[^.[(]|$)/;
function _wrapExpr (expr, asText, key) {
var tb;
expr = expr.replace(JS_VARNAME, function (match, p, mvar, pos, s) {
if (mvar) {
pos = tb ? 0 : pos + match.length;
if (mvar !== 'this' && mvar !== 'global' && mvar !== 'window') {
match = p + '("' + mvar + JS_CONTEXT + mvar;
if (pos) { tb = (s = s[pos]) === '.' || s === '(' || s === '['; }
} else if (pos) {
tb = !JS_NOPROPS.test(s.slice(pos));
}
}
return match
});
if (tb) {
expr = 'try{return ' + expr + '}catch(e){E(e,this)}';
}
if (key) {
expr = (tb
? 'function(){' + expr + '}.call(this)' : '(' + expr + ')'
) + '?"' + key + '":""';
} else if (asText) {
expr = 'function(v){' + (tb
? expr.replace('return ', 'v=') : 'v=(' + expr + ')'
) + ';return v||v===0?v:""}.call(this)';
}
return expr
}
_tmpl.version = brackets.version = 'v3.0.8';
return _tmpl
})();
/* istanbul ignore next */
var observable = function(el) {
/**
* Extend the original object or create a new empty one
* @type { Object }
*/
el = el || {};
/**
* Private variables
*/
var callbacks = {},
slice = Array.prototype.slice;
/**
* Public Api
*/
// extend the el object adding the observable methods
Object.defineProperties(el, {
/**
* Listen to the given `event` ands
* execute the `callback` each time an event is triggered.
* @param { String } event - event id
* @param { Function } fn - callback function
* @returns { Object } el
*/
on: {
value: function(event, fn) {
if (typeof fn == 'function')
{ (callbacks[event] = callbacks[event] || []).push(fn); }
return el
},
enumerable: false,
writable: false,
configurable: false
},
/**
* Removes the given `event` listeners
* @param { String } event - event id
* @param { Function } fn - callback function
* @returns { Object } el
*/
off: {
value: function(event, fn) {
if (event == '*' && !fn) { callbacks = {}; }
else {
if (fn) {
var arr = callbacks[event];
for (var i = 0, cb; cb = arr && arr[i]; ++i) {
if (cb == fn) { arr.splice(i--, 1); }
}
} else { delete callbacks[event]; }
}
return el
},
enumerable: false,
writable: false,
configurable: false
},
/**
* Listen to the given `event` and
* execute the `callback` at most once
* @param { String } event - event id
* @param { Function } fn - callback function
* @returns { Object } el
*/
one: {
value: function(event, fn) {
function on() {
el.off(event, on);
fn.apply(el, arguments);
}
return el.on(event, on)
},
enumerable: false,
writable: false,
configurable: false
},
/**
* Execute all callback functions that listen to
* the given `event`
* @param { String } event - event id
* @returns { Object } el
*/
trigger: {
value: function(event) {
var arguments$1 = arguments;
// getting the arguments
var arglen = arguments.length - 1,
args = new Array(arglen),
fns,
fn,
i;
for (i = 0; i < arglen; i++) {
args[i] = arguments$1[i + 1]; // skip first argument
}
fns = slice.call(callbacks[event] || [], 0);
for (i = 0; fn = fns[i]; ++i) {
fn.apply(el, args);
}
if (callbacks['*'] && event != '*')
{ el.trigger.apply(el, ['*', event].concat(args)); }
return el
},
enumerable: false,
writable: false,
configurable: false
}
});
return el
};
/**
* Short alias for Object.getOwnPropertyDescriptor
*/
function getPropDescriptor (o, k) {
return Object.getOwnPropertyDescriptor(o, k)
}
/**
* Check if passed argument is undefined
* @param { * } value -
* @returns { Boolean } -
*/
function isUndefined(value) {
return typeof value === T_UNDEF
}
/**
* Check whether object's property could be overridden
* @param { Object } obj - source object
* @param { String } key - object property
* @returns { Boolean } true if writable
*/
function isWritable(obj, key) {
var descriptor = getPropDescriptor(obj, key);
return isUndefined(obj[key]) || descriptor && descriptor.writable
}
/**
* Extend any object with other properties
* @param { Object } src - source object
* @returns { Object } the resulting extended object
*
* var obj = { foo: 'baz' }
* extend(obj, {bar: 'bar', foo: 'bar'})
* console.log(obj) => {bar: 'bar', foo: 'bar'}
*
*/
function extend(src) {
var obj;
var i = 1;
var args = arguments;
var l = args.length;
for (; i < l; i++) {
if (obj = args[i]) {
for (var key in obj) {
// check if this property of the source object could be overridden
if (isWritable(src, key))
{ src[key] = obj[key]; }
}
}
}
return src
}
/**
* Alias for Object.create
*/
function create(src) {
return Object.create(src)
}
var settings = extend(create(brackets.settings), {
skipAnonymousTags: true,
// the "value" attributes will be preserved
keepValueAttributes: false,
// handle the auto updates on any DOM event
autoUpdate: true
});
/**
* Shorter and fast way to select multiple nodes in the DOM
* @param { String } selector - DOM selector
* @param { Object } ctx - DOM node where the targets of our search will is located
* @returns { Object } dom nodes found
*/
function $$(selector, ctx) {
return [].slice.call((ctx || document).querySelectorAll(selector))
}
/**
* Create a document text node
* @returns { Object } create a text node to use as placeholder
*/
function createDOMPlaceholder() {
return document.createTextNode('')
}
/**
* Toggle the visibility of any DOM node
* @param { Object } dom - DOM node we want to hide
* @param { Boolean } show - do we want to show it?
*/
function toggleVisibility(dom, show) {
dom.style.display = show ? '' : 'none';
dom.hidden = show ? false : true;
}
/**
* Get the value of any DOM attribute on a node
* @param { Object } dom - DOM node we want to parse
* @param { String } name - name of the attribute we want to get
* @returns { String | undefined } name of the node attribute whether it exists
*/
function getAttribute(dom, name) {
return dom.getAttribute(name)
}
/**
* Remove any DOM attribute from a node
* @param { Object } dom - DOM node we want to update
* @param { String } name - name of the property we want to remove
*/
function removeAttribute(dom, name) {
dom.removeAttribute(name);
}
/**
* Set the inner html of any DOM node SVGs included
* @param { Object } container - DOM node where we'll inject new html
* @param { String } html - html to inject
* @param { Boolean } isSvg - svg tags should be treated a bit differently
*/
/* istanbul ignore next */
function setInnerHTML(container, html, isSvg) {
// innerHTML is not supported on svg tags so we neet to treat them differently
if (isSvg) {
var node = container.ownerDocument.importNode(
new DOMParser()
.parseFromString((""), 'application/xml')
.documentElement,
true
);
container.appendChild(node);
} else {
container.innerHTML = html;
}
}
/**
* Minimize risk: only zero or one _space_ between attr & value
* @param { String } html - html string we want to parse
* @param { Function } fn - callback function to apply on any attribute found
*/
function walkAttributes(html, fn) {
if (!html) { return }
var m;
while (m = RE_HTML_ATTRS.exec(html))
{ fn(m[1].toLowerCase(), m[2] || m[3] || m[4]); }
}
/**
* Create a document fragment
* @returns { Object } document fragment
*/
function createFragment() {
return document.createDocumentFragment()
}
/**
* Insert safely a tag to fix #1962 #1649
* @param { HTMLElement } root - children container
* @param { HTMLElement } curr - node to insert
* @param { HTMLElement } next - node that should preceed the current node inserted
*/
function safeInsert(root, curr, next) {
root.insertBefore(curr, next.parentNode && next);
}
/**
* Convert a style object to a string
* @param { Object } style - style object we need to parse
* @returns { String } resulting css string
* @example
* styleObjectToString({ color: 'red', height: '10px'}) // => 'color: red; height: 10px'
*/
function styleObjectToString(style) {
return Object.keys(style).reduce(function (acc, prop) {
return (acc + " " + prop + ": " + (style[prop]) + ";")
}, '')
}
/**
* Walk down recursively all the children tags starting dom node
* @param { Object } dom - starting node where we will start the recursion
* @param { Function } fn - callback to transform the child node just found
* @param { Object } context - fn can optionally return an object, which is passed to children
*/
function walkNodes(dom, fn, context) {
if (dom) {
var res = fn(dom, context);
var next;
// stop the recursion
if (res === false) { return }
dom = dom.firstChild;
while (dom) {
next = dom.nextSibling;
walkNodes(dom, fn, res);
dom = next;
}
}
}
var dom = /*#__PURE__*/Object.freeze({
$$: $$,
$: $,
createDOMPlaceholder: createDOMPlaceholder,
mkEl: makeElement,
setAttr: setAttribute,
toggleVisibility: toggleVisibility,
getAttr: getAttribute,
remAttr: removeAttribute,
setInnerHTML: setInnerHTML,
walkAttrs: walkAttributes,
createFrag: createFragment,
safeInsert: safeInsert,
styleObjectToString: styleObjectToString,
walkNodes: walkNodes
});
/**
* Check against the null and undefined values
* @param { * } value -
* @returns {Boolean} -
*/
function isNil(value) {
return isUndefined(value) || value === null
}
/**
* Check if passed argument is empty. Different from falsy, because we dont consider 0 or false to be blank
* @param { * } value -
* @returns { Boolean } -
*/
function isBlank(value) {
return isNil(value) || value === ''
}
/**
* Check if passed argument is a function
* @param { * } value -
* @returns { Boolean } -
*/
function isFunction(value) {
return typeof value === T_FUNCTION
}
/**
* Check if passed argument is an object, exclude null
* NOTE: use isObject(x) && !isArray(x) to excludes arrays.
* @param { * } value -
* @returns { Boolean } -
*/
function isObject(value) {
return value && typeof value === T_OBJECT // typeof null is 'object'
}
/**
* Check if a DOM node is an svg tag or part of an svg
* @param { HTMLElement } el - node we want to test
* @returns {Boolean} true if it's an svg node
*/
function isSvg(el) {
var owner = el.ownerSVGElement;
return !!owner || owner === null
}
/**
* Check if passed argument is a kind of array
* @param { * } value -
* @returns { Boolean } -
*/
function isArray(value) {
return Array.isArray(value) || value instanceof Array
}
/**
* Check if the passed argument is a boolean attribute
* @param { String } value -
* @returns { Boolean } -
*/
function isBoolAttr(value) {
return RE_BOOL_ATTRS.test(value)
}
/**
* Check if passed argument is a string
* @param { * } value -
* @returns { Boolean } -
*/
function isString(value) {
return typeof value === T_STRING
}
var check = /*#__PURE__*/Object.freeze({
isBlank: isBlank,
isFunction: isFunction,
isObject: isObject,
isSvg: isSvg,
isWritable: isWritable,
isArray: isArray,
isBoolAttr: isBoolAttr,
isNil: isNil,
isString: isString,
isUndefined: isUndefined
});
/**
* Check whether an array contains an item
* @param { Array } array - target array
* @param { * } item - item to test
* @returns { Boolean } -
*/
function contains(array, item) {
return array.indexOf(item) !== -1
}
/**
* Specialized function for looping an array-like collection with `each={}`
* @param { Array } list - collection of items
* @param {Function} fn - callback function
* @returns { Array } the array looped
*/
function each(list, fn) {
var len = list ? list.length : 0;
var i = 0;
for (; i < len; i++) { fn(list[i], i); }
return list
}
/**
* Faster String startsWith alternative
* @param { String } str - source string
* @param { String } value - test string
* @returns { Boolean } -
*/
function startsWith(str, value) {
return str.slice(0, value.length) === value
}
/**
* Function returning always a unique identifier
* @returns { Number } - number from 0...n
*/
var uid = (function uid() {
var i = -1;
return function () { return ++i; }
})();
/**
* Helper function to set an immutable property
* @param { Object } el - object where the new property will be set
* @param { String } key - object key where the new property will be stored
* @param { * } value - value of the new property
* @param { Object } options - set the propery overriding the default options
* @returns { Object } - the initial object
*/
function define(el, key, value, options) {
Object.defineProperty(el, key, extend({
value: value,
enumerable: false,
writable: false,
configurable: true
}, options));
return el
}
/**
* Convert a string containing dashes to camel case
* @param { String } str - input string
* @returns { String } my-string -> myString
*/
function toCamel(str) {
return str.replace(/-(\w)/g, function (_, c) { return c.toUpperCase(); })
}
/**
* Warn a message via console
* @param {String} message - warning message
*/
function warn(message) {
if (console && console.warn) { console.warn(message); }
}
var misc = /*#__PURE__*/Object.freeze({
contains: contains,
each: each,
getPropDescriptor: getPropDescriptor,
startsWith: startsWith,
uid: uid,
defineProperty: define,
objectCreate: create,
extend: extend,
toCamel: toCamel,
warn: warn
});
/**
* Set the property of an object for a given key. If something already
* exists there, then it becomes an array containing both the old and new value.
* @param { Object } obj - object on which to set the property
* @param { String } key - property name
* @param { Object } value - the value of the property to be set
* @param { Boolean } ensureArray - ensure that the property remains an array
* @param { Number } index - add the new item in a certain array position
*/
function arrayishAdd(obj, key, value, ensureArray, index) {
var dest = obj[key];
var isArr = isArray(dest);
var hasIndex = !isUndefined(index);
if (dest && dest === value) { return }
// if the key was never set, set it once
if (!dest && ensureArray) { obj[key] = [value]; }
else if (!dest) { obj[key] = value; }
// if it was an array and not yet set
else {
if (isArr) {
var oldIndex = dest.indexOf(value);
// this item never changed its position
if (oldIndex === index) { return }
// remove the item from its old position
if (oldIndex !== -1) { dest.splice(oldIndex, 1); }
// move or add the item
if (hasIndex) {
dest.splice(index, 0, value);
} else {
dest.push(value);
}
} else { obj[key] = [dest, value]; }
}
}
/**
* Detect the tag implementation by a DOM node
* @param { Object } dom - DOM node we need to parse to get its tag implementation
* @returns { Object } it returns an object containing the implementation of a custom tag (template and boot function)
*/
function get(dom) {
return dom.tagName && __TAG_IMPL[getAttribute(dom, IS_DIRECTIVE) ||
getAttribute(dom, IS_DIRECTIVE) || dom.tagName.toLowerCase()]
}
/**
* Get the tag name of any DOM node
* @param { Object } dom - DOM node we want to parse
* @param { Boolean } skipDataIs - hack to ignore the data-is attribute when attaching to parent
* @returns { String } name to identify this dom node in riot
*/
function getName(dom, skipDataIs) {
var child = get(dom);
var namedTag = !skipDataIs && getAttribute(dom, IS_DIRECTIVE);
return namedTag && !tmpl.hasExpr(namedTag) ?
namedTag : child ? child.name : dom.tagName.toLowerCase()
}
/**
* Return a temporary context containing also the parent properties
* @this Tag
* @param { Tag } - temporary tag context containing all the parent properties
*/
function inheritParentProps() {
if (this.parent) { return extend(create(this), this.parent) }
return this
}
/*
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/
*/
var
reHasYield = /|>([\S\s]*?)<\/yield\s*>|>)/ig,
reYieldSrc = /]*)['"]\s*>([\S\s]*?)<\/yield\s*>/ig,
reYieldDest = / |>([\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) {
var
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)
var 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`
var 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_.
*/
function mkdom(tmpl, html, isSvg) {
var match = tmpl && tmpl.match(/^\s*<([-\w]+)/);
var tagName = match && match[1].toLowerCase();
var 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
}
var EVENT_ATTR_RE = /^on/;
/**
* True if the event attribute starts with 'on'
* @param { String } attribute - event attribute
* @returns { Boolean }
*/
function isEventAttribute(attribute) {
return EVENT_ATTR_RE.test(attribute)
}
/**
* Loop backward all the parents tree to detect the first custom parent tag
* @param { Object } tag - a Tag instance
* @returns { Object } the instance of the first custom parent tag found
*/
function getImmediateCustomParent(tag) {
var ptag = tag;
while (ptag.__.isAnonymous) {
if (!ptag.parent) { break }
ptag = ptag.parent;
}
return ptag
}
/**
* Trigger DOM events
* @param { HTMLElement } dom - dom element target of the event
* @param { Function } handler - user function
* @param { Object } e - event object
*/
function handleEvent(dom, handler, e) {
var ptag = this.__.parent;
var item = this.__.item;
if (!item)
{ while (ptag && !item) {
item = ptag.__.item;
ptag = ptag.__.parent;
} }
// override the event properties
/* istanbul ignore next */
if (isWritable(e, 'currentTarget')) { e.currentTarget = dom; }
/* istanbul ignore next */
if (isWritable(e, 'target')) { e.target = e.srcElement; }
/* istanbul ignore next */
if (isWritable(e, 'which')) { e.which = e.charCode || e.keyCode; }
e.item = item;
handler.call(this, e);
// avoid auto updates
if (!settings.autoUpdate) { return }
if (!e.preventUpdate) {
var p = getImmediateCustomParent(this);
// fixes #2083
if (p.isMounted) { p.update(); }
}
}
/**
* Attach an event to a DOM node
* @param { String } name - event name
* @param { Function } handler - event callback
* @param { Object } dom - dom node
* @param { Tag } tag - tag instance
*/
function setEventHandler(name, handler, dom, tag) {
var eventName;
var cb = handleEvent.bind(tag, dom, handler);
// avoid to bind twice the same event
// possible fix for #2332
dom[name] = null;
// normalize event name
eventName = name.replace(RE_EVENTS_PREFIX, '');
// cache the listener into the listeners array
if (!contains(tag.__.listeners, dom)) { tag.__.listeners.push(dom); }
if (!dom[RIOT_EVENTS_KEY]) { dom[RIOT_EVENTS_KEY] = {}; }
if (dom[RIOT_EVENTS_KEY][name]) { dom.removeEventListener(eventName, dom[RIOT_EVENTS_KEY][name]); }
dom[RIOT_EVENTS_KEY][name] = cb;
dom.addEventListener(eventName, cb, false);
}
/**
* Create a new child tag including it correctly into its parent
* @param { Object } child - child tag implementation
* @param { Object } opts - tag options containing the DOM node where the tag will be mounted
* @param { String } innerHTML - inner html of the child node
* @param { Object } parent - instance of the parent tag including the child custom tag
* @returns { Object } instance of the new child tag just created
*/
function initChild(child, opts, innerHTML, parent) {
var tag = createTag(child, opts, innerHTML);
var tagName = opts.tagName || getName(opts.root, true);
var ptag = getImmediateCustomParent(parent);
// fix for the parent attribute in the looped elements
define(tag, 'parent', ptag);
// store the real parent tag
// in some cases this could be different from the custom parent tag
// for example in nested loops
tag.__.parent = parent;
// add this tag to the custom parent tag
arrayishAdd(ptag.tags, tagName, tag);
// and also to the real parent tag
if (ptag !== parent)
{ arrayishAdd(parent.tags, tagName, tag); }
return tag
}
/**
* Removes an item from an object at a given key. If the key points to an array,
* then the item is just removed from the array.
* @param { Object } obj - object on which to remove the property
* @param { String } key - property name
* @param { Object } value - the value of the property to be removed
* @param { Boolean } ensureArray - ensure that the property remains an array
*/
function arrayishRemove(obj, key, value, ensureArray) {
if (isArray(obj[key])) {
var index = obj[key].indexOf(value);
if (index !== -1) { obj[key].splice(index, 1); }
if (!obj[key].length) { delete obj[key]; }
else if (obj[key].length === 1 && !ensureArray) { obj[key] = obj[key][0]; }
} else if (obj[key] === value)
{ delete obj[key]; } // otherwise just delete the key
}
/**
* Adds the elements for a virtual tag
* @this Tag
* @param { Node } src - the node that will do the inserting or appending
* @param { Tag } target - only if inserting, insert before this tag's first child
*/
function makeVirtual(src, target) {
var this$1 = this;
var head = createDOMPlaceholder();
var tail = createDOMPlaceholder();
var frag = createFragment();
var sib;
var el;
this.root.insertBefore(head, this.root.firstChild);
this.root.appendChild(tail);
this.__.head = el = head;
this.__.tail = tail;
while (el) {
sib = el.nextSibling;
frag.appendChild(el);
this$1.__.virts.push(el); // hold for unmounting
el = sib;
}
if (target)
{ src.insertBefore(frag, target.__.head); }
else
{ src.appendChild(frag); }
}
/**
* makes a tag virtual and replaces a reference in the dom
* @this Tag
* @param { tag } the tag to make virtual
* @param { ref } the dom reference location
*/
function makeReplaceVirtual(tag, ref) {
if (!ref.parentNode) { return }
var frag = createFragment();
makeVirtual.call(tag, frag);
ref.parentNode.replaceChild(frag, ref);
}
/**
* Update dynamically created data-is tags with changing expressions
* @param { Object } expr - expression tag and expression info
* @param { Tag } parent - parent for tag creation
* @param { String } tagName - tag implementation we want to use
*/
function updateDataIs(expr, parent, tagName) {
var tag = expr.tag || expr.dom._tag;
var ref;
var ref$1 = tag ? tag.__ : {};
var head = ref$1.head;
var isVirtual = expr.dom.tagName === 'VIRTUAL';
if (tag && expr.tagName === tagName) {
tag.update();
return
}
// sync _parent to accommodate changing tagnames
if (tag) {
// need placeholder before unmount
if(isVirtual) {
ref = createDOMPlaceholder();
head.parentNode.insertBefore(ref, head);
}
tag.unmount(true);
}
// unable to get the tag name
if (!isString(tagName)) { return }
expr.impl = __TAG_IMPL[tagName];
// unknown implementation
if (!expr.impl) { return }
expr.tag = tag = initChild(
expr.impl, {
root: expr.dom,
parent: parent,
tagName: tagName
},
expr.dom.innerHTML,
parent
);
each(expr.attrs, function (a) { return setAttribute(tag.root, a.name, a.value); });
expr.tagName = tagName;
tag.mount();
// root exist first time, after use placeholder
if (isVirtual) { makeReplaceVirtual(tag, ref || tag.root); }
// parent is the placeholder tag, not the dynamic tag so clean up
parent.__.onUnmount = function () {
var delName = tag.opts.dataIs;
arrayishRemove(tag.parent.tags, delName, tag);
arrayishRemove(tag.__.parent.tags, delName, tag);
tag.unmount();
};
}
/**
* Nomalize any attribute removing the "riot-" prefix
* @param { String } attrName - original attribute name
* @returns { String } valid html attribute name
*/
function normalizeAttrName(attrName) {
if (!attrName) { return null }
attrName = attrName.replace(ATTRS_PREFIX, '');
if (CASE_SENSITIVE_ATTRIBUTES[attrName]) { attrName = CASE_SENSITIVE_ATTRIBUTES[attrName]; }
return attrName
}
/**
* Update on single tag expression
* @this Tag
* @param { Object } expr - expression logic
* @returns { undefined }
*/
function updateExpression(expr) {
if (this.root && getAttribute(this.root,'virtualized')) { return }
var dom = expr.dom;
// remove the riot- prefix
var attrName = normalizeAttrName(expr.attr);
var isToggle = contains([SHOW_DIRECTIVE, HIDE_DIRECTIVE], attrName);
var isVirtual = expr.root && expr.root.tagName === 'VIRTUAL';
var ref = this.__;
var isAnonymous = ref.isAnonymous;
var parent = dom && (expr.parent || dom.parentNode);
var keepValueAttributes = settings.keepValueAttributes;
// detect the style attributes
var isStyleAttr = attrName === 'style';
var isClassAttr = attrName === 'class';
var isValueAttr = attrName === 'value';
var value;
// if it's a tag we could totally skip the rest
if (expr._riot_id) {
if (expr.__.wasCreated) {
expr.update();
// if it hasn't been mounted yet, do that now.
} else {
expr.mount();
if (isVirtual) {
makeReplaceVirtual(expr, expr.root);
}
}
return
}
// if this expression has the update method it means it can handle the DOM changes by itself
if (expr.update) { return expr.update() }
var context = isToggle && !isAnonymous ? inheritParentProps.call(this) : this;
// ...it seems to be a simple expression so we try to calculate its value
value = tmpl(expr.expr, context);
var hasValue = !isBlank(value);
var isObj = isObject(value);
// convert the style/class objects to strings
if (isObj) {
if (isClassAttr) {
value = tmpl(JSON.stringify(value), this);
} else if (isStyleAttr) {
value = styleObjectToString(value);
}
}
// remove original attribute
if (expr.attr &&
(
// the original attribute can be removed only if we are parsing the original expression
!expr.wasParsedOnce ||
// or its value is false
value === false ||
// or if its value is currently falsy...
// We will keep the "value" attributes if the "keepValueAttributes"
// is enabled though
(!hasValue && (!isValueAttr || isValueAttr && !keepValueAttributes))
)
) {
// remove either riot-* attributes or just the attribute name
removeAttribute(dom, getAttribute(dom, expr.attr) ? expr.attr : attrName);
}
// for the boolean attributes we don't need the value
// we can convert it to checked=true to checked=checked
if (expr.bool) { value = value ? attrName : false; }
if (expr.isRtag) { return updateDataIs(expr, this, value) }
if (expr.wasParsedOnce && expr.value === value) { return }
// update the expression value
expr.value = value;
expr.wasParsedOnce = true;
// if the value is an object (and it's not a style or class attribute) we can not do much more with it
if (isObj && !isClassAttr && !isStyleAttr && !isToggle) { return }
// avoid to render undefined/null values
if (!hasValue) { value = ''; }
// textarea and text nodes have no attribute name
if (!attrName) {
// about #815 w/o replace: the browser converts the value to a string,
// the comparison by "==" does too, but not in the server
value += '';
// test for parent avoids error with invalid assignment to nodeValue
if (parent) {
// cache the parent node because somehow it will become null on IE
// on the next iteration
expr.parent = parent;
if (parent.tagName === 'TEXTAREA') {
parent.value = value; // #1113
if (!IE_VERSION) { dom.nodeValue = value; } // #1625 IE throws here, nodeValue
} // will be available on 'updated'
else { dom.nodeValue = value; }
}
return
}
switch (true) {
// handle events binding
case isFunction(value):
if (isEventAttribute(attrName)) {
setEventHandler(attrName, value, dom, this);
}
break
// show / hide
case isToggle:
toggleVisibility(dom, attrName === HIDE_DIRECTIVE ? !value : value);
break
// handle attributes
default:
if (expr.bool) {
dom[attrName] = value;
}
if (isValueAttr && dom.value !== value) {
dom.value = value;
} else if (hasValue && value !== false) {
setAttribute(dom, attrName, value);
}
// make sure that in case of style changes
// the element stays hidden
if (isStyleAttr && dom.hidden) { toggleVisibility(dom, false); }
}
}
/**
* Update all the expressions in a Tag instance
* @this Tag
* @param { Array } expressions - expression that must be re evaluated
*/
function update(expressions) {
each(expressions, updateExpression.bind(this));
}
/**
* We need to update opts for this tag. That requires updating the expressions
* in any attributes on the tag, and then copying the result onto opts.
* @this Tag
* @param {Boolean} isLoop - is it a loop tag?
* @param { Tag } parent - parent tag node
* @param { Boolean } isAnonymous - is it a tag without any impl? (a tag not registered)
* @param { Object } opts - tag options
* @param { Array } instAttrs - tag attributes array
*/
function updateOpts(isLoop, parent, isAnonymous, opts, instAttrs) {
// isAnonymous `each` tags treat `dom` and `root` differently. In this case
// (and only this case) we don't need to do updateOpts, because the regular parse
// will update those attrs. Plus, isAnonymous tags don't need opts anyway
if (isLoop && isAnonymous) { return }
var ctx = isLoop ? inheritParentProps.call(this) : parent || this;
each(instAttrs, function (attr) {
if (attr.expr) { updateExpression.call(ctx, attr.expr); }
// normalize the attribute names
opts[toCamel(attr.name).replace(ATTRS_PREFIX, '')] = attr.expr ? attr.expr.value : attr.value;
});
}
/**
* Update the tag expressions and options
* @param { Tag } tag - tag object
* @param { * } data - data we want to use to extend the tag properties
* @param { Array } expressions - component expressions array
* @returns { Tag } the current tag instance
*/
function componentUpdate(tag, data, expressions) {
var __ = tag.__;
var nextOpts = {};
var canTrigger = tag.isMounted && !__.skipAnonymous;
// inherit properties from the parent tag
if (__.isAnonymous && __.parent) { extend(tag, __.parent); }
extend(tag, data);
updateOpts.apply(tag, [__.isLoop, __.parent, __.isAnonymous, nextOpts, __.instAttrs]);
if (
canTrigger &&
tag.isMounted &&
isFunction(tag.shouldUpdate) && !tag.shouldUpdate(data, nextOpts)
) {
return tag
}
extend(tag.opts, nextOpts);
if (canTrigger) { tag.trigger('update', data); }
update.call(tag, expressions);
if (canTrigger) { tag.trigger('updated'); }
return tag
}
/**
* Get selectors for tags
* @param { Array } tags - tag names to select
* @returns { String } selector
*/
function query(tags) {
// select all tags
if (!tags) {
var keys = Object.keys(__TAG_IMPL);
return keys + query(keys)
}
return tags
.filter(function (t) { return !/[^-\w]/.test(t); })
.reduce(function (list, t) {
var name = t.trim().toLowerCase();
return list + ",[" + IS_DIRECTIVE + "=\"" + name + "\"]"
}, '')
}
/**
* Another way to create a riot tag a bit more es6 friendly
* @param { HTMLElement } el - tag DOM selector or DOM node/s
* @param { Object } opts - tag logic
* @returns { Tag } new riot tag instance
*/
function Tag(el, opts) {
// get the tag properties from the class constructor
var ref = this;
var name = ref.name;
var tmpl = ref.tmpl;
var css = ref.css;
var attrs = ref.attrs;
var onCreate = ref.onCreate;
// register a new tag and cache the class prototype
if (!__TAG_IMPL[name]) {
tag(name, tmpl, css, attrs, onCreate);
// cache the class constructor
__TAG_IMPL[name].class = this.constructor;
}
// mount the tag using the class instance
mount$1(el, name, opts, this);
// inject the component css
if (css) { styleManager.inject(); }
return this
}
/**
* Create a new riot tag implementation
* @param { String } name - name/id of the new riot tag
* @param { String } tmpl - tag template
* @param { String } css - custom tag css
* @param { String } attrs - root tag attributes
* @param { Function } fn - user function
* @returns { String } name/id of the tag just created
*/
function tag(name, tmpl, css, attrs, fn) {
if (isFunction(attrs)) {
fn = attrs;
if (/^[\w-]+\s?=/.test(css)) {
attrs = css;
css = '';
} else
{ attrs = ''; }
}
if (css) {
if (isFunction(css))
{ fn = css; }
else
{ styleManager.add(css, name); }
}
name = name.toLowerCase();
__TAG_IMPL[name] = { name: name, tmpl: tmpl, attrs: attrs, fn: fn };
return name
}
/**
* Create a new riot tag implementation (for use by the compiler)
* @param { String } name - name/id of the new riot tag
* @param { String } tmpl - tag template
* @param { String } css - custom tag css
* @param { String } attrs - root tag attributes
* @param { Function } fn - user function
* @returns { String } name/id of the tag just created
*/
function tag2(name, tmpl, css, attrs, fn) {
if (css) { styleManager.add(css, name); }
__TAG_IMPL[name] = { name: name, tmpl: tmpl, attrs: attrs, fn: fn };
return name
}
/**
* Mount a tag using a specific tag implementation
* @param { * } selector - tag DOM selector or DOM node/s
* @param { String } tagName - tag implementation name
* @param { Object } opts - tag logic
* @returns { Array } new tags instances
*/
function mount(selector, tagName, opts) {
var tags = [];
var elem, allTags;
function pushTagsTo(root) {
if (root.tagName) {
var riotTag = getAttribute(root, IS_DIRECTIVE), tag;
// have tagName? force riot-tag to be the same
if (tagName && riotTag !== tagName) {
riotTag = tagName;
setAttribute(root, IS_DIRECTIVE, tagName);
}
tag = mount$1(
root,
riotTag || root.tagName.toLowerCase(),
isFunction(opts) ? opts() : opts
);
if (tag)
{ tags.push(tag); }
} else if (root.length)
{ each(root, pushTagsTo); } // assume nodeList
}
// inject styles into DOM
styleManager.inject();
if (isObject(tagName) || isFunction(tagName)) {
opts = tagName;
tagName = 0;
}
// crawl the DOM to find the tag
if (isString(selector)) {
selector = selector === '*' ?
// select all registered tags
// & tags found with the riot-tag attribute set
allTags = query() :
// or just the ones named like the selector
selector + query(selector.split(/, */));
// make sure to pass always a selector
// to the querySelectorAll function
elem = selector ? $$(selector) : [];
}
else
// probably you have passed already a tag or a NodeList
{ elem = selector; }
// select all the registered and mount them inside their root elements
if (tagName === '*') {
// get all custom tags
tagName = allTags || query();
// if the root els it's just a single tag
if (elem.tagName)
{ elem = $$(tagName, elem); }
else {
// select all the children for all the different root elements
var nodeList = [];
each(elem, function (_el) { return nodeList.push($$(tagName, _el)); });
elem = nodeList;
}
// get rid of the tagName
tagName = 0;
}
pushTagsTo(elem);
return tags
}
// Create a mixin that could be globally shared across all the tags
var mixins = {};
var globals = mixins[GLOBAL_MIXIN] = {};
var mixins_id = 0;
/**
* Create/Return a mixin by its name
* @param { String } name - mixin name (global mixin if object)
* @param { Object } mix - mixin logic
* @param { Boolean } g - is global?
* @returns { Object } the mixin logic
*/
function mixin(name, mix, g) {
// Unnamed global
if (isObject(name)) {
mixin(("__" + (mixins_id++) + "__"), name, true);
return
}
var store = g ? globals : mixins;
// Getter
if (!mix) {
if (isUndefined(store[name]))
{ throw new Error(("Unregistered mixin: " + name)) }
return store[name]
}
// Setter
store[name] = isFunction(mix) ?
extend(mix.prototype, store[name] || {}) && mix :
extend(store[name] || {}, mix);
}
/**
* Update all the tags instances created
* @returns { Array } all the tags instances
*/
function update$1() {
return each(__TAGS_CACHE, function (tag) { return tag.update(); })
}
function unregister(name) {
styleManager.remove(name);
return delete __TAG_IMPL[name]
}
var version = 'v3.13.2';
var core = /*#__PURE__*/Object.freeze({
Tag: Tag,
tag: tag,
tag2: tag2,
mount: mount,
mixin: mixin,
update: update$1,
unregister: unregister,
version: version
});
/**
* Add a mixin to this tag
* @returns { Tag } the current tag instance
*/
function componentMixin(tag$$1) {
var mixins = [], len = arguments.length - 1;
while ( len-- > 0 ) mixins[ len ] = arguments[ len + 1 ];
each(mixins, function (mix) {
var instance;
var obj;
var props = [];
// properties blacklisted and will not be bound to the tag instance
var propsBlacklist = ['init', '__proto__'];
mix = isString(mix) ? mixin(mix) : mix;
// check if the mixin is a function
if (isFunction(mix)) {
// create the new mixin instance
instance = new mix();
} else { instance = mix; }
var proto = Object.getPrototypeOf(instance);
// build multilevel prototype inheritance chain property list
do { props = props.concat(Object.getOwnPropertyNames(obj || instance)); }
while (obj = Object.getPrototypeOf(obj || instance))
// loop the keys in the function prototype or the all object keys
each(props, function (key) {
// bind methods to tag
// allow mixins to override other properties/parent mixins
if (!contains(propsBlacklist, key)) {
// check for getters/setters
var descriptor = getPropDescriptor(instance, key) || getPropDescriptor(proto, key);
var hasGetterSetter = descriptor && (descriptor.get || descriptor.set);
// apply method only if it does not already exist on the instance
if (!tag$$1.hasOwnProperty(key) && hasGetterSetter) {
Object.defineProperty(tag$$1, key, descriptor);
} else {
tag$$1[key] = isFunction(instance[key]) ?
instance[key].bind(tag$$1) :
instance[key];
}
}
});
// init method will be called automatically
if (instance.init)
{ instance.init.bind(tag$$1)(tag$$1.opts); }
});
return tag$$1
}
/**
* Move the position of a custom tag in its parent tag
* @this Tag
* @param { String } tagName - key where the tag was stored
* @param { Number } newPos - index where the new tag will be stored
*/
function moveChild(tagName, newPos) {
var parent = this.parent;
var tags;
// no parent no move
if (!parent) { return }
tags = parent.tags[tagName];
if (isArray(tags))
{ tags.splice(newPos, 0, tags.splice(tags.indexOf(this), 1)[0]); }
else { arrayishAdd(parent.tags, tagName, this); }
}
/**
* Move virtual tag and all child nodes
* @this Tag
* @param { Node } src - the node that will do the inserting
* @param { Tag } target - insert before this tag's first child
*/
function moveVirtual(src, target) {
var this$1 = this;
var el = this.__.head;
var sib;
var frag = createFragment();
while (el) {
sib = el.nextSibling;
frag.appendChild(el);
el = sib;
if (el === this$1.__.tail) {
frag.appendChild(el);
src.insertBefore(frag, target.__.head);
break
}
}
}
/**
* Convert the item looped into an object used to extend the child tag properties
* @param { Object } expr - object containing the keys used to extend the children tags
* @param { * } key - value to assign to the new object returned
* @param { * } val - value containing the position of the item in the array
* @returns { Object } - new object containing the values of the original item
*
* The variables 'key' and 'val' are arbitrary.
* They depend on the collection type looped (Array, Object)
* and on the expression used on the each tag
*
*/
function mkitem(expr, key, val) {
var item = {};
item[expr.key] = key;
if (expr.pos) { item[expr.pos] = val; }
return item
}
/**
* Unmount the redundant tags
* @param { Array } items - array containing the current items to loop
* @param { Array } tags - array containing all the children tags
*/
function unmountRedundant(items, tags, filteredItemsCount) {
var i = tags.length;
var j = items.length - filteredItemsCount;
while (i > j) {
i--;
remove.apply(tags[i], [tags, i]);
}
}
/**
* Remove a child tag
* @this Tag
* @param { Array } tags - tags collection
* @param { Number } i - index of the tag to remove
*/
function remove(tags, i) {
tags.splice(i, 1);
this.unmount();
arrayishRemove(this.parent, this, this.__.tagName, true);
}
/**
* Move the nested custom tags in non custom loop tags
* @this Tag
* @param { Number } i - current position of the loop tag
*/
function moveNestedTags(i) {
var this$1 = this;
each(Object.keys(this.tags), function (tagName) {
moveChild.apply(this$1.tags[tagName], [tagName, i]);
});
}
/**
* Move a child tag
* @this Tag
* @param { HTMLElement } root - dom node containing all the loop children
* @param { Tag } nextTag - instance of the next tag preceding the one we want to move
* @param { Boolean } isVirtual - is it a virtual tag?
*/
function move(root, nextTag, isVirtual) {
if (isVirtual)
{ moveVirtual.apply(this, [root, nextTag]); }
else
{ safeInsert(root, this.root, nextTag.root); }
}
/**
* Insert and mount a child tag
* @this Tag
* @param { HTMLElement } root - dom node containing all the loop children
* @param { Tag } nextTag - instance of the next tag preceding the one we want to insert
* @param { Boolean } isVirtual - is it a virtual tag?
*/
function insert(root, nextTag, isVirtual) {
if (isVirtual)
{ makeVirtual.apply(this, [root, nextTag]); }
else
{ safeInsert(root, this.root, nextTag.root); }
}
/**
* Append a new tag into the DOM
* @this Tag
* @param { HTMLElement } root - dom node containing all the loop children
* @param { Boolean } isVirtual - is it a virtual tag?
*/
function append(root, isVirtual) {
if (isVirtual)
{ makeVirtual.call(this, root); }
else
{ root.appendChild(this.root); }
}
/**
* Return the value we want to use to lookup the postion of our items in the collection
* @param { String } keyAttr - lookup string or expression
* @param { * } originalItem - original item from the collection
* @param { Object } keyedItem - object created by riot via { item, i in collection }
* @param { Boolean } hasKeyAttrExpr - flag to check whether the key is an expression
* @returns { * } value that we will use to figure out the item position via collection.indexOf
*/
function getItemId(keyAttr, originalItem, keyedItem, hasKeyAttrExpr) {
if (keyAttr) {
return hasKeyAttrExpr ? tmpl(keyAttr, keyedItem) : originalItem[keyAttr]
}
return originalItem
}
/**
* Manage tags having the 'each'
* @param { HTMLElement } dom - DOM node we need to loop
* @param { Tag } parent - parent tag instance where the dom node is contained
* @param { String } expr - string contained in the 'each' attribute
* @returns { Object } expression object for this each loop
*/
function _each(dom, parent, expr) {
var mustReorder = typeof getAttribute(dom, LOOP_NO_REORDER_DIRECTIVE) !== T_STRING || removeAttribute(dom, LOOP_NO_REORDER_DIRECTIVE);
var keyAttr = getAttribute(dom, KEY_DIRECTIVE);
var hasKeyAttrExpr = keyAttr ? tmpl.hasExpr(keyAttr) : false;
var tagName = getName(dom);
var impl = __TAG_IMPL[tagName];
var parentNode = dom.parentNode;
var placeholder = createDOMPlaceholder();
var child = get(dom);
var ifExpr = getAttribute(dom, CONDITIONAL_DIRECTIVE);
var tags = [];
var isLoop = true;
var innerHTML = dom.innerHTML;
var isAnonymous = !__TAG_IMPL[tagName];
var isVirtual = dom.tagName === 'VIRTUAL';
var oldItems = [];
// remove the each property from the original tag
removeAttribute(dom, LOOP_DIRECTIVE);
removeAttribute(dom, KEY_DIRECTIVE);
// parse the each expression
expr = tmpl.loopKeys(expr);
expr.isLoop = true;
if (ifExpr) { removeAttribute(dom, CONDITIONAL_DIRECTIVE); }
// insert a marked where the loop tags will be injected
parentNode.insertBefore(placeholder, dom);
parentNode.removeChild(dom);
expr.update = function updateEach() {
// get the new items collection
expr.value = tmpl(expr.val, parent);
var items = expr.value;
var frag = createFragment();
var isObject = !isArray(items) && !isString(items);
var root = placeholder.parentNode;
var tmpItems = [];
var hasKeys = isObject && !!items;
// if this DOM was removed the update here is useless
// this condition fixes also a weird async issue on IE in our unit test
if (!root) { return }
// object loop. any changes cause full redraw
if (isObject) {
items = items ? Object.keys(items).map(function (key) { return mkitem(expr, items[key], key); }) : [];
}
// store the amount of filtered items
var filteredItemsCount = 0;
// loop all the new items
each(items, function (_item, index) {
var i = index - filteredItemsCount;
var item = !hasKeys && expr.key ? mkitem(expr, _item, index) : _item;
// skip this item because it must be filtered
if (ifExpr && !tmpl(ifExpr, extend(create(parent), item))) {
filteredItemsCount ++;
return
}
var itemId = getItemId(keyAttr, _item, item, hasKeyAttrExpr);
// reorder only if the items are not objects
// or a key attribute has been provided
var doReorder = !isObject && mustReorder && typeof _item === T_OBJECT || keyAttr;
var oldPos = oldItems.indexOf(itemId);
var isNew = oldPos === -1;
var pos = !isNew && doReorder ? oldPos : i;
// does a tag exist in this position?
var tag = tags[pos];
var mustAppend = i >= oldItems.length;
var mustCreate = doReorder && isNew || !doReorder && !tag || !tags[i];
// new tag
if (mustCreate) {
tag = createTag(impl, {
parent: parent,
isLoop: isLoop,
isAnonymous: isAnonymous,
tagName: tagName,
root: dom.cloneNode(isAnonymous),
item: item,
index: i,
}, innerHTML);
// mount the tag
tag.mount();
if (mustAppend)
{ append.apply(tag, [frag || root, isVirtual]); }
else
{ insert.apply(tag, [root, tags[i], isVirtual]); }
if (!mustAppend) { oldItems.splice(i, 0, item); }
tags.splice(i, 0, tag);
if (child) { arrayishAdd(parent.tags, tagName, tag, true); }
} else if (pos !== i && doReorder) {
// move
if (keyAttr || contains(items, oldItems[pos])) {
move.apply(tag, [root, tags[i], isVirtual]);
// move the old tag instance
tags.splice(i, 0, tags.splice(pos, 1)[0]);
// move the old item
oldItems.splice(i, 0, oldItems.splice(pos, 1)[0]);
}
// update the position attribute if it exists
if (expr.pos) { tag[expr.pos] = i; }
// if the loop tags are not custom
// we need to move all their custom tags into the right position
if (!child && tag.tags) { moveNestedTags.call(tag, i); }
}
// cache the original item to use it in the events bound to this node
// and its children
extend(tag.__, {
item: item,
index: i,
parent: parent
});
tmpItems[i] = itemId;
if (!mustCreate) { tag.update(item); }
});
// remove the redundant tags
unmountRedundant(items, tags, filteredItemsCount);
// clone the items array
oldItems = tmpItems.slice();
root.insertBefore(frag, placeholder);
};
expr.unmount = function () {
each(tags, function (t) { t.unmount(); });
};
return expr
}
var RefExpr = {
init: function init(dom, parent, attrName, attrValue) {
this.dom = dom;
this.attr = attrName;
this.rawValue = attrValue;
this.parent = parent;
this.hasExp = tmpl.hasExpr(attrValue);
return this
},
update: function update() {
var old = this.value;
var customParent = this.parent && getImmediateCustomParent(this.parent);
// if the referenced element is a custom tag, then we set the tag itself, rather than DOM
var tagOrDom = this.dom.__ref || this.tag || this.dom;
this.value = this.hasExp ? tmpl(this.rawValue, this.parent) : this.rawValue;
// the name changed, so we need to remove it from the old key (if present)
if (!isBlank(old) && customParent) { arrayishRemove(customParent.refs, old, tagOrDom); }
if (!isBlank(this.value) && isString(this.value)) {
// add it to the refs of parent tag (this behavior was changed >=3.0)
if (customParent) { arrayishAdd(
customParent.refs,
this.value,
tagOrDom,
// use an array if it's a looped node and the ref is not an expression
null,
this.parent.__.index
); }
if (this.value !== old) {
setAttribute(this.dom, this.attr, this.value);
}
} else {
removeAttribute(this.dom, this.attr);
}
// cache the ref bound to this dom node
// to reuse it in future (see also #2329)
if (!this.dom.__ref) { this.dom.__ref = tagOrDom; }
},
unmount: function unmount() {
var tagOrDom = this.tag || this.dom;
var customParent = this.parent && getImmediateCustomParent(this.parent);
if (!isBlank(this.value) && customParent)
{ arrayishRemove(customParent.refs, this.value, tagOrDom); }
}
};
/**
* Create a new ref directive
* @param { HTMLElement } dom - dom node having the ref attribute
* @param { Tag } context - tag instance where the DOM node is located
* @param { String } attrName - either 'ref' or 'data-ref'
* @param { String } attrValue - value of the ref attribute
* @returns { RefExpr } a new RefExpr object
*/
function createRefDirective(dom, tag, attrName, attrValue) {
return create(RefExpr).init(dom, tag, attrName, attrValue)
}
/**
* Trigger the unmount method on all the expressions
* @param { Array } expressions - DOM expressions
*/
function unmountAll(expressions) {
each(expressions, function (expr) {
if (expr.unmount) { expr.unmount(true); }
else if (expr.tagName) { expr.tag.unmount(true); }
else if (expr.unmount) { expr.unmount(); }
});
}
var IfExpr = {
init: function init(dom, tag, expr) {
removeAttribute(dom, CONDITIONAL_DIRECTIVE);
extend(this, { tag: tag, expr: expr, stub: createDOMPlaceholder(), pristine: dom });
var p = dom.parentNode;
p.insertBefore(this.stub, dom);
p.removeChild(dom);
return this
},
update: function update$$1() {
this.value = tmpl(this.expr, this.tag);
if (!this.stub.parentNode) { return }
if (this.value && !this.current) { // insert
this.current = this.pristine.cloneNode(true);
this.stub.parentNode.insertBefore(this.current, this.stub);
this.expressions = parseExpressions.apply(this.tag, [this.current, true]);
} else if (!this.value && this.current) { // remove
this.unmount();
this.current = null;
this.expressions = [];
}
if (this.value) { update.call(this.tag, this.expressions); }
},
unmount: function unmount() {
if (this.current) {
if (this.current._tag) {
this.current._tag.unmount();
} else if (this.current.parentNode) {
this.current.parentNode.removeChild(this.current);
}
}
unmountAll(this.expressions || []);
}
};
/**
* Create a new if directive
* @param { HTMLElement } dom - if root dom node
* @param { Tag } context - tag instance where the DOM node is located
* @param { String } attr - if expression
* @returns { IFExpr } a new IfExpr object
*/
function createIfDirective(dom, tag, attr) {
return create(IfExpr).init(dom, tag, attr)
}
/**
* Walk the tag DOM to detect the expressions to evaluate
* @this Tag
* @param { HTMLElement } root - root tag where we will start digging the expressions
* @param { Boolean } mustIncludeRoot - flag to decide whether the root must be parsed as well
* @returns { Array } all the expressions found
*/
function parseExpressions(root, mustIncludeRoot) {
var this$1 = this;
var expressions = [];
walkNodes(root, function (dom) {
var type = dom.nodeType;
var attr;
var tagImpl;
if (!mustIncludeRoot && dom === root) { return }
// text node
if (type === 3 && dom.parentNode.tagName !== 'STYLE' && tmpl.hasExpr(dom.nodeValue))
{ expressions.push({dom: dom, expr: dom.nodeValue}); }
if (type !== 1) { return }
var isVirtual = dom.tagName === 'VIRTUAL';
// loop. each does it's own thing (for now)
if (attr = getAttribute(dom, LOOP_DIRECTIVE)) {
if(isVirtual) { setAttribute(dom, 'loopVirtual', true); } // ignore here, handled in _each
expressions.push(_each(dom, this$1, attr));
return false
}
// if-attrs become the new parent. Any following expressions (either on the current
// element, or below it) become children of this expression.
if (attr = getAttribute(dom, CONDITIONAL_DIRECTIVE)) {
expressions.push(createIfDirective(dom, this$1, attr));
return false
}
if (attr = getAttribute(dom, IS_DIRECTIVE)) {
if (tmpl.hasExpr(attr)) {
expressions.push({
isRtag: true,
expr: attr,
dom: dom,
attrs: [].slice.call(dom.attributes)
});
return false
}
}
// if this is a tag, stop traversing here.
// we ignore the root, since parseExpressions is called while we're mounting that root
tagImpl = get(dom);
if(isVirtual) {
if(getAttribute(dom, 'virtualized')) {dom.parentElement.removeChild(dom); } // tag created, remove from dom
if(!tagImpl && !getAttribute(dom, 'virtualized') && !getAttribute(dom, 'loopVirtual')) // ok to create virtual tag
{ tagImpl = { tmpl: dom.outerHTML }; }
}
if (tagImpl && (dom !== root || mustIncludeRoot)) {
var hasIsDirective = getAttribute(dom, IS_DIRECTIVE);
if(isVirtual && !hasIsDirective) { // handled in update
// can not remove attribute like directives
// so flag for removal after creation to prevent maximum stack error
setAttribute(dom, 'virtualized', true);
var tag = createTag(
{tmpl: dom.outerHTML},
{root: dom, parent: this$1},
dom.innerHTML
);
expressions.push(tag); // no return, anonymous tag, keep parsing
} else {
if (hasIsDirective && isVirtual)
{ warn(("Virtual tags shouldn't be used together with the \"" + IS_DIRECTIVE + "\" attribute - https://github.com/riot/riot/issues/2511")); }
expressions.push(
initChild(
tagImpl,
{
root: dom,
parent: this$1
},
dom.innerHTML,
this$1
)
);
return false
}
}
// attribute expressions
parseAttributes.apply(this$1, [dom, dom.attributes, function (attr, expr) {
if (!expr) { return }
expressions.push(expr);
}]);
});
return expressions
}
/**
* Calls `fn` for every attribute on an element. If that attr has an expression,
* it is also passed to fn.
* @this Tag
* @param { HTMLElement } dom - dom node to parse
* @param { Array } attrs - array of attributes
* @param { Function } fn - callback to exec on any iteration
*/
function parseAttributes(dom, attrs, fn) {
var this$1 = this;
each(attrs, function (attr) {
if (!attr) { return false }
var name = attr.name;
var bool = isBoolAttr(name);
var expr;
if (contains(REF_DIRECTIVES, name) && dom.tagName.toLowerCase() !== YIELD_TAG) {
expr = createRefDirective(dom, this$1, name, attr.value);
} else if (tmpl.hasExpr(attr.value)) {
expr = {dom: dom, expr: attr.value, attr: name, bool: bool};
}
fn(attr, expr);
});
}
/**
* Manage the mount state of a tag triggering also the observable events
* @this Tag
* @param { Boolean } value - ..of the isMounted flag
*/
function setMountState(value) {
var ref = this.__;
var isAnonymous = ref.isAnonymous;
var skipAnonymous = ref.skipAnonymous;
define(this, 'isMounted', value);
if (!isAnonymous || !skipAnonymous) {
if (value) { this.trigger('mount'); }
else {
this.trigger('unmount');
this.off('*');
this.__.wasCreated = false;
}
}
}
/**
* Mount the current tag instance
* @returns { Tag } the current tag instance
*/
function componentMount(tag$$1, dom, expressions, opts) {
var __ = tag$$1.__;
var root = __.root;
root._tag = tag$$1; // keep a reference to the tag just created
// Read all the attrs on this instance. This give us the info we need for updateOpts
parseAttributes.apply(__.parent, [root, root.attributes, function (attr, expr) {
if (!__.isAnonymous && RefExpr.isPrototypeOf(expr)) { expr.tag = tag$$1; }
attr.expr = expr;
__.instAttrs.push(attr);
}]);
// update the root adding custom attributes coming from the compiler
walkAttributes(__.impl.attrs, function (k, v) { __.implAttrs.push({name: k, value: v}); });
parseAttributes.apply(tag$$1, [root, __.implAttrs, function (attr, expr) {
if (expr) { expressions.push(expr); }
else { setAttribute(root, attr.name, attr.value); }
}]);
// initialiation
updateOpts.apply(tag$$1, [__.isLoop, __.parent, __.isAnonymous, opts, __.instAttrs]);
// add global mixins
var globalMixin = mixin(GLOBAL_MIXIN);
if (globalMixin && !__.skipAnonymous) {
for (var i in globalMixin) {
if (globalMixin.hasOwnProperty(i)) {
tag$$1.mixin(globalMixin[i]);
}
}
}
if (__.impl.fn) { __.impl.fn.call(tag$$1, opts); }
if (!__.skipAnonymous) { tag$$1.trigger('before-mount'); }
// parse layout after init. fn may calculate args for nested custom tags
each(parseExpressions.apply(tag$$1, [dom, __.isAnonymous]), function (e) { return expressions.push(e); });
tag$$1.update(__.item);
if (!__.isAnonymous && !__.isInline) {
while (dom.firstChild) { root.appendChild(dom.firstChild); }
}
define(tag$$1, 'root', root);
// if we need to wait that the parent "mount" or "updated" event gets triggered
if (!__.skipAnonymous && tag$$1.parent) {
var p = getImmediateCustomParent(tag$$1.parent);
p.one(!p.isMounted ? 'mount' : 'updated', function () {
setMountState.call(tag$$1, true);
});
} else {
// otherwise it's not a child tag we can trigger its mount event
setMountState.call(tag$$1, true);
}
tag$$1.__.wasCreated = true;
return tag$$1
}
/**
* Unmount the tag instance
* @param { Boolean } mustKeepRoot - if it's true the root node will not be removed
* @returns { Tag } the current tag instance
*/
function tagUnmount(tag, mustKeepRoot, expressions) {
var __ = tag.__;
var root = __.root;
var tagIndex = __TAGS_CACHE.indexOf(tag);
var p = root.parentNode;
if (!__.skipAnonymous) { tag.trigger('before-unmount'); }
// clear all attributes coming from the mounted tag
walkAttributes(__.impl.attrs, function (name) {
if (startsWith(name, ATTRS_PREFIX))
{ name = name.slice(ATTRS_PREFIX.length); }
removeAttribute(root, name);
});
// remove all the event listeners
tag.__.listeners.forEach(function (dom) {
Object.keys(dom[RIOT_EVENTS_KEY]).forEach(function (eventName) {
dom.removeEventListener(eventName, dom[RIOT_EVENTS_KEY][eventName]);
});
});
// remove tag instance from the global tags cache collection
if (tagIndex !== -1) { __TAGS_CACHE.splice(tagIndex, 1); }
// clean up the parent tags object
if (__.parent && !__.isAnonymous) {
var ptag = getImmediateCustomParent(__.parent);
if (__.isVirtual) {
Object
.keys(tag.tags)
.forEach(function (tagName) { return arrayishRemove(ptag.tags, tagName, tag.tags[tagName]); });
} else {
arrayishRemove(ptag.tags, __.tagName, tag);
}
}
// unmount all the virtual directives
if (tag.__.virts) {
each(tag.__.virts, function (v) {
if (v.parentNode) { v.parentNode.removeChild(v); }
});
}
// allow expressions to unmount themselves
unmountAll(expressions);
each(__.instAttrs, function (a) { return a.expr && a.expr.unmount && a.expr.unmount(); });
// clear the tag html if it's necessary
if (mustKeepRoot) { setInnerHTML(root, ''); }
// otherwise detach the root tag from the DOM
else if (p) { p.removeChild(root); }
// custom internal unmount function to avoid relying on the observable
if (__.onUnmount) { __.onUnmount(); }
// weird fix for a weird edge case #2409 and #2436
// some users might use your software not as you've expected
// so I need to add these dirty hacks to mitigate unexpected issues
if (!tag.isMounted) { setMountState.call(tag, true); }
setMountState.call(tag, false);
delete root._tag;
return tag
}
/**
* Tag creation factory function
* @constructor
* @param { Object } impl - it contains the tag template, and logic
* @param { Object } conf - tag options
* @param { String } innerHTML - html that eventually we need to inject in the tag
*/
function createTag(impl, conf, innerHTML) {
if ( impl === void 0 ) impl = {};
if ( conf === void 0 ) conf = {};
var tag = conf.context || {};
var opts = conf.opts || {};
var parent = conf.parent;
var isLoop = conf.isLoop;
var isAnonymous = !!conf.isAnonymous;
var skipAnonymous = settings.skipAnonymousTags && isAnonymous;
var item = conf.item;
// available only for the looped nodes
var index = conf.index;
// All attributes on the Tag when it's first parsed
var instAttrs = [];
// expressions on this type of Tag
var implAttrs = [];
var tmpl = impl.tmpl;
var expressions = [];
var root = conf.root;
var tagName = conf.tagName || getName(root);
var isVirtual = tagName === 'virtual';
var isInline = !isVirtual && !tmpl;
var dom;
if (isInline || isLoop && isAnonymous) {
dom = root;
} else {
if (!isVirtual) { root.innerHTML = ''; }
dom = mkdom(tmpl, innerHTML, isSvg(root));
}
// make this tag observable
if (!skipAnonymous) { observable(tag); }
// only call unmount if we have a valid __TAG_IMPL (has name property)
if (impl.name && root._tag) { root._tag.unmount(true); }
define(tag, '__', {
impl: impl,
root: root,
skipAnonymous: skipAnonymous,
implAttrs: implAttrs,
isAnonymous: isAnonymous,
instAttrs: instAttrs,
innerHTML: innerHTML,
tagName: tagName,
index: index,
isLoop: isLoop,
isInline: isInline,
item: item,
parent: parent,
// tags having event listeners
// it would be better to use weak maps here but we can not introduce breaking changes now
listeners: [],
// these vars will be needed only for the virtual tags
virts: [],
wasCreated: false,
tail: null,
head: null
});
// tag protected properties
return [
['isMounted', false],
// create a unique id to this tag
// it could be handy to use it also to improve the virtual dom rendering speed
['_riot_id', uid()],
['root', root],
['opts', opts, { writable: true, enumerable: true }],
['parent', parent || null],
// protect the "tags" and "refs" property from being overridden
['tags', {}],
['refs', {}],
['update', function (data) { return componentUpdate(tag, data, expressions); }],
['mixin', function () {
var mixins = [], len = arguments.length;
while ( len-- ) mixins[ len ] = arguments[ len ];
return componentMixin.apply(void 0, [ tag ].concat( mixins ));
}],
['mount', function () { return componentMount(tag, dom, expressions, opts); }],
['unmount', function (mustKeepRoot) { return tagUnmount(tag, mustKeepRoot, expressions); }]
].reduce(function (acc, ref) {
var key = ref[0];
var value = ref[1];
var opts = ref[2];
define(tag, key, value, opts);
return acc
}, extend(tag, item))
}
/**
* Mount a tag creating new Tag instance
* @param { Object } root - dom node where the tag will be mounted
* @param { String } tagName - name of the riot tag we want to mount
* @param { Object } opts - options to pass to the Tag instance
* @param { Object } ctx - optional context that will be used to extend an existing class ( used in riot.Tag )
* @returns { Tag } a new Tag instance
*/
function mount$1(root, tagName, opts, ctx) {
var impl = __TAG_IMPL[tagName];
var implClass = __TAG_IMPL[tagName].class;
var context = ctx || (implClass ? create(implClass.prototype) : {});
// cache the inner HTML to fix #855
var innerHTML = root._innerHTML = root._innerHTML || root.innerHTML;
var conf = extend({ root: root, opts: opts, context: context }, { parent: opts ? opts.parent : null });
var tag;
if (impl && root) { tag = createTag(impl, conf, innerHTML); }
if (tag && tag.mount) {
tag.mount(true);
// add this tag to the virtualDom variable
if (!contains(__TAGS_CACHE, tag)) { __TAGS_CACHE.push(tag); }
}
return tag
}
var tags = /*#__PURE__*/Object.freeze({
arrayishAdd: arrayishAdd,
getTagName: getName,
inheritParentProps: inheritParentProps,
mountTo: mount$1,
selectTags: query,
arrayishRemove: arrayishRemove,
getTag: get,
initChildTag: initChild,
moveChildTag: moveChild,
makeReplaceVirtual: makeReplaceVirtual,
getImmediateCustomParentTag: getImmediateCustomParent,
makeVirtual: makeVirtual,
moveVirtual: moveVirtual,
unmountAll: unmountAll,
createIfDirective: createIfDirective,
createRefDirective: createRefDirective
});
/**
* Riot public api
*/
var settings$1 = settings;
var util = {
tmpl: tmpl,
brackets: brackets,
styleManager: styleManager,
vdom: __TAGS_CACHE,
styleNode: styleManager.styleNode,
// export the riot internal utils as well
dom: dom,
check: check,
misc: misc,
tags: tags
};
// export the core props/methods
var Tag$1 = Tag;
var tag$1 = tag;
var tag2$1 = tag2;
var mount$2 = mount;
var mixin$1 = mixin;
var update$2 = update$1;
var unregister$1 = unregister;
var version$1 = version;
var observable$1 = observable;
var riot$1 = extend({}, core, {
observable: observable,
settings: settings$1,
util: util,
});
var riot$2 = /*#__PURE__*/Object.freeze({
settings: settings$1,
util: util,
Tag: Tag$1,
tag: tag$1,
tag2: tag2$1,
mount: mount$2,
mixin: mixin$1,
update: update$2,
unregister: unregister$1,
version: version$1,
observable: observable$1,
default: riot$1
});
/**
* Compiler for riot custom tags
* @version v3.5.2
*/
// istanbul ignore next
function safeRegex (re) {
var arguments$1 = arguments;
var src = re.source;
var opt = re.global ? 'g' : '';
if (re.ignoreCase) { opt += 'i'; }
if (re.multiline) { opt += 'm'; }
for (var i = 1; i < arguments.length; i++) {
src = src.replace('@', '\\' + arguments$1[i]);
}
return new RegExp(src, opt)
}
/**
* @module parsers
*/
var parsers = (function (win) {
var _p = {};
function _r (name) {
var parser = win[name];
if (parser) { return parser }
throw new Error('Parser "' + name + '" not loaded.')
}
function _req (name) {
var parts = name.split('.');
if (parts.length !== 2) { throw new Error('Bad format for parsers._req') }
var parser = _p[parts[0]][parts[1]];
if (parser) { return parser }
throw new Error('Parser "' + name + '" not found.')
}
function extend (obj, props) {
if (props) {
for (var prop in props) {
/* istanbul ignore next */
if (props.hasOwnProperty(prop)) {
obj[prop] = props[prop];
}
}
}
return obj
}
function renderPug (compilerName, html, opts, url) {
opts = extend({
pretty: true,
filename: url,
doctype: 'html'
}, opts);
return _r(compilerName).render(html, opts)
}
_p.html = {
jade: function (html, opts, url) {
/* eslint-disable */
console.log('DEPRECATION WARNING: jade was renamed "pug" - The jade parser will be removed in [email protected]!');
/* eslint-enable */
return renderPug('jade', html, opts, url)
},
pug: function (html, opts, url) {
return renderPug('pug', html, opts, url)
}
};
_p.css = {
less: function (tag, css, opts, url) {
var ret;
opts = extend({
sync: true,
syncImport: true,
filename: url
}, opts);
_r('less').render(css, opts, function (err, result) {
// istanbul ignore next
if (err) { throw err }
ret = result.css;
});
return ret
}
};
_p.js = {
es6: function (js, opts, url) { // eslint-disable-line no-unused-vars
return _r('Babel').transform( // eslint-disable-line
js,
extend({
plugins: [
['transform-es2015-template-literals', { loose: true }],
'transform-es2015-literals',
'transform-es2015-function-name',
'transform-es2015-arrow-functions',
'transform-es2015-block-scoped-functions',
['transform-es2015-classes', { loose: true }],
'transform-es2015-object-super',
'transform-es2015-shorthand-properties',
'transform-es2015-duplicate-keys',
['transform-es2015-computed-properties', { loose: true }],
['transform-es2015-for-of', { loose: true }],
'transform-es2015-sticky-regex',
'transform-es2015-unicode-regex',
'check-es2015-constants',
['transform-es2015-spread', { loose: true }],
'transform-es2015-parameters',
['transform-es2015-destructuring', { loose: true }],
'transform-es2015-block-scoping',
'transform-es2015-typeof-symbol',
['transform-es2015-modules-commonjs', { allowTopLevelThis: true }],
['transform-regenerator', { async: false, asyncGenerators: false }]
]
},
opts
)).code
},
buble: function (js, opts, url) {
opts = extend({
source: url,
modules: false
}, opts);
return _r('buble').transform(js, opts).code
},
coffee: function (js, opts) {
return _r('CoffeeScript').compile(js, extend({ bare: true }, opts))
},
livescript: function (js, opts) {
return _r('livescript').compile(js, extend({ bare: true, header: false }, opts))
},
typescript: function (js, opts) {
return _r('typescript')(js, opts)
},
none: function (js) {
return js
}
};
_p.js.javascript = _p.js.none;
_p.js.coffeescript = _p.js.coffee;
_p._req = _req;
_p.utils = {
extend: extend
};
return _p
})(window || global);
var S_SQ_STR = /'[^'\n\r\\]*(?:\\(?:\r\n?|[\S\s])[^'\n\r\\]*)*'/.source;
var S_R_SRC1 = [
/\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//.source,
'//.*',
S_SQ_STR,
S_SQ_STR.replace(/'/g, '"'),
'([/`])'
].join('|');
var S_R_SRC2 = (S_R_SRC1.slice(0, -2)) + "{}])";
function skipES6str (code, start, stack) {
var re = /[`$\\]/g;
re.lastIndex = start;
while (re.exec(code)) {
var end = re.lastIndex;
var c = code[end - 1];
if (c === '`') {
return end
}
if (c === '$' && code[end] === '{') {
stack.push('`', '}');
return end + 1
}
re.lastIndex++;
}
throw new Error('Unclosed ES6 template')
}
function jsSplitter (code, start) {
var re1 = new RegExp(S_R_SRC1, 'g');
var re2;
/* istanbul ignore next */
var skipRegex = brackets.skipRegex;
var offset = start | 0;
var result = [[]];
var stack = [];
var re = re1;
var lastPos = re.lastIndex = offset;
var str, ch, idx, end, match;
while ((match = re.exec(code))) {
idx = match.index;
end = re.lastIndex;
str = '';
ch = match[1];
if (ch) {
if (ch === '{') {
stack.push('}');
} else if (ch === '}') {
if (stack.pop() !== ch) {
throw new Error("Unexpected '}'")
} else if (stack[stack.length - 1] === '`') {
ch = stack.pop();
}
} else if (ch === '/') {
end = skipRegex(code, idx);
if (end > idx + 1) {
str = code.slice(idx, end);
}
}
if (ch === '`') {
end = skipES6str(code, end, stack);
str = code.slice(idx, end);
if (stack.length) {
re = re2 || (re2 = new RegExp(S_R_SRC2, 'g'));
} else {
re = re1;
}
}
} else {
str = match[0];
if (str[0] === '/') {
str = str[1] === '*' ? ' ' : '';
code = code.slice(offset, idx) + str + code.slice(end);
end = idx + str.length;
str = '';
} else if (str.length === 2) {
str = '';
}
}
if (str) {
result[0].push(code.slice(lastPos, idx));
result.push(str);
lastPos = end;
}
re.lastIndex = end;
}
result[0].push(code.slice(lastPos));
return result
}
/**
* @module compiler
*/
var extend$1 = parsers.utils.extend;
/* eslint-enable */
var S_LINESTR = /"[^"\n\\]*(?:\\[\S\s][^"\n\\]*)*"|'[^'\n\\]*(?:\\[\S\s][^'\n\\]*)*'/.source;
var S_STRINGS = brackets.R_STRINGS.source;
var HTML_ATTRS = / *([-\w:\xA0-\xFF]+) ?(?:= ?('[^']*'|"[^"]*"|\S+))?/g;
var HTML_COMMS = RegExp(//.source + '|' + S_LINESTR, 'g');
var HTML_TAGS = /<(-?[A-Za-z][-\w\xA0-\xFF]*)(?:\s+([^"'/>]*(?:(?:"[^"]*"|'[^']*'|\/[^>])[^'"/>]*)*)|\s*)(\/?)>/g;
var HTML_PACK = />[ \t]+<(-?[A-Za-z]|\/[-A-Za-z])/g;
var RIOT_ATTRS = ['style', 'src', 'd', 'value'];
var VOID_TAGS = /^(?:input|img|br|wbr|hr|area|base|col|embed|keygen|link|meta|param|source|track)$/;
var PRE_TAGS = /]*|"[^"]*")*)?>([\S\s]+?)<\/pre\s*>/gi;
var SPEC_TYPES = /^"(?:number|date(?:time)?|time|month|email|color)\b/i;
var IMPORT_STATEMENT = /^\s*import(?!\w|(\s)?\()(?:(?:\s|[^\s'"])*)['|"].*\n?/gm;
var TRIM_TRAIL = /[ \t]+$/gm;
var
RE_HASEXPR = safeRegex(/@#\d/, 'x01'),
RE_REPEXPR = safeRegex(/@#(\d+)/g, 'x01'),
CH_IDEXPR = '\x01#',
CH_DQCODE = '\u2057',
DQ = '"',
SQ = "'";
function cleanSource (src) {
var
mm,
re = HTML_COMMS;
if (src.indexOf('\r') !== 1) {
src = src.replace(/\r\n?/g, '\n');
}
re.lastIndex = 0;
while ((mm = re.exec(src))) {
if (mm[0][0] === '<') {
src = RegExp.leftContext + RegExp.rightContext;
re.lastIndex = mm[3] + 1;
}
}
return src
}
function parseAttribs (str, pcex) {
var
list = [],
match,
type, vexp;
HTML_ATTRS.lastIndex = 0;
str = str.replace(/\s+/g, ' ');
while ((match = HTML_ATTRS.exec(str))) {
var
k = match[1].toLowerCase(),
v = match[2];
if (!v) {
list.push(k);
} else {
if (v[0] !== DQ) {
v = DQ + (v[0] === SQ ? v.slice(1, -1) : v) + DQ;
}
if (k === 'type' && SPEC_TYPES.test(v)) {
type = v;
} else {
if (RE_HASEXPR.test(v)) {
if (k === 'value') { vexp = 1; }
if (RIOT_ATTRS.indexOf(k) !== -1) { k = 'riot-' + k; }
}
list.push(k + '=' + v);
}
}
}
if (type) {
if (vexp) { type = DQ + pcex._bp[0] + SQ + type.slice(1, -1) + SQ + pcex._bp[1] + DQ; }
list.push('type=' + type);
}
return list.join(' ')
}
function splitHtml (html, opts, pcex) {
var _bp = pcex._bp;
if (html && _bp[4].test(html)) {
var
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0,
list = brackets.split(html, 0, _bp),
expr;
for (var i = 1; i < list.length; i += 2) {
expr = list[i];
if (expr[0] === '^') {
expr = expr.slice(1);
} else if (jsfn) {
expr = jsfn(expr, opts).trim();
if (expr.slice(-1) === ';') { expr = expr.slice(0, -1); }
}
list[i] = CH_IDEXPR + (pcex.push(expr) - 1) + _bp[1];
}
html = list.join('');
}
return html
}
function restoreExpr (html, pcex) {
if (pcex.length) {
html = html.replace(RE_REPEXPR, function (_, d) {
return pcex._bp[0] + pcex[d].trim().replace(/[\r\n]+/g, ' ').replace(/"/g, CH_DQCODE)
});
}
return html
}
function _compileHTML (html, opts, pcex) {
if (!/\S/.test(html)) { return '' }
html = splitHtml(html, opts, pcex)
.replace(HTML_TAGS, function (_, name, attr, ends) {
name = name.toLowerCase();
ends = ends && !VOID_TAGS.test(name) ? '>' + name : '';
if (attr) { name += ' ' + parseAttribs(attr, pcex); }
return '<' + name + ends + '>'
});
if (!opts.whitespace) {
var p = [];
if (/]/.test(html)) {
html = html.replace(PRE_TAGS, function (q) {
p.push(q);
return '\u0002'
});
}
html = html.trim().replace(/\s+/g, ' ');
if (p.length) { html = html.replace(/\u0002/g, function () { return p.shift() }); } // eslint-disable-line
}
if (opts.compact) { html = html.replace(HTML_PACK, '><$1'); }
return restoreExpr(html, pcex).replace(TRIM_TRAIL, '')
}
function compileHTML (html, opts, pcex) {
if (Array.isArray(opts)) {
pcex = opts;
opts = {};
} else {
if (!pcex) { pcex = []; }
if (!opts) { opts = {}; }
}
pcex._bp = brackets.array(opts.brackets);
return _compileHTML(cleanSource(html), opts, pcex)
}
var JS_ES6SIGN = /^[ \t]*(((?:async|\*)\s*)?([$_A-Za-z][$\w]*))\s*\([^()]*\)\s*{/m;
function riotjs (js) {
var
parts = [],
match,
toes5,
pos,
method,
prefix,
name,
RE = RegExp;
var src = jsSplitter(js);
js = src.shift().join('<%>');
while ((match = js.match(JS_ES6SIGN))) {
parts.push(RE.leftContext);
js = RE.rightContext;
pos = skipBody(js);
method = match[1];
prefix = match[2] || '';
name = match[3];
toes5 = !/^(?:if|while|for|switch|catch|function)$/.test(name);
if (toes5) {
name = match[0].replace(method, 'this.' + name + ' =' + prefix + ' function');
} else {
name = match[0];
}
parts.push(name, js.slice(0, pos));
js = js.slice(pos);
if (toes5 && !/^\s*.\s*bind\b/.test(js)) { parts.push('.bind(this)'); }
}
if (parts.length) {
js = parts.join('') + js;
}
if (src.length) {
js = js.replace(/<%>/g, function () {
return src.shift()
});
}
return js
function skipBody (s) {
var r = /[{}]/g;
var i = 1;
while (i && r.exec(s)) {
if (s[r.lastIndex - 1] === '{') { ++i; }
else { --i; }
}
return i ? s.length : r.lastIndex
}
}
function _compileJS (js, opts, type, parserOpts, url) {
if (!/\S/.test(js)) { return '' }
if (!type) { type = opts.type; }
var parser = opts.parser || type && parsers._req('js.' + type, true) || riotjs;
return parser(js, parserOpts, url).replace(/\r\n?/g, '\n').replace(TRIM_TRAIL, '')
}
function compileJS (js, opts, type, userOpts) {
if (typeof opts === 'string') {
userOpts = type;
type = opts;
opts = {};
}
if (type && typeof type === 'object') {
userOpts = type;
type = '';
}
if (!userOpts) { userOpts = {}; }
return _compileJS(js, opts || {}, type, userOpts.parserOptions, userOpts.url)
}
var CSS_SELECTOR = RegExp('([{}]|^)[; ]*((?:[^@ ;{}][^{}]*)?[^@ ;{}:] ?)(?={)|' + S_LINESTR, 'g');
function scopedCSS (tag, css) {
var scope = ':scope';
return css.replace(CSS_SELECTOR, function (m, p1, p2) {
if (!p2) { return m }
p2 = p2.replace(/[^,]+/g, function (sel) {
var s = sel.trim();
if (s.indexOf(tag) === 0) {
return sel
}
if (!s || s === 'from' || s === 'to' || s.slice(-1) === '%') {
return sel
}
if (s.indexOf(scope) < 0) {
s = tag + ' ' + s + ',[data-is="' + tag + '"] ' + s;
} else {
s = s.replace(scope, tag) + ',' +
s.replace(scope, '[data-is="' + tag + '"]');
}
return s
});
return p1 ? p1 + ' ' + p2 : p2
})
}
function _compileCSS (css, tag, type, opts) {
opts = opts || {};
if (type) {
if (type !== 'css') {
var parser = parsers._req('css.' + type, true);
css = parser(tag, css, opts.parserOpts || {}, opts.url);
}
}
css = css.replace(brackets.R_MLCOMMS, '').replace(/\s+/g, ' ').trim();
if (tag) { css = scopedCSS(tag, css); }
return css
}
function compileCSS (css, type, opts) {
if (type && typeof type === 'object') {
opts = type;
type = '';
} else if (!opts) { opts = {}; }
return _compileCSS(css, opts.tagName, type, opts)
}
var TYPE_ATTR = /\stype\s*=\s*(?:(['"])(.+?)\1|(\S+))/i;
var MISC_ATTR = '\\s*=\\s*(' + S_STRINGS + '|{[^}]+}|\\S+)';
var END_TAGS = /\/>\n|^<(?:\/?-?[A-Za-z][-\w\xA0-\xFF]*\s*|-?[A-Za-z][-\w\xA0-\xFF]*\s+[-\w:\xA0-\xFF][\S\s]*?)>\n/;
function _q (s, r) {
if (!s) { return "''" }
s = SQ + s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + SQ;
return r && s.indexOf('\n') !== -1 ? s.replace(/\n/g, '\\n') : s
}
function mktag (name, html, css, attr, js, imports, opts) {
var
c = opts.debug ? ',\n ' : ', ',
s = '});';
if (js && js.slice(-1) !== '\n') { s = '\n' + s; }
return imports + 'riot.tag2(\'' + name + SQ +
c + _q(html, 1) +
c + _q(css) +
c + _q(attr) + ', function(opts) {\n' + js + s
}
function splitBlocks (str) {
if (/<[-\w]/.test(str)) {
var
m,
k = str.lastIndexOf('<'),
n = str.length;
while (k !== -1) {
m = str.slice(k, n).match(END_TAGS);
if (m) {
k += m.index + m[0].length;
m = str.slice(0, k);
if (m.slice(-5) === '<-/>\n') { m = m.slice(0, -5); }
return [m, str.slice(k)]
}
n = k;
k = str.lastIndexOf('<', k - 1);
}
}
return ['', str]
}
function getType (attribs) {
if (attribs) {
var match = attribs.match(TYPE_ATTR);
match = match && (match[2] || match[3]);
if (match) {
return match.replace('text/', '')
}
}
return ''
}
function getAttrib (attribs, name) {
if (attribs) {
var match = attribs.match(RegExp('\\s' + name + MISC_ATTR, 'i'));
match = match && match[1];
if (match) {
return (/^['"]/).test(match) ? match.slice(1, -1) : match
}
}
return ''
}
function unescapeHTML (str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, '\'')
}
function getParserOptions (attribs) {
var opts = unescapeHTML(getAttrib(attribs, 'options'));
return opts ? JSON.parse(opts) : null
}
function getCode (code, opts, attribs, base) {
var
type = getType(attribs),
src = getAttrib(attribs, 'src'),
jsParserOptions = extend$1({}, opts.parserOptions.js);
if (src) { return false }
return _compileJS(
code,
opts,
type,
extend$1(jsParserOptions, getParserOptions(attribs)),
base
)
}
function cssCode (code, opts, attribs, url, tag) {
var
parserStyleOptions = extend$1({}, opts.parserOptions.style),
extraOpts = {
parserOpts: extend$1(parserStyleOptions, getParserOptions(attribs)),
url: url
};
return _compileCSS(code, tag, getType(attribs) || opts.style, extraOpts)
}
function compileTemplate (html, url, lang, opts) {
var parser = parsers._req('html.' + lang, true);
return parser(html, opts, url)
}
var
CUST_TAG = RegExp(/^([ \t]*)<(-?[A-Za-z][-\w\xA0-\xFF]*)(?:\s+([^'"/>]+(?:(?:@|\/[^>])[^'"/>]*)*)|\s*)?(?:\/>|>[ \t]*\n?([\S\s]*)^\1<\/\2\s*>|>(.*)<\/\2\s*>)/
.source.replace('@', S_STRINGS), 'gim'),
SCRIPTS = /