Skip to content

Instantly share code, notes, and snippets.

@tholman
Last active April 25, 2017 03:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tholman/8471aa2108bff253894fbcfb9deb80b5 to your computer and use it in GitHub Desktop.
Save tholman/8471aa2108bff253894fbcfb9deb80b5 to your computer and use it in GitHub Desktop.
requirebin sketch
// Welcome! require() some modules from npm (like you were using browserify)
// and then hit Run Code to run your code on the right side.
// Modules get downloaded from browserify-cdn and bundled in your browser.
require('@emmetio/abbreviation');
require('@emmetio/html-transform');
setTimeout(function(){
;require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
/**
* Attribute descriptor of parsed abbreviation node
* @param {String} name Attribute name
* @param {String} value Attribute value
* @param {Object} options Additional custom attribute options
* @param {Boolean} options.boolean Attribute is boolean (e.g. name equals value)
* @param {Boolean} options.implied Attribute is implied (e.g. must be outputted
* only if contains non-null value)
*/
class Attribute {
constructor(name, value, options) {
this.name = name;
this.value = value != null ? value : null;
this.options = options || {};
}
/**
* Create a copy of current attribute
* @return {Attribute}
*/
clone() {
return new Attribute(this.name, this.value, Object.assign({}, this.options));
}
/**
* A string representation of current node
*/
valueOf() {
return `${this.name}="${this.value}"`;
}
}
/**
* A parsed abbreviation AST node. Nodes build up an abbreviation AST tree
*/
class Node {
/**
* Creates a new node
* @param {String} [name] Node name
* @param {Array} [attributes] Array of attributes to add
*/
constructor(name, attributes) {
// own properties
this.name = name || null;
this.value = null;
this.repeat = null;
this.selfClosing = false;
this.children = [];
/** @type {Node} Pointer to parent node */
this.parent = null;
/** @type {Node} Pointer to next sibling */
this.next = null;
/** @type {Node} Pointer to previous sibling */
this.previous = null;
this._attributes = [];
if (Array.isArray(attributes)) {
attributes.forEach(attr => this.setAttribute(attr));
}
}
/**
* Array of current node attributes
* @return {Attribute[]} Array of attributes
*/
get attributes() {
return this._attributes;
}
/**
* A shorthand to retreive node attributes as map
* @return {Object}
*/
get attributesMap() {
return this.attributes.reduce((out, attr) => {
out[attr.name] = attr.options.boolean ? attr.name : attr.value;
return out;
}, {});
}
/**
* Check if current node is a grouping one, e.g. has no actual representation
* and is used for grouping subsequent nodes only
* @return {Boolean}
*/
get isGroup() {
return !this.name && !this.value && !this._attributes.length;
}
/**
* Check if given node is a text-only node, e.g. contains only value
* @return {Boolean}
*/
get isTextOnly() {
return !this.name && !!this.value && !this._attributes.length;
}
/**
* Returns first child node
* @return {Node}
*/
get firstChild() {
return this.children[0];
}
/**
* Returns last child of current node
* @return {Node}
*/
get lastChild() {
return this.children[this.children.length - 1];
}
/**
* Return index of current node in its parent child list
* @return {Number} Returns -1 if current node is a root one
*/
get childIndex() {
return this.parent ? this.parent.children.indexOf(this) : -1;
}
/**
* Returns next sibling of current node
* @return {Node}
*/
get nextSibling() {
return this.next;
}
/**
* Returns previous sibling of current node
* @return {Node}
*/
get previousSibling() {
return this.previous;
}
/**
* Returns array of unique class names in current node
* @return {String[]}
*/
get classList() {
const attr = this.getAttribute('class');
return attr && attr.value
? attr.value.split(/\s+/g).filter(uniqueClass)
: [];
}
/**
* Convenient alias to create a new node instance
* @param {String} [name] Node name
* @param {Object} [attributes] Attributes hash
* @return {Node}
*/
create(name, attributes) {
return new Node(name, attributes);
}
/**
* Sets given attribute for current node
* @param {String|Object|Attribute} name Attribute name or attribute object
* @param {String} [value] Attribute value
*/
setAttribute(name, value) {
const attr = createAttribute(name, value);
const curAttr = this.getAttribute(name);
if (curAttr) {
this.replaceAttribute(curAttr, attr);
} else {
this._attributes.push(attr);
}
}
/**
* Check if attribute with given name exists in node
* @param {String} name
* @return {Boolean}
*/
hasAttribute(name) {
return !!this.getAttribute(name);
}
/**
* Returns attribute object by given name
* @param {String} name
* @return {Attribute}
*/
getAttribute(name) {
if (typeof name === 'object') {
name = name.name;
}
for (var i = 0; i < this._attributes.length; i++) {
const attr = this._attributes[i];
if (attr.name === name) {
return attr;
}
}
}
/**
* Replaces attribute with new instance
* @param {String|Attribute} curAttribute Current attribute name or instance
* to replace
* @param {String|Object|Attribute} newName New attribute name or attribute object
* @param {String} [newValue] New attribute value
*/
replaceAttribute(curAttribute, newName, newValue) {
if (typeof curAttribute === 'string') {
curAttribute = this.getAttribute(curAttribute);
}
const ix = this._attributes.indexOf(curAttribute);
if (ix !== -1) {
this._attributes.splice(ix, 1, createAttribute(newName, newValue));
}
}
/**
* Removes attribute with given name
* @param {String|Attribute} attr Atrtibute name or instance
*/
removeAttribute(attr) {
if (typeof attr === 'string') {
attr = this.getAttribute(attr);
}
const ix = this._attributes.indexOf(attr);
if (ix !== -1) {
this._attributes.splice(ix, 1);
}
}
/**
* Removes all attributes from current node
*/
clearAttributes() {
this._attributes.length = 0;
}
/**
* Adds given class name to class attribute
* @param {String} token Class name token
*/
addClass(token) {
token = normalize(token);
if (!this.hasAttribute('class')) {
this.setAttribute('class', token);
} else if (token && !this.hasClass(token)) {
this.setAttribute('class', this.classList.concat(token).join(' '));
}
}
/**
* Check if current node contains given class name
* @param {String} token Class name token
* @return {Boolean}
*/
hasClass(token) {
return this.classList.indexOf(normalize(token)) !== -1;
}
/**
* Removes given class name from class attribute
* @param {String} token Class name token
*/
removeClass(token) {
token = normalize(token);
if (this.hasClass(token)) {
this.setAttribute('class', this.classList.filter(name => name !== token).join(' '));
}
}
/**
* Appends child to current node
* @param {Node} node
*/
appendChild(node) {
this.insertAt(node, this.children.length);
}
/**
* Inserts given `newNode` before `refNode` child node
* @param {Node} newNode
* @param {Node} refNode
*/
insertBefore(newNode, refNode) {
this.insertAt(newNode, this.children.indexOf(refNode));
}
/**
* Insert given `node` at `pos` position of child list
* @param {Node} node
* @param {Number} pos
*/
insertAt(node, pos) {
if (pos < 0 || pos > this.children.length) {
throw new Error('Unable to insert node: position is out of child list range');
}
const prev = this.children[pos - 1];
const next = this.children[pos];
node.remove();
node.parent = this;
this.children.splice(pos, 0, node);
if (prev) {
node.previous = prev;
prev.next = node;
}
if (next) {
node.next = next;
next.previous = node;
}
}
/**
* Removes given child from current node
* @param {Node} node
*/
removeChild(node) {
const ix = this.children.indexOf(node);
if (ix !== -1) {
this.children.splice(ix, 1);
if (node.previous) {
node.previous.next = node.next;
}
if (node.next) {
node.next.previous = node.previous;
}
node.parent = node.next = node.previous = null;
}
}
/**
* Removes current node from its parent
*/
remove() {
if (this.parent) {
this.parent.removeChild(this);
}
}
/**
* Creates a detached copy of current node
* @param {Boolean} deep Clone node contents as well
* @return {Node}
*/
clone(deep) {
const clone = new Node(this.name);
clone.value = this.value;
clone.selfClosing = this.selfClosing;
if (this.repeat) {
clone.repeat = Object.assign({}, this.repeat);
}
this._attributes.forEach(attr => clone.setAttribute(attr.clone()));
if (deep) {
this.children.forEach(child => clone.appendChild(child.clone(true)));
}
return clone;
}
/**
* Walks on each descendant node and invokes given `fn` function on it.
* The function receives two arguments: the node itself and its depth level
* from current node. If function returns `false`, it stops walking
* @param {Function} fn
*/
walk(fn, _level) {
_level = _level || 0;
let ctx = this.firstChild;
while (ctx) {
// in case if context node will be detached during `fn` call
const next = ctx.next;
if (fn(ctx, _level) === false || ctx.walk(fn, _level + 1) === false) {
return false;
}
ctx = next;
}
}
/**
* A helper method for transformation chaining: runs given `fn` function on
* current node and returns the same node
*/
use(fn) {
const args = [this];
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
fn.apply(null, args);
return this;
}
toString() {
const attrs = this.attributes.map(attr => {
attr = this.getAttribute(attr.name);
const opt = attr.options;
let out = `${opt && opt.implied ? '!' : ''}${attr.name || ''}`;
if (opt && opt.boolean) {
out += '.';
} else if (attr.value != null) {
out += `="${attr.value}"`;
}
return out;
});
let out = `${this.name || ''}`;
if (attrs.length) {
out += `[${attrs.join(' ')}]`;
}
if (this.value != null) {
out += `{${this.value}}`;
}
if (this.selfClosing) {
out += '/';
}
if (this.repeat) {
out += `*${this.repeat.count ? this.repeat.count : ''}`;
if (this.repeat.value != null) {
out += `@${this.repeat.value}`;
}
}
return out;
}
}
/**
* Attribute factory
* @param {String|Attribute|Object} name Attribute name or attribute descriptor
* @param {*} value Attribute value
* @return {Attribute}
*/
function createAttribute(name, value) {
if (name instanceof Attribute) {
return name;
}
if (typeof name === 'string') {
return new Attribute(name, value);
}
if (name && typeof name === 'object') {
return new Attribute(name.name, name.value, name.options);
}
}
/**
* @param {String} str
* @return {String}
*/
function normalize(str) {
return String(str).trim();
}
function uniqueClass(item, i, arr) {
return item && arr.indexOf(item) === i;
}
module.exports = Node;
},{}],2:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
/**
* Methods for consuming quoted values
*/
const SINGLE_QUOTE = 39; // '
const DOUBLE_QUOTE = 34; // "
const defaultOptions = {
escape: 92, // \ character
throws: false
};
/**
* Consumes 'single' or "double"-quoted string from given string, if possible
* @param {StreamReader} stream
* @param {Number} options.escape A character code of quote-escape symbol
* @param {Boolean} options.throws Throw error if quotes string can’t be properly consumed
* @return {Boolean} `true` if quoted string was consumed. The contents
* of quoted string will be availabe as `stream.current()`
*/
var eatQuoted = function(stream, options) {
options = options ? Object.assign({}, defaultOptions, options) : defaultOptions;
const start = stream.pos;
const quote = stream.peek();
if (stream.eat(isQuote)) {
while (!stream.eof()) {
switch (stream.next()) {
case quote:
stream.start = start;
return true;
case options.escape:
stream.next();
break;
}
}
// If we’re here then stream wasn’t properly consumed.
// Revert stream and decide what to do
stream.pos = start;
if (options.throws) {
throw stream.error('Unable to consume quoted string');
}
}
return false;
};
function isQuote(code) {
return code === SINGLE_QUOTE || code === DOUBLE_QUOTE;
}
/**
* Check if given code is a number
* @param {Number} code
* @return {Boolean}
*/
function isNumber(code) {
return code > 47 && code < 58;
}
/**
* Check if given character code is alpha code (letter through A to Z)
* @param {Number} code
* @param {Number} [from]
* @param {Number} [to]
* @return {Boolean}
*/
function isAlpha(code, from, to) {
from = from || 65; // A
to = to || 90; // Z
code &= ~32; // quick hack to convert any char code to uppercase char code
return code >= from && code <= to;
}
/**
* Check if given character code is alpha-numeric (letter through A to Z or number)
* @param {Number} code
* @return {Boolean}
*/
function isAlphaNumeric(code) {
return isNumber(code) || isAlpha(code);
}
function isWhiteSpace(code) {
return code === 32 /* space */
|| code === 9 /* tab */
|| code === 160; /* non-breaking space */
}
/**
* Check if given character code is a space
* @param {Number} code
* @return {Boolean}
*/
function isSpace(code) {
return isWhiteSpace(code)
|| code === 10 /* LF */
|| code === 13; /* CR */
}
const defaultOptions$1 = {
escape: 92, // \ character
throws: false
};
/**
* Eats paired characters substring, for example `(foo)` or `[bar]`
* @param {StreamReader} stream
* @param {Number} open Character code of pair openinig
* @param {Number} close Character code of pair closing
* @param {Object} [options]
* @return {Boolean} Returns `true` if chacarter pair was successfully
* consumed, it’s content will be available as `stream.current()`
*/
function eatPair(stream, open, close, options) {
options = options ? Object.assign({}, defaultOptions$1, options) : defaultOptions$1;
const start = stream.pos;
if (stream.eat(open)) {
let stack = 1, ch;
while (!stream.eof()) {
if (eatQuoted(stream, options)) {
continue;
}
ch = stream.next();
if (ch === open) {
stack++;
} else if (ch === close) {
stack--;
if (!stack) {
stream.start = start;
return true;
}
} else if (ch === options.escape) {
stream.next();
}
}
// If we’re here then paired character can’t be consumed
stream.pos = start;
if (options.throws) {
throw stream.error(`Unable to find matching pair for ${String.fromCharCode(open)}`);
}
}
return false;
}
exports.eatQuoted = eatQuoted;
exports.isQuote = isQuote;
exports.isAlpha = isAlpha;
exports.isNumber = isNumber;
exports.isAlphaNumeric = isAlphaNumeric;
exports.isSpace = isSpace;
exports.isWhiteSpace = isWhiteSpace;
exports.eatPair = eatPair;
},{}],3:[function(require,module,exports){
'use strict';
/**
* A streaming, character code-based string reader
*/
class StreamReader {
constructor(string, start, end) {
if (end == null && typeof string === 'string') {
end = string.length;
}
this.string = string;
this.pos = this.start = start || 0;
this.end = end;
}
/**
* Returns true only if the stream is at the end of the file.
* @returns {Boolean}
*/
eof() {
return this.pos >= this.end;
}
/**
* Creates a new stream instance which is limited to given `start` and `end`
* range. E.g. its `eof()` method will look at `end` property, not actual
* stream end
* @param {Point} start
* @param {Point} end
* @return {StreamReader}
*/
limit(start, end) {
return new this.constructor(this.string, start, end);
}
/**
* Returns the next character code in the stream without advancing it.
* Will return NaN at the end of the file.
* @returns {Number}
*/
peek() {
return this.string.charCodeAt(this.pos);
}
/**
* Returns the next character in the stream and advances it.
* Also returns <code>undefined</code> when no more characters are available.
* @returns {Number}
*/
next() {
if (this.pos < this.string.length) {
return this.string.charCodeAt(this.pos++);
}
}
/**
* `match` can be a character code or a function that takes a character code
* and returns a boolean. If the next character in the stream 'matches'
* the given argument, it is consumed and returned.
* Otherwise, `false` is returned.
* @param {Number|Function} match
* @returns {Boolean}
*/
eat(match) {
const ch = this.peek();
const ok = typeof match === 'function' ? match(ch) : ch === match;
if (ok) {
this.next();
}
return ok;
}
/**
* Repeatedly calls <code>eat</code> with the given argument, until it
* fails. Returns <code>true</code> if any characters were eaten.
* @param {Object} match
* @returns {Boolean}
*/
eatWhile(match) {
const start = this.pos;
while (!this.eof() && this.eat(match)) {}
return this.pos !== start;
}
/**
* Backs up the stream n characters. Backing it up further than the
* start of the current token will cause things to break, so be careful.
* @param {Number} n
*/
backUp(n) {
this.pos -= (n || 1);
}
/**
* Get the string between the start of the current token and the
* current stream position.
* @returns {String}
*/
current() {
return this.string.slice(this.start, this.pos);
}
/**
* Creates error object with current stream state
* @param {String} message
* @return {Error}
*/
error(message) {
const err = new Error(`${message} at char ${this.pos + 1}`);
err.originalMessage = message;
err.pos = this.pos;
err.string = this.string;
return err;
}
}
module.exports = StreamReader;
},{}],"@emmetio/abbreviation":[function(require,module,exports){
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var Node = _interopDefault(require('@emmetio/node'));
var StreamReader = _interopDefault(require('@emmetio/stream-reader'));
var _emmetio_streamReaderUtils = require('@emmetio/stream-reader-utils');
const ASTERISK = 42; // *
/**
* Consumes node repeat token from current stream position and returns its
* parsed value
* @param {StringReader} stream
* @return {Object}
*/
var consumeRepeat = function(stream) {
if (stream.eat(ASTERISK)) {
stream.start = stream.pos;
// XXX think about extending repeat syntax with through numbering
return { count: stream.eatWhile(_emmetio_streamReaderUtils.isNumber) ? +stream.current() : null };
}
};
const opt = { throws: true };
/**
* Consumes quoted literal from current stream position and returns it’s inner,
* unquoted, value
* @param {StringReader} stream
* @return {String} Returns `null` if unable to consume quoted value from current
* position
*/
var consumeQuoted = function(stream) {
if (_emmetio_streamReaderUtils.eatQuoted(stream, opt)) {
return stream.current().slice(1, -1);
}
};
const LCURLY = 123; // {
const RCURLY = 125; // }
const opt$1 = { throws: true };
/**
* Consumes text node, e.g. contents of `{...}` and returns its inner value
* @param {StringReader} stream
* @return {String} Consumed text content or `null` otherwise
*/
var consumeTextNode = function(stream) {
return _emmetio_streamReaderUtils.eatPair(stream, LCURLY, RCURLY, opt$1)
? stream.current().slice(1, -1)
: null;
};
const EXCL = 33; // .
const DOT$1 = 46; // .
const EQUALS = 61; // =
const ATTR_OPEN = 91; // [
const ATTR_CLOSE = 93; // ]
const reAttributeName = /^\!?[\w\-:\$@]+\.?$/;
/**
* Consumes attributes defined in square braces from given stream.
* Example:
* [attr col=3 title="Quoted string" selected. support={react}]
* @param {StringReader} stream
* @returns {Array} Array of consumed attributes
*/
var consumeAttributes = function(stream) {
if (!stream.eat(ATTR_OPEN)) {
return null;
}
const result = [];
let token, attr;
while (!stream.eof()) {
stream.eatWhile(_emmetio_streamReaderUtils.isWhiteSpace);
if (stream.eat(ATTR_CLOSE)) {
return result; // End of attribute set
} else if ((token = consumeQuoted(stream)) != null) {
// Consumed quoted value: anonymous attribute
result.push({
name: null,
value: token
});
} else if (eatUnquoted(stream)) {
// Consumed next word: could be either attribute name or unquoted default value
token = stream.current();
if (!reAttributeName.test(token)) {
// anonymous attribute
result.push({ name: null, value: token });
} else {
// Looks like a regular attribute
attr = parseAttributeName(token);
result.push(attr);
if (stream.eat(EQUALS)) {
// Explicitly defined value. Could be a word, a quoted string
// or React-like expression
if ((token = consumeQuoted(stream)) != null) {
attr.value = token;
} else if ((token = consumeTextNode(stream)) != null) {
attr.value = token;
attr.options = {
before: '{',
after: '}'
};
} else if (eatUnquoted(stream)) {
attr.value = stream.current();
}
}
}
} else {
throw stream.error('Expected attribute name');
}
}
throw stream.error('Expected closing "]" brace');
};
function parseAttributeName(name) {
const options = {};
// If a first character in attribute name is `!` — it’s an implied
// default attribute
if (name.charCodeAt(0) === EXCL) {
name = name.slice(1);
options.implied = true;
}
// Check for last character: if it’s a `.`, user wants boolean attribute
if (name.charCodeAt(name.length - 1) === DOT$1) {
name = name.slice(0, name.length - 1);
options.boolean = true;
}
const attr = { name };
if (Object.keys(options).length) {
attr.options = options;
}
return attr;
}
/**
* Eats token that can be an unquoted value from given stream
* @param {StreamReader} stream
* @return {Boolean}
*/
function eatUnquoted(stream) {
const start = stream.pos;
if (stream.eatWhile(isUnquoted)) {
stream.start = start;
return true;
}
}
function isUnquoted(code) {
return !_emmetio_streamReaderUtils.isSpace(code) && !_emmetio_streamReaderUtils.isQuote(code)
&& code !== ATTR_OPEN && code !== ATTR_CLOSE && code !== EQUALS;
}
const HASH = 35; // #
const DOT = 46; // .
const SLASH = 47; // /
/**
* Consumes a single element node from current abbreviation stream
* @param {StringReader} stream
* @return {Node}
*/
var consumeElement = function(stream) {
// consume element name, if provided
const start = stream.pos;
const node = new Node(eatName(stream));
let next;
while (!stream.eof()) {
if (stream.eat(DOT)) {
node.addClass(eatName(stream));
} else if (stream.eat(HASH)) {
node.setAttribute('id', eatName(stream));
} else if (stream.eat(SLASH)) {
// A self-closing indicator must be at the end of non-grouping node
if (node.isGroup) {
stream.backUp(1);
throw stream.error('Unexpected self-closing indicator');
}
node.selfClosing = true;
if (next = consumeRepeat(stream)) {
node.repeat = next;
}
break;
} else if (next = consumeAttributes(stream)) {
for (let i = 0, il = next.length; i < il; i++) {
node.setAttribute(next[i]);
}
} else if ((next = consumeTextNode(stream)) !== null) {
node.value = next;
} else if (next = consumeRepeat(stream)) {
node.repeat = next;
} else {
break;
}
}
if (start === stream.pos) {
throw stream.error(`Unable to consume abbreviation node, unexpected ${stream.peek()}`);
}
return node;
};
function eatName(stream) {
stream.start = stream.pos;
stream.eatWhile(isName);
return stream.current();
}
function isName(code) {
return _emmetio_streamReaderUtils.isAlphaNumeric(code)
|| code === 45 /* - */
|| code === 58 /* : */
|| code === 36 /* $ */
|| code === 64 /* @ */
|| code === 33 /* ! */
|| code === 37 /* % */;
}
const GROUP_START = 40; // (
const GROUP_END = 41; // )
const OP_SIBLING = 43; // +
const OP_CHILD = 62; // >
const OP_CLIMB = 94; // ^
/**
* Parses given string into a node tree
* @param {String} str Abbreviation to parse
* @return {Node}
*/
function parse(str) {
const stream = new StreamReader(str.trim());
const root = new Node();
let ctx = root, groupStack = [], ch;
while (!stream.eof()) {
ch = stream.peek();
if (ch === GROUP_START) { // start of group
// The grouping node should be detached to properly handle
// out-of-bounds `^` operator. Node will be attached right on group end
const node = new Node();
const groupCtx = groupStack.length ? last(groupStack)[0] : ctx;
groupStack.push([node, groupCtx, stream.pos]);
ctx = node;
stream.next();
continue;
} else if (ch === GROUP_END) { // end of group
const lastGroup = groupStack.pop();
if (!lastGroup) {
throw stream.error('Unexpected ")" group end');
}
const node = lastGroup[0];
ctx = lastGroup[1];
stream.next();
// a group can have a repeater
if (node.repeat = consumeRepeat(stream)) {
ctx.appendChild(node);
} else {
// move all children of group into parent node
while (node.firstChild) {
ctx.appendChild(node.firstChild);
}
// for convenience, groups can be joined with optional `+` operator
stream.eat(OP_SIBLING);
}
continue;
}
const node = consumeElement(stream);
ctx.appendChild(node);
if (stream.eof()) {
break;
}
switch (stream.peek()) {
case OP_SIBLING:
stream.next();
continue;
case OP_CHILD:
stream.next();
ctx = node;
continue;
case OP_CLIMB:
// it’s perfectly valid to have multiple `^` operators
while (stream.eat(OP_CLIMB)) {
ctx = ctx.parent || ctx;
}
continue;
}
}
if (groupStack.length) {
stream.pos = groupStack.pop()[2];
throw stream.error('Expected group close');
}
return root;
}
function last(arr) {
return arr[arr.length - 1];
}
/**
* Parses given abbreviation and un-rolls it into a full tree: recursively
* replaces repeated elements with actual nodes
* @param {String} abbr
* @return {Node}
*/
var index = function(abbr) {
const tree = parse(abbr);
tree.walk(unroll);
return tree;
};
function unroll(node) {
if (!node.repeat || !node.repeat.count) {
return;
}
for (let i = 1; i < node.repeat.count; i++) {
const clone = node.clone(true);
clone.repeat.value = i;
clone.walk(unroll);
node.parent.insertBefore(clone, node);
}
node.repeat.value = node.repeat.count;
}
module.exports = index;
},{"@emmetio/node":1,"@emmetio/stream-reader":3,"@emmetio/stream-reader-utils":2}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm5vZGVfbW9kdWxlcy9AZW1tZXRpby9ub2RlL2Rpc3Qvbm9kZS5janMuanMiLCJub2RlX21vZHVsZXMvQGVtbWV0aW8vc3RyZWFtLXJlYWRlci11dGlscy9kaXN0L3N0cmVhbS1yZWFkZXItdXRpbHMuY2pzLmpzIiwibm9kZV9tb2R1bGVzL0BlbW1ldGlvL3N0cmVhbS1yZWFkZXIvZGlzdC9zdHJlYW0tcmVhZGVyLmNqcy5qcyIsIkBlbW1ldGlvJTJGYWJicmV2aWF0aW9uIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbmVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQXR0cmlidXRlIGRlc2NyaXB0b3Igb2YgcGFyc2VkIGFiYnJldmlhdGlvbiBub2RlXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBBdHRyaWJ1dGUgbmFtZVxuICogQHBhcmFtIHtTdHJpbmd9IHZhbHVlIEF0dHJpYnV0ZSB2YWx1ZVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgQWRkaXRpb25hbCBjdXN0b20gYXR0cmlidXRlIG9wdGlvbnNcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gb3B0aW9ucy5ib29sZWFuIEF0dHJpYnV0ZSBpcyBib29sZWFuIChlLmcuIG5hbWUgZXF1YWxzIHZhbHVlKVxuICogQHBhcmFtIHtCb29sZWFufSBvcHRpb25zLmltcGxpZWQgQXR0cmlidXRlIGlzIGltcGxpZWQgKGUuZy4gbXVzdCBiZSBvdXRwdXR0ZWRcbiAqIG9ubHkgaWYgY29udGFpbnMgbm9uLW51bGwgdmFsdWUpXG4gKi9cbmNsYXNzIEF0dHJpYnV0ZSB7XG5cdGNvbnN0cnVjdG9yKG5hbWUsIHZhbHVlLCBvcHRpb25zKSB7XG5cdFx0dGhpcy5uYW1lID0gbmFtZTtcblx0XHR0aGlzLnZhbHVlID0gdmFsdWUgIT0gbnVsbCA/IHZhbHVlIDogbnVsbDtcblx0XHR0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZSBhIGNvcHkgb2YgY3VycmVudCBhdHRyaWJ1dGVcblx0ICogQHJldHVybiB7QXR0cmlidXRlfVxuXHQgKi9cblx0Y2xvbmUoKSB7XG5cdFx0cmV0dXJuIG5ldyBBdHRyaWJ1dGUodGhpcy5uYW1lLCB0aGlzLnZhbHVlLCBPYmplY3QuYXNzaWduKHt9LCB0aGlzLm9wdGlvbnMpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBjdXJyZW50IG5vZGVcblx0ICovXG5cdHZhbHVlT2YoKSB7XG5cdFx0cmV0dXJuIGAke3RoaXMubmFtZX09XCIke3RoaXMudmFsdWV9XCJgO1xuXHR9XG59XG5cbi8qKlxuICogQSBwYXJzZWQgYWJicmV2aWF0aW9uIEFTVCBub2RlLiBOb2RlcyBidWlsZCB1cCBhbiBhYmJyZXZpYXRpb24gQVNUIHRyZWVcbiAqL1xuY2xhc3MgTm9kZSB7XG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IG5vZGVcblx0ICogQHBhcmFtIHtTdHJpbmd9IFtuYW1lXSBOb2RlIG5hbWVcblx0ICogQHBhcmFtIHtBcnJheX0gW2F0dHJpYnV0ZXNdIEFycmF5IG9mIGF0dHJpYnV0ZXMgdG8gYWRkXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihuYW1lLCBhdHRyaWJ1dGVzKSB7XG5cdFx0Ly8gb3duIHByb3BlcnRpZXNcblx0XHR0aGlzLm5hbWUgPSBuYW1lIHx8IG51bGw7XG5cdFx0dGhpcy52YWx1ZSA9IG51bGw7XG5cdFx0dGhpcy5yZXBlYXQgPSBudWxsO1xuXHRcdHRoaXMuc2VsZkNsb3NpbmcgPSBmYWxzZTtcblxuXHRcdHRoaXMuY2hpbGRyZW4gPSBbXTtcblxuXHRcdC8qKiBAdHlwZSB7Tm9kZX0gUG9pbnRlciB0byBwYXJlbnQgbm9kZSAqL1xuXHRcdHRoaXMucGFyZW50ID0gbnVsbDtcblxuXHRcdC8qKiBAdHlwZSB7Tm9kZX0gUG9pbnRlciB0byBuZXh0IHNpYmxpbmcgKi9cblx0XHR0aGlzLm5leHQgPSBudWxsO1xuXG5cdFx0LyoqIEB0eXBlIHtOb2RlfSBQb2ludGVyIHRvIHByZXZpb3VzIHNpYmxpbmcgKi9cblx0XHR0aGlzLnByZXZpb3VzID0gbnVsbDtcblxuXHRcdHRoaXMuX2F0dHJpYnV0ZXMgPSBbXTtcblxuXHRcdGlmIChBcnJheS5pc0FycmF5KGF0dHJpYnV0ZXMpKSB7XG5cdFx0XHRhdHRyaWJ1dGVzLmZvckVhY2goYXR0ciA9PiB0aGlzLnNldEF0dHJpYnV0ZShhdHRyKSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEFycmF5IG9mIGN1cnJlbnQgbm9kZSBhdHRyaWJ1dGVzXG5cdCAqIEByZXR1cm4ge0F0dHJpYnV0ZVtdfSBBcnJheSBvZiBhdHRyaWJ1dGVzXG5cdCAqL1xuXHRnZXQgYXR0cmlidXRlcygpIHtcblx0XHRyZXR1cm4gdGhpcy5fYXR0cmlidXRlcztcblx0fVxuXG5cdC8qKlxuXHQgKiBBIHNob3J0aGFuZCB0byByZXRyZWl2ZSBub2RlIGF0dHJpYnV0ZXMgYXMgbWFwXG5cdCAqIEByZXR1cm4ge09iamVjdH1cblx0ICovXG5cdGdldCBhdHRyaWJ1dGVzTWFwKCkge1xuXHRcdHJldHVybiB0aGlzLmF0dHJpYnV0ZXMucmVkdWNlKChvdXQsIGF0dHIpID0+IHtcblx0XHRcdG91dFthdHRyLm5hbWVdID0gYXR0ci5vcHRpb25zLmJvb2xlYW4gPyBhdHRyLm5hbWUgOiBhdHRyLnZhbHVlO1xuXHRcdFx0cmV0dXJuIG91dDtcblx0XHR9LCB7fSk7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2sgaWYgY3VycmVudCBub2RlIGlzIGEgZ3JvdXBpbmcgb25lLCBlLmcuIGhhcyBubyBhY3R1YWwgcmVwcmVzZW50YXRpb25cblx0ICogYW5kIGlzIHVzZWQgZm9yIGdyb3VwaW5nIHN1YnNlcXVlbnQgbm9kZXMgb25seVxuXHQgKiBAcmV0dXJuIHtCb29sZWFufVxuXHQgKi9cblx0Z2V0IGlzR3JvdXAoKSB7XG5cdFx0cmV0dXJuICF0aGlzLm5hbWUgJiYgIXRoaXMudmFsdWUgJiYgIXRoaXMuX2F0dHJpYnV0ZXMubGVuZ3RoO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrIGlmIGdpdmVuIG5vZGUgaXMgYSB0ZXh0LW9ubHkgbm9kZSwgZS5nLiBjb250YWlucyBvbmx5IHZhbHVlXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59XG5cdCAqL1xuXHRnZXQgaXNUZXh0T25seSgpIHtcblx0XHRyZXR1cm4gIXRoaXMubmFtZSAmJiAhIXRoaXMudmFsdWUgJiYgIXRoaXMuX2F0dHJpYnV0ZXMubGVuZ3RoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgZmlyc3QgY2hpbGQgbm9kZVxuXHQgKiBAcmV0dXJuIHtOb2RlfVxuXHQgKi9cblx0Z2V0IGZpcnN0Q2hpbGQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2hpbGRyZW5bMF07XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBsYXN0IGNoaWxkIG9mIGN1cnJlbnQgbm9kZVxuXHQgKiBAcmV0dXJuIHtOb2RlfVxuXHQgKi9cblx0Z2V0IGxhc3RDaGlsZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5jaGlsZHJlblt0aGlzLmNoaWxkcmVuLmxlbmd0aCAtIDFdO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybiBpbmRleCBvZiBjdXJyZW50IG5vZGUgaW4gaXRzIHBhcmVudCBjaGlsZCBsaXN0XG5cdCAqIEByZXR1cm4ge051bWJlcn0gUmV0dXJucyAtMSBpZiBjdXJyZW50IG5vZGUgaXMgYSByb290IG9uZVxuXHQgKi9cblx0Z2V0IGNoaWxkSW5kZXgoKSB7XG5cdFx0cmV0dXJuIHRoaXMucGFyZW50ID8gdGhpcy5wYXJlbnQuY2hpbGRyZW4uaW5kZXhPZih0aGlzKSA6IC0xO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgbmV4dCBzaWJsaW5nIG9mIGN1cnJlbnQgbm9kZVxuXHQgKiBAcmV0dXJuIHtOb2RlfVxuXHQgKi9cblx0Z2V0IG5leHRTaWJsaW5nKCkge1xuXHRcdHJldHVybiB0aGlzLm5leHQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBwcmV2aW91cyBzaWJsaW5nIG9mIGN1cnJlbnQgbm9kZVxuXHQgKiBAcmV0dXJuIHtOb2RlfVxuXHQgKi9cblx0Z2V0IHByZXZpb3VzU2libGluZygpIHtcblx0XHRyZXR1cm4gdGhpcy5wcmV2aW91cztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGFycmF5IG9mIHVuaXF1ZSBjbGFzcyBuYW1lcyBpbiBjdXJyZW50IG5vZGVcblx0ICogQHJldHVybiB7U3RyaW5nW119XG5cdCAqL1xuXHRnZXQgY2xhc3NMaXN0KCkge1xuXHRcdGNvbnN0IGF0dHIgPSB0aGlzLmdldEF0dHJpYnV0ZSgnY2xhc3MnKTtcblx0XHRyZXR1cm4gYXR0ciAmJiBhdHRyLnZhbHVlXG5cdFx0XHQ/IGF0dHIudmFsdWUuc3BsaXQoL1xccysvZykuZmlsdGVyKHVuaXF1ZUNsYXNzKVxuXHRcdFx0OiBbXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZW5pZW50IGFsaWFzIHRvIGNyZWF0ZSBhIG5ldyBub2RlIGluc3RhbmNlXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBbbmFtZV0gTm9kZSBuYW1lXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBbYXR0cmlidXRlc10gQXR0cmlidXRlcyBoYXNoXG5cdCAqIEByZXR1cm4ge05vZGV9XG5cdCAqL1xuXHRjcmVhdGUobmFtZSwgYXR0cmlidXRlcykge1xuXHRcdHJldHVybiBuZXcgTm9kZShuYW1lLCBhdHRyaWJ1dGVzKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGdpdmVuIGF0dHJpYnV0ZSBmb3IgY3VycmVudCBub2RlXG5cdCAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxBdHRyaWJ1dGV9IG5hbWUgQXR0cmlidXRlIG5hbWUgb3IgYXR0cmlidXRlIG9iamVjdFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gW3ZhbHVlXSBBdHRyaWJ1dGUgdmFsdWVcblx0ICovXG5cdHNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSkge1xuXHRcdGNvbnN0IGF0dHIgPSBjcmVhdGVBdHRyaWJ1dGUobmFtZSwgdmFsdWUpO1xuXHRcdGNvbnN0IGN1ckF0dHIgPSB0aGlzLmdldEF0dHJpYnV0ZShuYW1lKTtcblx0XHRpZiAoY3VyQXR0cikge1xuXHRcdFx0dGhpcy5yZXBsYWNlQXR0cmlidXRlKGN1ckF0dHIsIGF0dHIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9hdHRyaWJ1dGVzLnB1c2goYXR0cik7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrIGlmIGF0dHJpYnV0ZSB3aXRoIGdpdmVuIG5hbWUgZXhpc3RzIGluIG5vZGVcblx0ICogQHBhcmFtICB7U3RyaW5nfSBuYW1lXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59XG5cdCAqL1xuXHRoYXNBdHRyaWJ1dGUobmFtZSkge1xuXHRcdHJldHVybiAhIXRoaXMuZ2V0QXR0cmlidXRlKG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYXR0cmlidXRlIG9iamVjdCBieSBnaXZlbiBuYW1lXG5cdCAqIEBwYXJhbSAge1N0cmluZ30gbmFtZVxuXHQgKiBAcmV0dXJuIHtBdHRyaWJ1dGV9XG5cdCAqL1xuXHRnZXRBdHRyaWJ1dGUobmFtZSkge1xuXHRcdGlmICh0eXBlb2YgbmFtZSA9PT0gJ29iamVjdCcpIHtcblx0XHRcdG5hbWUgPSBuYW1lLm5hbWU7XG5cdFx0fVxuXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9hdHRyaWJ1dGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCBhdHRyID0gdGhpcy5fYXR0cmlidXRlc1tpXTtcblx0XHRcdGlmIChhdHRyLm5hbWUgPT09IG5hbWUpIHtcblx0XHRcdFx0cmV0dXJuIGF0dHI7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlcGxhY2VzIGF0dHJpYnV0ZSB3aXRoIG5ldyBpbnN0YW5jZVxuXHQgKiBAcGFyYW0ge1N0cmluZ3xBdHRyaWJ1dGV9IGN1ckF0dHJpYnV0ZSBDdXJyZW50IGF0dHJpYnV0ZSBuYW1lIG9yIGluc3RhbmNlXG5cdCAqIHRvIHJlcGxhY2Vcblx0ICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fEF0dHJpYnV0ZX0gbmV3TmFtZSBOZXcgYXR0cmlidXRlIG5hbWUgb3IgYXR0cmlidXRlIG9iamVjdFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gW25ld1ZhbHVlXSBOZXcgYXR0cmlidXRlIHZhbHVlXG5cdCAqL1xuXHRyZXBsYWNlQXR0cmlidXRlKGN1ckF0dHJpYnV0ZSwgbmV3TmFtZSwgbmV3VmFsdWUpIHtcblx0XHRpZiAodHlwZW9mIGN1ckF0dHJpYnV0ZSA9PT0gJ3N0cmluZycpIHtcblx0XHRcdGN1ckF0dHJpYnV0ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKGN1ckF0dHJpYnV0ZSk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgaXggPSB0aGlzLl9hdHRyaWJ1dGVzLmluZGV4T2YoY3VyQXR0cmlidXRlKTtcblx0XHRpZiAoaXggIT09IC0xKSB7XG5cdFx0XHR0aGlzLl9hdHRyaWJ1dGVzLnNwbGljZShpeCwgMSwgY3JlYXRlQXR0cmlidXRlKG5ld05hbWUsIG5ld1ZhbHVlKSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYXR0cmlidXRlIHdpdGggZ2l2ZW4gbmFtZVxuXHQgKiBAcGFyYW0gIHtTdHJpbmd8QXR0cmlidXRlfSBhdHRyIEF0cnRpYnV0ZSBuYW1lIG9yIGluc3RhbmNlXG5cdCAqL1xuXHRyZW1vdmVBdHRyaWJ1dGUoYXR0cikge1xuXHRcdGlmICh0eXBlb2YgYXR0ciA9PT0gJ3N0cmluZycpIHtcblx0XHRcdGF0dHIgPSB0aGlzLmdldEF0dHJpYnV0ZShhdHRyKTtcblx0XHR9XG5cblx0XHRjb25zdCBpeCA9IHRoaXMuX2F0dHJpYnV0ZXMuaW5kZXhPZihhdHRyKTtcblx0XHRpZiAoaXggIT09IC0xKSB7XG5cdFx0XHR0aGlzLl9hdHRyaWJ1dGVzLnNwbGljZShpeCwgMSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYWxsIGF0dHJpYnV0ZXMgZnJvbSBjdXJyZW50IG5vZGVcblx0ICovXG5cdGNsZWFyQXR0cmlidXRlcygpIHtcblx0XHR0aGlzLl9hdHRyaWJ1dGVzLmxlbmd0aCA9IDA7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBnaXZlbiBjbGFzcyBuYW1lIHRvIGNsYXNzIGF0dHJpYnV0ZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdG9rZW4gQ2xhc3MgbmFtZSB0b2tlblxuXHQgKi9cblx0YWRkQ2xhc3ModG9rZW4pIHtcblx0XHR0b2tlbiA9IG5vcm1hbGl6ZSh0b2tlbik7XG5cblx0XHRpZiAoIXRoaXMuaGFzQXR0cmlidXRlKCdjbGFzcycpKSB7XG5cdFx0XHR0aGlzLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCB0b2tlbik7XG5cdFx0fSBlbHNlIGlmICh0b2tlbiAmJiAhdGhpcy5oYXNDbGFzcyh0b2tlbikpIHtcblx0XHRcdHRoaXMuc2V0QXR0cmlidXRlKCdjbGFzcycsIHRoaXMuY2xhc3NMaXN0LmNvbmNhdCh0b2tlbikuam9pbignICcpKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2sgaWYgY3VycmVudCBub2RlIGNvbnRhaW5zIGdpdmVuIGNsYXNzIG5hbWVcblx0ICogQHBhcmFtIHtTdHJpbmd9IHRva2VuIENsYXNzIG5hbWUgdG9rZW5cblx0ICogQHJldHVybiB7Qm9vbGVhbn1cblx0ICovXG5cdGhhc0NsYXNzKHRva2VuKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2xhc3NMaXN0LmluZGV4T2Yobm9ybWFsaXplKHRva2VuKSkgIT09IC0xO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgZ2l2ZW4gY2xhc3MgbmFtZSBmcm9tIGNsYXNzIGF0dHJpYnV0ZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdG9rZW4gQ2xhc3MgbmFtZSB0b2tlblxuXHQgKi9cblx0cmVtb3ZlQ2xhc3ModG9rZW4pIHtcblx0XHR0b2tlbiA9IG5vcm1hbGl6ZSh0b2tlbik7XG5cdFx0aWYgKHRoaXMuaGFzQ2xhc3ModG9rZW4pKSB7XG5cdFx0XHR0aGlzLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCB0aGlzLmNsYXNzTGlzdC5maWx0ZXIobmFtZSA9PiBuYW1lICE9PSB0b2tlbikuam9pbignICcpKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQXBwZW5kcyBjaGlsZCB0byBjdXJyZW50IG5vZGVcblx0ICogQHBhcmFtIHtOb2RlfSBub2RlXG5cdCAqL1xuXHRhcHBlbmRDaGlsZChub2RlKSB7XG5cdFx0dGhpcy5pbnNlcnRBdChub2RlLCB0aGlzLmNoaWxkcmVuLmxlbmd0aCk7XG5cdH1cblxuXHQvKipcblx0ICogSW5zZXJ0cyBnaXZlbiBgbmV3Tm9kZWAgYmVmb3JlIGByZWZOb2RlYCBjaGlsZCBub2RlXG5cdCAqIEBwYXJhbSB7Tm9kZX0gbmV3Tm9kZVxuXHQgKiBAcGFyYW0ge05vZGV9IHJlZk5vZGVcblx0ICovXG5cdGluc2VydEJlZm9yZShuZXdOb2RlLCByZWZOb2RlKSB7XG5cdFx0dGhpcy5pbnNlcnRBdChuZXdOb2RlLCB0aGlzLmNoaWxkcmVuLmluZGV4T2YocmVmTm9kZSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluc2VydCBnaXZlbiBgbm9kZWAgYXQgYHBvc2AgcG9zaXRpb24gb2YgY2hpbGQgbGlzdFxuXHQgKiBAcGFyYW0ge05vZGV9IG5vZGVcblx0ICogQHBhcmFtIHtOdW1iZXJ9IHBvc1xuXHQgKi9cblx0aW5zZXJ0QXQobm9kZSwgcG9zKSB7XG5cdFx0aWYgKHBvcyA8IDAgfHwgcG9zID4gdGhpcy5jaGlsZHJlbi5sZW5ndGgpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGluc2VydCBub2RlOiBwb3NpdGlvbiBpcyBvdXQgb2YgY2hpbGQgbGlzdCByYW5nZScpO1xuXHRcdH1cblxuXHRcdGNvbnN0IHByZXYgPSB0aGlzLmNoaWxkcmVuW3BvcyAtIDFdO1xuXHRcdGNvbnN0IG5leHQgPSB0aGlzLmNoaWxkcmVuW3Bvc107XG5cblx0XHRub2RlLnJlbW92ZSgpO1xuXHRcdG5vZGUucGFyZW50ID0gdGhpcztcblx0XHR0aGlzLmNoaWxkcmVuLnNwbGljZShwb3MsIDAsIG5vZGUpO1xuXG5cdFx0aWYgKHByZXYpIHtcblx0XHRcdG5vZGUucHJldmlvdXMgPSBwcmV2O1xuXHRcdFx0cHJldi5uZXh0ID0gbm9kZTtcblx0XHR9XG5cblx0XHRpZiAobmV4dCkge1xuXHRcdFx0bm9kZS5uZXh0ID0gbmV4dDtcblx0XHRcdG5leHQucHJldmlvdXMgPSBub2RlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGdpdmVuIGNoaWxkIGZyb20gY3VycmVudCBub2RlXG5cdCAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuXHQgKi9cblx0cmVtb3ZlQ2hpbGQobm9kZSkge1xuXHRcdGNvbnN0IGl4ID0gdGhpcy5jaGlsZHJlbi5pbmRleE9mKG5vZGUpO1xuXHRcdGlmIChpeCAhPT0gLTEpIHtcblx0XHRcdHRoaXMuY2hpbGRyZW4uc3BsaWNlKGl4LCAxKTtcblx0XHRcdGlmIChub2RlLnByZXZpb3VzKSB7XG5cdFx0XHRcdG5vZGUucHJldmlvdXMubmV4dCA9IG5vZGUubmV4dDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKG5vZGUubmV4dCkge1xuXHRcdFx0XHRub2RlLm5leHQucHJldmlvdXMgPSBub2RlLnByZXZpb3VzO1xuXHRcdFx0fVxuXG5cdFx0XHRub2RlLnBhcmVudCA9IG5vZGUubmV4dCA9IG5vZGUucHJldmlvdXMgPSBudWxsO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGN1cnJlbnQgbm9kZSBmcm9tIGl0cyBwYXJlbnRcblx0ICovXG5cdHJlbW92ZSgpIHtcblx0XHRpZiAodGhpcy5wYXJlbnQpIHtcblx0XHRcdHRoaXMucGFyZW50LnJlbW92ZUNoaWxkKHRoaXMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgZGV0YWNoZWQgY29weSBvZiBjdXJyZW50IG5vZGVcblx0ICogQHBhcmFtIHtCb29sZWFufSBkZWVwIENsb25lIG5vZGUgY29udGVudHMgYXMgd2VsbFxuXHQgKiBAcmV0dXJuIHtOb2RlfVxuXHQgKi9cblx0Y2xvbmUoZGVlcCkge1xuXHRcdGNvbnN0IGNsb25lID0gbmV3IE5vZGUodGhpcy5uYW1lKTtcblx0XHRjbG9uZS52YWx1ZSA9IHRoaXMudmFsdWU7XG5cdFx0Y2xvbmUuc2VsZkNsb3NpbmcgPSB0aGlzLnNlbGZDbG9zaW5nO1xuXHRcdGlmICh0aGlzLnJlcGVhdCkge1xuXHRcdFx0Y2xvbmUucmVwZWF0ID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5yZXBlYXQpO1xuXHRcdH1cblxuXHRcdHRoaXMuX2F0dHJpYnV0ZXMuZm9yRWFjaChhdHRyID0+IGNsb25lLnNldEF0dHJpYnV0ZShhdHRyLmNsb25lKCkpKTtcblxuXHRcdGlmIChkZWVwKSB7XG5cdFx0XHR0aGlzLmNoaWxkcmVuLmZvckVhY2goY2hpbGQgPT4gY2xvbmUuYXBwZW5kQ2hpbGQoY2hpbGQuY2xvbmUodHJ1ZSkpKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gY2xvbmU7XG5cdH1cblxuXHQvKipcblx0ICogV2Fsa3Mgb24gZWFjaCBkZXNjZW5kYW50IG5vZGUgYW5kIGludm9rZXMgZ2l2ZW4gYGZuYCBmdW5jdGlvbiBvbiBpdC5cblx0ICogVGhlIGZ1bmN0aW9uIHJlY2VpdmVzIHR3byBhcmd1bWVudHM6IHRoZSBub2RlIGl0c2VsZiBhbmQgaXRzIGRlcHRoIGxldmVsXG5cdCAqIGZyb20gY3VycmVudCBub2RlLiBJZiBmdW5jdGlvbiByZXR1cm5zIGBmYWxzZWAsIGl0IHN0b3BzIHdhbGtpbmdcblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cblx0ICovXG5cdHdhbGsoZm4sIF9sZXZlbCkge1xuXHRcdF9sZXZlbCA9IF9sZXZlbCB8fCAwO1xuXHRcdGxldCBjdHggPSB0aGlzLmZpcnN0Q2hpbGQ7XG5cblx0XHR3aGlsZSAoY3R4KSB7XG5cdFx0XHQvLyBpbiBjYXNlIGlmIGNvbnRleHQgbm9kZSB3aWxsIGJlIGRldGFjaGVkIGR1cmluZyBgZm5gIGNhbGxcblx0XHRcdGNvbnN0IG5leHQgPSBjdHgubmV4dDtcblxuXHRcdFx0aWYgKGZuKGN0eCwgX2xldmVsKSA9PT0gZmFsc2UgfHwgY3R4LndhbGsoZm4sIF9sZXZlbCArIDEpID09PSBmYWxzZSkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdGN0eCA9IG5leHQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEEgaGVscGVyIG1ldGhvZCBmb3IgdHJhbnNmb3JtYXRpb24gY2hhaW5pbmc6IHJ1bnMgZ2l2ZW4gYGZuYCBmdW5jdGlvbiBvblxuXHQgKiBjdXJyZW50IG5vZGUgYW5kIHJldHVybnMgdGhlIHNhbWUgbm9kZVxuXHQgKi9cblx0dXNlKGZuKSB7XG5cdFx0Y29uc3QgYXJncyA9IFt0aGlzXTtcblx0XHRmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0YXJncy5wdXNoKGFyZ3VtZW50c1tpXSk7XG5cdFx0fVxuXG5cdFx0Zm4uYXBwbHkobnVsbCwgYXJncyk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHR0b1N0cmluZygpIHtcblx0XHRjb25zdCBhdHRycyA9IHRoaXMuYXR0cmlidXRlcy5tYXAoYXR0ciA9PiB7XG5cdFx0XHRhdHRyID0gdGhpcy5nZXRBdHRyaWJ1dGUoYXR0ci5uYW1lKTtcblx0XHRcdGNvbnN0IG9wdCA9IGF0dHIub3B0aW9ucztcblx0XHRcdGxldCBvdXQgPSBgJHtvcHQgJiYgb3B0LmltcGxpZWQgPyAnIScgOiAnJ30ke2F0dHIubmFtZSB8fCAnJ31gO1xuXHRcdFx0aWYgKG9wdCAmJiBvcHQuYm9vbGVhbikge1xuXHRcdFx0XHRvdXQgKz0gJy4nO1xuXHRcdFx0fSBlbHNlIGlmIChhdHRyLnZhbHVlICE9IG51bGwpIHtcblx0XHRcdFx0b3V0ICs9IGA9XCIke2F0dHIudmFsdWV9XCJgO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG91dDtcblx0XHR9KTtcblxuXHRcdGxldCBvdXQgPSBgJHt0aGlzLm5hbWUgfHwgJyd9YDtcblx0XHRpZiAoYXR0cnMubGVuZ3RoKSB7XG5cdFx0XHRvdXQgKz0gYFske2F0dHJzLmpvaW4oJyAnKX1dYDtcblx0XHR9XG5cblx0XHRpZiAodGhpcy52YWx1ZSAhPSBudWxsKSB7XG5cdFx0XHRvdXQgKz0gYHske3RoaXMudmFsdWV9fWA7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMuc2VsZkNsb3NpbmcpIHtcblx0XHRcdG91dCArPSAnLyc7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMucmVwZWF0KSB7XG5cdFx0XHRvdXQgKz0gYCoke3RoaXMucmVwZWF0LmNvdW50ID8gdGhpcy5yZXBlYXQuY291bnQgOiAnJ31gO1xuXHRcdFx0aWYgKHRoaXMucmVwZWF0LnZhbHVlICE9IG51bGwpIHtcblx0XHRcdFx0b3V0ICs9IGBAJHt0aGlzLnJlcGVhdC52YWx1ZX1gO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBvdXQ7XG5cdH1cbn1cblxuLyoqXG4gKiBBdHRyaWJ1dGUgZmFjdG9yeVxuICogQHBhcmFtICB7U3RyaW5nfEF0dHJpYnV0ZXxPYmplY3R9IG5hbWUgIEF0dHJpYnV0ZSBuYW1lIG9yIGF0dHJpYnV0ZSBkZXNjcmlwdG9yXG4gKiBAcGFyYW0gIHsqfSB2YWx1ZSBBdHRyaWJ1dGUgdmFsdWVcbiAqIEByZXR1cm4ge0F0dHJpYnV0ZX1cbiAqL1xuZnVuY3Rpb24gY3JlYXRlQXR0cmlidXRlKG5hbWUsIHZhbHVlKSB7XG5cdGlmIChuYW1lIGluc3RhbmNlb2YgQXR0cmlidXRlKSB7XG5cdFx0cmV0dXJuIG5hbWU7XG5cdH1cblxuXHRpZiAodHlwZW9mIG5hbWUgPT09ICdzdHJpbmcnKSB7XG5cdFx0cmV0dXJuIG5ldyBBdHRyaWJ1dGUobmFtZSwgdmFsdWUpO1xuXHR9XG5cblx0aWYgKG5hbWUgJiYgdHlwZW9mIG5hbWUgPT09ICdvYmplY3QnKSB7XG5cdFx0cmV0dXJuIG5ldyBBdHRyaWJ1dGUobmFtZS5uYW1lLCBuYW1lLnZhbHVlLCBuYW1lLm9wdGlvbnMpO1xuXHR9XG59XG5cbi8qKlxuICogQHBhcmFtICB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplKHN0cikge1xuXHRyZXR1cm4gU3RyaW5nKHN0cikudHJpbSgpO1xufVxuXG5mdW5jdGlvbiB1bmlxdWVDbGFzcyhpdGVtLCBpLCBhcnIpIHtcblx0cmV0dXJuIGl0ZW0gJiYgYXJyLmluZGV4T2YoaXRlbSkgPT09IGk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gTm9kZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxuLyoqXG4gKiBNZXRob2RzIGZvciBjb25zdW1pbmcgcXVvdGVkIHZhbHVlc1xuICovXG5cbmNvbnN0IFNJTkdMRV9RVU9URSA9IDM5OyAvLyAnXG5jb25zdCBET1VCTEVfUVVPVEUgPSAzNDsgLy8gXCJcblxuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG5cdGVzY2FwZTogOTIsICAgLy8gXFwgY2hhcmFjdGVyXG5cdHRocm93czogZmFsc2Vcbn07XG5cbi8qKlxuICogQ29uc3VtZXMgJ3NpbmdsZScgb3IgXCJkb3VibGVcIi1xdW90ZWQgc3RyaW5nIGZyb20gZ2l2ZW4gc3RyaW5nLCBpZiBwb3NzaWJsZVxuICogQHBhcmFtICB7U3RyZWFtUmVhZGVyfSBzdHJlYW1cbiAqIEBwYXJhbSAge051bWJlcn0gIG9wdGlvbnMuZXNjYXBlIEEgY2hhcmFjdGVyIGNvZGUgb2YgcXVvdGUtZXNjYXBlIHN5bWJvbFxuICogQHBhcmFtICB7Qm9vbGVhbn0gb3B0aW9ucy50aHJvd3MgVGhyb3cgZXJyb3IgaWYgcXVvdGVzIHN0cmluZyBjYW7igJl0IGJlIHByb3Blcmx5IGNvbnN1bWVkXG4gKiBAcmV0dXJuIHtCb29sZWFufSBgdHJ1ZWAgaWYgcXVvdGVkIHN0cmluZyB3YXMgY29uc3VtZWQuIFRoZSBjb250ZW50c1xuICogICAgICAgICAgICAgICAgICAgb2YgcXVvdGVkIHN0cmluZyB3aWxsIGJlIGF2YWlsYWJlIGFzIGBzdHJlYW0uY3VycmVudCgpYFxuICovXG52YXIgZWF0UXVvdGVkID0gZnVuY3Rpb24oc3RyZWFtLCBvcHRpb25zKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zID8gT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdE9wdGlvbnMsIG9wdGlvbnMpIDogZGVmYXVsdE9wdGlvbnM7XG5cdGNvbnN0IHN0YXJ0ID0gc3RyZWFtLnBvcztcblx0Y29uc3QgcXVvdGUgPSBzdHJlYW0ucGVlaygpO1xuXG5cdGlmIChzdHJlYW0uZWF0KGlzUXVvdGUpKSB7XG5cdFx0d2hpbGUgKCFzdHJlYW0uZW9mKCkpIHtcblx0XHRcdHN3aXRjaCAoc3RyZWFtLm5leHQoKSkge1xuXHRcdFx0XHRjYXNlIHF1b3RlOlxuXHRcdFx0XHRcdHN0cmVhbS5zdGFydCA9IHN0YXJ0O1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXG5cdFx0XHRcdGNhc2Ugb3B0aW9ucy5lc2NhcGU6XG5cdFx0XHRcdFx0c3RyZWFtLm5leHQoKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBJZiB3ZeKAmXJlIGhlcmUgdGhlbiBzdHJlYW0gd2FzbuKAmXQgcHJvcGVybHkgY29uc3VtZWQuXG5cdFx0Ly8gUmV2ZXJ0IHN0cmVhbSBhbmQgZGVjaWRlIHdoYXQgdG8gZG9cblx0XHRzdHJlYW0ucG9zID0gc3RhcnQ7XG5cblx0XHRpZiAob3B0aW9ucy50aHJvd3MpIHtcblx0XHRcdHRocm93IHN0cmVhbS5lcnJvcignVW5hYmxlIHRvIGNvbnN1bWUgcXVvdGVkIHN0cmluZycpO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBmYWxzZTtcbn07XG5cbmZ1bmN0aW9uIGlzUXVvdGUoY29kZSkge1xuXHRyZXR1cm4gY29kZSA9PT0gU0lOR0xFX1FVT1RFIHx8IGNvZGUgPT09IERPVUJMRV9RVU9URTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBnaXZlbiBjb2RlIGlzIGEgbnVtYmVyXG4gKiBAcGFyYW0gIHtOdW1iZXJ9ICBjb2RlXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5mdW5jdGlvbiBpc051bWJlcihjb2RlKSB7XG5cdHJldHVybiBjb2RlID4gNDcgJiYgY29kZSA8IDU4O1xufVxuXG4vKipcbiAqIENoZWNrIGlmIGdpdmVuIGNoYXJhY3RlciBjb2RlIGlzIGFscGhhIGNvZGUgKGxldHRlciB0aHJvdWdoIEEgdG8gWilcbiAqIEBwYXJhbSAge051bWJlcn0gIGNvZGVcbiAqIEBwYXJhbSAge051bWJlcn0gIFtmcm9tXVxuICogQHBhcmFtICB7TnVtYmVyfSAgW3RvXVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNBbHBoYShjb2RlLCBmcm9tLCB0bykge1xuXHRmcm9tID0gZnJvbSB8fCA2NTsgLy8gQVxuXHR0byAgID0gdG8gICB8fCA5MDsgLy8gWlxuXHRjb2RlICY9IH4zMjsgLy8gcXVpY2sgaGFjayB0byBjb252ZXJ0IGFueSBjaGFyIGNvZGUgdG8gdXBwZXJjYXNlIGNoYXIgY29kZVxuXG5cdHJldHVybiBjb2RlID49IGZyb20gJiYgY29kZSA8PSB0bztcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBnaXZlbiBjaGFyYWN0ZXIgY29kZSBpcyBhbHBoYS1udW1lcmljIChsZXR0ZXIgdGhyb3VnaCBBIHRvIFogb3IgbnVtYmVyKVxuICogQHBhcmFtICB7TnVtYmVyfSAgY29kZVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNBbHBoYU51bWVyaWMoY29kZSkge1xuXHRyZXR1cm4gaXNOdW1iZXIoY29kZSkgfHwgaXNBbHBoYShjb2RlKTtcbn1cblxuZnVuY3Rpb24gaXNXaGl0ZVNwYWNlKGNvZGUpIHtcblx0cmV0dXJuIGNvZGUgPT09IDMyICAgLyogc3BhY2UgKi9cblx0XHR8fCBjb2RlID09PSA5ICAgIC8qIHRhYiAqL1xuXHRcdHx8IGNvZGUgPT09IDE2MDsgLyogbm9uLWJyZWFraW5nIHNwYWNlICovXG59XG5cbi8qKlxuICogQ2hlY2sgaWYgZ2l2ZW4gY2hhcmFjdGVyIGNvZGUgaXMgYSBzcGFjZVxuICogQHBhcmFtICB7TnVtYmVyfSAgY29kZVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNTcGFjZShjb2RlKSB7XG5cdHJldHVybiBpc1doaXRlU3BhY2UoY29kZSlcblx0XHR8fCBjb2RlID09PSAxMCAgLyogTEYgKi9cblx0XHR8fCBjb2RlID09PSAxMzsgLyogQ1IgKi9cbn1cblxuY29uc3QgZGVmYXVsdE9wdGlvbnMkMSA9IHtcblx0ZXNjYXBlOiA5MiwgICAvLyBcXCBjaGFyYWN0ZXJcblx0dGhyb3dzOiBmYWxzZVxufTtcblxuLyoqXG4gKiBFYXRzIHBhaXJlZCBjaGFyYWN0ZXJzIHN1YnN0cmluZywgZm9yIGV4YW1wbGUgYChmb28pYCBvciBgW2Jhcl1gXG4gKiBAcGFyYW0gIHtTdHJlYW1SZWFkZXJ9IHN0cmVhbVxuICogQHBhcmFtICB7TnVtYmVyfSBvcGVuICAgICAgQ2hhcmFjdGVyIGNvZGUgb2YgcGFpciBvcGVuaW5pZ1xuICogQHBhcmFtICB7TnVtYmVyfSBjbG9zZSAgICAgQ2hhcmFjdGVyIGNvZGUgb2YgcGFpciBjbG9zaW5nXG4gKiBAcGFyYW0gIHtPYmplY3R9IFtvcHRpb25zXVxuICogQHJldHVybiB7Qm9vbGVhbn0gICAgICAgUmV0dXJucyBgdHJ1ZWAgaWYgY2hhY2FydGVyIHBhaXIgd2FzIHN1Y2Nlc3NmdWxseVxuICogICAgICAgICAgICAgICAgICAgICAgICAgY29uc3VtZWQsIGl04oCZcyBjb250ZW50IHdpbGwgYmUgYXZhaWxhYmxlIGFzIGBzdHJlYW0uY3VycmVudCgpYFxuICovXG5mdW5jdGlvbiBlYXRQYWlyKHN0cmVhbSwgb3BlbiwgY2xvc2UsIG9wdGlvbnMpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnMgPyBPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0T3B0aW9ucyQxLCBvcHRpb25zKSA6IGRlZmF1bHRPcHRpb25zJDE7XG5cdGNvbnN0IHN0YXJ0ID0gc3RyZWFtLnBvcztcblxuXHRpZiAoc3RyZWFtLmVhdChvcGVuKSkge1xuXHRcdGxldCBzdGFjayA9IDEsIGNoO1xuXG5cdFx0d2hpbGUgKCFzdHJlYW0uZW9mKCkpIHtcblx0XHRcdGlmIChlYXRRdW90ZWQoc3RyZWFtLCBvcHRpb25zKSkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Y2ggPSBzdHJlYW0ubmV4dCgpO1xuXHRcdFx0aWYgKGNoID09PSBvcGVuKSB7XG5cdFx0XHRcdHN0YWNrKys7XG5cdFx0XHR9IGVsc2UgaWYgKGNoID09PSBjbG9zZSkge1xuXHRcdFx0XHRzdGFjay0tO1xuXHRcdFx0XHRpZiAoIXN0YWNrKSB7XG5cdFx0XHRcdFx0c3RyZWFtLnN0YXJ0ID0gc3RhcnQ7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoY2ggPT09IG9wdGlvbnMuZXNjYXBlKSB7XG5cdFx0XHRcdHN0cmVhbS5uZXh0KCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gSWYgd2XigJlyZSBoZXJlIHRoZW4gcGFpcmVkIGNoYXJhY3RlciBjYW7igJl0IGJlIGNvbnN1bWVkXG5cdFx0c3RyZWFtLnBvcyA9IHN0YXJ0O1xuXG5cdFx0aWYgKG9wdGlvbnMudGhyb3dzKSB7XG5cdFx0XHR0aHJvdyBzdHJlYW0uZXJyb3IoYFVuYWJsZSB0byBmaW5kIG1hdGNoaW5nIHBhaXIgZm9yICR7U3RyaW5nLmZyb21DaGFyQ29kZShvcGVuKX1gKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydHMuZWF0UXVvdGVkID0gZWF0UXVvdGVkO1xuZXhwb3J0cy5pc1F1b3RlID0gaXNRdW90ZTtcbmV4cG9ydHMuaXNBbHBoYSA9IGlzQWxwaGE7XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG5leHBvcnRzLmlzQWxwaGFOdW1lcmljID0gaXNBbHBoYU51bWVyaWM7XG5leHBvcnRzLmlzU3BhY2UgPSBpc1NwYWNlO1xuZXhwb3J0cy5pc1doaXRlU3BhY2UgPSBpc1doaXRlU3BhY2U7XG5leHBvcnRzLmVhdFBhaXIgPSBlYXRQYWlyO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIEEgc3RyZWFtaW5nLCBjaGFyYWN0ZXIgY29kZS1iYXNlZCBzdHJpbmcgcmVhZGVyXG4gKi9cbmNsYXNzIFN0cmVhbVJlYWRlciB7XG5cdGNvbnN0cnVjdG9yKHN0cmluZywgc3RhcnQsIGVuZCkge1xuXHRcdGlmIChlbmQgPT0gbnVsbCAmJiB0eXBlb2Ygc3RyaW5nID09PSAnc3RyaW5nJykge1xuXHRcdFx0ZW5kID0gc3RyaW5nLmxlbmd0aDtcblx0XHR9XG5cblx0XHR0aGlzLnN0cmluZyA9IHN0cmluZztcblx0XHR0aGlzLnBvcyA9IHRoaXMuc3RhcnQgPSBzdGFydCB8fCAwO1xuXHRcdHRoaXMuZW5kID0gZW5kO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBvbmx5IGlmIHRoZSBzdHJlYW0gaXMgYXQgdGhlIGVuZCBvZiB0aGUgZmlsZS5cblx0ICogQHJldHVybnMge0Jvb2xlYW59XG5cdCAqL1xuXHRlb2YoKSB7XG5cdFx0cmV0dXJuIHRoaXMucG9zID49IHRoaXMuZW5kO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgc3RyZWFtIGluc3RhbmNlIHdoaWNoIGlzIGxpbWl0ZWQgdG8gZ2l2ZW4gYHN0YXJ0YCBhbmQgYGVuZGBcblx0ICogcmFuZ2UuIEUuZy4gaXRzIGBlb2YoKWAgbWV0aG9kIHdpbGwgbG9vayBhdCBgZW5kYCBwcm9wZXJ0eSwgbm90IGFjdHVhbFxuXHQgKiBzdHJlYW0gZW5kXG5cdCAqIEBwYXJhbSAge1BvaW50fSBzdGFydFxuXHQgKiBAcGFyYW0gIHtQb2ludH0gZW5kXG5cdCAqIEByZXR1cm4ge1N0cmVhbVJlYWRlcn1cblx0ICovXG5cdGxpbWl0KHN0YXJ0LCBlbmQpIHtcblx0XHRyZXR1cm4gbmV3IHRoaXMuY29uc3RydWN0b3IodGhpcy5zdHJpbmcsIHN0YXJ0LCBlbmQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG5leHQgY2hhcmFjdGVyIGNvZGUgaW4gdGhlIHN0cmVhbSB3aXRob3V0IGFkdmFuY2luZyBpdC5cblx0ICogV2lsbCByZXR1cm4gTmFOIGF0IHRoZSBlbmQgb2YgdGhlIGZpbGUuXG5cdCAqIEByZXR1cm5zIHtOdW1iZXJ9XG5cdCAqL1xuXHRwZWVrKCkge1xuXHRcdHJldHVybiB0aGlzLnN0cmluZy5jaGFyQ29kZUF0KHRoaXMucG9zKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBuZXh0IGNoYXJhY3RlciBpbiB0aGUgc3RyZWFtIGFuZCBhZHZhbmNlcyBpdC5cblx0ICogQWxzbyByZXR1cm5zIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4gd2hlbiBubyBtb3JlIGNoYXJhY3RlcnMgYXJlIGF2YWlsYWJsZS5cblx0ICogQHJldHVybnMge051bWJlcn1cblx0ICovXG5cdG5leHQoKSB7XG5cdFx0aWYgKHRoaXMucG9zIDwgdGhpcy5zdHJpbmcubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5zdHJpbmcuY2hhckNvZGVBdCh0aGlzLnBvcysrKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogYG1hdGNoYCBjYW4gYmUgYSBjaGFyYWN0ZXIgY29kZSBvciBhIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBjaGFyYWN0ZXIgY29kZVxuXHQgKiBhbmQgcmV0dXJucyBhIGJvb2xlYW4uIElmIHRoZSBuZXh0IGNoYXJhY3RlciBpbiB0aGUgc3RyZWFtICdtYXRjaGVzJ1xuXHQgKiB0aGUgZ2l2ZW4gYXJndW1lbnQsIGl0IGlzIGNvbnN1bWVkIGFuZCByZXR1cm5lZC5cblx0ICogT3RoZXJ3aXNlLCBgZmFsc2VgIGlzIHJldHVybmVkLlxuXHQgKiBAcGFyYW0ge051bWJlcnxGdW5jdGlvbn0gbWF0Y2hcblx0ICogQHJldHVybnMge0Jvb2xlYW59XG5cdCAqL1xuXHRlYXQobWF0Y2gpIHtcblx0XHRjb25zdCBjaCA9IHRoaXMucGVlaygpO1xuXHRcdGNvbnN0IG9rID0gdHlwZW9mIG1hdGNoID09PSAnZnVuY3Rpb24nID8gbWF0Y2goY2gpIDogY2ggPT09IG1hdGNoO1xuXG5cdFx0aWYgKG9rKSB7XG5cdFx0XHR0aGlzLm5leHQoKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gb2s7XG5cdH1cblxuXHQvKipcblx0ICogUmVwZWF0ZWRseSBjYWxscyA8Y29kZT5lYXQ8L2NvZGU+IHdpdGggdGhlIGdpdmVuIGFyZ3VtZW50LCB1bnRpbCBpdFxuXHQgKiBmYWlscy4gUmV0dXJucyA8Y29kZT50cnVlPC9jb2RlPiBpZiBhbnkgY2hhcmFjdGVycyB3ZXJlIGVhdGVuLlxuXHQgKiBAcGFyYW0ge09iamVjdH0gbWF0Y2hcblx0ICogQHJldHVybnMge0Jvb2xlYW59XG5cdCAqL1xuXHRlYXRXaGlsZShtYXRjaCkge1xuXHRcdGNvbnN0IHN0YXJ0ID0gdGhpcy5wb3M7XG5cdFx0d2hpbGUgKCF0aGlzLmVvZigpICYmIHRoaXMuZWF0KG1hdGNoKSkge31cblx0XHRyZXR1cm4gdGhpcy5wb3MgIT09IHN0YXJ0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEJhY2tzIHVwIHRoZSBzdHJlYW0gbiBjaGFyYWN0ZXJzLiBCYWNraW5nIGl0IHVwIGZ1cnRoZXIgdGhhbiB0aGVcblx0ICogc3RhcnQgb2YgdGhlIGN1cnJlbnQgdG9rZW4gd2lsbCBjYXVzZSB0aGluZ3MgdG8gYnJlYWssIHNvIGJlIGNhcmVmdWwuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBuXG5cdCAqL1xuXHRiYWNrVXAobikge1xuXHRcdHRoaXMucG9zIC09IChuIHx8IDEpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCB0aGUgc3RyaW5nIGJldHdlZW4gdGhlIHN0YXJ0IG9mIHRoZSBjdXJyZW50IHRva2VuIGFuZCB0aGVcblx0ICogY3VycmVudCBzdHJlYW0gcG9zaXRpb24uXG5cdCAqIEByZXR1cm5zIHtTdHJpbmd9XG5cdCAqL1xuXHRjdXJyZW50KCkge1xuXHRcdHJldHVybiB0aGlzLnN0cmluZy5zbGljZSh0aGlzLnN0YXJ0LCB0aGlzLnBvcyk7XG5cdH1cblxuXHQvKipcblx0ICogQ3JlYXRlcyBlcnJvciBvYmplY3Qgd2l0aCBjdXJyZW50IHN0cmVhbSBzdGF0ZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuXHQgKiBAcmV0dXJuIHtFcnJvcn1cblx0ICovXG5cdGVycm9yKG1lc3NhZ2UpIHtcblx0XHRjb25zdCBlcnIgPSBuZXcgRXJyb3IoYCR7bWVzc2FnZX0gYXQgY2hhciAke3RoaXMucG9zICsgMX1gKTtcblx0XHRlcnIub3JpZ2luYWxNZXNzYWdlID0gbWVzc2FnZTtcblx0XHRlcnIucG9zID0gdGhpcy5wb3M7XG5cdFx0ZXJyLnN0cmluZyA9IHRoaXMuc3RyaW5nO1xuXHRcdHJldHVybiBlcnI7XG5cdH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBTdHJlYW1SZWFkZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wRGVmYXVsdCAoZXgpIHsgcmV0dXJuIChleCAmJiAodHlwZW9mIGV4ID09PSAnb2JqZWN0JykgJiYgJ2RlZmF1bHQnIGluIGV4KSA/IGV4WydkZWZhdWx0J10gOiBleDsgfVxuXG52YXIgTm9kZSA9IF9pbnRlcm9wRGVmYXVsdChyZXF1aXJlKCdAZW1tZXRpby9ub2RlJykpO1xudmFyIFN0cmVhbVJlYWRlciA9IF9pbnRlcm9wRGVmYXVsdChyZXF1aXJlKCdAZW1tZXRpby9zdHJlYW0tcmVhZGVyJykpO1xudmFyIF9lbW1ldGlvX3N0cmVhbVJlYWRlclV0aWxzID0gcmVxdWlyZSgnQGVtbWV0aW8vc3RyZWFtLXJlYWRlci11dGlscycpO1xuXG5jb25zdCBBU1RFUklTSyA9IDQyOyAvLyAqXG5cbi8qKlxuICogQ29uc3VtZXMgbm9kZSByZXBlYXQgdG9rZW4gZnJvbSBjdXJyZW50IHN0cmVhbSBwb3NpdGlvbiBhbmQgcmV0dXJucyBpdHNcbiAqIHBhcnNlZCB2YWx1ZVxuICogQHBhcmFtICB7U3RyaW5nUmVhZGVyfSBzdHJlYW1cbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xudmFyIGNvbnN1bWVSZXBlYXQgPSBmdW5jdGlvbihzdHJlYW0pIHtcblx0aWYgKHN0cmVhbS5lYXQoQVNURVJJU0spKSB7XG5cdFx0c3RyZWFtLnN0YXJ0ID0gc3RyZWFtLnBvcztcblxuXHRcdC8vIFhYWCB0aGluayBhYm91dCBleHRlbmRpbmcgcmVwZWF0IHN5bnRheCB3aXRoIHRocm91Z2ggbnVtYmVyaW5nXG5cdFx0cmV0dXJuIHsgY291bnQ6IHN0cmVhbS5lYXRXaGlsZShfZW1tZXRpb19zdHJlYW1SZWFkZXJVdGlscy5pc051bWJlcikgPyArc3RyZWFtLmN1cnJlbnQoKSA6IG51bGwgfTtcblx0fVxufTtcblxuY29uc3Qgb3B0ID0geyB0aHJvd3M6IHRydWUgfTtcblxuLyoqXG4gKiBDb25zdW1lcyBxdW90ZWQgbGl0ZXJhbCBmcm9tIGN1cnJlbnQgc3RyZWFtIHBvc2l0aW9uIGFuZCByZXR1cm5zIGl04oCZcyBpbm5lcixcbiAqIHVucXVvdGVkLCB2YWx1ZVxuICogQHBhcmFtICB7U3RyaW5nUmVhZGVyfSBzdHJlYW1cbiAqIEByZXR1cm4ge1N0cmluZ30gUmV0dXJucyBgbnVsbGAgaWYgdW5hYmxlIHRvIGNvbnN1bWUgcXVvdGVkIHZhbHVlIGZyb20gY3VycmVudFxuICogcG9zaXRpb25cbiAqL1xudmFyIGNvbnN1bWVRdW90ZWQgPSBmdW5jdGlvbihzdHJlYW0pIHtcblx0aWYgKF9lbW1ldGlvX3N0cmVhbVJlYWRlclV0aWxzLmVhdFF1b3RlZChzdHJlYW0sIG9wdCkpIHtcblx0XHRyZXR1cm4gc3RyZWFtLmN1cnJlbnQoKS5zbGljZSgxLCAtMSk7XG5cdH1cbn07XG5cbmNvbnN0IExDVVJMWSA9IDEyMzsgLy8ge1xuY29uc3QgUkNVUkxZID0gMTI1OyAvLyB9XG5cbmNvbnN0IG9wdCQxID0geyB0aHJvd3M6IHRydWUgfTtcblxuLyoqXG4gKiBDb25zdW1lcyB0ZXh0IG5vZGUsIGUuZy4gY29udGVudHMgb2YgYHsuLi59YCBhbmQgcmV0dXJucyBpdHMgaW5uZXIgdmFsdWVcbiAqIEBwYXJhbSAge1N0cmluZ1JlYWRlcn0gc3RyZWFtXG4gKiBAcmV0dXJuIHtTdHJpbmd9IENvbnN1bWVkIHRleHQgY29udGVudCBvciBgbnVsbGAgb3RoZXJ3aXNlXG4gKi9cbnZhciBjb25zdW1lVGV4dE5vZGUgPSBmdW5jdGlvbihzdHJlYW0pIHtcblx0cmV0dXJuIF9lbW1ldGlvX3N0cmVhbVJlYWRlclV0aWxzLmVhdFBhaXIoc3RyZWFtLCBMQ1VSTFksIFJDVVJMWSwgb3B0JDEpXG5cdFx0PyBzdHJlYW0uY3VycmVudCgpLnNsaWNlKDEsIC0xKVxuXHRcdDogbnVsbDtcbn07XG5cbmNvbnN0IEVYQ0wgICAgICAgPSAzMzsgLy8gLlxuY29uc3QgRE9UJDEgICAgICAgID0gNDY7IC8vIC5cbmNvbnN0IEVRVUFMUyAgICAgPSA2MTsgLy8gPVxuY29uc3QgQVRUUl9PUEVOICA9IDkxOyAvLyBbXG5jb25zdCBBVFRSX0NMT1NFID0gOTM7IC8vIF1cblxuY29uc3QgcmVBdHRyaWJ1dGVOYW1lID0gL15cXCE/W1xcd1xcLTpcXCRAXStcXC4/JC87XG5cbi8qKlxuICogQ29uc3VtZXMgYXR0cmlidXRlcyBkZWZpbmVkIGluIHNxdWFyZSBicmFjZXMgZnJvbSBnaXZlbiBzdHJlYW0uXG4gKiBFeGFtcGxlOlxuICogW2F0dHIgY29sPTMgdGl0bGU9XCJRdW90ZWQgc3RyaW5nXCIgc2VsZWN0ZWQuIHN1cHBvcnQ9e3JlYWN0fV1cbiAqIEBwYXJhbSB7U3RyaW5nUmVhZGVyfSBzdHJlYW1cbiAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2YgY29uc3VtZWQgYXR0cmlidXRlc1xuICovXG52YXIgY29uc3VtZUF0dHJpYnV0ZXMgPSBmdW5jdGlvbihzdHJlYW0pIHtcblx0aWYgKCFzdHJlYW0uZWF0KEFUVFJfT1BFTikpIHtcblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdGNvbnN0IHJlc3VsdCA9IFtdO1xuXHRsZXQgdG9rZW4sIGF0dHI7XG5cblx0d2hpbGUgKCFzdHJlYW0uZW9mKCkpIHtcblx0XHRzdHJlYW0uZWF0V2hpbGUoX2VtbWV0aW9fc3RyZWFtUmVhZGVyVXRpbHMuaXNXaGl0ZVNwYWNlKTtcblxuXHRcdGlmIChzdHJlYW0uZWF0KEFUVFJfQ0xPU0UpKSB7XG5cdFx0XHRyZXR1cm4gcmVzdWx0OyAvLyBFbmQgb2YgYXR0cmlidXRlIHNldFxuXHRcdH0gZWxzZSBpZiAoKHRva2VuID0gY29uc3VtZVF1b3RlZChzdHJlYW0pKSAhPSBudWxsKSB7XG5cdFx0XHQvLyBDb25zdW1lZCBxdW90ZWQgdmFsdWU6IGFub255bW91cyBhdHRyaWJ1dGVcblx0XHRcdHJlc3VsdC5wdXNoKHtcblx0XHRcdFx0bmFtZTogbnVsbCxcblx0XHRcdFx0dmFsdWU6IHRva2VuXG5cdFx0XHR9KTtcblx0XHR9IGVsc2UgaWYgKGVhdFVucXVvdGVkKHN0cmVhbSkpIHtcblx0XHRcdC8vIENvbnN1bWVkIG5leHQgd29yZDogY291bGQgYmUgZWl0aGVyIGF0dHJpYnV0ZSBuYW1lIG9yIHVucXVvdGVkIGRlZmF1bHQgdmFsdWVcblx0XHRcdHRva2VuID0gc3RyZWFtLmN1cnJlbnQoKTtcblx0XHRcdGlmICghcmVBdHRyaWJ1dGVOYW1lLnRlc3QodG9rZW4pKSB7XG5cdFx0XHRcdC8vIGFub255bW91cyBhdHRyaWJ1dGVcblx0XHRcdFx0cmVzdWx0LnB1c2goeyBuYW1lOiBudWxsLCB2YWx1ZTogdG9rZW4gfSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBMb29rcyBsaWtlIGEgcmVndWxhciBhdHRyaWJ1dGVcblx0XHRcdFx0YXR0ciA9IHBhcnNlQXR0cmlidXRlTmFtZSh0b2tlbik7XG5cdFx0XHRcdHJlc3VsdC5wdXNoKGF0dHIpO1xuXG5cdFx0XHRcdGlmIChzdHJlYW0uZWF0KEVRVUFMUykpIHtcblx0XHRcdFx0XHQvLyBFeHBsaWNpdGx5IGRlZmluZWQgdmFsdWUuIENvdWxkIGJlIGEgd29yZCwgYSBxdW90ZWQgc3RyaW5nXG5cdFx0XHRcdFx0Ly8gb3IgUmVhY3QtbGlrZSBleHByZXNzaW9uXG5cdFx0XHRcdFx0aWYgKCh0b2tlbiA9IGNvbnN1bWVRdW90ZWQoc3RyZWFtKSkgIT0gbnVsbCkge1xuXHRcdFx0XHRcdFx0YXR0ci52YWx1ZSA9IHRva2VuO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoKHRva2VuID0gY29uc3VtZVRleHROb2RlKHN0cmVhbSkpICE9IG51bGwpIHtcblx0XHRcdFx0XHRcdGF0dHIudmFsdWUgPSB0b2tlbjtcblx0XHRcdFx0XHRcdGF0dHIub3B0aW9ucyA9IHtcblx0XHRcdFx0XHRcdFx0YmVmb3JlOiAneycsXG5cdFx0XHRcdFx0XHRcdGFmdGVyOiAnfSdcblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChlYXRVbnF1b3RlZChzdHJlYW0pKSB7XG5cdFx0XHRcdFx0XHRhdHRyLnZhbHVlID0gc3RyZWFtLmN1cnJlbnQoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhyb3cgc3RyZWFtLmVycm9yKCdFeHBlY3RlZCBhdHRyaWJ1dGUgbmFtZScpO1xuXHRcdH1cblx0fVxuXG5cdHRocm93IHN0cmVhbS5lcnJvcignRXhwZWN0ZWQgY2xvc2luZyBcIl1cIiBicmFjZScpO1xufTtcblxuZnVuY3Rpb24gcGFyc2VBdHRyaWJ1dGVOYW1lKG5hbWUpIHtcblx0Y29uc3Qgb3B0aW9ucyA9IHt9O1xuXG5cdC8vIElmIGEgZmlyc3QgY2hhcmFjdGVyIGluIGF0dHJpYnV0ZSBuYW1lIGlzIGAhYCDigJQgaXTigJlzIGFuIGltcGxpZWRcblx0Ly8gZGVmYXVsdCBhdHRyaWJ1dGVcblx0aWYgKG5hbWUuY2hhckNvZGVBdCgwKSA9PT0gRVhDTCkge1xuXHRcdG5hbWUgPSBuYW1lLnNsaWNlKDEpO1xuXHRcdG9wdGlvbnMuaW1wbGllZCA9IHRydWU7XG5cdH1cblxuXHQvLyBDaGVjayBmb3IgbGFzdCBjaGFyYWN0ZXI6IGlmIGl04oCZcyBhIGAuYCwgdXNlciB3YW50cyBib29sZWFuIGF0dHJpYnV0ZVxuXHRpZiAobmFtZS5jaGFyQ29kZUF0KG5hbWUubGVuZ3RoIC0gMSkgPT09IERPVCQxKSB7XG5cdFx0bmFtZSA9IG5hbWUuc2xpY2UoMCwgbmFtZS5sZW5ndGggLSAxKTtcblx0XHRvcHRpb25zLmJvb2xlYW4gPSB0cnVlO1xuXHR9XG5cblx0Y29uc3QgYXR0ciA9IHsgbmFtZSB9O1xuXHRpZiAoT2JqZWN0LmtleXMob3B0aW9ucykubGVuZ3RoKSB7XG5cdFx0YXR0ci5vcHRpb25zID0gb3B0aW9ucztcblx0fVxuXG5cdHJldHVybiBhdHRyO1xufVxuXG4vKipcbiAqIEVhdHMgdG9rZW4gdGhhdCBjYW4gYmUgYW4gdW5xdW90ZWQgdmFsdWUgZnJvbSBnaXZlbiBzdHJlYW1cbiAqIEBwYXJhbSAge1N0cmVhbVJlYWRlcn0gc3RyZWFtXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5mdW5jdGlvbiBlYXRVbnF1b3RlZChzdHJlYW0pIHtcblx0Y29uc3Qgc3RhcnQgPSBzdHJlYW0ucG9zO1xuXHRpZiAoc3RyZWFtLmVhdFdoaWxlKGlzVW5xdW90ZWQpKSB7XG5cdFx0c3RyZWFtLnN0YXJ0ID0gc3RhcnQ7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cbn1cblxuZnVuY3Rpb24gaXNVbnF1b3RlZChjb2RlKSB7XG5cdHJldHVybiAhX2VtbWV0aW9fc3RyZWFtUmVhZGVyVXRpbHMuaXNTcGFjZShjb2RlKSAmJiAhX2VtbWV0aW9fc3RyZWFtUmVhZGVyVXRpbHMuaXNRdW90ZShjb2RlKVxuXHRcdCYmIGNvZGUgIT09IEFUVFJfT1BFTiAmJiBjb2RlICE9PSBBVFRSX0NMT1NFICYmIGNvZGUgIT09IEVRVUFMUztcbn1cblxuY29uc3QgSEFTSCAgICA9IDM1OyAvLyAjXG5jb25zdCBET1QgICAgID0gNDY7IC8vIC5cbmNvbnN0IFNMQVNIICAgPSA0NzsgLy8gL1xuXG4vKipcbiAqIENvbnN1bWVzIGEgc2luZ2xlIGVsZW1lbnQgbm9kZSBmcm9tIGN1cnJlbnQgYWJicmV2aWF0aW9uIHN0cmVhbVxuICogQHBhcmFtICB7U3RyaW5nUmVhZGVyfSBzdHJlYW1cbiAqIEByZXR1cm4ge05vZGV9XG4gKi9cbnZhciBjb25zdW1lRWxlbWVudCA9IGZ1bmN0aW9uKHN0cmVhbSkge1xuXHQvLyBjb25zdW1lIGVsZW1lbnQgbmFtZSwgaWYgcHJvdmlkZWRcblx0Y29uc3Qgc3RhcnQgPSBzdHJlYW0ucG9zO1xuXHRjb25zdCBub2RlID0gbmV3IE5vZGUoZWF0TmFtZShzdHJlYW0pKTtcblx0bGV0IG5leHQ7XG5cblx0d2hpbGUgKCFzdHJlYW0uZW9mKCkpIHtcblx0XHRpZiAoc3RyZWFtLmVhdChET1QpKSB7XG5cdFx0XHRub2RlLmFkZENsYXNzKGVhdE5hbWUoc3RyZWFtKSk7XG5cdFx0fSBlbHNlIGlmIChzdHJlYW0uZWF0KEhBU0gpKSB7XG5cdFx0XHRub2RlLnNldEF0dHJpYnV0ZSgnaWQnLCBlYXROYW1lKHN0cmVhbSkpO1xuXHRcdH0gZWxzZSBpZiAoc3RyZWFtLmVhdChTTEFTSCkpIHtcblx0XHRcdC8vIEEgc2VsZi1jbG9zaW5nIGluZGljYXRvciBtdXN0IGJlIGF0IHRoZSBlbmQgb2Ygbm9uLWdyb3VwaW5nIG5vZGVcblx0XHRcdGlmIChub2RlLmlzR3JvdXApIHtcblx0XHRcdFx0c3RyZWFtLmJhY2tVcCgxKTtcblx0XHRcdFx0dGhyb3cgc3RyZWFtLmVycm9yKCdVbmV4cGVjdGVkIHNlbGYtY2xvc2luZyBpbmRpY2F0b3InKTtcblx0XHRcdH1cblx0XHRcdG5vZGUuc2VsZkNsb3NpbmcgPSB0cnVlO1xuXHRcdFx0aWYgKG5leHQgPSBjb25zdW1lUmVwZWF0KHN0cmVhbSkpIHtcblx0XHRcdFx0bm9kZS5yZXBlYXQgPSBuZXh0O1xuXHRcdFx0fVxuXHRcdFx0YnJlYWs7XG5cdFx0fSBlbHNlIGlmIChuZXh0ID0gY29uc3VtZUF0dHJpYnV0ZXMoc3RyZWFtKSkge1xuXHRcdFx0Zm9yIChsZXQgaSA9IDAsIGlsID0gbmV4dC5sZW5ndGg7IGkgPCBpbDsgaSsrKSB7XG5cdFx0XHRcdG5vZGUuc2V0QXR0cmlidXRlKG5leHRbaV0pO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoKG5leHQgPSBjb25zdW1lVGV4dE5vZGUoc3RyZWFtKSkgIT09IG51bGwpIHtcblx0XHRcdG5vZGUudmFsdWUgPSBuZXh0O1xuXHRcdH0gZWxzZSBpZiAobmV4dCA9IGNvbnN1bWVSZXBlYXQoc3RyZWFtKSkge1xuXHRcdFx0bm9kZS5yZXBlYXQgPSBuZXh0O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHRpZiAoc3RhcnQgPT09IHN0cmVhbS5wb3MpIHtcblx0XHR0aHJvdyBzdHJlYW0uZXJyb3IoYFVuYWJsZSB0byBjb25zdW1lIGFiYnJldmlhdGlvbiBub2RlLCB1bmV4cGVjdGVkICR7c3RyZWFtLnBlZWsoKX1gKTtcblx0fVxuXG5cdHJldHVybiBub2RlO1xufTtcblxuZnVuY3Rpb24gZWF0TmFtZShzdHJlYW0pIHtcblx0c3RyZWFtLnN0YXJ0ID0gc3RyZWFtLnBvcztcblx0c3RyZWFtLmVhdFdoaWxlKGlzTmFtZSk7XG5cdHJldHVybiBzdHJlYW0uY3VycmVudCgpO1xufVxuXG5mdW5jdGlvbiBpc05hbWUoY29kZSkge1xuXHRyZXR1cm4gX2VtbWV0aW9fc3RyZWFtUmVhZGVyVXRpbHMuaXNBbHBoYU51bWVyaWMoY29kZSlcblx0XHR8fCBjb2RlID09PSA0NSAvKiAtICovXG5cdFx0fHwgY29kZSA9PT0gNTggLyogOiAqL1xuXHRcdHx8IGNvZGUgPT09IDM2IC8qICQgKi9cblx0XHR8fCBjb2RlID09PSA2NCAvKiBAICovXG5cdFx0fHwgY29kZSA9PT0gMzMgLyogISAqL1xuXHRcdHx8IGNvZGUgPT09IDM3IC8qICUgKi87XG59XG5cbmNvbnN0IEdST1VQX1NUQVJUID0gNDA7IC8vIChcbmNvbnN0IEdST1VQX0VORCAgID0gNDE7IC8vIClcbmNvbnN0IE9QX1NJQkxJTkcgID0gNDM7IC8vICtcbmNvbnN0IE9QX0NISUxEICAgID0gNjI7IC8vID5cbmNvbnN0IE9QX0NMSU1CICAgID0gOTQ7IC8vIF5cblxuLyoqXG4gKiBQYXJzZXMgZ2l2ZW4gc3RyaW5nIGludG8gYSBub2RlIHRyZWVcbiAqIEBwYXJhbSAge1N0cmluZ30gc3RyIEFiYnJldmlhdGlvbiB0byBwYXJzZVxuICogQHJldHVybiB7Tm9kZX1cbiAqL1xuZnVuY3Rpb24gcGFyc2Uoc3RyKSB7XG5cdGNvbnN0IHN0cmVhbSA9IG5ldyBTdHJlYW1SZWFkZXIoc3RyLnRyaW0oKSk7XG5cdGNvbnN0IHJvb3QgPSBuZXcgTm9kZSgpO1xuXHRsZXQgY3R4ID0gcm9vdCwgZ3JvdXBTdGFjayA9IFtdLCBjaDtcblxuXHR3aGlsZSAoIXN0cmVhbS5lb2YoKSkge1xuXHRcdGNoID0gc3RyZWFtLnBlZWsoKTtcblxuXHRcdGlmIChjaCA9PT0gR1JPVVBfU1RBUlQpIHsgLy8gc3RhcnQgb2YgZ3JvdXBcblx0XHRcdC8vIFRoZSBncm91cGluZyBub2RlIHNob3VsZCBiZSBkZXRhY2hlZCB0byBwcm9wZXJseSBoYW5kbGVcblx0XHRcdC8vIG91dC1vZi1ib3VuZHMgYF5gIG9wZXJhdG9yLiBOb2RlIHdpbGwgYmUgYXR0YWNoZWQgcmlnaHQgb24gZ3JvdXAgZW5kXG5cdFx0XHRjb25zdCBub2RlID0gbmV3IE5vZGUoKTtcblx0XHRcdGNvbnN0IGdyb3VwQ3R4ID0gZ3JvdXBTdGFjay5sZW5ndGggPyBsYXN0KGdyb3VwU3RhY2spWzBdIDogY3R4O1xuXHRcdFx0Z3JvdXBTdGFjay5wdXNoKFtub2RlLCBncm91cEN0eCwgc3RyZWFtLnBvc10pO1xuXHRcdFx0Y3R4ID0gbm9kZTtcblx0XHRcdHN0cmVhbS5uZXh0KCk7XG5cdFx0XHRjb250aW51ZTtcblx0XHR9IGVsc2UgaWYgKGNoID09PSBHUk9VUF9FTkQpIHsgLy8gZW5kIG9mIGdyb3VwXG5cdFx0XHRjb25zdCBsYXN0R3JvdXAgPSBncm91cFN0YWNrLnBvcCgpO1xuXHRcdFx0aWYgKCFsYXN0R3JvdXApIHtcblx0XHRcdFx0dGhyb3cgc3RyZWFtLmVycm9yKCdVbmV4cGVjdGVkIFwiKVwiIGdyb3VwIGVuZCcpO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBub2RlID0gbGFzdEdyb3VwWzBdO1xuXHRcdFx0Y3R4ID0gbGFzdEdyb3VwWzFdO1xuXHRcdFx0c3RyZWFtLm5leHQoKTtcblxuXHRcdFx0Ly8gYSBncm91cCBjYW4gaGF2ZSBhIHJlcGVhdGVyXG5cdFx0XHRpZiAobm9kZS5yZXBlYXQgPSBjb25zdW1lUmVwZWF0KHN0cmVhbSkpIHtcblx0XHRcdFx0Y3R4LmFwcGVuZENoaWxkKG5vZGUpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gbW92ZSBhbGwgY2hpbGRyZW4gb2YgZ3JvdXAgaW50byBwYXJlbnQgbm9kZVxuXHRcdFx0XHR3aGlsZSAobm9kZS5maXJzdENoaWxkKSB7XG5cdFx0XHRcdFx0Y3R4LmFwcGVuZENoaWxkKG5vZGUuZmlyc3RDaGlsZCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gZm9yIGNvbnZlbmllbmNlLCBncm91cHMgY2FuIGJlIGpvaW5lZCB3aXRoIG9wdGlvbmFsIGArYCBvcGVyYXRvclxuXHRcdFx0XHRzdHJlYW0uZWF0KE9QX1NJQkxJTkcpO1xuXHRcdFx0fVxuXG5cdFx0XHRjb250aW51ZTtcblx0XHR9XG5cblx0XHRjb25zdCBub2RlID0gY29uc3VtZUVsZW1lbnQoc3RyZWFtKTtcblx0XHRjdHguYXBwZW5kQ2hpbGQobm9kZSk7XG5cblx0XHRpZiAoc3RyZWFtLmVvZigpKSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cblx0XHRzd2l0Y2ggKHN0cmVhbS5wZWVrKCkpIHtcblx0XHRcdGNhc2UgT1BfU0lCTElORzpcblx0XHRcdFx0c3RyZWFtLm5leHQoKTtcblx0XHRcdFx0Y29udGludWU7XG5cblx0XHRcdGNhc2UgT1BfQ0hJTEQ6XG5cdFx0XHRcdHN0cmVhbS5uZXh0KCk7XG5cdFx0XHRcdGN0eCA9IG5vZGU7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXG5cdFx0XHRjYXNlIE9QX0NMSU1COlxuXHRcdFx0XHQvLyBpdOKAmXMgcGVyZmVjdGx5IHZhbGlkIHRvIGhhdmUgbXVsdGlwbGUgYF5gIG9wZXJhdG9yc1xuXHRcdFx0XHR3aGlsZSAoc3RyZWFtLmVhdChPUF9DTElNQikpIHtcblx0XHRcdFx0XHRjdHggPSBjdHgucGFyZW50IHx8IGN0eDtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb250aW51ZTtcblx0XHR9XG5cdH1cblxuXHRpZiAoZ3JvdXBTdGFjay5sZW5ndGgpIHtcblx0XHRzdHJlYW0ucG9zID0gZ3JvdXBTdGFjay5wb3AoKVsyXTtcblx0XHR0aHJvdyBzdHJlYW0uZXJyb3IoJ0V4cGVjdGVkIGdyb3VwIGNsb3NlJyk7XG5cdH1cblxuXHRyZXR1cm4gcm9vdDtcbn1cblxuZnVuY3Rpb24gbGFzdChhcnIpIHtcblx0cmV0dXJuIGFyclthcnIubGVuZ3RoIC0gMV07XG59XG5cbi8qKlxuICogUGFyc2VzIGdpdmVuIGFiYnJldmlhdGlvbiBhbmQgdW4tcm9sbHMgaXQgaW50byBhIGZ1bGwgdHJlZTogcmVjdXJzaXZlbHlcbiAqIHJlcGxhY2VzIHJlcGVhdGVkIGVsZW1lbnRzIHdpdGggYWN0dWFsIG5vZGVzXG4gKiBAcGFyYW0gIHtTdHJpbmd9IGFiYnJcbiAqIEByZXR1cm4ge05vZGV9XG4gKi9cbnZhciBpbmRleCA9IGZ1bmN0aW9uKGFiYnIpIHtcblx0Y29uc3QgdHJlZSA9IHBhcnNlKGFiYnIpO1xuXHR0cmVlLndhbGsodW5yb2xsKTtcblx0cmV0dXJuIHRyZWU7XG59O1xuXG5mdW5jdGlvbiB1bnJvbGwobm9kZSkge1xuXHRpZiAoIW5vZGUucmVwZWF0IHx8ICFub2RlLnJlcGVhdC5jb3VudCkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGZvciAobGV0IGkgPSAxOyBpIDwgbm9kZS5yZXBlYXQuY291bnQ7IGkrKykge1xuXHRcdGNvbnN0IGNsb25lID0gbm9kZS5jbG9uZSh0cnVlKTtcblx0XHRjbG9uZS5yZXBlYXQudmFsdWUgPSBpO1xuXHRcdGNsb25lLndhbGsodW5yb2xsKTtcblx0XHRub2RlLnBhcmVudC5pbnNlcnRCZWZvcmUoY2xvbmUsIG5vZGUpO1xuXHR9XG5cblx0bm9kZS5yZXBlYXQudmFsdWUgPSBub2RlLnJlcGVhdC5jb3VudDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpbmRleDtcbiJdfQ==
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
const inlineElements = new Set('a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'.split(','));
const elementMap = {
p: 'span',
ul: 'li',
ol: 'li',
table: 'tr',
tr: 'td',
tbody: 'tr',
thead: 'tr',
tfoot: 'tr',
colgroup: 'col',
select: 'option',
optgroup: 'option',
audio: 'source',
video: 'source',
object: 'param',
map: 'area'
};
/**
* Returns best child node name for given parent node name
* @param {String} parentName Name of parent node
* @return {String}
*/
function resolveImplicitName(parentName) {
parentName = (parentName || '').toLowerCase();
return elementMap[parentName]
|| (inlineElements.has(parentName) ? 'span' : 'div');
}
module.exports = resolveImplicitName;
},{}],"@emmetio/html-transform":[function(require,module,exports){
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var resolveImplicitTag = _interopDefault(require('@emmetio/implicit-tag'));
/**
* Adds missing tag names for given tree depending on node’s parent name
*/
var implicitTags = function(tree) {
tree.walk(node => {
// resolve only nameless nodes without content
if (node.name == null && node.attributes.length) {
node.name = resolveImplicitTag(node.parent.name);
}
});
return tree;
};
/**
* Locates all occurances of given `token` which are not escaped (e.g. are not
* preceded with `\`) given in `str`
* @param {String} str
* @return {Array} Array of token ranges
*/
function findUnescapedTokens(str, token) {
const result = new Set();
const tlen = token.length;
// 1. Find all occurances of tokens
let pos = 0;
while ((pos = str.indexOf(token, pos)) !== -1) {
result.add(pos);
pos += tlen;
}
if (result.size) {
// 2. Remove ones that escaped
let pos = 0;
const len = str.length;
while (pos < len) {
if (str[pos++] === '\\') {
result.delete(pos++);
}
}
}
return Array.from(result).map(ix => range(ix, tlen));
}
/**
* Replaces `ranges`, generated by `range()` function, with given `value` in `str`
* @param {String} str Where to replace ranges
* @param {Array} ranges Ranes, created by `range()` function
* @param {String|Function} value Replacement value. If it’s a function, it
* will take a range value as argument and should return a new string
* @return {String}
*/
function replaceRanges(str, ranges, value) {
// should walk from the end of array to keep ranges valid after replacement
for (let i = ranges.length - 1; i >= 0; i--) {
const r = ranges[i];
str = str.substring(0, r[0])
+ (typeof value === 'function' ? value(str.substr(r[0], r[1])) : value)
+ str.substring(r[0] + r[1]);
}
return str;
}
function range(start, length) {
return [start, length];
}
const numberingToken = '$';
/**
* Numbering of expanded abbreviation: finds all nodes with `$` in value
* or attributes and replaces its occurances with repeater value
*/
var applyNumbering = function(tree) {
tree.walk(applyNumbering$1);
return tree;
};
/**
* Applies numbering for given node: replaces occurances of numbering token
* in node’s name, content and attributes
* @param {Node} node
* @return {Node}
*/
function applyNumbering$1(node) {
const repeater = findRepeater(node);
if (repeater && repeater.value != null) {
// NB replace numbering in nodes with explicit repeater only:
// it solves issues with abbreviations like `xsl:if[test=$foo]` where
// `$foo` is preferred output
const value = repeater.value;
node.name = replaceNumbering(node.name, value);
node.value = replaceNumbering(node.value, value);
node.attributes.forEach(attr => {
const copy = node.getAttribute(attr.name).clone();
copy.name = replaceNumbering(attr.name, value);
copy.value = replaceNumbering(attr.value, value);
node.replaceAttribute(attr.name, copy);
});
}
return node;
}
/**
* Returns repeater object for given node
* @param {Node} node
* @return {Object}
*/
function findRepeater(node) {
while (node) {
if (node.repeat) {
return node.repeat;
}
node = node.parent;
}
}
/**
* Replaces numbering in given string
* @param {String} str
* @param {Number} value
* @return {String}
*/
function replaceNumbering(str, value) {
// replace numbering in strings only: skip explicit wrappers that could
// contain unescaped numbering tokens
if (typeof str === 'string') {
const ranges = getNumberingRanges(str);
return replaceNumberingRanges(str, ranges, value);
}
return str;
}
/**
* Returns numbering ranges, e.g. ranges of `$` occurances, in given string.
* Multiple adjacent ranges are combined
* @param {String} str
* @return {Array}
*/
function getNumberingRanges(str) {
return findUnescapedTokens(str || '', numberingToken)
.reduce((out, range$$1) => {
// skip ranges that actually belongs to output placeholder or tabstops
if (!/[#{]/.test(str[range$$1[0] + 1] || '')) {
const lastRange = out[out.length - 1];
if (lastRange && lastRange[0] + lastRange[1] === range$$1[0]) {
lastRange[1] += range$$1[1];
} else {
out.push(range$$1);
}
}
return out;
}, []);
}
/**
* @param {String} str
* @param {Array} ranges
* @param {Number} value
* @return {String}
*/
function replaceNumberingRanges(str, ranges, value) {
const replaced = replaceRanges(str, ranges, token => {
let _value = String(value);
// pad values for multiple numbering tokens, e.g. 3 for $$$ becomes 003
while (_value.length < token.length) {
_value = '0' + _value;
}
return _value;
});
// unescape screened numbering tokens
return unescapeString(replaced);
}
/**
* Unescapes characters, screened with `\`, in given string
* @param {String} str
* @return {String}
*/
function unescapeString(str) {
let i = 0, result = '';
const len = str.length;
while (i < len) {
const ch = str[i++];
result += (ch === '\\') ? (str[i++] || '') : ch;
}
return result;
}
/** Placeholder for inserted content */
const placeholder = '$#';
/** Placeholder for caret */
const caret = '|';
const reUrl = /^((?:https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
const reEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
const reProto = /^([a-z]+:)?\/\//i;
/**
* Inserts content into node with implicit repeat count: this node is then
* duplicated for each content item and content itself is inserted either into
* deepest child or instead of a special token.
*
* This method uses two distinct steps: `prepare()` and `insert()` since most
* likely these steps will be used separately to properly insert content
* with unescaped `$` numbering markers.
*
* @param {Node} tree Parsed abbreviation
* @param {String[]} content Array of content items to insert
* @return {Node}
*/
/**
* Finds nodes with implicit repeat and creates `amount` copies of it in tree
* @param {Node} tree
* @param {Number} amount
* @return {Node}
*/
function prepare(tree, amount) {
amount = amount || 1;
tree.walk(node => {
if (node.repeat && node.repeat.count === null) {
for (let i = 0; i < amount; i++) {
const clone = node.clone(true);
clone.repeat.implicit = true;
clone.repeat.count = amount;
clone.repeat.value = i + 1;
clone.repeat.index = i;
node.parent.insertBefore(clone, node);
}
node.remove();
}
});
return tree;
}
/**
* Inserts content into implicitly repeated nodes, created by `prepare()` method
* @param {Node} tree
* @param {String[]} content
* @return {Node}
*/
function insert(tree, content) {
if (Array.isArray(content) && content.length) {
let updated = false;
tree.walk(node => {
if (node.repeat && node.repeat.implicit) {
updated = true;
insertContent(node, content[node.repeat.index]);
}
});
if (!updated) {
// no node with implicit repeat was found, insert content as
// deepest child
setNodeContent(findDeepestNode(tree), content.join('\n'));
}
}
return tree;
}
/**
* Inserts `content` into given `node`: either replaces output placeholders
* or inserts it into deepest child node
* @param {Node} node
* @param {String} content
* @return {Node}
*/
function insertContent(node, content) {
let inserted = insertContentIntoPlaceholder(node, content);
node.walk(child => inserted |= insertContentIntoPlaceholder(child, content));
if (!inserted) {
// no placeholders were found in node, insert content into deepest child
setNodeContent(findDeepestNode(node), content);
}
return node;
}
/**
* Inserts given `content` into placeholders for given `node`. Placeholders
* might be available in attribute values and node content
* @param {Node} node
* @param {String} content
* @return {Boolean} Returns `true` if placeholders were found and replaced in node
*/
function insertContentIntoPlaceholder(node, content) {
const state = {replaced: false};
node.value = replacePlaceholder(node.value, content, state);
node.attributes.forEach(attr => {
if (attr.value) {
node.setAttribute(attr.name, replacePlaceholder(attr.value, content, state));
}
});
return state.replaced;
}
/**
* Replaces all placeholder occurances in given `str` with `value`
* @param {String} str
* @param {String} value
* @param {Object} [_state] If provided, set `replaced` property of given
* object to `true` if placeholder was found and replaced
* @return {String}
*/
function replacePlaceholder(str, value, _state) {
if (typeof str === 'string') {
const ranges = findUnescapedTokens(str, placeholder);
if (ranges.length) {
if (_state) {
_state.replaced = true;
}
str = replaceRanges(str, ranges, value);
}
}
return str;
}
/**
* Finds node which is the deepest for in current node or node iteself.
* @param {Node} node
* @return {Node}
*/
function findDeepestNode(node) {
while (node.children.length) {
node = node.children[node.children.length - 1];
}
return node;
}
/**
* Updates content of given node
* @param {Node} node
* @param {String} content
*/
function setNodeContent(node, content) {
// find caret position and replace it with content, if possible
if (node.value) {
const ranges = findUnescapedTokens(node.value, caret);
if (ranges.length) {
node.value = replaceRanges(node.value, ranges, content);
return;
}
}
if (node.name.toLowerCase('a') || node.hasAttribute('href')) {
// special case: inserting content into `<a>` tag
if (reUrl.test(content)) {
node.setAttribute('href', (reProto.test(content) ? '' : 'http://') + content);
} else if (reEmail.test(content)) {
node.setAttribute('href', 'mailto:' + content);
}
}
node.value = content;
}
const defaultOptions = {
element: '__',
modifier: '_'
};
const reElement = /^(-+)([a-z0-9]+)/i;
const reModifier = /^(_+)([a-z0-9]+)/i;
const blockCandidates1 = className => /^[a-z]\-/i.test(className);
const blockCandidates2 = className => /^[a-z]/i.test(className);
/**
* BEM transformer: updates class names written as `-element` and
* `_modifier` into full class names as described in BEM specs. Also adds missing
* class names: fir example, if node contains `.block_modifier` class, ensures
* that element contains `.block` class as well
*/
var bem = function(tree, options) {
options = Object.assign({}, defaultOptions, options);
tree.walk(node => expandClassNames(node, options));
const lookup = createBlockLookup(tree);
tree.walk(node => expandShortNotation(node, lookup, options));
return tree;
};
/**
* Expands existing class names in BEM notation in given `node`.
* For example, if node contains `b__el_mod` class name, this method ensures
* that element contains `b__el` class as well
* @param {Node} node
* @param {Object} options
* @return {Set}
*/
function expandClassNames(node, options) {
const classNames = node.classList.reduce((out, cl) => {
// remove all modifiers from class name to get a base element name
const ix = cl.indexOf(options.modifier);
if (ix !== -1) {
out.add(cl.slice(0, ix));
}
return out.add(cl);
}, new Set());
if (classNames.size) {
node.setAttribute('class', Array.from(classNames).join(' '));
}
}
/**
* Expands short BEM notation, e.g. `-element` and `_modifier`
* @param {Node} node Parsed Emmet abbreviation node
* @param {Map} lookup BEM block name lookup
* @param {Object} options
*/
function expandShortNotation(node, lookup, options) {
const classNames = node.classList.reduce((out, cl) => {
let prefix, m;
const originalClass = cl;
// parse element definition (could be only one)
if (m = cl.match(reElement)) {
prefix = getBlockName(node, lookup, m[1]) + options.element + m[2];
out.add(prefix);
cl = cl.slice(m[0].length);
}
// parse modifiers definitions (may contain multiple)
while (m = cl.match(reModifier)) {
if (!prefix) {
prefix = getBlockName(node, lookup, m[1]);
out.add(prefix);
}
out.add(`${prefix}${options.modifier}${m[2]}`);
cl = cl.slice(m[0].length);
}
if (cl === originalClass) {
// class name wasn’t modified: it’s not a BEM-specific class,
// add it as-is into output
out.add(originalClass);
}
return out;
}, new Set());
node.setAttribute('class', Array.from(classNames).join(' '));
}
/**
* Creates block name lookup for each node in given tree, e.g. finds block
* name explicitly for each node
* @param {Node} tree
* @return {Map}
*/
function createBlockLookup(tree) {
const lookup = new Map();
tree.walk(node => {
const classNames = node.classList;
if (classNames.length) {
// guess best block name from class or use parent’s block name
lookup.set(node,
find(classNames, blockCandidates1)
|| find(classNames, blockCandidates2)
|| lookup.get(node.parent)
);
}
});
return lookup;
}
/**
* Returns block name for given `node` by `prefix`, which tells the depth of
* of parent node lookup
* @param {Node} node
* @param {Map} lookup
* @param {String} prefix
* @return {String}
*/
function getBlockName(node, lookup, prefix) {
let depth = prefix.length > 1 ? prefix.length : 0;
while (node.parent && depth--) {
node = node.parent;
}
return lookup.get(node);
}
function find(arr, filter) {
return arr.filter(filter)[0];
}
/**
* JSX transformer: replaces `class` and `for` attributes with `className` and
* `htmlFor` attributes respectively
*/
var jsx = function(tree) {
tree.walk(node => {
replace(node, 'class', 'className');
replace(node, 'for', 'htmlFor');
});
return tree;
};
function replace(node, oldName, newName) {
let attr = node.getAttribute(oldName);
if (attr) {
attr.name = newName;
}
}
const reSupporterNames = /^xsl:(variable|with\-param)$/i;
/**
* XSL transformer: removes `select` attributes from certain nodes that contain
* children
*/
var xsl = function(tree) {
tree.walk(node => {
if (reSupporterNames.test(node.name || '') && (node.children.length || node.value)) {
node.removeAttribute('select');
}
});
return tree;
};
const supportedAddons = { bem, jsx, xsl };
/**
* Runs additional transforms on given tree.
* These transforms may introduce side-effects and unexpected result
* so they are not applied by default, authors must specify which addons
* in `addons` argument as `{addonName: addonOptions}`
* @param {Node} tree Parsed Emmet abbreviation
* @param {Object} addons Add-ons to apply and their options
*/
var addons = function(tree, addons) {
Object.keys(addons || {}).forEach(key => {
if (key in supportedAddons) {
const addonOpt = typeof addons[key] === 'object' ? addons[key] : null;
tree = tree.use(supportedAddons[key], addonOpt);
}
});
return tree;
};
/**
* Applies basic HTML-specific transformations for given parsed abbreviation:
* – resolve implied tag names
* – insert repeated content
* – resolve node numbering
*/
var index = function(tree, content, appliedAddons) {
if (typeof content === 'string') {
content = [content];
} else if (content && typeof content === 'object' && !Array.isArray(content)) {
appliedAddons = content;
content = null;
}
return tree
.use(implicitTags)
.use(prepare, Array.isArray(content) ? content.length : null)
.use(applyNumbering)
.use(insert, content)
.use(addons, appliedAddons);
};
module.exports = index;
},{"@emmetio/implicit-tag":1}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm5vZGVfbW9kdWxlcy9AZW1tZXRpby9pbXBsaWNpdC10YWcvZGlzdC9pbXBsaWNpdC10YWcuY2pzLmpzIiwiQGVtbWV0aW8lMkZodG1sLXRyYW5zZm9ybSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiJ3VzZSBzdHJpY3QnO1xuXG5jb25zdCBpbmxpbmVFbGVtZW50cyA9IG5ldyBTZXQoJ2EsYWJicixhY3JvbnltLGFwcGxldCxiLGJhc2Vmb250LGJkbyxiaWcsYnIsYnV0dG9uLGNpdGUsY29kZSxkZWwsZGZuLGVtLGZvbnQsaSxpZnJhbWUsaW1nLGlucHV0LGlucyxrYmQsbGFiZWwsbWFwLG9iamVjdCxxLHMsc2FtcCxzZWxlY3Qsc21hbGwsc3BhbixzdHJpa2Usc3Ryb25nLHN1YixzdXAsdGV4dGFyZWEsdHQsdSx2YXInLnNwbGl0KCcsJykpO1xuY29uc3QgZWxlbWVudE1hcCA9IHtcbiAgICBwOiAnc3BhbicsXG4gICAgdWw6ICdsaScsXG4gICAgb2w6ICdsaScsXG4gICAgdGFibGU6ICd0cicsXG4gICAgdHI6ICd0ZCcsXG4gICAgdGJvZHk6ICd0cicsXG4gICAgdGhlYWQ6ICd0cicsXG4gICAgdGZvb3Q6ICd0cicsXG4gICAgY29sZ3JvdXA6ICdjb2wnLFxuICAgIHNlbGVjdDogJ29wdGlvbicsXG4gICAgb3B0Z3JvdXA6ICdvcHRpb24nLFxuICAgIGF1ZGlvOiAnc291cmNlJyxcbiAgICB2aWRlbzogJ3NvdXJjZScsXG4gICAgb2JqZWN0OiAncGFyYW0nLFxuICAgIG1hcDogJ2FyZWEnXG59O1xuXG4vKipcbiAqIFJldHVybnMgYmVzdCBjaGlsZCBub2RlIG5hbWUgZm9yIGdpdmVuIHBhcmVudCBub2RlIG5hbWVcbiAqIEBwYXJhbSAge1N0cmluZ30gcGFyZW50TmFtZSBOYW1lIG9mIHBhcmVudCBub2RlXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVJbXBsaWNpdE5hbWUocGFyZW50TmFtZSkge1xuICAgIHBhcmVudE5hbWUgPSAocGFyZW50TmFtZSB8fCAnJykudG9Mb3dlckNhc2UoKTtcbiAgICByZXR1cm4gZWxlbWVudE1hcFtwYXJlbnROYW1lXVxuICAgICAgICB8fCAoaW5saW5lRWxlbWVudHMuaGFzKHBhcmVudE5hbWUpID8gJ3NwYW4nIDogJ2RpdicpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVJbXBsaWNpdE5hbWU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wRGVmYXVsdCAoZXgpIHsgcmV0dXJuIChleCAmJiAodHlwZW9mIGV4ID09PSAnb2JqZWN0JykgJiYgJ2RlZmF1bHQnIGluIGV4KSA/IGV4WydkZWZhdWx0J10gOiBleDsgfVxuXG52YXIgcmVzb2x2ZUltcGxpY2l0VGFnID0gX2ludGVyb3BEZWZhdWx0KHJlcXVpcmUoJ0BlbW1ldGlvL2ltcGxpY2l0LXRhZycpKTtcblxuLyoqXG4gKiBBZGRzIG1pc3NpbmcgdGFnIG5hbWVzIGZvciBnaXZlbiB0cmVlIGRlcGVuZGluZyBvbiBub2Rl4oCZcyBwYXJlbnQgbmFtZVxuICovXG52YXIgaW1wbGljaXRUYWdzID0gZnVuY3Rpb24odHJlZSkge1xuICAgIHRyZWUud2Fsayhub2RlID0+IHtcbiAgICAgICAgLy8gcmVzb2x2ZSBvbmx5IG5hbWVsZXNzIG5vZGVzIHdpdGhvdXQgY29udGVudFxuICAgICAgICBpZiAobm9kZS5uYW1lID09IG51bGwgJiYgbm9kZS5hdHRyaWJ1dGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgbm9kZS5uYW1lID0gcmVzb2x2ZUltcGxpY2l0VGFnKG5vZGUucGFyZW50Lm5hbWUpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHRyZWU7XG59O1xuXG4vKipcbiAqIExvY2F0ZXMgYWxsIG9jY3VyYW5jZXMgb2YgZ2l2ZW4gYHRva2VuYCB3aGljaCBhcmUgbm90IGVzY2FwZWQgKGUuZy4gYXJlIG5vdFxuICogcHJlY2VkZWQgd2l0aCBgXFxgKSBnaXZlbiBpbiBgc3RyYFxuICogQHBhcmFtICB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge0FycmF5fSAgQXJyYXkgb2YgdG9rZW4gcmFuZ2VzXG4gKi9cbmZ1bmN0aW9uIGZpbmRVbmVzY2FwZWRUb2tlbnMoc3RyLCB0b2tlbikge1xuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBTZXQoKTtcbiAgICBjb25zdCB0bGVuID0gdG9rZW4ubGVuZ3RoO1xuXG4gICAgLy8gMS4gRmluZCBhbGwgb2NjdXJhbmNlcyBvZiB0b2tlbnNcbiAgICBsZXQgcG9zID0gMDtcbiAgICB3aGlsZSAoKHBvcyA9IHN0ci5pbmRleE9mKHRva2VuLCBwb3MpKSAhPT0gLTEpIHtcbiAgICAgICAgcmVzdWx0LmFkZChwb3MpO1xuICAgICAgICBwb3MgKz0gdGxlbjtcbiAgICB9XG5cbiAgICBpZiAocmVzdWx0LnNpemUpIHtcbiAgICAgICAgLy8gMi4gUmVtb3ZlIG9uZXMgdGhhdCBlc2NhcGVkXG4gICAgICAgIGxldCBwb3MgPSAwO1xuICAgICAgICBjb25zdCBsZW4gPSBzdHIubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlIChwb3MgPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChzdHJbcG9zKytdID09PSAnXFxcXCcpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQuZGVsZXRlKHBvcysrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBBcnJheS5mcm9tKHJlc3VsdCkubWFwKGl4ID0+IHJhbmdlKGl4LCB0bGVuKSk7XG59XG5cbi8qKlxuICogUmVwbGFjZXMgYHJhbmdlc2AsIGdlbmVyYXRlZCBieSBgcmFuZ2UoKWAgZnVuY3Rpb24sIHdpdGggZ2l2ZW4gYHZhbHVlYCBpbiBgc3RyYFxuICogQHBhcmFtICB7U3RyaW5nfSBzdHIgICAgV2hlcmUgdG8gcmVwbGFjZSByYW5nZXNcbiAqIEBwYXJhbSAge0FycmF5fSByYW5nZXMgUmFuZXMsIGNyZWF0ZWQgYnkgYHJhbmdlKClgIGZ1bmN0aW9uXG4gKiBAcGFyYW0gIHtTdHJpbmd8RnVuY3Rpb259IHZhbHVlICBSZXBsYWNlbWVudCB2YWx1ZS4gSWYgaXTigJlzIGEgZnVuY3Rpb24sIGl0XG4gKiB3aWxsIHRha2UgYSByYW5nZSB2YWx1ZSBhcyBhcmd1bWVudCBhbmQgc2hvdWxkIHJldHVybiBhIG5ldyBzdHJpbmdcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqL1xuZnVuY3Rpb24gcmVwbGFjZVJhbmdlcyhzdHIsIHJhbmdlcywgdmFsdWUpIHtcblx0Ly8gc2hvdWxkIHdhbGsgZnJvbSB0aGUgZW5kIG9mIGFycmF5IHRvIGtlZXAgcmFuZ2VzIHZhbGlkIGFmdGVyIHJlcGxhY2VtZW50XG5cdGZvciAobGV0IGkgPSByYW5nZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcblx0XHRjb25zdCByID0gcmFuZ2VzW2ldO1xuXG5cdFx0c3RyID0gc3RyLnN1YnN0cmluZygwLCByWzBdKVxuXHRcdFx0KyAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nID8gdmFsdWUoc3RyLnN1YnN0cihyWzBdLCByWzFdKSkgOiB2YWx1ZSlcblx0XHRcdCsgc3RyLnN1YnN0cmluZyhyWzBdICsgclsxXSk7XG5cdH1cblxuXHRyZXR1cm4gc3RyO1xufVxuXG5mdW5jdGlvbiByYW5nZShzdGFydCwgbGVuZ3RoKSB7XG4gICAgcmV0dXJuIFtzdGFydCwgbGVuZ3RoXTtcbn1cblxuY29uc3QgbnVtYmVyaW5nVG9rZW4gPSAnJCc7XG5cbi8qKlxuICogTnVtYmVyaW5nIG9mIGV4cGFuZGVkIGFiYnJldmlhdGlvbjogZmluZHMgYWxsIG5vZGVzIHdpdGggYCRgIGluIHZhbHVlXG4gKiBvciBhdHRyaWJ1dGVzIGFuZCByZXBsYWNlcyBpdHMgb2NjdXJhbmNlcyB3aXRoIHJlcGVhdGVyIHZhbHVlXG4gKi9cbnZhciBhcHBseU51bWJlcmluZyA9IGZ1bmN0aW9uKHRyZWUpIHtcbiAgICB0cmVlLndhbGsoYXBwbHlOdW1iZXJpbmckMSk7XG4gICAgcmV0dXJuIHRyZWU7XG59O1xuXG4vKipcbiAqIEFwcGxpZXMgbnVtYmVyaW5nIGZvciBnaXZlbiBub2RlOiByZXBsYWNlcyBvY2N1cmFuY2VzIG9mIG51bWJlcmluZyB0b2tlblxuICogaW4gbm9kZeKAmXMgbmFtZSwgY29udGVudCBhbmQgYXR0cmlidXRlc1xuICogQHBhcmFtICB7Tm9kZX0gbm9kZVxuICogQHJldHVybiB7Tm9kZX1cbiAqL1xuZnVuY3Rpb24gYXBwbHlOdW1iZXJpbmckMShub2RlKSB7XG4gICAgY29uc3QgcmVwZWF0ZXIgPSBmaW5kUmVwZWF0ZXIobm9kZSk7XG5cbiAgICBpZiAocmVwZWF0ZXIgJiYgcmVwZWF0ZXIudmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAvLyBOQiByZXBsYWNlIG51bWJlcmluZyBpbiBub2RlcyB3aXRoIGV4cGxpY2l0IHJlcGVhdGVyIG9ubHk6XG4gICAgICAgIC8vIGl0IHNvbHZlcyBpc3N1ZXMgd2l0aCBhYmJyZXZpYXRpb25zIGxpa2UgYHhzbDppZlt0ZXN0PSRmb29dYCB3aGVyZVxuICAgICAgICAvLyBgJGZvb2AgaXMgcHJlZmVycmVkIG91dHB1dFxuICAgICAgICBjb25zdCB2YWx1ZSA9IHJlcGVhdGVyLnZhbHVlO1xuXG4gICAgICAgIG5vZGUubmFtZSA9IHJlcGxhY2VOdW1iZXJpbmcobm9kZS5uYW1lLCB2YWx1ZSk7XG4gICAgICAgIG5vZGUudmFsdWUgPSByZXBsYWNlTnVtYmVyaW5nKG5vZGUudmFsdWUsIHZhbHVlKTtcbiAgICAgICAgbm9kZS5hdHRyaWJ1dGVzLmZvckVhY2goYXR0ciA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb3B5ID0gbm9kZS5nZXRBdHRyaWJ1dGUoYXR0ci5uYW1lKS5jbG9uZSgpO1xuICAgICAgICAgICAgY29weS5uYW1lID0gcmVwbGFjZU51bWJlcmluZyhhdHRyLm5hbWUsIHZhbHVlKTtcbiAgICAgICAgICAgIGNvcHkudmFsdWUgPSByZXBsYWNlTnVtYmVyaW5nKGF0dHIudmFsdWUsIHZhbHVlKTtcbiAgICAgICAgICAgIG5vZGUucmVwbGFjZUF0dHJpYnV0ZShhdHRyLm5hbWUsIGNvcHkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHJlcGVhdGVyIG9iamVjdCBmb3IgZ2l2ZW4gbm9kZVxuICogQHBhcmFtICB7Tm9kZX0gbm9kZVxuICogQHJldHVybiB7T2JqZWN0fVxuICovXG5mdW5jdGlvbiBmaW5kUmVwZWF0ZXIobm9kZSkge1xuICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgIGlmIChub2RlLnJlcGVhdCkge1xuICAgICAgICAgICAgcmV0dXJuIG5vZGUucmVwZWF0O1xuICAgICAgICB9XG5cbiAgICAgICAgbm9kZSA9IG5vZGUucGFyZW50O1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXBsYWNlcyBudW1iZXJpbmcgaW4gZ2l2ZW4gc3RyaW5nXG4gKiBAcGFyYW0gIHtTdHJpbmd9IHN0clxuICogQHBhcmFtICB7TnVtYmVyfSB2YWx1ZVxuICogQHJldHVybiB7U3RyaW5nfVxuICovXG5mdW5jdGlvbiByZXBsYWNlTnVtYmVyaW5nKHN0ciwgdmFsdWUpIHtcbiAgICAvLyByZXBsYWNlIG51bWJlcmluZyBpbiBzdHJpbmdzIG9ubHk6IHNraXAgZXhwbGljaXQgd3JhcHBlcnMgdGhhdCBjb3VsZFxuICAgIC8vIGNvbnRhaW4gdW5lc2NhcGVkIG51bWJlcmluZyB0b2tlbnNcbiAgICBpZiAodHlwZW9mIHN0ciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc3QgcmFuZ2VzID0gZ2V0TnVtYmVyaW5nUmFuZ2VzKHN0cik7XG4gICAgICAgIHJldHVybiByZXBsYWNlTnVtYmVyaW5nUmFuZ2VzKHN0ciwgcmFuZ2VzLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0cjtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIG51bWJlcmluZyByYW5nZXMsIGUuZy4gcmFuZ2VzIG9mIGAkYCBvY2N1cmFuY2VzLCBpbiBnaXZlbiBzdHJpbmcuXG4gKiBNdWx0aXBsZSBhZGphY2VudCByYW5nZXMgYXJlIGNvbWJpbmVkXG4gKiBAcGFyYW0gIHtTdHJpbmd9IHN0clxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cbmZ1bmN0aW9uIGdldE51bWJlcmluZ1JhbmdlcyhzdHIpIHtcbiAgICByZXR1cm4gZmluZFVuZXNjYXBlZFRva2VucyhzdHIgfHwgJycsIG51bWJlcmluZ1Rva2VuKVxuICAgIC5yZWR1Y2UoKG91dCwgcmFuZ2UkJDEpID0+IHtcbiAgICAgICAgLy8gc2tpcCByYW5nZXMgdGhhdCBhY3R1YWxseSBiZWxvbmdzIHRvIG91dHB1dCBwbGFjZWhvbGRlciBvciB0YWJzdG9wc1xuICAgICAgICBpZiAoIS9bI3tdLy50ZXN0KHN0cltyYW5nZSQkMVswXSArIDFdIHx8ICcnKSkge1xuICAgICAgICAgICAgY29uc3QgbGFzdFJhbmdlID0gb3V0W291dC5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgIGlmIChsYXN0UmFuZ2UgJiYgbGFzdFJhbmdlWzBdICsgbGFzdFJhbmdlWzFdID09PSByYW5nZSQkMVswXSkge1xuICAgICAgICAgICAgICAgIGxhc3RSYW5nZVsxXSArPSByYW5nZSQkMVsxXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb3V0LnB1c2gocmFuZ2UkJDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9LCBbXSk7XG59XG5cbi8qKlxuICogQHBhcmFtICB7U3RyaW5nfSBzdHJcbiAqIEBwYXJhbSAge0FycmF5fSByYW5nZXNcbiAqIEBwYXJhbSAge051bWJlcn0gdmFsdWVcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqL1xuZnVuY3Rpb24gcmVwbGFjZU51bWJlcmluZ1JhbmdlcyhzdHIsIHJhbmdlcywgdmFsdWUpIHtcbiAgICBjb25zdCByZXBsYWNlZCA9IHJlcGxhY2VSYW5nZXMoc3RyLCByYW5nZXMsIHRva2VuID0+IHtcbiAgICAgICAgbGV0IF92YWx1ZSA9IFN0cmluZyh2YWx1ZSk7XG4gICAgICAgIC8vIHBhZCB2YWx1ZXMgZm9yIG11bHRpcGxlIG51bWJlcmluZyB0b2tlbnMsIGUuZy4gMyBmb3IgJCQkIGJlY29tZXMgMDAzXG4gICAgICAgIHdoaWxlIChfdmFsdWUubGVuZ3RoIDwgdG9rZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICBfdmFsdWUgPSAnMCcgKyBfdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF92YWx1ZTtcbiAgICB9KTtcblxuICAgIC8vIHVuZXNjYXBlIHNjcmVlbmVkIG51bWJlcmluZyB0b2tlbnNcbiAgICByZXR1cm4gdW5lc2NhcGVTdHJpbmcocmVwbGFjZWQpO1xufVxuXG4vKipcbiAqIFVuZXNjYXBlcyBjaGFyYWN0ZXJzLCBzY3JlZW5lZCB3aXRoIGBcXGAsIGluIGdpdmVuIHN0cmluZ1xuICogQHBhcmFtICB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqL1xuZnVuY3Rpb24gdW5lc2NhcGVTdHJpbmcoc3RyKSB7XG4gICAgbGV0IGkgPSAwLCByZXN1bHQgPSAnJztcbiAgICBjb25zdCBsZW4gPSBzdHIubGVuZ3RoO1xuXG4gICAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICAgICAgY29uc3QgY2ggPSBzdHJbaSsrXTtcbiAgICAgICAgcmVzdWx0ICs9IChjaCA9PT0gJ1xcXFwnKSA/IChzdHJbaSsrXSB8fCAnJykgOiBjaDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKiogUGxhY2Vob2xkZXIgZm9yIGluc2VydGVkIGNvbnRlbnQgKi9cbmNvbnN0IHBsYWNlaG9sZGVyID0gJyQjJztcblxuLyoqIFBsYWNlaG9sZGVyIGZvciBjYXJldCAqL1xuY29uc3QgY2FyZXQgPSAnfCc7XG5cbmNvbnN0IHJlVXJsID0gL14oKD86aHR0cHM/fGZ0cHxmaWxlKTpcXC9cXC8pPyhbXFxkYS16XFwuLV0rKVxcLihbYS16XFwuXXsyLDZ9KShbXFwvXFx3IFxcLi1dKikqXFwvPyQvO1xuY29uc3QgcmVFbWFpbCA9IC9eKFthLXowLTlfXFwuLV0rKUAoW1xcZGEtelxcLi1dKylcXC4oW2EtelxcLl17Miw2fSkkLztcbmNvbnN0IHJlUHJvdG8gPSAvXihbYS16XSs6KT9cXC9cXC8vaTtcblxuLyoqXG4gKiBJbnNlcnRzIGNvbnRlbnQgaW50byBub2RlIHdpdGggaW1wbGljaXQgcmVwZWF0IGNvdW50OiB0aGlzIG5vZGUgaXMgdGhlblxuICogZHVwbGljYXRlZCBmb3IgZWFjaCBjb250ZW50IGl0ZW0gYW5kIGNvbnRlbnQgaXRzZWxmIGlzIGluc2VydGVkIGVpdGhlciBpbnRvXG4gKiBkZWVwZXN0IGNoaWxkIG9yIGluc3RlYWQgb2YgYSBzcGVjaWFsIHRva2VuLlxuICpcbiAqIFRoaXMgbWV0aG9kIHVzZXMgdHdvIGRpc3RpbmN0IHN0ZXBzOiBgcHJlcGFyZSgpYCBhbmQgYGluc2VydCgpYCBzaW5jZSBtb3N0XG4gKiBsaWtlbHkgdGhlc2Ugc3RlcHMgd2lsbCBiZSB1c2VkIHNlcGFyYXRlbHkgdG8gcHJvcGVybHkgaW5zZXJ0IGNvbnRlbnRcbiAqIHdpdGggdW5lc2NhcGVkIGAkYCBudW1iZXJpbmcgbWFya2Vycy5cbiAqXG4gKiBAcGFyYW0ge05vZGV9IHRyZWUgUGFyc2VkIGFiYnJldmlhdGlvblxuICogQHBhcmFtIHtTdHJpbmdbXX0gY29udGVudCBBcnJheSBvZiBjb250ZW50IGl0ZW1zIHRvIGluc2VydFxuICogQHJldHVybiB7Tm9kZX1cbiAqL1xuLyoqXG4gKiBGaW5kcyBub2RlcyB3aXRoIGltcGxpY2l0IHJlcGVhdCBhbmQgY3JlYXRlcyBgYW1vdW50YCBjb3BpZXMgb2YgaXQgaW4gdHJlZVxuICogQHBhcmFtICB7Tm9kZX0gdHJlZVxuICogQHBhcmFtICB7TnVtYmVyfSBhbW91bnRcbiAqIEByZXR1cm4ge05vZGV9XG4gKi9cbmZ1bmN0aW9uIHByZXBhcmUodHJlZSwgYW1vdW50KSB7XG4gICAgYW1vdW50ID0gYW1vdW50IHx8IDE7XG4gICAgdHJlZS53YWxrKG5vZGUgPT4ge1xuICAgICAgICBpZiAobm9kZS5yZXBlYXQgJiYgbm9kZS5yZXBlYXQuY291bnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYW1vdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjbG9uZSA9IG5vZGUuY2xvbmUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgY2xvbmUucmVwZWF0LmltcGxpY2l0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjbG9uZS5yZXBlYXQuY291bnQgPSBhbW91bnQ7XG4gICAgICAgICAgICAgICAgY2xvbmUucmVwZWF0LnZhbHVlID0gaSArIDE7XG4gICAgICAgICAgICAgICAgY2xvbmUucmVwZWF0LmluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBub2RlLnBhcmVudC5pbnNlcnRCZWZvcmUoY2xvbmUsIG5vZGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBub2RlLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdHJlZTtcbn1cblxuLyoqXG4gKiBJbnNlcnRzIGNvbnRlbnQgaW50byBpbXBsaWNpdGx5IHJlcGVhdGVkIG5vZGVzLCBjcmVhdGVkIGJ5IGBwcmVwYXJlKClgIG1ldGhvZFxuICogQHBhcmFtICB7Tm9kZX0gdHJlZVxuICogQHBhcmFtICB7U3RyaW5nW119IGNvbnRlbnRcbiAqIEByZXR1cm4ge05vZGV9XG4gKi9cbmZ1bmN0aW9uIGluc2VydCh0cmVlLCBjb250ZW50KSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29udGVudCkgJiYgY29udGVudC5sZW5ndGgpIHtcbiAgICAgICAgbGV0IHVwZGF0ZWQgPSBmYWxzZTtcbiAgICAgICAgdHJlZS53YWxrKG5vZGUgPT4ge1xuICAgICAgICAgICAgaWYgKG5vZGUucmVwZWF0ICYmIG5vZGUucmVwZWF0LmltcGxpY2l0KSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgaW5zZXJ0Q29udGVudChub2RlLCBjb250ZW50W25vZGUucmVwZWF0LmluZGV4XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghdXBkYXRlZCkge1xuICAgICAgICAgICAgLy8gbm8gbm9kZSB3aXRoIGltcGxpY2l0IHJlcGVhdCB3YXMgZm91bmQsIGluc2VydCBjb250ZW50IGFzXG4gICAgICAgICAgICAvLyBkZWVwZXN0IGNoaWxkXG4gICAgICAgICAgICBzZXROb2RlQ29udGVudChmaW5kRGVlcGVzdE5vZGUodHJlZSksIGNvbnRlbnQuam9pbignXFxuJykpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyZWU7XG59XG5cbi8qKlxuICogSW5zZXJ0cyBgY29udGVudGAgaW50byBnaXZlbiBgbm9kZWA6IGVpdGhlciByZXBsYWNlcyBvdXRwdXQgcGxhY2Vob2xkZXJzXG4gKiBvciBpbnNlcnRzIGl0IGludG8gZGVlcGVzdCBjaGlsZCBub2RlXG4gKiBAcGFyYW0gIHtOb2RlfSBub2RlXG4gKiBAcGFyYW0gIHtTdHJpbmd9IGNvbnRlbnRcbiAqIEByZXR1cm4ge05vZGV9XG4gKi9cbmZ1bmN0aW9uIGluc2VydENvbnRlbnQobm9kZSwgY29udGVudCkge1xuXHRsZXQgaW5zZXJ0ZWQgPSBpbnNlcnRDb250ZW50SW50b1BsYWNlaG9sZGVyKG5vZGUsIGNvbnRlbnQpO1xuXHRub2RlLndhbGsoY2hpbGQgPT4gaW5zZXJ0ZWQgfD0gaW5zZXJ0Q29udGVudEludG9QbGFjZWhvbGRlcihjaGlsZCwgY29udGVudCkpO1xuXG5cdGlmICghaW5zZXJ0ZWQpIHtcblx0XHQvLyBubyBwbGFjZWhvbGRlcnMgd2VyZSBmb3VuZCBpbiBub2RlLCBpbnNlcnQgY29udGVudCBpbnRvIGRlZXBlc3QgY2hpbGRcblx0XHRzZXROb2RlQ29udGVudChmaW5kRGVlcGVzdE5vZGUobm9kZSksIGNvbnRlbnQpO1xuXHR9XG5cblx0cmV0dXJuIG5vZGU7XG59XG5cbi8qKlxuICogSW5zZXJ0cyBnaXZlbiBgY29udGVudGAgaW50byBwbGFjZWhvbGRlcnMgZm9yIGdpdmVuIGBub2RlYC4gUGxhY2Vob2xkZXJzXG4gKiBtaWdodCBiZSBhdmFpbGFibGUgaW4gYXR0cmlidXRlIHZhbHVlcyBhbmQgbm9kZSBjb250ZW50XG4gKiBAcGFyYW0gIHtOb2RlfSBub2RlXG4gKiBAcGFyYW0gIHtTdHJpbmd9IGNvbnRlbnRcbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHBsYWNlaG9sZGVycyB3ZXJlIGZvdW5kIGFuZCByZXBsYWNlZCBpbiBub2RlXG4gKi9cbmZ1bmN0aW9uIGluc2VydENvbnRlbnRJbnRvUGxhY2Vob2xkZXIobm9kZSwgY29udGVudCkge1xuXHRjb25zdCBzdGF0ZSA9IHtyZXBsYWNlZDogZmFsc2V9O1xuXG5cdG5vZGUudmFsdWUgPSByZXBsYWNlUGxhY2Vob2xkZXIobm9kZS52YWx1ZSwgY29udGVudCwgc3RhdGUpO1xuXHRub2RlLmF0dHJpYnV0ZXMuZm9yRWFjaChhdHRyID0+IHtcblx0XHRpZiAoYXR0ci52YWx1ZSkge1xuXHRcdFx0bm9kZS5zZXRBdHRyaWJ1dGUoYXR0ci5uYW1lLCByZXBsYWNlUGxhY2Vob2xkZXIoYXR0ci52YWx1ZSwgY29udGVudCwgc3RhdGUpKTtcblx0XHR9XG5cdH0pO1xuXG5cdHJldHVybiBzdGF0ZS5yZXBsYWNlZDtcbn1cblxuLyoqXG4gKiBSZXBsYWNlcyBhbGwgcGxhY2Vob2xkZXIgb2NjdXJhbmNlcyBpbiBnaXZlbiBgc3RyYCB3aXRoIGB2YWx1ZWBcbiAqIEBwYXJhbSAge1N0cmluZ30gc3RyXG4gKiBAcGFyYW0gIHtTdHJpbmd9IHZhbHVlXG4gKiBAcGFyYW0gIHtPYmplY3R9IFtfc3RhdGVdIElmIHByb3ZpZGVkLCBzZXQgYHJlcGxhY2VkYCBwcm9wZXJ0eSBvZiBnaXZlblxuICogb2JqZWN0IHRvIGB0cnVlYCBpZiBwbGFjZWhvbGRlciB3YXMgZm91bmQgYW5kIHJlcGxhY2VkXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIHJlcGxhY2VQbGFjZWhvbGRlcihzdHIsIHZhbHVlLCBfc3RhdGUpIHtcblx0aWYgKHR5cGVvZiBzdHIgPT09ICdzdHJpbmcnKSB7XG5cdFx0Y29uc3QgcmFuZ2VzID0gZmluZFVuZXNjYXBlZFRva2VucyhzdHIsIHBsYWNlaG9sZGVyKTtcblx0XHRpZiAocmFuZ2VzLmxlbmd0aCkge1xuXHRcdFx0aWYgKF9zdGF0ZSkge1xuXHRcdFx0XHRfc3RhdGUucmVwbGFjZWQgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRzdHIgPSByZXBsYWNlUmFuZ2VzKHN0ciwgcmFuZ2VzLCB2YWx1ZSk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHN0cjtcbn1cblxuLyoqXG4gKiBGaW5kcyBub2RlIHdoaWNoIGlzIHRoZSBkZWVwZXN0IGZvciBpbiBjdXJyZW50IG5vZGUgb3Igbm9kZSBpdGVzZWxmLlxuICogQHBhcmFtICB7Tm9kZX0gbm9kZVxuICogQHJldHVybiB7Tm9kZX1cbiAqL1xuZnVuY3Rpb24gZmluZERlZXBlc3ROb2RlKG5vZGUpIHtcblx0d2hpbGUgKG5vZGUuY2hpbGRyZW4ubGVuZ3RoKSB7XG5cdFx0bm9kZSA9IG5vZGUuY2hpbGRyZW5bbm9kZS5jaGlsZHJlbi5sZW5ndGggLSAxXTtcblx0fVxuXG5cdHJldHVybiBub2RlO1xufVxuXG4vKipcbiAqIFVwZGF0ZXMgY29udGVudCBvZiBnaXZlbiBub2RlXG4gKiBAcGFyYW0ge05vZGV9IG5vZGVcbiAqIEBwYXJhbSB7U3RyaW5nfSBjb250ZW50XG4gKi9cbmZ1bmN0aW9uIHNldE5vZGVDb250ZW50KG5vZGUsIGNvbnRlbnQpIHtcblx0Ly8gZmluZCBjYXJldCBwb3NpdGlvbiBhbmQgcmVwbGFjZSBpdCB3aXRoIGNvbnRlbnQsIGlmIHBvc3NpYmxlXG5cdGlmIChub2RlLnZhbHVlKSB7XG5cdFx0Y29uc3QgcmFuZ2VzID0gZmluZFVuZXNjYXBlZFRva2Vucyhub2RlLnZhbHVlLCBjYXJldCk7XG5cdFx0aWYgKHJhbmdlcy5sZW5ndGgpIHtcblx0XHRcdG5vZGUudmFsdWUgPSByZXBsYWNlUmFuZ2VzKG5vZGUudmFsdWUsIHJhbmdlcywgY29udGVudCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHR9XG5cblx0aWYgKG5vZGUubmFtZS50b0xvd2VyQ2FzZSgnYScpIHx8IG5vZGUuaGFzQXR0cmlidXRlKCdocmVmJykpIHtcblx0XHQvLyBzcGVjaWFsIGNhc2U6IGluc2VydGluZyBjb250ZW50IGludG8gYDxhPmAgdGFnXG5cdFx0aWYgKHJlVXJsLnRlc3QoY29udGVudCkpIHtcblx0XHRcdG5vZGUuc2V0QXR0cmlidXRlKCdocmVmJywgKHJlUHJvdG8udGVzdChjb250ZW50KSA/ICcnIDogJ2h0dHA6Ly8nKSArIGNvbnRlbnQpO1xuXHRcdH0gZWxzZSBpZiAocmVFbWFpbC50ZXN0KGNvbnRlbnQpKSB7XG5cdFx0XHRub2RlLnNldEF0dHJpYnV0ZSgnaHJlZicsICdtYWlsdG86JyArIGNvbnRlbnQpO1xuXHRcdH1cblx0fVxuXG5cdG5vZGUudmFsdWUgPSBjb250ZW50O1xufVxuXG5jb25zdCBkZWZhdWx0T3B0aW9ucyA9IHtcblx0ZWxlbWVudDogJ19fJyxcblx0bW9kaWZpZXI6ICdfJ1xufTtcblxuY29uc3QgcmVFbGVtZW50ICA9IC9eKC0rKShbYS16MC05XSspL2k7XG5jb25zdCByZU1vZGlmaWVyID0gL14oXyspKFthLXowLTldKykvaTtcbmNvbnN0IGJsb2NrQ2FuZGlkYXRlczEgPSBjbGFzc05hbWUgPT4gL15bYS16XVxcLS9pLnRlc3QoY2xhc3NOYW1lKTtcbmNvbnN0IGJsb2NrQ2FuZGlkYXRlczIgPSBjbGFzc05hbWUgPT4gL15bYS16XS9pLnRlc3QoY2xhc3NOYW1lKTtcblxuLyoqXG4gKiBCRU0gdHJhbnNmb3JtZXI6IHVwZGF0ZXMgY2xhc3MgbmFtZXMgd3JpdHRlbiBhcyBgLWVsZW1lbnRgIGFuZFxuICogYF9tb2RpZmllcmAgaW50byBmdWxsIGNsYXNzIG5hbWVzIGFzIGRlc2NyaWJlZCBpbiBCRU0gc3BlY3MuIEFsc28gYWRkcyBtaXNzaW5nXG4gKiBjbGFzcyBuYW1lczogZmlyIGV4YW1wbGUsIGlmIG5vZGUgY29udGFpbnMgYC5ibG9ja19tb2RpZmllcmAgY2xhc3MsIGVuc3VyZXNcbiAqIHRoYXQgZWxlbWVudCBjb250YWlucyBgLmJsb2NrYCBjbGFzcyBhcyB3ZWxsXG4gKi9cbnZhciBiZW0gPSBmdW5jdGlvbih0cmVlLCBvcHRpb25zKSB7XG5cdG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0T3B0aW9ucywgb3B0aW9ucyk7XG5cblx0dHJlZS53YWxrKG5vZGUgPT4gZXhwYW5kQ2xhc3NOYW1lcyhub2RlLCBvcHRpb25zKSk7XG5cblx0Y29uc3QgbG9va3VwID0gY3JlYXRlQmxvY2tMb29rdXAodHJlZSk7XG4gICAgdHJlZS53YWxrKG5vZGUgPT4gZXhwYW5kU2hvcnROb3RhdGlvbihub2RlLCBsb29rdXAsIG9wdGlvbnMpKTtcblxuXHRyZXR1cm4gdHJlZTtcbn07XG5cbi8qKlxuICogRXhwYW5kcyBleGlzdGluZyBjbGFzcyBuYW1lcyBpbiBCRU0gbm90YXRpb24gaW4gZ2l2ZW4gYG5vZGVgLlxuICogRm9yIGV4YW1wbGUsIGlmIG5vZGUgY29udGFpbnMgYGJfX2VsX21vZGAgY2xhc3MgbmFtZSwgdGhpcyBtZXRob2QgZW5zdXJlc1xuICogdGhhdCBlbGVtZW50IGNvbnRhaW5zIGBiX19lbGAgY2xhc3MgYXMgd2VsbFxuICogQHBhcmFtICB7Tm9kZX0gbm9kZVxuICogQHBhcmFtICB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcmV0dXJuIHtTZXR9XG4gKi9cbmZ1bmN0aW9uIGV4cGFuZENsYXNzTmFtZXMobm9kZSwgb3B0aW9ucykge1xuXHRjb25zdCBjbGFzc05hbWVzID0gbm9kZS5jbGFzc0xpc3QucmVkdWNlKChvdXQsIGNsKSA9PiB7XG5cdFx0Ly8gcmVtb3ZlIGFsbCBtb2RpZmllcnMgZnJvbSBjbGFzcyBuYW1lIHRvIGdldCBhIGJhc2UgZWxlbWVudCBuYW1lXG5cdFx0Y29uc3QgaXggPSBjbC5pbmRleE9mKG9wdGlvbnMubW9kaWZpZXIpO1xuXHRcdGlmIChpeCAhPT0gLTEpIHtcblx0XHRcdG91dC5hZGQoY2wuc2xpY2UoMCwgaXgpKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gb3V0LmFkZChjbCk7XG5cdH0sIG5ldyBTZXQoKSk7XG5cblx0aWYgKGNsYXNzTmFtZXMuc2l6ZSkge1xuXHRcdG5vZGUuc2V0QXR0cmlidXRlKCdjbGFzcycsIEFycmF5LmZyb20oY2xhc3NOYW1lcykuam9pbignICcpKTtcblx0fVxufVxuXG4vKipcbiAqIEV4cGFuZHMgc2hvcnQgQkVNIG5vdGF0aW9uLCBlLmcuIGAtZWxlbWVudGAgYW5kIGBfbW9kaWZpZXJgXG4gKiBAcGFyYW0gIHtOb2RlfSBub2RlICAgICAgUGFyc2VkIEVtbWV0IGFiYnJldmlhdGlvbiBub2RlXG4gKiBAcGFyYW0gIHtNYXB9IGxvb2t1cCAgICAgQkVNIGJsb2NrIG5hbWUgbG9va3VwXG4gKiBAcGFyYW0gIHtPYmplY3R9IG9wdGlvbnNcbiAqL1xuZnVuY3Rpb24gZXhwYW5kU2hvcnROb3RhdGlvbihub2RlLCBsb29rdXAsIG9wdGlvbnMpIHtcblx0Y29uc3QgY2xhc3NOYW1lcyA9IG5vZGUuY2xhc3NMaXN0LnJlZHVjZSgob3V0LCBjbCkgPT4ge1xuXHRcdGxldCBwcmVmaXgsIG07XG5cdFx0Y29uc3Qgb3JpZ2luYWxDbGFzcyA9IGNsO1xuXG5cdFx0Ly8gcGFyc2UgZWxlbWVudCBkZWZpbml0aW9uIChjb3VsZCBiZSBvbmx5IG9uZSlcblx0XHRpZiAobSA9IGNsLm1hdGNoKHJlRWxlbWVudCkpIHtcblx0XHRcdHByZWZpeCA9IGdldEJsb2NrTmFtZShub2RlLCBsb29rdXAsIG1bMV0pICsgb3B0aW9ucy5lbGVtZW50ICsgbVsyXTtcblx0XHRcdG91dC5hZGQocHJlZml4KTtcblx0XHRcdGNsID0gY2wuc2xpY2UobVswXS5sZW5ndGgpO1xuXHRcdH1cblxuXHRcdC8vIHBhcnNlIG1vZGlmaWVycyBkZWZpbml0aW9ucyAobWF5IGNvbnRhaW4gbXVsdGlwbGUpXG5cdFx0d2hpbGUgKG0gPSBjbC5tYXRjaChyZU1vZGlmaWVyKSkge1xuXHRcdFx0aWYgKCFwcmVmaXgpIHtcblx0XHRcdFx0cHJlZml4ID0gZ2V0QmxvY2tOYW1lKG5vZGUsIGxvb2t1cCwgbVsxXSk7XG5cdFx0XHRcdG91dC5hZGQocHJlZml4KTtcblx0XHRcdH1cblxuXHRcdFx0b3V0LmFkZChgJHtwcmVmaXh9JHtvcHRpb25zLm1vZGlmaWVyfSR7bVsyXX1gKTtcblx0XHRcdGNsID0gY2wuc2xpY2UobVswXS5sZW5ndGgpO1xuXHRcdH1cblxuXHRcdGlmIChjbCA9PT0gb3JpZ2luYWxDbGFzcykge1xuXHRcdFx0Ly8gY2xhc3MgbmFtZSB3YXNu4oCZdCBtb2RpZmllZDogaXTigJlzIG5vdCBhIEJFTS1zcGVjaWZpYyBjbGFzcyxcblx0XHRcdC8vIGFkZCBpdCBhcy1pcyBpbnRvIG91dHB1dFxuXHRcdFx0b3V0LmFkZChvcmlnaW5hbENsYXNzKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gb3V0O1xuXHR9LCBuZXcgU2V0KCkpO1xuXG5cdG5vZGUuc2V0QXR0cmlidXRlKCdjbGFzcycsIEFycmF5LmZyb20oY2xhc3NOYW1lcykuam9pbignICcpKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGJsb2NrIG5hbWUgbG9va3VwIGZvciBlYWNoIG5vZGUgaW4gZ2l2ZW4gdHJlZSwgZS5nLiBmaW5kcyBibG9ja1xuICogbmFtZSBleHBsaWNpdGx5IGZvciBlYWNoIG5vZGVcbiAqIEBwYXJhbSAge05vZGV9IHRyZWVcbiAqIEByZXR1cm4ge01hcH1cbiAqL1xuZnVuY3Rpb24gY3JlYXRlQmxvY2tMb29rdXAodHJlZSkge1xuXHRjb25zdCBsb29rdXAgPSBuZXcgTWFwKCk7XG5cblx0dHJlZS53YWxrKG5vZGUgPT4ge1xuXHRcdGNvbnN0IGNsYXNzTmFtZXMgPSBub2RlLmNsYXNzTGlzdDtcblx0XHRpZiAoY2xhc3NOYW1lcy5sZW5ndGgpIHtcblx0XHRcdC8vIGd1ZXNzIGJlc3QgYmxvY2sgbmFtZSBmcm9tIGNsYXNzIG9yIHVzZSBwYXJlbnTigJlzIGJsb2NrIG5hbWVcblx0XHRcdGxvb2t1cC5zZXQobm9kZSxcblx0XHRcdFx0ZmluZChjbGFzc05hbWVzLCBibG9ja0NhbmRpZGF0ZXMxKVxuXHRcdFx0XHR8fCBmaW5kKGNsYXNzTmFtZXMsIGJsb2NrQ2FuZGlkYXRlczIpXG5cdFx0XHRcdHx8IGxvb2t1cC5nZXQobm9kZS5wYXJlbnQpXG5cdFx0XHQpO1xuXHRcdH1cblx0fSk7XG5cblx0cmV0dXJuIGxvb2t1cDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGJsb2NrIG5hbWUgZm9yIGdpdmVuIGBub2RlYCBieSBgcHJlZml4YCwgd2hpY2ggdGVsbHMgdGhlIGRlcHRoIG9mXG4gKiBvZiBwYXJlbnQgbm9kZSBsb29rdXBcbiAqIEBwYXJhbSAge05vZGV9IG5vZGVcbiAqIEBwYXJhbSAge01hcH0gbG9va3VwXG4gKiBAcGFyYW0gIHtTdHJpbmd9IHByZWZpeFxuICogQHJldHVybiB7U3RyaW5nfVxuICovXG5mdW5jdGlvbiBnZXRCbG9ja05hbWUobm9kZSwgbG9va3VwLCBwcmVmaXgpIHtcblx0bGV0IGRlcHRoID0gcHJlZml4Lmxlbmd0aCA+IDEgPyBwcmVmaXgubGVuZ3RoIDogMDtcblx0d2hpbGUgKG5vZGUucGFyZW50ICYmIGRlcHRoLS0pIHtcblx0XHRub2RlID0gbm9kZS5wYXJlbnQ7XG5cdH1cblxuXHRyZXR1cm4gbG9va3VwLmdldChub2RlKTtcbn1cblxuZnVuY3Rpb24gZmluZChhcnIsIGZpbHRlcikge1xuXHRyZXR1cm4gYXJyLmZpbHRlcihmaWx0ZXIpWzBdO1xufVxuXG4vKipcbiAqIEpTWCB0cmFuc2Zvcm1lcjogcmVwbGFjZXMgYGNsYXNzYCBhbmQgYGZvcmAgYXR0cmlidXRlcyB3aXRoIGBjbGFzc05hbWVgIGFuZFxuICogYGh0bWxGb3JgIGF0dHJpYnV0ZXMgcmVzcGVjdGl2ZWx5XG4gKi9cbnZhciBqc3ggPSBmdW5jdGlvbih0cmVlKSB7XG5cdHRyZWUud2Fsayhub2RlID0+IHtcblx0XHRyZXBsYWNlKG5vZGUsICdjbGFzcycsICdjbGFzc05hbWUnKTtcblx0XHRyZXBsYWNlKG5vZGUsICdmb3InLCAnaHRtbEZvcicpO1xuXHR9KTtcblx0cmV0dXJuIHRyZWU7XG59O1xuXG5mdW5jdGlvbiByZXBsYWNlKG5vZGUsIG9sZE5hbWUsIG5ld05hbWUpIHtcblx0bGV0IGF0dHIgPSBub2RlLmdldEF0dHJpYnV0ZShvbGROYW1lKTtcblx0aWYgKGF0dHIpIHtcblx0XHRhdHRyLm5hbWUgPSBuZXdOYW1lO1xuXHR9XG59XG5cbmNvbnN0IHJlU3VwcG9ydGVyTmFtZXMgPSAvXnhzbDoodmFyaWFibGV8d2l0aFxcLXBhcmFtKSQvaTtcblxuLyoqXG4gKiBYU0wgdHJhbnNmb3JtZXI6IHJlbW92ZXMgYHNlbGVjdGAgYXR0cmlidXRlcyBmcm9tIGNlcnRhaW4gbm9kZXMgdGhhdCBjb250YWluXG4gKiBjaGlsZHJlblxuICovXG52YXIgeHNsID0gZnVuY3Rpb24odHJlZSkge1xuXHR0cmVlLndhbGsobm9kZSA9PiB7XG5cdFx0aWYgKHJlU3VwcG9ydGVyTmFtZXMudGVzdChub2RlLm5hbWUgfHwgJycpICYmIChub2RlLmNoaWxkcmVuLmxlbmd0aCB8fCBub2RlLnZhbHVlKSkge1xuXHRcdFx0bm9kZS5yZW1vdmVBdHRyaWJ1dGUoJ3NlbGVjdCcpO1xuXHRcdH1cblx0fSk7XG5cdHJldHVybiB0cmVlO1xufTtcblxuY29uc3Qgc3VwcG9ydGVkQWRkb25zID0geyBiZW0sIGpzeCwgeHNsIH07XG5cbi8qKlxuICogUnVucyBhZGRpdGlvbmFsIHRyYW5zZm9ybXMgb24gZ2l2ZW4gdHJlZS5cbiAqIFRoZXNlIHRyYW5zZm9ybXMgbWF5IGludHJvZHVjZSBzaWRlLWVmZmVjdHMgYW5kIHVuZXhwZWN0ZWQgcmVzdWx0XG4gKiBzbyB0aGV5IGFyZSBub3QgYXBwbGllZCBieSBkZWZhdWx0LCBhdXRob3JzIG11c3Qgc3BlY2lmeSB3aGljaCBhZGRvbnNcbiAqIGluIGBhZGRvbnNgIGFyZ3VtZW50IGFzIGB7YWRkb25OYW1lOiBhZGRvbk9wdGlvbnN9YFxuICogQHBhcmFtIHtOb2RlfSB0cmVlIFBhcnNlZCBFbW1ldCBhYmJyZXZpYXRpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBhZGRvbnMgQWRkLW9ucyB0byBhcHBseSBhbmQgdGhlaXIgb3B0aW9uc1xuICovXG52YXIgYWRkb25zID0gZnVuY3Rpb24odHJlZSwgYWRkb25zKSB7XG4gICAgT2JqZWN0LmtleXMoYWRkb25zIHx8IHt9KS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgIGlmIChrZXkgaW4gc3VwcG9ydGVkQWRkb25zKSB7XG4gICAgICAgICAgICBjb25zdCBhZGRvbk9wdCA9IHR5cGVvZiBhZGRvbnNba2V5XSA9PT0gJ29iamVjdCcgPyBhZGRvbnNba2V5XSA6IG51bGw7XG4gICAgICAgICAgICB0cmVlID0gdHJlZS51c2Uoc3VwcG9ydGVkQWRkb25zW2tleV0sIGFkZG9uT3B0KTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRyZWU7XG59O1xuXG4vKipcbiAqIEFwcGxpZXMgYmFzaWMgSFRNTC1zcGVjaWZpYyB0cmFuc2Zvcm1hdGlvbnMgZm9yIGdpdmVuIHBhcnNlZCBhYmJyZXZpYXRpb246XG4gKiDigJMgcmVzb2x2ZSBpbXBsaWVkIHRhZyBuYW1lc1xuICog4oCTIGluc2VydCByZXBlYXRlZCBjb250ZW50XG4gKiDigJMgcmVzb2x2ZSBub2RlIG51bWJlcmluZ1xuICovXG52YXIgaW5kZXggPSBmdW5jdGlvbih0cmVlLCBjb250ZW50LCBhcHBsaWVkQWRkb25zKSB7XG4gICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICBjb250ZW50ID0gW2NvbnRlbnRdO1xuICAgIH0gZWxzZSBpZiAoY29udGVudCAmJiB0eXBlb2YgY29udGVudCA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoY29udGVudCkpIHtcbiAgICAgICAgYXBwbGllZEFkZG9ucyA9IGNvbnRlbnQ7XG4gICAgICAgIGNvbnRlbnQgPSBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB0cmVlXG4gICAgLnVzZShpbXBsaWNpdFRhZ3MpXG4gICAgLnVzZShwcmVwYXJlLCBBcnJheS5pc0FycmF5KGNvbnRlbnQpID8gY29udGVudC5sZW5ndGggOiBudWxsKVxuICAgIC51c2UoYXBwbHlOdW1iZXJpbmcpXG4gICAgLnVzZShpbnNlcnQsIGNvbnRlbnQpXG4gICAgLnVzZShhZGRvbnMsIGFwcGxpZWRBZGRvbnMpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBpbmRleDtcbiJdfQ==
// Welcome! require() some modules from npm (like you were using browserify)
// and then hit Run Code to run your code on the right side.
// Modules get downloaded from browserify-cdn and bundled in your browser.
require('@emmetio/abbreviation');
require('@emmetio/html-transform');
;}, 0)
{
"name": "requirebin-sketch",
"version": "1.0.0",
"dependencies": {
"@emmetio/abbreviation": "0.6.0",
"@emmetio/html-transform": "0.3.1"
}
}
<!-- contents of this file will be placed inside the <body> -->
<!-- contents of this file will be placed inside the <head> -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment