From bdf7ba8a00d227ed92a06ceeff0c7bff505abe40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20M=C3=BCller?= Date: Mon, 11 May 2015 16:54:09 +0200 Subject: [PATCH] Built browser version --- unexpected-dom.js | 1062 +++++++++++++++++++++++++++++++++++------ unexpected-dom.min.js | 4 +- 2 files changed, 932 insertions(+), 134 deletions(-) diff --git a/unexpected-dom.js b/unexpected-dom.js index f6dc84e0..795c1645 100644 --- a/unexpected-dom.js +++ b/unexpected-dom.js @@ -42,6 +42,7 @@ function getClassNamesFromAttributeValue(attributeValue) { } function getAttributes(element) { + var isHtml = element.ownerDocument.contentType === 'text/html'; var attrs = element.attributes; var result = {}; @@ -51,7 +52,7 @@ function getAttributes(element) { } else if (attrs[i].name === 'style') { result[attrs[i].name] = styleStringToObject(attrs[i].value); } else { - result[attrs[i].name] = isBooleanAttribute(attrs[i].name) ? true : (attrs[i].value || ''); + result[attrs[i].name] = isHtml && isBooleanAttribute(attrs[i].name) ? true : (attrs[i].value || ''); } } @@ -77,9 +78,9 @@ function isVoidElement(elementName) { return (/(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)/i).test(elementName); } -function writeAttributeToMagicPen(output, attributeName, value) { - output['prism:attr-name'](attributeName); - if (!isBooleanAttribute(attributeName)) { +function writeAttributeToMagicPen(output, attributeName, value, isHtml) { + output.prismAttrName(attributeName); + if (!isHtml || !isBooleanAttribute(attributeName)) { if (attributeName === 'class') { value = value.join(' '); } else if (attributeName === 'style') { @@ -87,9 +88,10 @@ function writeAttributeToMagicPen(output, attributeName, value) { return cssProp + ': ' + value[cssProp]; }).join('; '); } - output['prism:punctuation']('="'); - output['prism:attr-value'](entitify(value)); - output['prism:punctuation']('"'); + output + .prismPunctuation('="') + .prismAttrValue(entitify(value)) + .prismPunctuation('"'); } } @@ -108,7 +110,7 @@ function stringifyAttribute(attributeName, value) { } function stringifyStartTag(element) { - var elementName = element.nodeName.toLowerCase(); + var elementName = element.ownerDocument.contentType === 'text/html' ? element.nodeName.toLowerCase() : element.nodeName; var str = '<' + elementName; var attrs = getCanonicalAttributes(element); @@ -121,8 +123,9 @@ function stringifyStartTag(element) { } function stringifyEndTag(element) { - var elementName = element.nodeName.toLowerCase(); - if (isVoidElement(elementName) && element.childNodes.length === 0) { + var isHtml = element.ownerDocument.contentType === 'text/html'; + var elementName = isHtml ? element.nodeName.toLowerCase() : element.nodeName; + if (isHtml && isVoidElement(elementName) && element.childNodes.length === 0) { return ''; } else { return ''; @@ -170,6 +173,7 @@ function diffNodeLists(actual, expected, output, diff, inspect, equal) { module.exports = { name: 'unexpected-dom', installInto: function (expect) { + expect.output.installPlugin(require('magicpen-prism')); var topLevelExpect = expect; expect.addType({ name: 'DOMNode', @@ -266,14 +270,14 @@ module.exports = { }); expect.addType({ - name: 'HTMLDocument', + name: 'DOMDocument', base: 'DOMNode', identify: function (obj) { return obj && typeof obj.nodeType === 'number' && obj.nodeType === 9 && obj.documentElement && obj.implementation; }, inspect: function (document, depth, output, inspect) { for (var i = 0 ; i < document.childNodes.length ; i += 1) { - output.append(inspect(document.childNodes[i])); + output.append(inspect(document.childNodes[i], depth - 1)); } }, diff: function (actual, expected, output, diff, inspect, equal) { @@ -287,7 +291,29 @@ module.exports = { }); expect.addType({ - name: 'HTMLElement', + name: 'HTMLDocument', + base: 'DOMDocument', + identify: function (obj) { + return this.baseType.identify(obj) && obj.contentType === 'text/html'; + } + }); + + expect.addType({ + name: 'XMLDocument', + base: 'DOMDocument', + identify: function (obj) { + return this.baseType.identify(obj) && /^(?:application|text)\/xml|\+xml\b/.test(obj.contentType); + }, + inspect: function (document, depth, output, inspect) { + output.code('', 'xml'); + for (var i = 0 ; i < document.childNodes.length ; i += 1) { + output.append(inspect(document.childNodes[i], depth - 1)); + } + } + }); + + expect.addType({ + name: 'DOMElement', base: 'DOMNode', identify: function (obj) { return obj && typeof obj.nodeType === 'number' && obj.nodeType === 1 && obj.nodeName && obj.attributes; @@ -343,6 +369,7 @@ module.exports = { }, diffLimit: 512, diff: function (actual, expected, output, diff, inspect, equal) { + var isHtml = actual.ownerDocument.contentType === 'text/html'; var result = { diff: output, inline: true @@ -358,11 +385,12 @@ module.exports = { if (conflictingElement) { var canContinueLine = true; - output['prism:punctuation']('<'); - output['prism:tag'](actual.nodeName.toLowerCase()); + output + .prismPunctuation('<') + .prismTag(actual.nodeName.toLowerCase()); if (actual.nodeName.toLowerCase() !== expected.nodeName.toLowerCase()) { output.sp().annotationBlock(function () { - this.error('should be').sp()['prism:tag'](expected.nodeName.toLowerCase()); + this.error('should be').sp().prismTag(expected.nodeName.toLowerCase()); }).nl(); canContinueLine = false; } @@ -370,7 +398,7 @@ module.exports = { var expectedAttributes = getAttributes(expected); Object.keys(actualAttributes).forEach(function (attributeName) { output.sp(canContinueLine ? 1 : 2 + actual.nodeName.length); - writeAttributeToMagicPen(output, attributeName, actualAttributes[attributeName]); + writeAttributeToMagicPen(output, attributeName, actualAttributes[attributeName], isHtml); if (attributeName in expectedAttributes) { if (actualAttributes[attributeName] === expectedAttributes[attributeName]) { canContinueLine = true; @@ -392,11 +420,11 @@ module.exports = { output.sp(canContinueLine ? 1 : 2 + actual.nodeName.length); output.annotationBlock(function () { this.error('missing').sp(); - writeAttributeToMagicPen(this, attributeName, expectedAttributes[attributeName]); + writeAttributeToMagicPen(this, attributeName, expectedAttributes[attributeName], isHtml); }).nl(); canContinueLine = false; }); - output['prism:punctuation']('>'); + output.prismPunctuation('>'); } else { output.code(stringifyStartTag(actual), 'html'); } @@ -412,7 +440,7 @@ module.exports = { } }); - expect.addAssertion('HTMLElement', 'to [only] have (class|classes)', function (expect, subject, value) { + expect.addAssertion('DOMElement', 'to [only] have (class|classes)', function (expect, subject, value) { var flags = this.flags; if (flags.only) { return expect(subject, 'to have attributes', { @@ -433,144 +461,203 @@ module.exports = { } }); - expect.addAssertion('HTMLElement', 'to [only] have (attribute|attributes)', function (expect, subject, value) { - var flags = this.flags; - var attrs = getAttributes(subject); + expect.addAssertion('DOMTextNode', 'to satisfy', function (expect, subject, value) { + return expect(subject.nodeValue, 'to satisfy', value); + }); - if (typeof value === 'string') { - value = Array.prototype.slice.call(arguments, 2); - } - var expectedValueByAttributeName = {}; - if (Array.isArray(value)) { - value.forEach(function (attributeName) { - expectedValueByAttributeName[attributeName] = true; + expect.addAssertion('DOMElement', 'to satisfy', function (expect, subject, value) { + var isHtml = subject.ownerDocument.contentType === 'text/html'; + if (value && typeof value === 'object') { + var unsupportedOptions = Object.keys(value).filter(function (key) { + return key !== 'attributes' && key !== 'name' && key !== 'children' && key !== 'onlyAttributes'; }); - } else if (value && typeof value === 'object') { - expectedValueByAttributeName = value; - } else { - throw new Error('to have attributes: Argument must be a string, an array, or an object'); - } - var expectedValueByLowerCasedAttributeName = {}, - expectedAttributeNames = []; - Object.keys(expectedValueByAttributeName).forEach(function (attributeName) { - var lowerCasedAttributeName = attributeName.toLowerCase(); - expectedAttributeNames.push(lowerCasedAttributeName); - if (expectedValueByLowerCasedAttributeName.hasOwnProperty(lowerCasedAttributeName)) { - throw new Error('Duplicate expected attribute with different casing: ' + attributeName); + if (unsupportedOptions.length > 0) { + throw new Error('Unsupported option' + (unsupportedOptions.length === 1 ? '' : 's') + ': ' + unsupportedOptions.join(', ')); } - expectedValueByLowerCasedAttributeName[lowerCasedAttributeName] = expectedValueByAttributeName[attributeName]; - }); - expectedValueByAttributeName = expectedValueByLowerCasedAttributeName; + } var promiseByKey = { - presence: expect.promise(function () { - var attributeNamesExpectedToBeDefined = []; - expectedAttributeNames.forEach(function (attributeName) { - if (typeof expectedValueByAttributeName[attributeName] === 'undefined') { - expect(attrs, 'not to have key', attributeName); - } else { - attributeNamesExpectedToBeDefined.push(attributeName); - expect(attrs, 'to have key', attributeName); - } - }); - if (flags.only) { - expect(Object.keys(attrs).sort(), 'to equal', attributeNamesExpectedToBeDefined.sort()); + name: expect.promise(function () { + if (value && typeof value.name !== 'undefined') { + return topLevelExpect(isHtml ? subject.nodeName.toLowerCase() : subject.nodeName, 'to satisfy', value.name); + } + }), + children: expect.promise(function () { + if (typeof value.children !== 'undefined') { + return topLevelExpect(subject.childNodes, 'to satisfy', value.children); } }), attributes: {} }; - expectedAttributeNames.forEach(function (attributeName) { - var attributeValue = subject.getAttribute(attributeName); - var expectedAttributeValue = expectedValueByAttributeName[attributeName]; - promiseByKey.attributes[attributeName] = expect.promise(function () { - if (attributeName === 'class' && (typeof expectedAttributeValue === 'string' || Array.isArray(expectedAttributeValue))) { - var actualClasses = getClassNamesFromAttributeValue(attributeValue); - var expectedClasses = expectedAttributeValue; - if (typeof expectedClasses === 'string') { - expectedClasses = getClassNamesFromAttributeValue(expectedAttributeValue); - } - if (flags.only) { - return topLevelExpect(actualClasses.sort(), 'to equal', expectedClasses.sort()); - } else { - return topLevelExpect.apply(topLevelExpect, [actualClasses, 'to contain'].concat(expectedClasses)); - } - } else if (attributeName === 'style') { - var expectedStyleObj; - if (typeof expectedValueByAttributeName.style === 'string') { - expectedStyleObj = styleStringToObject(expectedValueByAttributeName.style); + var onlyAttributes = value && value.onlyAttributes; + var attrs = getAttributes(subject); + var expectedAttributes = value && value.attributes; + var expectedAttributeNames = []; + + if (typeof expectedAttributes !== 'undefined') { + if (typeof expectedAttributes === 'string') { + expectedAttributes = [expectedAttributes]; + } + var expectedValueByAttributeName = {}; + if (Array.isArray(expectedAttributes)) { + expectedAttributes.forEach(function (attributeName) { + expectedValueByAttributeName[attributeName] = true; + }); + } else if (expectedAttributes && typeof expectedAttributes === 'object') { + expectedValueByAttributeName = expectedAttributes; + } + Object.keys(expectedValueByAttributeName).forEach(function (attributeName) { + expectedAttributeNames.push(attributeName); + }); + + expectedAttributeNames.forEach(function (attributeName) { + var attributeValue = subject.getAttribute(attributeName); + var expectedAttributeValue = expectedValueByAttributeName[attributeName]; + promiseByKey.attributes[attributeName] = expect.promise(function () { + if (attributeName === 'class' && (typeof expectedAttributeValue === 'string' || Array.isArray(expectedAttributeValue))) { + var actualClasses = getClassNamesFromAttributeValue(attributeValue); + var expectedClasses = expectedAttributeValue; + if (typeof expectedClasses === 'string') { + expectedClasses = getClassNamesFromAttributeValue(expectedAttributeValue); + } + if (onlyAttributes) { + return topLevelExpect(actualClasses.sort(), 'to equal', expectedClasses.sort()); + } else { + return topLevelExpect.apply(topLevelExpect, [actualClasses, 'to contain'].concat(expectedClasses)); + } + } else if (attributeName === 'style') { + var expectedStyleObj; + if (typeof expectedValueByAttributeName.style === 'string') { + expectedStyleObj = styleStringToObject(expectedValueByAttributeName.style); + } else { + expectedStyleObj = expectedValueByAttributeName.style; + } + + if (onlyAttributes) { + return topLevelExpect(attrs.style, 'to exhaustively satisfy', expectedStyleObj); + } else { + return topLevelExpect(attrs.style, 'to satisfy', expectedStyleObj); + } + } else if (expectedAttributeValue === true) { + expect(subject.hasAttribute(attributeName), 'to be true'); } else { - expectedStyleObj = expectedValueByAttributeName.style; + return topLevelExpect(attributeValue, 'to satisfy', expectedAttributeValue); } + }); + }); - if (flags.only) { - return topLevelExpect(attrs.style, 'to exhaustively satisfy', expectedStyleObj); + promiseByKey.attributePresence = expect.promise(function () { + var attributeNamesExpectedToBeDefined = []; + expectedAttributeNames.forEach(function (attributeName) { + if (typeof expectedValueByAttributeName[attributeName] === 'undefined') { + expect(attrs, 'not to have key', attributeName); } else { - return topLevelExpect(attrs.style, 'to satisfy', expectedStyleObj); + attributeNamesExpectedToBeDefined.push(attributeName); + expect(attrs, 'to have key', attributeName); } - } else if (expectedAttributeValue === true) { - expect(subject.hasAttribute(attributeName), 'to be true'); - } else { - return topLevelExpect(attributeValue, 'to satisfy', expectedAttributeValue); + }); + if (onlyAttributes) { + expect(Object.keys(attrs).sort(), 'to equal', attributeNamesExpectedToBeDefined.sort()); } }); - }); + } return expect.promise.all(promiseByKey).caught(function () { return expect.promise.settle(promiseByKey).then(function () { expect.fail({ diff: function (output, diff, inspect, equal) { - output['prism:punctuation']('<')['prism:tag'](subject.nodeName.toLowerCase()); - var canContinueLine = true; - Object.keys(attrs).forEach(function (attributeName) { - var lowerCaseAttributeName = attributeName.toLowerCase(); - var promise = promiseByKey.attributes[lowerCaseAttributeName]; - output.sp(canContinueLine ? 1 : 2 + subject.nodeName.length); - writeAttributeToMagicPen(output, attributeName, attrs[attributeName]); - if ((promise && promise.isFulfilled()) || (!promise && (!flags.only || expectedAttributeNames.indexOf(lowerCaseAttributeName) !== -1))) { - canContinueLine = true; - } else { - output - .sp() - .annotationBlock(function () { - if (promise) { - this.append(promise.reason().output); // v8: getErrorMessage - } else { - // flags.only === true - this.error('should be removed'); - } - }) - .nl(); + output.block(function () { + var output = this; + output + .prismPunctuation('<') + .prismTag(isHtml ? subject.nodeName.toLowerCase() : subject.nodeName); + var canContinueLine = true; + if (promiseByKey.name.isRejected()) { + var nameError = promiseByKey.name.reason(); + output.sp().annotationBlock(function () { + this + .error((nameError && nameError.label) || 'should satisfy') // v8: err.getLabel() + .sp() + .append(inspect(value.name)); + }).nl(); canContinueLine = false; } - }); - expectedAttributeNames.forEach(function (attributeName) { - if (!subject.hasAttribute(attributeName)) { + Object.keys(attrs).forEach(function (attributeName) { var promise = promiseByKey.attributes[attributeName]; - if (!promise || promise.isRejected()) { - var err = promise && promise.reason(); + output.sp(canContinueLine ? 1 : 2 + subject.nodeName.length); + writeAttributeToMagicPen(output, attributeName, attrs[attributeName], isHtml); + if ((promise && promise.isFulfilled()) || (!promise && (!onlyAttributes || expectedAttributeNames.indexOf(attributeName) !== -1))) { + canContinueLine = true; + } else { output - .nl() - .sp(2 + subject.nodeName.length) + .sp() .annotationBlock(function () { - this - .error('missing') - .sp() - ['prism:attr-name'](attributeName, 'html'); - if (expectedValueByAttributeName[attributeName] !== true) { - this - .sp() - .error((err && err.label) || 'should satisfy') // v8: err.getLabel() - .sp() - .append(inspect(expectedValueByAttributeName[attributeName])); + if (promise) { + this.append(promise.reason().output); // v8: getErrorMessage + } else { + // onlyAttributes === true + this.error('should be removed'); } }) .nl(); + canContinueLine = false; + } + }); + expectedAttributeNames.forEach(function (attributeName) { + if (!subject.hasAttribute(attributeName)) { + var promise = promiseByKey.attributes[attributeName]; + if (!promise || promise.isRejected()) { + var err = promise && promise.reason(); + output + .nl() + .sp(2 + subject.nodeName.length) + .annotationBlock(function () { + this + .error('missing') + .sp() + .prismAttrName(attributeName, 'html'); + if (expectedValueByAttributeName[attributeName] !== true) { + this + .sp() + .error((err && err.label) || 'should satisfy') // v8: err.getLabel() + .sp() + .append(inspect(expectedValueByAttributeName[attributeName])); + } + }) + .nl(); + } + canContinueLine = false; + } + }); + output.prismPunctuation('>'); + var childrenError = promiseByKey.children.isRejected() && promiseByKey.children.reason(); + var childrenDiff = childrenError && childrenError.createDiff && childrenError.createDiff(output.clone(), diff, inspect, equal); + if (childrenError) { + output + .nl() + .indentLines() + .i().block(function () { + for (var i = 0 ; i < subject.childNodes.length ; i += 1) { + this.append(inspect(subject.childNodes[i])).nl(); + } + }); + if (childrenError) { + output.sp().annotationBlock(function () { // v8: childrenError.getErrorMessage() + this.append(childrenError.output); + if (childrenDiff && childrenDiff.diff) { + this.nl(2).append(childrenDiff.diff); + } + }); + } + output.nl(); + } else { + for (var i = 0 ; i < subject.childNodes.length ; i += 1) { + this.append(inspect(subject.childNodes[i])); } - canContinueLine = false; } + output.code(stringifyEndTag(subject), 'html'); }); - output['prism:punctuation']('>'); return { inline: true, diff: output @@ -581,7 +668,18 @@ module.exports = { }); }); - expect.addAssertion('HTMLElement', 'to have [no] (child|children)', function (expect, subject, query, cmp) { + expect.addAssertion('DOMElement', 'to [only] have (attribute|attributes)', function (expect, subject, value) { + if (typeof value === 'string') { + if (arguments.length > 3) { + value = Array.prototype.slice.call(arguments, 2); + } + } else if (!value || typeof value !== 'object') { + throw new Error('to have attributes: Argument must be a string, an array, or an object'); + } + return expect(subject, 'to satisfy', { attributes: value, onlyAttributes: this.flags.only }); + }); + + expect.addAssertion('DOMElement', 'to have [no] (child|children)', function (expect, subject, query, cmp) { if (this.flags.no) { this.errorMode = 'nested'; return expect(Array.prototype.slice.call(subject.childNodes), 'to be an empty array'); @@ -591,11 +689,11 @@ module.exports = { } }); - expect.addAssertion('HTMLElement', 'to have text', function (expect, subject, value) { + expect.addAssertion('DOMElement', 'to have text', function (expect, subject, value) { return expect(subject.textContent, 'to satisfy', value); }); - expect.addAssertion(['HTMLDocument', 'HTMLElement'], 'queried for [first]', function (expect, subject, value) { + expect.addAssertion(['DOMDocument', 'DOMElement'], 'queried for [first]', function (expect, subject, value) { var queryResult; this.errorMode = 'nested'; @@ -615,10 +713,11 @@ module.exports = { }); } } - this.shift(expect, queryResult, 1); + return this.shift(expect, queryResult, 1); }); expect.addAssertion('string', 'when parsed as (html|HTML)', function (expect, subject) { + this.errorMode = 'nested'; var htmlDocument; if (typeof DOMParser !== 'undefined') { htmlDocument = new DOMParser().parseFromString(subject, 'text/html'); @@ -631,15 +730,30 @@ module.exports = { try { htmlDocument = require('jsdom').jsdom(subject); } catch (err) { - throw new Error('The assertion `when parsed as html` was run outside a browser, but could not find the `jsdom` module. Please npm install jsdom to make this work.'); + throw new Error('The assertion `' + this.testDescription + '` was run outside a browser, but could not find the `jsdom` module. Please npm install jsdom to make this work.'); } } return this.shift(expect, htmlDocument, 0); }); + + expect.addAssertion('string', 'when parsed as (xml|XML)', function (expect, subject) { + this.errorMode = 'nested'; + var xmlDocument; + if (typeof DOMParser !== 'undefined') { + xmlDocument = new DOMParser().parseFromString(subject, 'text/xml'); + } else { + try { + xmlDocument = require('jsdom').jsdom(subject, { parsingMode: 'xml' }); + } catch (err) { + throw new Error('The assertion `' + this.testDescription + '` was outside a browser (or in a browser without DOMParser), but could not find the `jsdom` module. Please npm install jsdom to make this work.'); + } + } + return this.shift(expect, xmlDocument, 0); + }); } }; -},{"array-changes":2,"jsdom":"jsdom"}],2:[function(require,module,exports){ +},{"array-changes":2,"jsdom":"jsdom","magicpen-prism":5}],2:[function(require,module,exports){ var arrayDiff = require('arraydiff'); function extend(target) { @@ -989,6 +1103,688 @@ function arrayDiff(before, after, equalFn) { return removes.concat(outputMoves, inserts); } -},{}]},{},[1])(1) +},{}],4:[function(require,module,exports){ + + +/* ********************************************** + Begin prism-core.js +********************************************** */ + +var self = (typeof window !== 'undefined') ? window : {}; + +/** + * Prism: Lightweight, robust, elegant syntax highlighting + * MIT license http://www.opensource.org/licenses/mit-license.php/ + * @author Lea Verou http://lea.verou.me + */ + +var Prism = (function(){ + +// Private helper vars +var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i; + +var _ = self.Prism = { + util: { + type: function (o) { + return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]; + }, + + // Deep clone a language definition (e.g. to extend it) + clone: function (o) { + var type = _.util.type(o); + + switch (type) { + case 'Object': + var clone = {}; + + for (var key in o) { + if (o.hasOwnProperty(key)) { + clone[key] = _.util.clone(o[key]); + } + } + + return clone; + + case 'Array': + return o.slice(); + } + + return o; + } + }, + + languages: { + extend: function (id, redef) { + var lang = _.util.clone(_.languages[id]); + + for (var key in redef) { + lang[key] = redef[key]; + } + + return lang; + }, + + // Insert a token before another token in a language literal + insertBefore: function (inside, before, insert, root) { + root = root || _.languages; + var grammar = root[inside]; + var ret = {}; + + for (var token in grammar) { + + if (grammar.hasOwnProperty(token)) { + + if (token == before) { + + for (var newToken in insert) { + + if (insert.hasOwnProperty(newToken)) { + ret[newToken] = insert[newToken]; + } + } + } + + ret[token] = grammar[token]; + } + } + + return root[inside] = ret; + }, + + // Traverse a language definition with Depth First Search + DFS: function(o, callback) { + for (var i in o) { + callback.call(o, i, o[i]); + + if (_.util.type(o) === 'Object') { + _.languages.DFS(o[i], callback); + } + } + } + }, + + highlightAll: function(async, callback) { + var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'); + + for (var i=0, element; element = elements[i++];) { + _.highlightElement(element, async === true, callback); + } + }, + + highlightElement: function(element, async, callback) { + // Find language + var language, grammar, parent = element; + + while (parent && !lang.test(parent.className)) { + parent = parent.parentNode; + } + + if (parent) { + language = (parent.className.match(lang) || [,''])[1]; + grammar = _.languages[language]; + } + + if (!grammar) { + return; + } + + // Set language on the element, if not present + element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; + + // Set language on the parent, for styling + parent = element.parentNode; + + if (/pre/i.test(parent.nodeName)) { + parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; + } + + var code = element.textContent; + + if(!code) { + return; + } + + code = code.replace(/&/g, '&').replace(/ text.length) { + // Something went terribly wrong, ABORT, ABORT! + break tokenloop; + } + + if (str instanceof Token) { + continue; + } + + pattern.lastIndex = 0; + + var match = pattern.exec(str); + + if (match) { + if(lookbehind) { + lookbehindLength = match[1].length; + } + + var from = match.index - 1 + lookbehindLength, + match = match[0].slice(lookbehindLength), + len = match.length, + to = from + len, + before = str.slice(0, from + 1), + after = str.slice(to + 1); + + var args = [i, 1]; + + if (before) { + args.push(before); + } + + var wrapped = new Token(token, inside? _.tokenize(match, inside) : match); + + args.push(wrapped); + + if (after) { + args.push(after); + } + + Array.prototype.splice.apply(strarr, args); + } + } + } + + return strarr; + }, + + hooks: { + all: {}, + + add: function (name, callback) { + var hooks = _.hooks.all; + + hooks[name] = hooks[name] || []; + + hooks[name].push(callback); + }, + + run: function (name, env) { + var callbacks = _.hooks.all[name]; + + if (!callbacks || !callbacks.length) { + return; + } + + for (var i=0, callback; callback = callbacks[i++];) { + callback(env); + } + } + } +}; + +var Token = _.Token = function(type, content) { + this.type = type; + this.content = content; +}; + +Token.stringify = function(o, language, parent) { + if (typeof o == 'string') { + return o; + } + + if (Object.prototype.toString.call(o) == '[object Array]') { + return o.map(function(element) { + return Token.stringify(element, language, o); + }).join(''); + } + + var env = { + type: o.type, + content: Token.stringify(o.content, language, parent), + tag: 'span', + classes: ['token', o.type], + attributes: {}, + language: language, + parent: parent + }; + + if (env.type == 'comment') { + env.attributes['spellcheck'] = 'true'; + } + + _.hooks.run('wrap', env); + + var attributes = ''; + + for (var name in env.attributes) { + attributes += name + '="' + (env.attributes[name] || '') + '"'; + } + + return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + ''; + +}; + +if (!self.document) { + if (!self.addEventListener) { + // in Node.js + return self.Prism; + } + // In worker + self.addEventListener('message', function(evt) { + var message = JSON.parse(evt.data), + lang = message.language, + code = message.code; + + self.postMessage(JSON.stringify(_.tokenize(code, _.languages[lang]))); + self.close(); + }, false); + + return self.Prism; +} + +// Get current script and highlight +var script = document.getElementsByTagName('script'); + +script = script[script.length - 1]; + +if (script) { + _.filename = script.src; + + if (document.addEventListener && !script.hasAttribute('data-manual')) { + document.addEventListener('DOMContentLoaded', _.highlightAll); + } +} + +return self.Prism; + +})(); + +if (typeof module !== 'undefined' && module.exports) { + module.exports = Prism; +} + +/* ********************************************** + Begin prism-markup.js +********************************************** */ + +Prism.languages.markup = { + 'comment': /<!--[\w\W]*?-->/g, + 'prolog': /<\?.+?\?>/, + 'doctype': /<!DOCTYPE.+?>/, + 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i, + 'tag': { + pattern: /<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi, + inside: { + 'tag': { + pattern: /^<\/?[\w:-]+/i, + inside: { + 'punctuation': /^<\/?/, + 'namespace': /^[\w-]+?:/ + } + }, + 'attr-value': { + pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi, + inside: { + 'punctuation': /=|>|"/g + } + }, + 'punctuation': /\/?>/g, + 'attr-name': { + pattern: /[\w:-]+/g, + inside: { + 'namespace': /^[\w-]+?:/ + } + } + + } + }, + 'entity': /&#?[\da-z]{1,8};/gi +}; + +// Plugin to make entity title show the real entity, idea by Roman Komarov +Prism.hooks.add('wrap', function(env) { + + if (env.type === 'entity') { + env.attributes['title'] = env.content.replace(/&/, '&'); + } +}); + + +/* ********************************************** + Begin prism-css.js +********************************************** */ + +Prism.languages.css = { + 'comment': /\/\*[\w\W]*?\*\//g, + 'atrule': { + pattern: /@[\w-]+?.*?(;|(?=\s*{))/gi, + inside: { + 'punctuation': /[;:]/g + } + }, + 'url': /url\((["']?).*?\1\)/gi, + 'selector': /[^\{\}\s][^\{\};]*(?=\s*\{)/g, + 'property': /(\b|\B)[\w-]+(?=\s*:)/ig, + 'string': /("|')(\\?.)*?\1/g, + 'important': /\B!important\b/gi, + 'ignore': /&(lt|gt|amp);/gi, + 'punctuation': /[\{\};:]/g +}; + +if (Prism.languages.markup) { + Prism.languages.insertBefore('markup', 'tag', { + 'style': { + pattern: /(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig, + inside: { + 'tag': { + pattern: /(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig, + inside: Prism.languages.markup.tag.inside + }, + rest: Prism.languages.css + } + } + }); +} + +/* ********************************************** + Begin prism-clike.js +********************************************** */ + +Prism.languages.clike = { + 'comment': { + pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g, + lookbehind: true + }, + 'string': /("|')(\\?.)*?\1/g, + 'class-name': { + pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig, + lookbehind: true, + inside: { + punctuation: /(\.|\\)/ + } + }, + 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g, + 'boolean': /\b(true|false)\b/g, + 'function': { + pattern: /[a-z0-9_]+\(/ig, + inside: { + punctuation: /\(/ + } + }, + 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g, + 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g, + 'ignore': /&(lt|gt|amp);/gi, + 'punctuation': /[{}[\];(),.:]/g +}; + + +/* ********************************************** + Begin prism-javascript.js +********************************************** */ + +Prism.languages.javascript = Prism.languages.extend('clike', { + 'keyword': /\b(var|let|if|else|while|do|for|return|in|instanceof|function|get|set|new|with|typeof|try|throw|catch|finally|null|break|continue|this)\b/g, + 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g +}); + +Prism.languages.insertBefore('javascript', 'keyword', { + 'regex': { + pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g, + lookbehind: true + } +}); + +if (Prism.languages.markup) { + Prism.languages.insertBefore('markup', 'tag', { + 'script': { + pattern: /(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig, + inside: { + 'tag': { + pattern: /(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig, + inside: Prism.languages.markup.tag.inside + }, + rest: Prism.languages.javascript + } + } + }); +} + + +/* ********************************************** + Begin prism-file-highlight.js +********************************************** */ + +(function(){ + +if (!self.Prism || !self.document || !document.querySelector) { + return; +} + +var Extensions = { + 'js': 'javascript', + 'html': 'markup', + 'svg': 'markup' +}; + +Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function(pre) { + var src = pre.getAttribute('data-src'); + var extension = (src.match(/\.(\w+)$/) || [,''])[1]; + var language = Extensions[extension] || extension; + + var code = document.createElement('code'); + code.className = 'language-' + language; + + pre.textContent = ''; + + code.textContent = 'Loading…'; + + pre.appendChild(code); + + var xhr = new XMLHttpRequest(); + + xhr.open('GET', src, true); + + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + + if (xhr.status < 400 && xhr.responseText) { + code.textContent = xhr.responseText; + + Prism.highlightElement(code); + } + else if (xhr.status >= 400) { + code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText; + } + else { + code.textContent = '✖ Error: File does not exist or is empty'; + } + } + }; + + xhr.send(null); +}); + +})(); +},{}],5:[function(require,module,exports){ +var prism = require('../3rdparty/prism'), + defaultTheme = { + // Adapted from the default Prism theme: + prismComment: '#708090', // slategray + prismProlog: 'prismComment', + prismDoctype: 'prismComment', + prismCdata: 'prismComment', + + prismPunctuation: '#999', + + prismSymbol: '#905', + prismProperty: 'prismSymbol', + prismTag: 'prismSymbol', + prismBoolean: 'prismSymbol', + prismNumber: 'prismSymbol', + prismConstant: 'prismSymbol', + prismDeleted: 'prismSymbol', + + prismString: '#690', + prismSelector: 'prismString', + prismAttrName: 'prismString', + prismChar: 'prismString', + prismBuiltin: 'prismString', + prismInserted: 'prismString', + + prismOperator: '#a67f59', + prismVariable: 'prismOperator', + prismEntity: 'prismOperator', + prismUrl: 'prismOperator', + prismCssString: 'prismOperator', + + prismKeyword: '#07a', + prismAtrule: 'prismKeyword', + prismAttrValue: 'prismKeyword', + + prismFunction: '#DD4A68', + + prismRegex: '#e90', + prismImportant: ['#e90', 'bold'] + }, + languageMapping = { + 'text/html': 'markup', + 'application/xml': 'markup', + 'text/xml': 'markup', + 'application/json': 'javascript', + 'text/javascript': 'javascript', + 'application/javascript': 'javascript', + 'text/css': 'css', + html: 'markup', + xml: 'markup', + c: 'clike', + 'c++': 'clike', + 'cpp': 'clike', + 'c#': 'clike', + java: 'clike' + }; + +function upperCamelCase(str) { + return str.replace(/(?:^|-)([a-z])/g, function ($0, ch) { + return ch.toUpperCase(); + }); +} + +module.exports = { + name: 'magicpen-prism', + installInto: function (magicPen) { + magicPen.installTheme(defaultTheme); + + magicPen.addStyle('code', function (sourceText, language) { + if (language in languageMapping) { + language = languageMapping[language]; + } else if (/\+xml\b/.test(language)) { + language = 'markup'; + } + if (!(language in prism.languages)) { + return this.text(sourceText); + } + + sourceText = sourceText.replace(/"}}function diffNodeLists(actual,expected,output,diff,inspect,equal){var changes=arrayChanges(Array.prototype.slice.call(actual),Array.prototype.slice.call(expected),equal,function(a,b){return a.nodeType===1&&b.nodeType===1&&a.nodeName===b.nodeName});changes.forEach(function(diffItem,index){output.i().block(function(){var type=diffItem.type;if(type==="insert"){this.annotationBlock(function(){this.error("missing ").block(inspect(diffItem.value))})}else if(type==="remove"){this.block(inspect(diffItem.value).sp().error("// should be removed"))}else if(type==="equal"){this.block(inspect(diffItem.value))}else{var valueDiff=diff(diffItem.value,diffItem.expected);if(valueDiff&&valueDiff.inline){this.block(valueDiff.diff)}else if(valueDiff){this.block(inspect(diffItem.value).sp()).annotationBlock(function(){this.shouldEqualError(diffItem.expected,inspect).nl().append(valueDiff.diff)})}else{this.block(inspect(diffItem.value).sp()).annotationBlock(function(){this.shouldEqualError(diffItem.expected,inspect)})}}}).nl(index-1},equal:function(a,b){return a.nodeValue===b.nodeValue},inspect:function(element,depth,output){return output.code(element.nodeName+' "'+element.nodeValue+'"',"prism-string")}});expect.addType({name:"DOMComment",base:"DOMNode",identify:function(obj){return obj&&typeof obj.nodeType==="number"&&obj.nodeType===8},equal:function(a,b){return a.nodeValue===b.nodeValue},inspect:function(element,depth,output){return output.code("","html")},diff:function(actual,expected,output,diff,inspect,equal){var d=diff("","");d.inline=true;return d}});expect.addType({name:"DOMTextNode",base:"DOMNode",identify:function(obj){return obj&&typeof obj.nodeType==="number"&&obj.nodeType===3},equal:function(a,b){return a.nodeValue.trim()===b.nodeValue.trim()},inspect:function(element,depth,output){return output.code(entitify(element.nodeValue.trim()),"html")},diff:function(actual,expected,output,diff,inspect,equal){var d=diff(actual.nodeValue,expected.nodeValue);d.inline=true;return d}});expect.addType({name:"DOMNodeList",base:"array-like",prefix:function(output){return output.text("NodeList[")},suffix:function(output){return output.text("]")},delimiter:function(output){return output.text("delimiter")},identify:function(obj){return obj&&typeof obj.length==="number"&&typeof obj.toString==="function"&&typeof obj.item==="function"&&obj.toString().indexOf("NodeList")!==-1}});expect.addType({name:"HTMLDocType",base:"DOMNode",identify:function(obj){return obj&&typeof obj.nodeType==="number"&&obj.nodeType===10&&"publicId"in obj},inspect:function(doctype,depth,output,inspect){output.code("","html")},equal:function(a,b){return a.toString()===b.toString()},diff:function(actual,expected,output,diff){var d=diff("","");d.inline=true;return d}});expect.addType({name:"HTMLDocument",base:"DOMNode",identify:function(obj){return obj&&typeof obj.nodeType==="number"&&obj.nodeType===9&&obj.documentElement&&obj.implementation},inspect:function(document,depth,output,inspect){for(var i=0;i50||o.height>1});output.code(startTag,"html");if(element.childNodes.length>0){if(multipleLines){output.nl().indentLines();inspectedChildren.forEach(function(inspectedChild,index){output.i().block(inspectedChild).nl()});output.outdentLines()}else{inspectedChildren.forEach(function(inspectedChild,index){output.append(inspectedChild)})}}output.code(stringifyEndTag(element),"html");return output},diffLimit:512,diff:function(actual,expected,output,diff,inspect,equal){var result={diff:output,inline:true};if(Math.max(actual.length,expected.length)>this.diffLimit){result.diff.jsComment("Diff suppressed due to size > "+this.diffLimit);return result}var emptyElements=actual.childNodes.length===0&&expected.childNodes.length===0;var conflictingElement=actual.nodeName.toLowerCase()!==expected.nodeName.toLowerCase()||!equal(getAttributes(actual),getAttributes(expected));if(conflictingElement){var canContinueLine=true;output["prism:punctuation"]("<");output["prism:tag"](actual.nodeName.toLowerCase());if(actual.nodeName.toLowerCase()!==expected.nodeName.toLowerCase()){output.sp().annotationBlock(function(){this.error("should be").sp()["prism:tag"](expected.nodeName.toLowerCase())}).nl();canContinueLine=false}var actualAttributes=getAttributes(actual);var expectedAttributes=getAttributes(expected);Object.keys(actualAttributes).forEach(function(attributeName){output.sp(canContinueLine?1:2+actual.nodeName.length);writeAttributeToMagicPen(output,attributeName,actualAttributes[attributeName]);if(attributeName in expectedAttributes){if(actualAttributes[attributeName]===expectedAttributes[attributeName]){canContinueLine=true}else{output.sp().annotationBlock(function(){this.error("should equal").sp().append(inspect(entitify(expectedAttributes[attributeName])))}).nl();canContinueLine=false}delete expectedAttributes[attributeName]}else{output.sp().annotationBlock(function(){this.error("should be removed")}).nl();canContinueLine=false}});Object.keys(expectedAttributes).forEach(function(attributeName){output.sp(canContinueLine?1:2+actual.nodeName.length);output.annotationBlock(function(){this.error("missing").sp();writeAttributeToMagicPen(this,attributeName,expectedAttributes[attributeName])}).nl();canContinueLine=false});output["prism:punctuation"](">")}else{output.code(stringifyStartTag(actual),"html")}if(!emptyElements){output.nl().indentLines();diffNodeLists(actual.childNodes,expected.childNodes,output,diff,inspect,equal);output.nl().outdentLines()}output.code(stringifyEndTag(actual),"html");return result}});expect.addAssertion("HTMLElement","to [only] have (class|classes)",function(expect,subject,value){var flags=this.flags;if(flags.only){return expect(subject,"to have attributes",{"class":function(className){var actualClasses=getClassNamesFromAttributeValue(className);if(typeof value==="string"){value=getClassNamesFromAttributeValue(value)}if(flags.only){return topLevelExpect(actualClasses.sort(),"to equal",value.sort())}else{return topLevelExpect.apply(topLevelExpect,[actualClasses,"to contain"].concat(value))}}})}else{return expect(subject,"to have attributes",{"class":value})}});expect.addAssertion("HTMLElement","to [only] have (attribute|attributes)",function(expect,subject,value){var flags=this.flags;var attrs=getAttributes(subject);if(typeof value==="string"){value=Array.prototype.slice.call(arguments,2)}var expectedValueByAttributeName={};if(Array.isArray(value)){value.forEach(function(attributeName){expectedValueByAttributeName[attributeName]=true})}else if(value&&typeof value==="object"){expectedValueByAttributeName=value}else{throw new Error("to have attributes: Argument must be a string, an array, or an object")}var expectedValueByLowerCasedAttributeName={},expectedAttributeNames=[];Object.keys(expectedValueByAttributeName).forEach(function(attributeName){var lowerCasedAttributeName=attributeName.toLowerCase();expectedAttributeNames.push(lowerCasedAttributeName);if(expectedValueByLowerCasedAttributeName.hasOwnProperty(lowerCasedAttributeName)){throw new Error("Duplicate expected attribute with different casing: "+attributeName)}expectedValueByLowerCasedAttributeName[lowerCasedAttributeName]=expectedValueByAttributeName[attributeName]});expectedValueByAttributeName=expectedValueByLowerCasedAttributeName;var promiseByKey={presence:expect.promise(function(){var attributeNamesExpectedToBeDefined=[];expectedAttributeNames.forEach(function(attributeName){if(typeof expectedValueByAttributeName[attributeName]==="undefined"){expect(attrs,"not to have key",attributeName)}else{attributeNamesExpectedToBeDefined.push(attributeName);expect(attrs,"to have key",attributeName)}});if(flags.only){expect(Object.keys(attrs).sort(),"to equal",attributeNamesExpectedToBeDefined.sort())}}),attributes:{}};expectedAttributeNames.forEach(function(attributeName){var attributeValue=subject.getAttribute(attributeName);var expectedAttributeValue=expectedValueByAttributeName[attributeName];promiseByKey.attributes[attributeName]=expect.promise(function(){if(attributeName==="class"&&(typeof expectedAttributeValue==="string"||Array.isArray(expectedAttributeValue))){var actualClasses=getClassNamesFromAttributeValue(attributeValue);var expectedClasses=expectedAttributeValue;if(typeof expectedClasses==="string"){expectedClasses=getClassNamesFromAttributeValue(expectedAttributeValue)}if(flags.only){return topLevelExpect(actualClasses.sort(),"to equal",expectedClasses.sort())}else{return topLevelExpect.apply(topLevelExpect,[actualClasses,"to contain"].concat(expectedClasses))}}else if(attributeName==="style"){var expectedStyleObj;if(typeof expectedValueByAttributeName.style==="string"){expectedStyleObj=styleStringToObject(expectedValueByAttributeName.style)}else{expectedStyleObj=expectedValueByAttributeName.style}if(flags.only){return topLevelExpect(attrs.style,"to exhaustively satisfy",expectedStyleObj)}else{return topLevelExpect(attrs.style,"to satisfy",expectedStyleObj)}}else if(expectedAttributeValue===true){expect(subject.hasAttribute(attributeName),"to be true")}else{return topLevelExpect(attributeValue,"to satisfy",expectedAttributeValue)}})});return expect.promise.all(promiseByKey).caught(function(){return expect.promise.settle(promiseByKey).then(function(){expect.fail({diff:function(output,diff,inspect,equal){output["prism:punctuation"]("<")["prism:tag"](subject.nodeName.toLowerCase());var canContinueLine=true;Object.keys(attrs).forEach(function(attributeName){var lowerCaseAttributeName=attributeName.toLowerCase();var promise=promiseByKey.attributes[lowerCaseAttributeName];output.sp(canContinueLine?1:2+subject.nodeName.length);writeAttributeToMagicPen(output,attributeName,attrs[attributeName]);if(promise&&promise.isFulfilled()||!promise&&(!flags.only||expectedAttributeNames.indexOf(lowerCaseAttributeName)!==-1)){canContinueLine=true}else{output.sp().annotationBlock(function(){if(promise){this.append(promise.reason().output)}else{this.error("should be removed")}}).nl();canContinueLine=false}});expectedAttributeNames.forEach(function(attributeName){if(!subject.hasAttribute(attributeName)){var promise=promiseByKey.attributes[attributeName];if(!promise||promise.isRejected()){var err=promise&&promise.reason();output.nl().sp(2+subject.nodeName.length).annotationBlock(function(){this.error("missing").sp()["prism:attr-name"](attributeName,"html");if(expectedValueByAttributeName[attributeName]!==true){this.sp().error(err&&err.label||"should satisfy").sp().append(inspect(expectedValueByAttributeName[attributeName]))}}).nl()}canContinueLine=false}});output["prism:punctuation"](">");return{inline:true,diff:output}}})})})});expect.addAssertion("HTMLElement","to have [no] (child|children)",function(expect,subject,query,cmp){if(this.flags.no){this.errorMode="nested";return expect(Array.prototype.slice.call(subject.childNodes),"to be an empty array")}else{var children=Array.prototype.slice.call(subject.querySelectorAll(query));throw children}});expect.addAssertion("HTMLElement","to have text",function(expect,subject,value){return expect(subject.textContent,"to satisfy",value)});expect.addAssertion(["HTMLDocument","HTMLElement"],"queried for [first]",function(expect,subject,value){var queryResult;this.errorMode="nested";if(this.flags.first){queryResult=subject.querySelector(value);if(!queryResult){expect.fail(function(output){output.error("The selector").sp().jsString(value).sp().error("yielded no results")})}}else{queryResult=subject.querySelectorAll(value);if(queryResult.length===0){expect.fail(function(output){output.error("The selector").sp().jsString(value).sp().error("yielded no results")})}}this.shift(expect,queryResult,1)});expect.addAssertion("string","when parsed as (html|HTML)",function(expect,subject){var htmlDocument;if(typeof DOMParser!=="undefined"){htmlDocument=(new DOMParser).parseFromString(subject,"text/html")}else if(typeof document!=="undefined"&&document.implementation&&document.implementation.createHTMLDocument){htmlDocument=document.implementation.createHTMLDocument("");htmlDocument.open();htmlDocument.write(subject);htmlDocument.close()}else{try{htmlDocument=require("jsdom").jsdom(subject)}catch(err){throw new Error("The assertion `when parsed as html` was run outside a browser, but could not find the `jsdom` module. Please npm install jsdom to make this work.")}}return this.shift(expect,htmlDocument,0)})}}},{"array-changes":2,jsdom:"jsdom"}],2:[function(require,module,exports){var arrayDiff=require("arraydiff");function extend(target){for(var i=1;i0){mutatedArray[mutatedArray.length-1].last=true}similar=similar||function(a,b){return false};var itemsDiff=arrayDiff(actual,expected,function(a,b){return equal(a,b)||similar(a,b)});var removeTable=[];function offsetIndex(index){return index+(removeTable[index-1]||0)}var removes=itemsDiff.filter(function(diffItem){return diffItem.type==="remove"});var removesByIndex={};var removedItems=0;removes.forEach(function(diffItem){var removeIndex=removedItems+diffItem.index;mutatedArray.slice(removeIndex,diffItem.howMany+removeIndex).forEach(function(v){v.type="remove"});removedItems+=diffItem.howMany;removesByIndex[diffItem.index]=removedItems});function updateRemoveTable(){removedItems=0;actual.forEach(function(_,index){removedItems+=removesByIndex[index]||0;removeTable[index]=removedItems})}updateRemoveTable();var moves=itemsDiff.filter(function(diffItem){return diffItem.type==="move"});var movedItems=0;moves.forEach(function(diffItem){var moveFromIndex=offsetIndex(diffItem.from);var removed=mutatedArray.slice(moveFromIndex,diffItem.howMany+moveFromIndex);var added=removed.map(function(v){return extend({},v,{last:false,type:"insert"})});removed.forEach(function(v){v.type="remove"});Array.prototype.splice.apply(mutatedArray,[offsetIndex(diffItem.to),0].concat(added));movedItems+=diffItem.howMany;removesByIndex[diffItem.from]=movedItems;updateRemoveTable()});var inserts=itemsDiff.filter(function(diffItem){return diffItem.type==="insert"});inserts.forEach(function(diffItem){var added=new Array(diffItem.values.length);for(var i=0;i0){mutatedArray[mutatedArray.length-1].last=true}}mutatedArray.forEach(function(diffItem){if(diffItem.type==="similar"&&equal(diffItem.value,diffItem.expected)){diffItem.type="equal"}});return mutatedArray}},{arraydiff:3}],3:[function(require,module,exports){module.exports=arrayDiff;arrayDiff.InsertDiff=InsertDiff;arrayDiff.RemoveDiff=RemoveDiff;arrayDiff.MoveDiff=MoveDiff;function InsertDiff(index,values){this.index=index;this.values=values}InsertDiff.prototype.type="insert";InsertDiff.prototype.toJSON=function(){return{type:this.type,index:this.index,values:this.values}};function RemoveDiff(index,howMany){this.index=index;this.howMany=howMany}RemoveDiff.prototype.type="remove";RemoveDiff.prototype.toJSON=function(){return{type:this.type,index:this.index,howMany:this.howMany}};function MoveDiff(from,to,howMany){this.from=from;this.to=to;this.howMany=howMany}MoveDiff.prototype.type="move";MoveDiff.prototype.toJSON=function(){return{type:this.type,from:this.from,to:this.to,howMany:this.howMany}};function strictEqual(a,b){return a===b}function arrayDiff(before,after,equalFn){if(!equalFn)equalFn=strictEqual;var beforeLength=before.length;var afterLength=after.length;var moves=[];var beforeMarked={};var afterMarked={};for(var beforeIndex=0;beforeIndex=remove.index)move.from-=remove.howMany}}for(i=insertsLength;i--;){var insert=inserts[i];var howMany=insert.values.length;for(j=movesLength;j--;){var move=moves[j];if(move.to>=insert.index)move.to-=howMany}}for(i=movesLength;i-->1;){var move=moves[i];if(move.to===move.from)continue;for(j=i;j--;){var earlier=moves[j];if(earlier.to>=move.to)earlier.to-=move.howMany;if(earlier.to>=move.from)earlier.to+=move.howMany}}var outputMoves=[];for(i=0;i=move.from)later.from-=move.howMany;if(later.from>=move.to)later.from+=move.howMany}}return removes.concat(outputMoves,inserts)}},{}]},{},[1])(1)}); \ No newline at end of file +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.unexpected||(g.unexpected={})).dom=f()}})(function(){var define,module,exports;return 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"}}function diffNodeLists(actual,expected,output,diff,inspect,equal){var changes=arrayChanges(Array.prototype.slice.call(actual),Array.prototype.slice.call(expected),equal,function(a,b){return a.nodeType===1&&b.nodeType===1&&a.nodeName===b.nodeName});changes.forEach(function(diffItem,index){output.i().block(function(){var type=diffItem.type;if(type==="insert"){this.annotationBlock(function(){this.error("missing ").block(inspect(diffItem.value))})}else if(type==="remove"){this.block(inspect(diffItem.value).sp().error("// should be removed"))}else if(type==="equal"){this.block(inspect(diffItem.value))}else{var valueDiff=diff(diffItem.value,diffItem.expected);if(valueDiff&&valueDiff.inline){this.block(valueDiff.diff)}else if(valueDiff){this.block(inspect(diffItem.value).sp()).annotationBlock(function(){this.shouldEqualError(diffItem.expected,inspect).nl().append(valueDiff.diff)})}else{this.block(inspect(diffItem.value).sp()).annotationBlock(function(){this.shouldEqualError(diffItem.expected,inspect)})}}}).nl(index-1},equal:function(a,b){return a.nodeValue===b.nodeValue},inspect:function(element,depth,output){return output.code(element.nodeName+' "'+element.nodeValue+'"',"prism-string")}});expect.addType({name:"DOMComment",base:"DOMNode",identify:function(obj){return obj&&typeof obj.nodeType==="number"&&obj.nodeType===8},equal:function(a,b){return a.nodeValue===b.nodeValue},inspect:function(element,depth,output){return output.code("","html")},diff:function(actual,expected,output,diff,inspect,equal){var d=diff("","");d.inline=true;return d}});expect.addType({name:"DOMTextNode",base:"DOMNode",identify:function(obj){return obj&&typeof obj.nodeType==="number"&&obj.nodeType===3},equal:function(a,b){return a.nodeValue.trim()===b.nodeValue.trim()},inspect:function(element,depth,output){return output.code(entitify(element.nodeValue.trim()),"html")},diff:function(actual,expected,output,diff,inspect,equal){var d=diff(actual.nodeValue,expected.nodeValue);d.inline=true;return d}});expect.addType({name:"DOMNodeList",base:"array-like",prefix:function(output){return output.text("NodeList[")},suffix:function(output){return output.text("]")},delimiter:function(output){return output.text("delimiter")},identify:function(obj){return obj&&typeof obj.length==="number"&&typeof obj.toString==="function"&&typeof obj.item==="function"&&obj.toString().indexOf("NodeList")!==-1}});expect.addType({name:"HTMLDocType",base:"DOMNode",identify:function(obj){return obj&&typeof obj.nodeType==="number"&&obj.nodeType===10&&"publicId"in obj},inspect:function(doctype,depth,output,inspect){output.code("","html")},equal:function(a,b){return a.toString()===b.toString()},diff:function(actual,expected,output,diff){var d=diff("","");d.inline=true;return d}});expect.addType({name:"DOMDocument",base:"DOMNode",identify:function(obj){return obj&&typeof obj.nodeType==="number"&&obj.nodeType===9&&obj.documentElement&&obj.implementation},inspect:function(document,depth,output,inspect){for(var i=0;i',"xml");for(var i=0;i50||o.height>1});output.code(startTag,"html");if(element.childNodes.length>0){if(multipleLines){output.nl().indentLines();inspectedChildren.forEach(function(inspectedChild,index){output.i().block(inspectedChild).nl()});output.outdentLines()}else{inspectedChildren.forEach(function(inspectedChild,index){output.append(inspectedChild)})}}output.code(stringifyEndTag(element),"html");return output},diffLimit:512,diff:function(actual,expected,output,diff,inspect,equal){var isHtml=actual.ownerDocument.contentType==="text/html";var result={diff:output,inline:true};if(Math.max(actual.length,expected.length)>this.diffLimit){result.diff.jsComment("Diff suppressed due to size > "+this.diffLimit);return result}var emptyElements=actual.childNodes.length===0&&expected.childNodes.length===0;var conflictingElement=actual.nodeName.toLowerCase()!==expected.nodeName.toLowerCase()||!equal(getAttributes(actual),getAttributes(expected));if(conflictingElement){var canContinueLine=true;output.prismPunctuation("<").prismTag(actual.nodeName.toLowerCase());if(actual.nodeName.toLowerCase()!==expected.nodeName.toLowerCase()){output.sp().annotationBlock(function(){this.error("should be").sp().prismTag(expected.nodeName.toLowerCase())}).nl();canContinueLine=false}var actualAttributes=getAttributes(actual);var expectedAttributes=getAttributes(expected);Object.keys(actualAttributes).forEach(function(attributeName){output.sp(canContinueLine?1:2+actual.nodeName.length);writeAttributeToMagicPen(output,attributeName,actualAttributes[attributeName],isHtml);if(attributeName in expectedAttributes){if(actualAttributes[attributeName]===expectedAttributes[attributeName]){canContinueLine=true}else{output.sp().annotationBlock(function(){this.error("should equal").sp().append(inspect(entitify(expectedAttributes[attributeName])))}).nl();canContinueLine=false}delete expectedAttributes[attributeName]}else{output.sp().annotationBlock(function(){this.error("should be removed")}).nl();canContinueLine=false}});Object.keys(expectedAttributes).forEach(function(attributeName){output.sp(canContinueLine?1:2+actual.nodeName.length);output.annotationBlock(function(){this.error("missing").sp();writeAttributeToMagicPen(this,attributeName,expectedAttributes[attributeName],isHtml)}).nl();canContinueLine=false});output.prismPunctuation(">")}else{output.code(stringifyStartTag(actual),"html")}if(!emptyElements){output.nl().indentLines();diffNodeLists(actual.childNodes,expected.childNodes,output,diff,inspect,equal);output.nl().outdentLines()}output.code(stringifyEndTag(actual),"html");return result}});expect.addAssertion("DOMElement","to [only] have (class|classes)",function(expect,subject,value){var flags=this.flags;if(flags.only){return expect(subject,"to have attributes",{"class":function(className){var actualClasses=getClassNamesFromAttributeValue(className);if(typeof value==="string"){value=getClassNamesFromAttributeValue(value)}if(flags.only){return topLevelExpect(actualClasses.sort(),"to equal",value.sort())}else{return topLevelExpect.apply(topLevelExpect,[actualClasses,"to contain"].concat(value))}}})}else{return expect(subject,"to have attributes",{"class":value})}});expect.addAssertion("DOMTextNode","to satisfy",function(expect,subject,value){return expect(subject.nodeValue,"to satisfy",value)});expect.addAssertion("DOMElement","to satisfy",function(expect,subject,value){var isHtml=subject.ownerDocument.contentType==="text/html";if(value&&typeof value==="object"){var unsupportedOptions=Object.keys(value).filter(function(key){return key!=="attributes"&&key!=="name"&&key!=="children"&&key!=="onlyAttributes"});if(unsupportedOptions.length>0){throw new Error("Unsupported option"+(unsupportedOptions.length===1?"":"s")+": "+unsupportedOptions.join(", "))}}var promiseByKey={name:expect.promise(function(){if(value&&typeof value.name!=="undefined"){return topLevelExpect(isHtml?subject.nodeName.toLowerCase():subject.nodeName,"to satisfy",value.name)}}),children:expect.promise(function(){if(typeof value.children!=="undefined"){return topLevelExpect(subject.childNodes,"to satisfy",value.children)}}),attributes:{}};var onlyAttributes=value&&value.onlyAttributes;var attrs=getAttributes(subject);var expectedAttributes=value&&value.attributes;var expectedAttributeNames=[];if(typeof expectedAttributes!=="undefined"){if(typeof expectedAttributes==="string"){expectedAttributes=[expectedAttributes]}var expectedValueByAttributeName={};if(Array.isArray(expectedAttributes)){expectedAttributes.forEach(function(attributeName){expectedValueByAttributeName[attributeName]=true})}else if(expectedAttributes&&typeof expectedAttributes==="object"){expectedValueByAttributeName=expectedAttributes}Object.keys(expectedValueByAttributeName).forEach(function(attributeName){expectedAttributeNames.push(attributeName)});expectedAttributeNames.forEach(function(attributeName){var attributeValue=subject.getAttribute(attributeName);var expectedAttributeValue=expectedValueByAttributeName[attributeName];promiseByKey.attributes[attributeName]=expect.promise(function(){if(attributeName==="class"&&(typeof expectedAttributeValue==="string"||Array.isArray(expectedAttributeValue))){var actualClasses=getClassNamesFromAttributeValue(attributeValue);var expectedClasses=expectedAttributeValue;if(typeof expectedClasses==="string"){expectedClasses=getClassNamesFromAttributeValue(expectedAttributeValue)}if(onlyAttributes){return topLevelExpect(actualClasses.sort(),"to equal",expectedClasses.sort())}else{return topLevelExpect.apply(topLevelExpect,[actualClasses,"to contain"].concat(expectedClasses))}}else if(attributeName==="style"){var expectedStyleObj;if(typeof expectedValueByAttributeName.style==="string"){expectedStyleObj=styleStringToObject(expectedValueByAttributeName.style)}else{expectedStyleObj=expectedValueByAttributeName.style}if(onlyAttributes){return topLevelExpect(attrs.style,"to exhaustively satisfy",expectedStyleObj)}else{return topLevelExpect(attrs.style,"to satisfy",expectedStyleObj)}}else if(expectedAttributeValue===true){expect(subject.hasAttribute(attributeName),"to be true")}else{return topLevelExpect(attributeValue,"to satisfy",expectedAttributeValue)}})});promiseByKey.attributePresence=expect.promise(function(){var attributeNamesExpectedToBeDefined=[];expectedAttributeNames.forEach(function(attributeName){if(typeof expectedValueByAttributeName[attributeName]==="undefined"){expect(attrs,"not to have key",attributeName)}else{attributeNamesExpectedToBeDefined.push(attributeName);expect(attrs,"to have key",attributeName)}});if(onlyAttributes){expect(Object.keys(attrs).sort(),"to equal",attributeNamesExpectedToBeDefined.sort())}})}return expect.promise.all(promiseByKey).caught(function(){return expect.promise.settle(promiseByKey).then(function(){expect.fail({diff:function(output,diff,inspect,equal){output.block(function(){var output=this;output.prismPunctuation("<").prismTag(isHtml?subject.nodeName.toLowerCase():subject.nodeName);var canContinueLine=true;if(promiseByKey.name.isRejected()){var nameError=promiseByKey.name.reason();output.sp().annotationBlock(function(){this.error(nameError&&nameError.label||"should satisfy").sp().append(inspect(value.name))}).nl();canContinueLine=false}Object.keys(attrs).forEach(function(attributeName){var promise=promiseByKey.attributes[attributeName];output.sp(canContinueLine?1:2+subject.nodeName.length);writeAttributeToMagicPen(output,attributeName,attrs[attributeName],isHtml);if(promise&&promise.isFulfilled()||!promise&&(!onlyAttributes||expectedAttributeNames.indexOf(attributeName)!==-1)){canContinueLine=true}else{output.sp().annotationBlock(function(){if(promise){this.append(promise.reason().output)}else{this.error("should be removed")}}).nl();canContinueLine=false}});expectedAttributeNames.forEach(function(attributeName){if(!subject.hasAttribute(attributeName)){var promise=promiseByKey.attributes[attributeName];if(!promise||promise.isRejected()){var err=promise&&promise.reason();output.nl().sp(2+subject.nodeName.length).annotationBlock(function(){this.error("missing").sp().prismAttrName(attributeName,"html");if(expectedValueByAttributeName[attributeName]!==true){this.sp().error(err&&err.label||"should satisfy").sp().append(inspect(expectedValueByAttributeName[attributeName]))}}).nl()}canContinueLine=false}});output.prismPunctuation(">");var childrenError=promiseByKey.children.isRejected()&&promiseByKey.children.reason();var childrenDiff=childrenError&&childrenError.createDiff&&childrenError.createDiff(output.clone(),diff,inspect,equal);if(childrenError){output.nl().indentLines().i().block(function(){for(var i=0;i3){value=Array.prototype.slice.call(arguments,2)}}else if(!value||typeof value!=="object"){throw new Error("to have attributes: Argument must be a string, an array, or an object")}return expect(subject,"to satisfy",{attributes:value,onlyAttributes:this.flags.only})});expect.addAssertion("DOMElement","to have [no] (child|children)",function(expect,subject,query,cmp){if(this.flags.no){this.errorMode="nested";return expect(Array.prototype.slice.call(subject.childNodes),"to be an empty array")}else{var children=Array.prototype.slice.call(subject.querySelectorAll(query));throw children}});expect.addAssertion("DOMElement","to have text",function(expect,subject,value){return expect(subject.textContent,"to satisfy",value)});expect.addAssertion(["DOMDocument","DOMElement"],"queried for [first]",function(expect,subject,value){var queryResult;this.errorMode="nested";if(this.flags.first){queryResult=subject.querySelector(value);if(!queryResult){expect.fail(function(output){output.error("The selector").sp().jsString(value).sp().error("yielded no results")})}}else{queryResult=subject.querySelectorAll(value);if(queryResult.length===0){expect.fail(function(output){output.error("The selector").sp().jsString(value).sp().error("yielded no results")})}}return this.shift(expect,queryResult,1)});expect.addAssertion("string","when parsed as (html|HTML)",function(expect,subject){this.errorMode="nested";var htmlDocument;if(typeof DOMParser!=="undefined"){htmlDocument=(new DOMParser).parseFromString(subject,"text/html")}else if(typeof document!=="undefined"&&document.implementation&&document.implementation.createHTMLDocument){htmlDocument=document.implementation.createHTMLDocument("");htmlDocument.open();htmlDocument.write(subject);htmlDocument.close()}else{try{htmlDocument=require("jsdom").jsdom(subject)}catch(err){throw new Error("The assertion `"+this.testDescription+"` was run outside a browser, but could not find the `jsdom` module. Please npm install jsdom to make this work.")}}return this.shift(expect,htmlDocument,0)});expect.addAssertion("string","when parsed as (xml|XML)",function(expect,subject){this.errorMode="nested";var xmlDocument;if(typeof DOMParser!=="undefined"){xmlDocument=(new DOMParser).parseFromString(subject,"text/xml")}else{try{xmlDocument=require("jsdom").jsdom(subject,{parsingMode:"xml"})}catch(err){throw new Error("The assertion `"+this.testDescription+"` was outside a browser (or in a browser without DOMParser), but could not find the `jsdom` module. Please npm install jsdom to make this work.")}}return this.shift(expect,xmlDocument,0)})}}},{"array-changes":2,jsdom:"jsdom","magicpen-prism":5}],2:[function(require,module,exports){var arrayDiff=require("arraydiff");function extend(target){for(var i=1;i0){mutatedArray[mutatedArray.length-1].last=true}similar=similar||function(a,b){return false};var itemsDiff=arrayDiff(actual,expected,function(a,b){return equal(a,b)||similar(a,b)});var removeTable=[];function offsetIndex(index){return index+(removeTable[index-1]||0)}var removes=itemsDiff.filter(function(diffItem){return diffItem.type==="remove"});var removesByIndex={};var removedItems=0;removes.forEach(function(diffItem){var removeIndex=removedItems+diffItem.index;mutatedArray.slice(removeIndex,diffItem.howMany+removeIndex).forEach(function(v){v.type="remove"});removedItems+=diffItem.howMany;removesByIndex[diffItem.index]=removedItems});function updateRemoveTable(){removedItems=0;actual.forEach(function(_,index){removedItems+=removesByIndex[index]||0;removeTable[index]=removedItems})}updateRemoveTable();var moves=itemsDiff.filter(function(diffItem){return diffItem.type==="move"});var movedItems=0;moves.forEach(function(diffItem){var moveFromIndex=offsetIndex(diffItem.from);var removed=mutatedArray.slice(moveFromIndex,diffItem.howMany+moveFromIndex);var added=removed.map(function(v){return extend({},v,{last:false,type:"insert"})});removed.forEach(function(v){v.type="remove"});Array.prototype.splice.apply(mutatedArray,[offsetIndex(diffItem.to),0].concat(added));movedItems+=diffItem.howMany;removesByIndex[diffItem.from]=movedItems;updateRemoveTable()});var inserts=itemsDiff.filter(function(diffItem){return diffItem.type==="insert"});inserts.forEach(function(diffItem){var added=new Array(diffItem.values.length);for(var i=0;i0){mutatedArray[mutatedArray.length-1].last=true}}mutatedArray.forEach(function(diffItem){if(diffItem.type==="similar"&&equal(diffItem.value,diffItem.expected)){diffItem.type="equal"}});return mutatedArray}},{arraydiff:3}],3:[function(require,module,exports){module.exports=arrayDiff;arrayDiff.InsertDiff=InsertDiff;arrayDiff.RemoveDiff=RemoveDiff;arrayDiff.MoveDiff=MoveDiff;function InsertDiff(index,values){this.index=index;this.values=values}InsertDiff.prototype.type="insert";InsertDiff.prototype.toJSON=function(){return{type:this.type,index:this.index,values:this.values}};function RemoveDiff(index,howMany){this.index=index;this.howMany=howMany}RemoveDiff.prototype.type="remove";RemoveDiff.prototype.toJSON=function(){return{type:this.type,index:this.index,howMany:this.howMany}};function MoveDiff(from,to,howMany){this.from=from;this.to=to;this.howMany=howMany}MoveDiff.prototype.type="move";MoveDiff.prototype.toJSON=function(){return{type:this.type,from:this.from,to:this.to,howMany:this.howMany}};function strictEqual(a,b){return a===b}function arrayDiff(before,after,equalFn){if(!equalFn)equalFn=strictEqual;var beforeLength=before.length;var afterLength=after.length;var moves=[];var beforeMarked={};var afterMarked={};for(var beforeIndex=0;beforeIndex=remove.index)move.from-=remove.howMany}}for(i=insertsLength;i--;){var insert=inserts[i];var howMany=insert.values.length;for(j=movesLength;j--;){var move=moves[j];if(move.to>=insert.index)move.to-=howMany}}for(i=movesLength;i-->1;){var move=moves[i];if(move.to===move.from)continue;for(j=i;j--;){var earlier=moves[j];if(earlier.to>=move.to)earlier.to-=move.howMany;if(earlier.to>=move.from)earlier.to+=move.howMany}}var outputMoves=[];for(i=0;i=move.from)later.from-=move.howMany;if(later.from>=move.to)later.from+=move.howMany}}return removes.concat(outputMoves,inserts)}},{}],4:[function(require,module,exports){var self=typeof window!=="undefined"?window:{};var Prism=function(){var lang=/\blang(?:uage)?-(?!\*)(\w+)\b/i;var _=self.Prism={util:{type:function(o){return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]},clone:function(o){var type=_.util.type(o);switch(type){case"Object":var clone={};for(var key in o){if(o.hasOwnProperty(key)){clone[key]=_.util.clone(o[key])}}return clone;case"Array":return o.slice()}return o}},languages:{extend:function(id,redef){var lang=_.util.clone(_.languages[id]);for(var key in redef){lang[key]=redef[key]}return lang},insertBefore:function(inside,before,insert,root){root=root||_.languages;var grammar=root[inside];var ret={};for(var token in grammar){if(grammar.hasOwnProperty(token)){if(token==before){for(var newToken in insert){if(insert.hasOwnProperty(newToken)){ret[newToken]=insert[newToken]}}}ret[token]=grammar[token]}}return root[inside]=ret},DFS:function(o,callback){for(var i in o){callback.call(o,i,o[i]);if(_.util.type(o)==="Object"){_.languages.DFS(o[i],callback)}}}},highlightAll:function(async,callback){var elements=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,element;element=elements[i++];){_.highlightElement(element,async===true,callback)}},highlightElement:function(element,async,callback){var language,grammar,parent=element;while(parent&&!lang.test(parent.className)){parent=parent.parentNode}if(parent){language=(parent.className.match(lang)||[,""])[1];grammar=_.languages[language]}if(!grammar){return}element.className=element.className.replace(lang,"").replace(/\s+/g," ")+" language-"+language;parent=element.parentNode;if(/pre/i.test(parent.nodeName)){parent.className=parent.className.replace(lang,"").replace(/\s+/g," ")+" language-"+language}var code=element.textContent;if(!code){return}code=code.replace(/&/g,"&").replace(/text.length){break tokenloop}if(str instanceof Token){continue}pattern.lastIndex=0;var match=pattern.exec(str);if(match){if(lookbehind){lookbehindLength=match[1].length}var from=match.index-1+lookbehindLength,match=match[0].slice(lookbehindLength),len=match.length,to=from+len,before=str.slice(0,from+1),after=str.slice(to+1);var args=[i,1];if(before){args.push(before)}var wrapped=new Token(token,inside?_.tokenize(match,inside):match);args.push(wrapped);if(after){args.push(after)}Array.prototype.splice.apply(strarr,args)}}}return strarr},hooks:{all:{},add:function(name,callback){var hooks=_.hooks.all;hooks[name]=hooks[name]||[];hooks[name].push(callback); + +},run:function(name,env){var callbacks=_.hooks.all[name];if(!callbacks||!callbacks.length){return}for(var i=0,callback;callback=callbacks[i++];){callback(env)}}}};var Token=_.Token=function(type,content){this.type=type;this.content=content};Token.stringify=function(o,language,parent){if(typeof o=="string"){return o}if(Object.prototype.toString.call(o)=="[object Array]"){return o.map(function(element){return Token.stringify(element,language,o)}).join("")}var env={type:o.type,content:Token.stringify(o.content,language,parent),tag:"span",classes:["token",o.type],attributes:{},language:language,parent:parent};if(env.type=="comment"){env.attributes["spellcheck"]="true"}_.hooks.run("wrap",env);var attributes="";for(var name in env.attributes){attributes+=name+'="'+(env.attributes[name]||"")+'"'}return"<"+env.tag+' class="'+env.classes.join(" ")+'" '+attributes+">"+env.content+""};if(!self.document){if(!self.addEventListener){return self.Prism}self.addEventListener("message",function(evt){var message=JSON.parse(evt.data),lang=message.language,code=message.code;self.postMessage(JSON.stringify(_.tokenize(code,_.languages[lang])));self.close()},false);return self.Prism}var script=document.getElementsByTagName("script");script=script[script.length-1];if(script){_.filename=script.src;if(document.addEventListener&&!script.hasAttribute("data-manual")){document.addEventListener("DOMContentLoaded",_.highlightAll)}}return self.Prism}();if(typeof module!=="undefined"&&module.exports){module.exports=Prism}Prism.languages.markup={comment:/<!--[\w\W]*?-->/g,prolog:/<\?.+?\?>/,doctype:/<!DOCTYPE.+?>/,cdata:/<!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi,inside:{tag:{pattern:/^<\/?[\w:-]+/i,inside:{punctuation:/^<\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|>|"/g}},punctuation:/\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(env){if(env.type==="entity"){env.attributes["title"]=env.content.replace(/&/,"&")}});Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*{))/gi,inside:{punctuation:/[;:]/g}},url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/g,property:/(\b|\B)[\w-]+(?=\s*:)/gi,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};if(Prism.languages.markup){Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/gi,inside:{tag:{pattern:/(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}})}Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:true},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:true,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/gi,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|get|set|new|with|typeof|try|throw|catch|finally|null|break|continue|this)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g});Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:true}});if(Prism.languages.markup){Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/gi,inside:{tag:{pattern:/(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}})}(function(){if(!self.Prism||!self.document||!document.querySelector){return}var Extensions={js:"javascript",html:"markup",svg:"markup"};Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(pre){var src=pre.getAttribute("data-src");var extension=(src.match(/\.(\w+)$/)||[,""])[1];var language=Extensions[extension]||extension;var code=document.createElement("code");code.className="language-"+language;pre.textContent="";code.textContent="Loading…";pre.appendChild(code);var xhr=new XMLHttpRequest;xhr.open("GET",src,true);xhr.onreadystatechange=function(){if(xhr.readyState==4){if(xhr.status<400&&xhr.responseText){code.textContent=xhr.responseText;Prism.highlightElement(code)}else if(xhr.status>=400){code.textContent="✖ Error "+xhr.status+" while fetching file: "+xhr.statusText}else{code.textContent="✖ Error: File does not exist or is empty"}}};xhr.send(null)})})()},{}],5:[function(require,module,exports){var prism=require("../3rdparty/prism"),defaultTheme={prismComment:"#708090",prismProlog:"prismComment",prismDoctype:"prismComment",prismCdata:"prismComment",prismPunctuation:"#999",prismSymbol:"#905",prismProperty:"prismSymbol",prismTag:"prismSymbol",prismBoolean:"prismSymbol",prismNumber:"prismSymbol",prismConstant:"prismSymbol",prismDeleted:"prismSymbol",prismString:"#690",prismSelector:"prismString",prismAttrName:"prismString",prismChar:"prismString",prismBuiltin:"prismString",prismInserted:"prismString",prismOperator:"#a67f59",prismVariable:"prismOperator",prismEntity:"prismOperator",prismUrl:"prismOperator",prismCssString:"prismOperator",prismKeyword:"#07a",prismAtrule:"prismKeyword",prismAttrValue:"prismKeyword",prismFunction:"#DD4A68",prismRegex:"#e90",prismImportant:["#e90","bold"]},languageMapping={"text/html":"markup","application/xml":"markup","text/xml":"markup","application/json":"javascript","text/javascript":"javascript","application/javascript":"javascript","text/css":"css",html:"markup",xml:"markup",c:"clike","c++":"clike",cpp:"clike","c#":"clike",java:"clike"};function upperCamelCase(str){return str.replace(/(?:^|-)([a-z])/g,function($0,ch){return ch.toUpperCase()})}module.exports={name:"magicpen-prism",installInto:function(magicPen){magicPen.installTheme(defaultTheme);magicPen.addStyle("code",function(sourceText,language){if(language in languageMapping){language=languageMapping[language]}else if(/\+xml\b/.test(language)){language="markup"}if(!(language in prism.languages)){return this.text(sourceText)}sourceText=sourceText.replace(/