/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) {module.exports = global["VirtualMachine"] = __webpack_require__(1); /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { var EventEmitter = __webpack_require__(2); var util = __webpack_require__(3); var Runtime = __webpack_require__(7); var sb2import = __webpack_require__(34); var Sprite = __webpack_require__(89); var Blocks = __webpack_require__(35); /** * Handles connections between blocks, stage, and extensions. * * @author Andrew Sliwinski */ function VirtualMachine () { var instance = this; // Bind event emitter and runtime to VM instance EventEmitter.call(instance); /** * VM runtime, to store blocks, I/O devices, sprites/targets, etc. * @type {!Runtime} */ instance.runtime = new Runtime(); /** * The "currently editing"/selected target ID for the VM. * Block events from any Blockly workspace are routed to this target. * @type {!string} */ instance.editingTarget = null; // Runtime emits are passed along as VM emits. instance.runtime.on(Runtime.SCRIPT_GLOW_ON, function (id) { instance.emit(Runtime.SCRIPT_GLOW_ON, {id: id}); }); instance.runtime.on(Runtime.SCRIPT_GLOW_OFF, function (id) { instance.emit(Runtime.SCRIPT_GLOW_OFF, {id: id}); }); instance.runtime.on(Runtime.BLOCK_GLOW_ON, function (id) { instance.emit(Runtime.BLOCK_GLOW_ON, {id: id}); }); instance.runtime.on(Runtime.BLOCK_GLOW_OFF, function (id) { instance.emit(Runtime.BLOCK_GLOW_OFF, {id: id}); }); instance.runtime.on(Runtime.VISUAL_REPORT, function (id, value) { instance.emit(Runtime.VISUAL_REPORT, {id: id, value: value}); }); this.blockListener = this.blockListener.bind(this); } /** * Inherit from EventEmitter */ util.inherits(VirtualMachine, EventEmitter); /** * Start running the VM - do this before anything else. */ VirtualMachine.prototype.start = function () { this.runtime.start(); }; /** * "Green flag" handler - start all threads starting with a green flag. */ VirtualMachine.prototype.greenFlag = function () { this.runtime.greenFlag(); }; /** * Stop all threads and running activities. */ VirtualMachine.prototype.stopAll = function () { this.runtime.stopAll(); }; /** * Get data for playground. Data comes back in an emitted event. */ VirtualMachine.prototype.getPlaygroundData = function () { this.emit('playgroundData', { blocks: this.editingTarget.blocks, threads: this.runtime.threads }); }; /** * Handle an animation frame. */ VirtualMachine.prototype.animationFrame = function () { this.runtime.animationFrame(); }; /** * Post I/O data to the virtual devices. * @param {?string} device Name of virtual I/O device. * @param {Object} data Any data object to post to the I/O device. */ VirtualMachine.prototype.postIOData = function (device, data) { if (this.runtime.ioDevices[device]) { this.runtime.ioDevices[device].postData(data); } }; /** * Load a project from a Scratch 2.0 JSON representation. * @param {?string} json JSON string representing the project. */ VirtualMachine.prototype.loadProject = function (json) { // @todo: Handle other formats, e.g., Scratch 1.4, Scratch 3.0. sb2import(json, this.runtime); // Select the first target for editing, e.g., the stage. this.editingTarget = this.runtime.targets[0]; // Update the VM user's knowledge of targets and blocks on the workspace. this.emitTargetsUpdate(); this.emitWorkspaceUpdate(); this.runtime.setEditingTarget(this.editingTarget); }; /** * Temporary way to make an empty project, in case the desired project * cannot be loaded from the online server. */ VirtualMachine.prototype.createEmptyProject = function () { // Stage. var blocks2 = new Blocks(); var stage = new Sprite(blocks2); stage.name = 'Stage'; stage.costumes.push({ skin: '/assets/stage.png', name: 'backdrop1', bitmapResolution: 1, rotationCenterX: 240, rotationCenterY: 180 }); var target2 = stage.createClone(); this.runtime.targets.push(target2); target2.x = 0; target2.y = 0; target2.direction = 90; target2.size = 200; target2.visible = true; target2.isStage = true; // Sprite1 (cat). var blocks1 = new Blocks(); var sprite = new Sprite(blocks1); sprite.name = 'Sprite1'; sprite.costumes.push({ skin: '/assets/scratch_cat.svg', name: 'costume1', bitmapResolution: 1, rotationCenterX: 47, rotationCenterY: 55 }); var target1 = sprite.createClone(); this.runtime.targets.push(target1); target1.x = 0; target1.y = 0; target1.direction = 90; target1.size = 100; target1.visible = true; this.editingTarget = this.runtime.targets[0]; this.emitTargetsUpdate(); this.emitWorkspaceUpdate(); }; /** * Set the renderer for the VM/runtime * @param {!RenderWebGL} renderer The renderer to attach */ VirtualMachine.prototype.attachRenderer = function (renderer) { this.runtime.attachRenderer(renderer); }; /** * Handle a Blockly event for the current editing target. * @param {!Blockly.Event} e Any Blockly event. */ VirtualMachine.prototype.blockListener = function (e) { if (this.editingTarget) { this.editingTarget.blocks.blocklyListen( e, false, this.runtime ); } }; /** * Set an editing target. An editor UI can use this function to switch * between editing different targets, sprites, etc. * After switching the editing target, the VM may emit updates * to the list of targets and any attached workspace blocks * (see `emitTargetsUpdate` and `emitWorkspaceUpdate`). * @param {string} targetId Id of target to set as editing. */ VirtualMachine.prototype.setEditingTarget = function (targetId) { // Has the target id changed? If not, exit. if (targetId == this.editingTarget.id) { return; } var target = this.runtime.getTargetById(targetId); if (target) { this.editingTarget = target; // Emit appropriate UI updates. this.emitTargetsUpdate(); this.emitWorkspaceUpdate(); this.runtime.setEditingTarget(target); } }; /** * Emit metadata about available targets. * An editor UI could use this to display a list of targets and show * the currently editing one. */ VirtualMachine.prototype.emitTargetsUpdate = function () { this.emit('targetsUpdate', { // [[target id, human readable target name], ...]. targetList: this.runtime.targets.filter(function (target) { // Don't report clones. return !target.hasOwnProperty('isOriginal') || target.isOriginal; }).map(function(target) { return [target.id, target.getName()]; }), // Currently editing target id. editingTarget: this.editingTarget.id }); }; /** * Emit an Blockly/scratch-blocks compatible XML representation * of the current editing target's blocks. */ VirtualMachine.prototype.emitWorkspaceUpdate = function () { this.emit('workspaceUpdate', { 'xml': this.editingTarget.blocks.toXML() }); }; module.exports = VirtualMachine; /***/ }, /* 2 */ /***/ function(module, exports) { // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. function EventEmitter() { this._events = this._events || {}; this._maxListeners = this._maxListeners || undefined; } module.exports = EventEmitter; // Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter; EventEmitter.prototype._events = undefined; EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. EventEmitter.defaultMaxListeners = 10; // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function(n) { if (!isNumber(n) || n < 0 || isNaN(n)) throw TypeError('n must be a positive number'); this._maxListeners = n; return this; }; EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners; if (!this._events) this._events = {}; // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events.error || (isObject(this._events.error) && !this._events.error.length)) { er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } else { // At least give some kind of context to the user var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); err.context = er; throw err; } } } handler = this._events[type]; if (isUndefined(handler)) return false; if (isFunction(handler)) { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: args = Array.prototype.slice.call(arguments, 1); handler.apply(this, args); } } else if (isObject(handler)) { args = Array.prototype.slice.call(arguments, 1); listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) listeners[i].apply(this, args); } return true; }; EventEmitter.prototype.addListener = function(type, listener) { var m; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events) this._events = {}; // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (this._events.newListener) this.emit('newListener', type, isFunction(listener.listener) ? listener.listener : listener); if (!this._events[type]) // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; else if (isObject(this._events[type])) // If we've already got an array, just append. this._events[type].push(listener); else // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; // Check for listener leak if (isObject(this._events[type]) && !this._events[type].warned) { if (!isUndefined(this._maxListeners)) { m = this._maxListeners; } else { m = EventEmitter.defaultMaxListeners; } if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); if (typeof console.trace === 'function') { // not supported in IE 10 console.trace(); } } } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { if (!isFunction(listener)) throw TypeError('listener must be a function'); var fired = false; function g() { this.removeListener(type, g); if (!fired) { fired = true; listener.apply(this, arguments); } } g.listener = listener; this.on(type, g); return this; }; // emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events || !this._events[type]) return this; list = this._events[type]; length = list.length; position = -1; if (list === listener || (isFunction(list.listener) && list.listener === listener)) { delete this._events[type]; if (this._events.removeListener) this.emit('removeListener', type, listener); } else if (isObject(list)) { for (i = length; i-- > 0;) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) return this; if (list.length === 1) { list.length = 0; delete this._events[type]; } else { list.splice(position, 1); } if (this._events.removeListener) this.emit('removeListener', type, listener); } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners; if (!this._events) return this; // not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) delete this._events[type]; return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = {}; return this; } listeners = this._events[type]; if (isFunction(listeners)) { this.removeListener(type, listeners); } else if (listeners) { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } delete this._events[type]; return this; }; EventEmitter.prototype.listeners = function(type) { var ret; if (!this._events || !this._events[type]) ret = []; else if (isFunction(this._events[type])) ret = [this._events[type]]; else ret = this._events[type].slice(); return ret; }; EventEmitter.prototype.listenerCount = function(type) { if (this._events) { var evlistener = this._events[type]; if (isFunction(evlistener)) return 1; else if (evlistener) return evlistener.length; } return 0; }; EventEmitter.listenerCount = function(emitter, type) { return emitter.listenerCount(type); }; function isFunction(arg) { return typeof arg === 'function'; } function isNumber(arg) { return typeof arg === 'number'; } function isObject(arg) { return typeof arg === 'object' && arg !== null; } function isUndefined(arg) { return arg === void 0; } /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (!isString(f)) { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': try { return JSON.stringify(args[i++]); } catch (_) { return '[Circular]'; } default: return x; } }); for (var x = args[i]; i < len; x = args[++i]) { if (isNull(x) || !isObject(x)) { str += ' ' + x; } else { str += ' ' + inspect(x); } } return str; }; // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. exports.deprecate = function(fn, msg) { // Allow for deprecating things in the process of starting up. if (isUndefined(global.process)) { return function() { return exports.deprecate(fn, msg).apply(this, arguments); }; } if (process.noDeprecation === true) { return fn; } var warned = false; function deprecated() { if (!warned) { if (process.throwDeprecation) { throw new Error(msg); } else if (process.traceDeprecation) { console.trace(msg); } else { console.error(msg); } warned = true; } return fn.apply(this, arguments); } return deprecated; }; var debugs = {}; var debugEnviron; exports.debuglog = function(set) { if (isUndefined(debugEnviron)) debugEnviron = process.env.NODE_DEBUG || ''; set = set.toUpperCase(); if (!debugs[set]) { if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { var pid = process.pid; debugs[set] = function() { var msg = exports.format.apply(exports, arguments); console.error('%s %d: %s', set, pid, msg); }; } else { debugs[set] = function() {}; } } return debugs[set]; }; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect(obj, opts) { // default options var ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (isBoolean(opts)) { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object exports._extend(ctx, opts); } // set default options if (isUndefined(ctx.showHidden)) ctx.showHidden = false; if (isUndefined(ctx.depth)) ctx.depth = 2; if (isUndefined(ctx.colors)) ctx.colors = false; if (isUndefined(ctx.customInspect)) ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } exports.inspect = inspect; // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect.styles[styleType]; if (style) { return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && isFunction(value.inspect) && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { var ret = value.inspect(recurseTimes, ctx); if (!isString(ret)) { ret = formatValue(ctx, ret, recurseTimes); } return ret; } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. var keys = Object.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } // IE doesn't make error fields non-enumerable // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx if (isError(value) && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { return formatError(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if (isFunction(value)) { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (isFunction(value)) { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { if (isUndefined(value)) return ctx.stylize('undefined', 'undefined'); if (isString(value)) { var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); } if (isNumber(value)) return ctx.stylize('' + value, 'number'); if (isBoolean(value)) return ctx.stylize('' + value, 'boolean'); // For some reason typeof null is "object", so special case here. if (isNull(value)) return ctx.stylize('null', 'null'); } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (isNull(recurseTimes)) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (isUndefined(name)) { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar); } exports.isArray = isArray; function isBoolean(arg) { return typeof arg === 'boolean'; } exports.isBoolean = isBoolean; function isNull(arg) { return arg === null; } exports.isNull = isNull; function isNullOrUndefined(arg) { return arg == null; } exports.isNullOrUndefined = isNullOrUndefined; function isNumber(arg) { return typeof arg === 'number'; } exports.isNumber = isNumber; function isString(arg) { return typeof arg === 'string'; } exports.isString = isString; function isSymbol(arg) { return typeof arg === 'symbol'; } exports.isSymbol = isSymbol; function isUndefined(arg) { return arg === void 0; } exports.isUndefined = isUndefined; function isRegExp(re) { return isObject(re) && objectToString(re) === '[object RegExp]'; } exports.isRegExp = isRegExp; function isObject(arg) { return typeof arg === 'object' && arg !== null; } exports.isObject = isObject; function isDate(d) { return isObject(d) && objectToString(d) === '[object Date]'; } exports.isDate = isDate; function isError(e) { return isObject(e) && (objectToString(e) === '[object Error]' || e instanceof Error); } exports.isError = isError; function isFunction(arg) { return typeof arg === 'function'; } exports.isFunction = isFunction; function isPrimitive(arg) { return arg === null || typeof arg === 'boolean' || typeof arg === 'number' || typeof arg === 'string' || typeof arg === 'symbol' || // ES6 symbol typeof arg === 'undefined'; } exports.isPrimitive = isPrimitive; exports.isBuffer = __webpack_require__(5); function objectToString(o) { return Object.prototype.toString.call(o); } function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); } var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // 26 Feb 16:19:34 function timestamp() { var d = new Date(); var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':'); return [d.getDate(), months[d.getMonth()], time].join(' '); } // log is just a thin wrapper to console.log that prepends a timestamp exports.log = function() { console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); }; /** * Inherit the prototype methods from one constructor into another. * * The Function.prototype.inherits from lang.js rewritten as a standalone * function (not on Function.prototype). NOTE: If this file is to be loaded * during bootstrapping this function needs to be rewritten using some native * functions as prototype setup using normal JavaScript does not work as * expected during bootstrapping (see mirror.js in r114903). * * @param {function} ctor Constructor function which needs to inherit the * prototype. * @param {function} superCtor Constructor function to inherit prototype from. */ exports.inherits = __webpack_require__(6); exports._extend = function(origin, add) { // Don't do anything if add isn't an object if (!add || !isObject(add)) return origin; var keys = Object.keys(add); var i = keys.length; while (i--) { origin[keys[i]] = add[keys[i]]; } return origin; }; function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(4))) /***/ }, /* 4 */ /***/ function(module, exports) { // shim for using process in browser var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it // don't break things. But we need to wrap it in a try catch in case it is // wrapped in strict mode code which doesn't define any globals. It's inside a // function because try/catches deoptimize in certain engines. var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } (function () { try { if (typeof setTimeout === 'function') { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } } ()) function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); }; process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; /***/ }, /* 5 */ /***/ function(module, exports) { module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } /***/ }, /* 6 */ /***/ function(module, exports) { if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { var EventEmitter = __webpack_require__(2); var Sequencer = __webpack_require__(8); var Thread = __webpack_require__(10); var util = __webpack_require__(3); // Virtual I/O devices. var Clock = __webpack_require__(12); var Keyboard = __webpack_require__(13); var Mouse = __webpack_require__(16); var defaultBlockPackages = { 'scratch3_control': __webpack_require__(18), 'scratch3_event': __webpack_require__(29), 'scratch3_looks': __webpack_require__(30), 'scratch3_motion': __webpack_require__(31), 'scratch3_operators': __webpack_require__(32), 'scratch3_sensing': __webpack_require__(33) }; /** * Manages targets, scripts, and the sequencer. */ function Runtime () { // Bind event emitter EventEmitter.call(this); // State for the runtime /** * Target management and storage. * @type {Array.} */ this.targets = []; /** * A list of threads that are currently running in the VM. * Threads are added when execution starts and pruned when execution ends. * @type {Array.} */ this.threads = []; /** @type {!Sequencer} */ this.sequencer = new Sequencer(this); /** * Map to look up a block primitive's implementation function by its opcode. * This is a two-step lookup: package name first, then primitive name. * @type {Object.} */ this._primitives = {}; this._hats = {}; this._edgeActivatedHatValues = {}; this._registerBlockPackages(); this.ioDevices = { 'clock': new Clock(), 'keyboard': new Keyboard(this), 'mouse': new Mouse(this) }; this._scriptGlowsPreviousFrame = []; this._editingTarget = null; /** * Currently known number of clones. * @type {number} */ this._cloneCounter = 0; } /** * Event name for glowing a script. * @const {string} */ Runtime.SCRIPT_GLOW_ON = 'STACK_GLOW_ON'; /** * Event name for unglowing a script. * @const {string} */ Runtime.SCRIPT_GLOW_OFF = 'STACK_GLOW_OFF'; /** * Event name for glowing a block. * @const {string} */ Runtime.BLOCK_GLOW_ON = 'BLOCK_GLOW_ON'; /** * Event name for unglowing a block. * @const {string} */ Runtime.BLOCK_GLOW_OFF = 'BLOCK_GLOW_OFF'; /** * Event name for visual value report. * @const {string} */ Runtime.VISUAL_REPORT = 'VISUAL_REPORT'; /** * Inherit from EventEmitter */ util.inherits(Runtime, EventEmitter); /** * How rapidly we try to step threads, in ms. */ Runtime.THREAD_STEP_INTERVAL = 1000 / 60; /** * How many clones can be created at a time. * @const {number} */ Runtime.MAX_CLONES = 300; // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- /** * Register default block packages with this runtime. * @todo Prefix opcodes with package name. * @private */ Runtime.prototype._registerBlockPackages = function () { for (var packageName in defaultBlockPackages) { if (defaultBlockPackages.hasOwnProperty(packageName)) { // @todo pass a different runtime depending on package privilege? var packageObject = new (defaultBlockPackages[packageName])(this); // Collect primitives from package. if (packageObject.getPrimitives) { var packagePrimitives = packageObject.getPrimitives(); for (var op in packagePrimitives) { if (packagePrimitives.hasOwnProperty(op)) { this._primitives[op] = packagePrimitives[op].bind(packageObject); } } } // Collect hat metadata from package. if (packageObject.getHats) { var packageHats = packageObject.getHats(); for (var hatName in packageHats) { if (packageHats.hasOwnProperty(hatName)) { this._hats[hatName] = packageHats[hatName]; } } } } } }; /** * Retrieve the function associated with the given opcode. * @param {!string} opcode The opcode to look up. * @return {Function} The function which implements the opcode. */ Runtime.prototype.getOpcodeFunction = function (opcode) { return this._primitives[opcode]; }; // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- /** * Return whether an opcode represents a hat block. * @param {!string} opcode The opcode to look up. * @return {Boolean} True if the op is known to be a hat. */ Runtime.prototype.getIsHat = function (opcode) { return this._hats.hasOwnProperty(opcode); }; /** * Return whether an opcode represents an edge-activated hat block. * @param {!string} opcode The opcode to look up. * @return {Boolean} True if the op is known to be a edge-activated hat. */ Runtime.prototype.getIsEdgeActivatedHat = function (opcode) { return this._hats.hasOwnProperty(opcode) && this._hats[opcode].edgeActivated; }; /** * Update an edge-activated hat block value. * @param {!string} blockId ID of hat to store value for. * @param {*} newValue Value to store for edge-activated hat. * @return {*} The old value for the edge-activated hat. */ Runtime.prototype.updateEdgeActivatedValue = function (blockId, newValue) { var oldValue = this._edgeActivatedHatValues[blockId]; this._edgeActivatedHatValues[blockId] = newValue; return oldValue; }; /** * Clear all edge-activaed hat values. */ Runtime.prototype.clearEdgeActivatedValues = function () { this._edgeActivatedHatValues = {}; }; /** * Attach the renderer * @param {!RenderWebGL} renderer The renderer to attach */ Runtime.prototype.attachRenderer = function (renderer) { this.renderer = renderer; }; // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- /** * Create a thread and push it to the list of threads. * @param {!string} id ID of block that starts the stack. * @param {!Target} target Target to run thread on. * @return {!Thread} The newly created thread. */ Runtime.prototype._pushThread = function (id, target) { var thread = new Thread(id); thread.setTarget(target); thread.pushStack(id); this.threads.push(thread); return thread; }; /** * Remove a thread from the list of threads. * @param {?Thread} thread Thread object to remove from actives */ Runtime.prototype._removeThread = function (thread) { var i = this.threads.indexOf(thread); if (i > -1) { this.threads.splice(i, 1); } }; /** * Return whether a thread is currently active/running. * @param {?Thread} thread Thread object to check. * @return {Boolean} True if the thread is active/running. */ Runtime.prototype.isActiveThread = function (thread) { return this.threads.indexOf(thread) > -1; }; /** * Toggle a script. * @param {!string} topBlockId ID of block that starts the script. */ Runtime.prototype.toggleScript = function (topBlockId) { // Remove any existing thread. for (var i = 0; i < this.threads.length; i++) { if (this.threads[i].topBlock == topBlockId) { this._removeThread(this.threads[i]); return; } } // Otherwise add it. this._pushThread(topBlockId, this._editingTarget); }; /** * Run a function `f` for all scripts in a workspace. * `f` will be called with two parameters: * - the top block ID of the script. * - the target that owns the script. * @param {!Function} f Function to call for each script. * @param {Target=} opt_target Optionally, a target to restrict to. */ Runtime.prototype.allScriptsDo = function (f, opt_target) { var targets = this.targets; if (opt_target) { targets = [opt_target]; } for (var t = 0; t < targets.length; t++) { var target = targets[t]; var scripts = target.blocks.getScripts(); for (var j = 0; j < scripts.length; j++) { var topBlockId = scripts[j]; f(topBlockId, target); } } }; /** * Start all relevant hats. * @param {!string} requestedHatOpcode Opcode of hats to start. * @param {Object=} opt_matchFields Optionally, fields to match on the hat. * @param {Target=} opt_target Optionally, a target to restrict to. * @return {Array.} List of threads started by this function. */ Runtime.prototype.startHats = function (requestedHatOpcode, opt_matchFields, opt_target) { if (!this._hats.hasOwnProperty(requestedHatOpcode)) { // No known hat with this opcode. return; } var instance = this; var newThreads = []; // Consider all scripts, looking for hats with opcode `requestedHatOpcode`. this.allScriptsDo(function(topBlockId, target) { var potentialHatOpcode = target.blocks.getBlock(topBlockId).opcode; if (potentialHatOpcode !== requestedHatOpcode) { // Not the right hat. return; } // Match any requested fields. // For example: ensures that broadcasts match. // This needs to happen before the block is evaluated // (i.e., before the predicate can be run) because "broadcast and wait" // needs to have a precise collection of started threads. var hatFields = target.blocks.getFields(topBlockId); if (opt_matchFields) { for (var matchField in opt_matchFields) { if (hatFields[matchField].value !== opt_matchFields[matchField]) { // Field mismatch. return; } } } // Look up metadata for the relevant hat. var hatMeta = instance._hats[requestedHatOpcode]; if (hatMeta.restartExistingThreads) { // If `restartExistingThreads` is true, we should stop // any existing threads starting with the top block. for (var i = 0; i < instance.threads.length; i++) { if (instance.threads[i].topBlock === topBlockId && (!opt_target || instance.threads[i].target == opt_target)) { instance._removeThread(instance.threads[i]); } } } else { // If `restartExistingThreads` is false, we should // give up if any threads with the top block are running. for (var j = 0; j < instance.threads.length; j++) { if (instance.threads[j].topBlock === topBlockId && (!opt_target || instance.threads[j].target == opt_target)) { // Some thread is already running. return; } } } // Start the thread with this top block. newThreads.push(instance._pushThread(topBlockId, target)); }, opt_target); return newThreads; }; /** * Dispose of a target. * @param {!Target} target Target to dispose of. */ Runtime.prototype.disposeTarget = function (target) { // Allow target to do dispose actions. target.dispose(); // Remove from list of targets. var index = this.targets.indexOf(target); if (index > -1) { this.targets.splice(index, 1); } }; /** * Stop any threads acting on the target. * @param {!Target} target Target to stop threads for. */ Runtime.prototype.stopForTarget = function (target) { // Stop any threads on the target. for (var i = 0; i < this.threads.length; i++) { if (this.threads[i].target == target) { this._removeThread(this.threads[i]); } } }; /** * Start all threads that start with the green flag. */ Runtime.prototype.greenFlag = function () { this.stopAll(); this.ioDevices.clock.resetProjectTimer(); this.clearEdgeActivatedValues(); this.startHats('event_whenflagclicked'); }; /** * Stop "everything." */ Runtime.prototype.stopAll = function () { // Dispose all clones. var newTargets = []; for (var i = 0; i < this.targets.length; i++) { if (this.targets[i].hasOwnProperty('isOriginal') && !this.targets[i].isOriginal) { this.targets[i].dispose(); } else { newTargets.push(this.targets[i]); } } this.targets = newTargets; // Dispose all threads. var threadsCopy = this.threads.slice(); while (threadsCopy.length > 0) { var poppedThread = threadsCopy.pop(); this._removeThread(poppedThread); } }; /** * Repeatedly run `sequencer.stepThreads` and filter out * inactive threads after each iteration. */ Runtime.prototype._step = function () { // Find all edge-activated hats, and add them to threads to be evaluated. for (var hatType in this._hats) { var hat = this._hats[hatType]; if (hat.edgeActivated) { this.startHats(hatType); } } var inactiveThreads = this.sequencer.stepThreads(this.threads); this._updateScriptGlows(); for (var i = 0; i < inactiveThreads.length; i++) { this._removeThread(inactiveThreads[i]); } }; Runtime.prototype.setEditingTarget = function (editingTarget) { this._scriptGlowsPreviousFrame = []; this._editingTarget = editingTarget; this._updateScriptGlows(); }; Runtime.prototype._updateScriptGlows = function () { // Set of scripts that request a glow this frame. var requestedGlowsThisFrame = []; // Final set of scripts glowing during this frame. var finalScriptGlows = []; // Find all scripts that should be glowing. for (var i = 0; i < this.threads.length; i++) { var thread = this.threads[i]; var target = thread.target; if (thread.requestScriptGlowInFrame && target == this._editingTarget) { var blockForThread = thread.peekStack() || thread.topBlock; var script = target.blocks.getTopLevelScript(blockForThread); if (script) { requestedGlowsThisFrame.push(script); } } } // Compare to previous frame. for (var j = 0; j < this._scriptGlowsPreviousFrame.length; j++) { var previousFrameGlow = this._scriptGlowsPreviousFrame[j]; if (requestedGlowsThisFrame.indexOf(previousFrameGlow) < 0) { // Glow turned off. this.glowScript(previousFrameGlow, false); } else { // Still glowing. finalScriptGlows.push(previousFrameGlow); } } for (var k = 0; k < requestedGlowsThisFrame.length; k++) { var currentFrameGlow = requestedGlowsThisFrame[k]; if (this._scriptGlowsPreviousFrame.indexOf(currentFrameGlow) < 0) { // Glow turned on. this.glowScript(currentFrameGlow, true); finalScriptGlows.push(currentFrameGlow); } } this._scriptGlowsPreviousFrame = finalScriptGlows; }; /** * "Quiet" a script's glow: stop the VM from generating glow/unglow events * about that script. Use when a script has just been deleted, but we may * still be tracking glow data about it. * @param {!string} scriptBlockId Id of top-level block in script to quiet. */ Runtime.prototype.quietGlow = function (scriptBlockId) { var index = this._scriptGlowsPreviousFrame.indexOf(scriptBlockId); if (index > -1) { this._scriptGlowsPreviousFrame.splice(index, 1); } }; /** * Emit feedback for block glowing (used in the sequencer). * @param {?string} blockId ID for the block to update glow * @param {boolean} isGlowing True to turn on glow; false to turn off. */ Runtime.prototype.glowBlock = function (blockId, isGlowing) { if (isGlowing) { this.emit(Runtime.BLOCK_GLOW_ON, blockId); } else { this.emit(Runtime.BLOCK_GLOW_OFF, blockId); } }; /** * Emit feedback for script glowing. * @param {?string} topBlockId ID for the top block to update glow * @param {boolean} isGlowing True to turn on glow; false to turn off. */ Runtime.prototype.glowScript = function (topBlockId, isGlowing) { if (isGlowing) { this.emit(Runtime.SCRIPT_GLOW_ON, topBlockId); } else { this.emit(Runtime.SCRIPT_GLOW_OFF, topBlockId); } }; /** * Emit value for reporter to show in the blocks. * @param {string} blockId ID for the block. * @param {string} value Value to show associated with the block. */ Runtime.prototype.visualReport = function (blockId, value) { this.emit(Runtime.VISUAL_REPORT, blockId, String(value)); }; /** * Get a target by its id. * @param {string} targetId Id of target to find. * @return {?Target} The target, if found. */ Runtime.prototype.getTargetById = function (targetId) { for (var i = 0; i < this.targets.length; i++) { var target = this.targets[i]; if (target.id == targetId) { return target; } } }; /** * Get the first original (non-clone-block-created) sprite given a name. * @param {string} spriteName Name of sprite to look for. * @return {?Target} Target representing a sprite of the given name. */ Runtime.prototype.getSpriteTargetByName = function (spriteName) { for (var i = 0; i < this.targets.length; i++) { var target = this.targets[i]; if (target.sprite && target.sprite.name == spriteName) { return target; } } }; /** * Update the clone counter to track how many clones are created. * @param {number} changeAmount How many clones have been created/destroyed. */ Runtime.prototype.changeCloneCounter = function (changeAmount) { this._cloneCounter += changeAmount; }; /** * Return whether there are clones available. * @return {boolean} True until the number of clones hits Runtime.MAX_CLONES. */ Runtime.prototype.clonesAvailable = function () { return this._cloneCounter < Runtime.MAX_CLONES; }; /** * Get a target representing the Scratch stage, if one exists. * @return {?Target} The target, if found. */ Runtime.prototype.getTargetForStage = function () { for (var i = 0; i < this.targets.length; i++) { var target = this.targets[i]; if (target.isStage) { return target; } } }; /** * Handle an animation frame from the main thread. */ Runtime.prototype.animationFrame = function () { if (this.renderer) { this.renderer.draw(); } }; /** * Set up timers to repeatedly step in a browser */ Runtime.prototype.start = function () { self.setInterval(function() { this._step(); }.bind(this), Runtime.THREAD_STEP_INTERVAL); }; module.exports = Runtime; /***/ }, /* 8 */ /***/ function(module, exports, __webpack_require__) { var Timer = __webpack_require__(9); var Thread = __webpack_require__(10); var execute = __webpack_require__(11); function Sequencer (runtime) { /** * A utility timer for timing thread sequencing. * @type {!Timer} */ this.timer = new Timer(); /** * Reference to the runtime owning this sequencer. * @type {!Runtime} */ this.runtime = runtime; } /** * The sequencer does as much work as it can within WORK_TIME milliseconds, * then yields. This is essentially a rate-limiter for blocks. * In Scratch 2.0, this is set to 75% of the target stage frame-rate (30fps). * @const {!number} */ Sequencer.WORK_TIME = 10; /** * Step through all threads in `this.threads`, running them in order. * @param {Array.} threads List of which threads to step. * @return {Array.} All threads which have finished in this iteration. */ Sequencer.prototype.stepThreads = function (threads) { // Start counting toward WORK_TIME this.timer.start(); // List of threads which have been killed by this step. var inactiveThreads = []; // If all of the threads are yielding, we should yield. var numYieldingThreads = 0; // Clear all yield statuses that were for the previous frame. for (var t = 0; t < threads.length; t++) { if (threads[t].status === Thread.STATUS_YIELD_FRAME) { threads[t].setStatus(Thread.STATUS_RUNNING); } } // While there are still threads to run and we are within WORK_TIME, // continue executing threads. while (threads.length > 0 && threads.length > numYieldingThreads && this.timer.timeElapsed() < Sequencer.WORK_TIME) { // New threads at the end of the iteration. var newThreads = []; // Reset yielding thread count. numYieldingThreads = 0; // Attempt to run each thread one time for (var i = 0; i < threads.length; i++) { var activeThread = threads[i]; if (activeThread.status === Thread.STATUS_RUNNING) { // Normal-mode thread: step. this.startThread(activeThread); } else if (activeThread.status === Thread.STATUS_YIELD || activeThread.status === Thread.STATUS_YIELD_FRAME) { // Yielding thread: do nothing for this step. numYieldingThreads++; } if (activeThread.stack.length === 0 && activeThread.status === Thread.STATUS_DONE) { // Finished with this thread - tell runtime to clean it up. inactiveThreads.push(activeThread); } else { // Keep this thead in the loop. newThreads.push(activeThread); } } // Effectively filters out threads that have stopped. threads = newThreads; } return inactiveThreads; }; /** * Step the requested thread * @param {!Thread} thread Thread object to step */ Sequencer.prototype.startThread = function (thread) { var currentBlockId = thread.peekStack(); if (!currentBlockId) { // A "null block" - empty branch. // Yield for the frame. thread.popStack(); thread.setStatus(Thread.STATUS_YIELD_FRAME); return; } // Execute the current block execute(this, thread); // If the block executed without yielding and without doing control flow, // move to done. if (thread.status === Thread.STATUS_RUNNING && thread.peekStack() === currentBlockId) { this.proceedThread(thread); } }; /** * Step a thread into a block's branch. * @param {!Thread} thread Thread object to step to branch. * @param {Number} branchNum Which branch to step to (i.e., 1, 2). */ Sequencer.prototype.stepToBranch = function (thread, branchNum) { if (!branchNum) { branchNum = 1; } var currentBlockId = thread.peekStack(); var branchId = thread.target.blocks.getBranch( currentBlockId, branchNum ); if (branchId) { // Push branch ID to the thread's stack. thread.pushStack(branchId); } else { // Push null, so we come back to the current block. thread.pushStack(null); } }; /** * Step a thread into an input reporter, and manage its status appropriately. * @param {!Thread} thread Thread object to step to reporter. * @param {!string} blockId ID of reporter block. * @param {!string} inputName Name of input on parent block. * @return {boolean} True if yielded, false if it finished immediately. */ Sequencer.prototype.stepToReporter = function (thread, blockId, inputName) { var currentStackFrame = thread.peekStackFrame(); // Push to the stack to evaluate the reporter block. thread.pushStack(blockId); // Save name of input for `Thread.pushReportedValue`. currentStackFrame.waitingReporter = inputName; // Actually execute the block. this.startThread(thread); // If a reporter yielded, caller must wait for it to unyield. // The value will be populated once the reporter unyields, // and passed up to the currentStackFrame on next execution. return thread.status === Thread.STATUS_YIELD; }; /** * Finish stepping a thread and proceed it to the next block. * @param {!Thread} thread Thread object to proceed. */ Sequencer.prototype.proceedThread = function (thread) { var currentBlockId = thread.peekStack(); // Mark the status as done and proceed to the next block. // Pop from the stack - finished this level of execution. thread.popStack(); // Push next connected block, if there is one. var nextBlockId = thread.target.blocks.getNextBlock(currentBlockId); if (nextBlockId) { thread.pushStack(nextBlockId); } // If we can't find a next block to run, mark the thread as done. if (!thread.peekStack()) { thread.setStatus(Thread.STATUS_DONE); } }; /** * Retire a thread in the middle, without considering further blocks. * @param {!Thread} thread Thread object to retire. */ Sequencer.prototype.retireThread = function (thread) { thread.stack = []; thread.stackFrame = []; thread.requestScriptGlowInFrame = false; thread.setStatus(Thread.STATUS_DONE); }; module.exports = Sequencer; /***/ }, /* 9 */ /***/ function(module, exports) { /** * @fileoverview * A utility for accurately measuring time. * To use: * --- * var timer = new Timer(); * timer.start(); * ... pass some time ... * var timeDifference = timer.timeElapsed(); * --- * Or, you can use the `time` and `relativeTime` * to do some measurement yourself. */ /** * @constructor */ function Timer () {} /** * Used to store the start time of a timer action. * Updated when calling `timer.start`. */ Timer.prototype.startTime = 0; /** * Return the currently known absolute time, in ms precision. * @returns {number} ms elapsed since 1 January 1970 00:00:00 UTC. */ Timer.prototype.time = function () { if (Date.now) { return Date.now(); } else { return new Date().getTime(); } }; /** * Returns a time accurate relative to other times produced by this function. * If possible, will use sub-millisecond precision. * If not, will use millisecond precision. * Not guaranteed to produce the same absolute values per-system. * @returns {number} ms-scale accurate time relative to other relative times. */ Timer.prototype.relativeTime = function () { if (typeof self !== 'undefined' && self.performance && 'now' in self.performance) { return self.performance.now(); } else { return this.time(); } }; /** * Start a timer for measuring elapsed time, * at the most accurate precision possible. */ Timer.prototype.start = function () { this.startTime = this.relativeTime(); }; /** * Check time elapsed since `timer.start` was called. * @returns {number} Time elapsed, in ms (possibly sub-ms precision). */ Timer.prototype.timeElapsed = function () { return this.relativeTime() - this.startTime; }; module.exports = Timer; /***/ }, /* 10 */ /***/ function(module, exports) { /** * A thread is a running stack context and all the metadata needed. * @param {?string} firstBlock First block to execute in the thread. * @constructor */ function Thread (firstBlock) { /** * ID of top block of the thread * @type {!string} */ this.topBlock = firstBlock; /** * Stack for the thread. When the sequencer enters a control structure, * the block is pushed onto the stack so we know where to exit. * @type {Array.} */ this.stack = []; /** * Stack frames for the thread. Store metadata for the executing blocks. * @type {Array.} */ this.stackFrames = []; /** * Status of the thread, one of three states (below) * @type {number} */ this.status = 0; /* Thread.STATUS_RUNNING */ /** * Target of this thread. * @type {?Target} */ this.target = null; /** * Whether the thread requests its script to glow during this frame. * @type {boolean} */ this.requestScriptGlowInFrame = false; } /** * Thread status for initialized or running thread. * This is the default state for a thread - execution should run normally, * stepping from block to block. * @const */ Thread.STATUS_RUNNING = 0; /** * Thread status for a yielded thread. * Threads are in this state when a primitive has yielded; execution is paused * until the relevant primitive unyields. * @const */ Thread.STATUS_YIELD = 1; /** * Thread status for a single-frame yield. * @const */ Thread.STATUS_YIELD_FRAME = 2; /** * Thread status for a finished/done thread. * Thread is in this state when there are no more blocks to execute. * @const */ Thread.STATUS_DONE = 3; /** * Push stack and update stack frames appropriately. * @param {string} blockId Block ID to push to stack. */ Thread.prototype.pushStack = function (blockId) { this.stack.push(blockId); // Push an empty stack frame, if we need one. // Might not, if we just popped the stack. if (this.stack.length > this.stackFrames.length) { this.stackFrames.push({ reported: {}, // Collects reported input values. waitingReporter: null, // Name of waiting reporter. executionContext: {} // A context passed to block implementations. }); } }; /** * Pop last block on the stack and its stack frame. * @return {string} Block ID popped from the stack. */ Thread.prototype.popStack = function () { this.stackFrames.pop(); return this.stack.pop(); }; /** * Get top stack item. * @return {?string} Block ID on top of stack. */ Thread.prototype.peekStack = function () { return this.stack[this.stack.length - 1]; }; /** * Get top stack frame. * @return {?Object} Last stack frame stored on this thread. */ Thread.prototype.peekStackFrame = function () { return this.stackFrames[this.stackFrames.length - 1]; }; /** * Get stack frame above the current top. * @return {?Object} Second to last stack frame stored on this thread. */ Thread.prototype.peekParentStackFrame = function () { return this.stackFrames[this.stackFrames.length - 2]; }; /** * Push a reported value to the parent of the current stack frame. * @param {!Any} value Reported value to push. */ Thread.prototype.pushReportedValue = function (value) { var parentStackFrame = this.peekParentStackFrame(); if (parentStackFrame) { var waitingReporter = parentStackFrame.waitingReporter; parentStackFrame.reported[waitingReporter] = value; parentStackFrame.waitingReporter = null; } }; /** * Whether the current execution of a thread is at the top of the stack. * @return {Boolean} True if execution is at top of the stack. */ Thread.prototype.atStackTop = function () { return this.peekStack() === this.topBlock; }; /** * Set thread status. * @param {number} status Enum representing thread status. */ Thread.prototype.setStatus = function (status) { this.status = status; }; /** * Set thread target. * @param {?Target} target Target for this thread. */ Thread.prototype.setTarget = function (target) { this.target = target; }; /** * Get thread target. * @return {?Target} Target for this thread, if available. */ Thread.prototype.getTarget = function () { return this.target; }; module.exports = Thread; /***/ }, /* 11 */ /***/ function(module, exports, __webpack_require__) { var Thread = __webpack_require__(10); /** * Utility function to determine if a value is a Promise. * @param {*} value Value to check for a Promise. * @return {Boolean} True if the value appears to be a Promise. */ var isPromise = function (value) { return value && value.then && typeof value.then === 'function'; }; /** * Execute a block. * @param {!Sequencer} sequencer Which sequencer is executing. * @param {!Thread} thread Thread which to read and execute. */ var execute = function (sequencer, thread) { var runtime = sequencer.runtime; var target = thread.target; // Current block to execute is the one on the top of the stack. var currentBlockId = thread.peekStack(); var currentStackFrame = thread.peekStackFrame(); // Verify that the block still exists. if (!target || typeof target.blocks.getBlock(currentBlockId) === 'undefined') { // No block found: stop the thread; script no longer exists. sequencer.retireThread(thread); return; } // Query info about the block. var opcode = target.blocks.getOpcode(currentBlockId); var blockFunction = runtime.getOpcodeFunction(opcode); var isHat = runtime.getIsHat(opcode); var fields = target.blocks.getFields(currentBlockId); var inputs = target.blocks.getInputs(currentBlockId); if (!opcode) { console.warn('Could not get opcode for block: ' + currentBlockId); return; } /** * Handle any reported value from the primitive, either directly returned * or after a promise resolves. * @param {*} resolvedValue Value eventually returned from the primitive. */ var handleReport = function (resolvedValue) { thread.pushReportedValue(resolvedValue); if (isHat) { // Hat predicate was evaluated. if (runtime.getIsEdgeActivatedHat(opcode)) { // If this is an edge-activated hat, only proceed if // the value is true and used to be false. var oldEdgeValue = runtime.updateEdgeActivatedValue( currentBlockId, resolvedValue ); var edgeWasActivated = !oldEdgeValue && resolvedValue; if (!edgeWasActivated) { sequencer.retireThread(thread); } } else { // Not an edge-activated hat: retire the thread // if predicate was false. if (!resolvedValue) { sequencer.retireThread(thread); } } } else { // In a non-hat, report the value visually if necessary if // at the top of the thread stack. if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) { runtime.visualReport(currentBlockId, resolvedValue); } // Finished any yields. thread.setStatus(Thread.STATUS_RUNNING); } }; // Hats and single-field shadows are implemented slightly differently // from regular blocks. // For hats: if they have an associated block function, // it's treated as a predicate; if not, execution will proceed as a no-op. // For single-field shadows: If the block has a single field, and no inputs, // immediately return the value of the field. if (!blockFunction) { if (isHat) { // Skip through the block (hat with no predicate). return; } else { if (Object.keys(fields).length == 1 && Object.keys(inputs).length == 0) { // One field and no inputs - treat as arg. for (var fieldKey in fields) { // One iteration. handleReport(fields[fieldKey].value); } } else { console.warn('Could not get implementation for opcode: ' + opcode); } thread.requestScriptGlowInFrame = true; return; } } // Generate values for arguments (inputs). var argValues = {}; // Add all fields on this block to the argValues. for (var fieldName in fields) { argValues[fieldName] = fields[fieldName].value; } // Recursively evaluate input blocks. for (var inputName in inputs) { var input = inputs[inputName]; var inputBlockId = input.block; // Is there no value for this input waiting in the stack frame? if (typeof currentStackFrame.reported[inputName] === 'undefined') { // If there's not, we need to evaluate the block. var reporterYielded = ( sequencer.stepToReporter(thread, inputBlockId, inputName) ); // If the reporter yielded, return immediately; // it needs time to finish and report its value. if (reporterYielded) { return; } } argValues[inputName] = currentStackFrame.reported[inputName]; } // If we've gotten this far, all of the input blocks are evaluated, // and `argValues` is fully populated. So, execute the block primitive. // First, clear `currentStackFrame.reported`, so any subsequent execution // (e.g., on return from a branch) gets fresh inputs. currentStackFrame.reported = {}; var primitiveReportedValue = null; primitiveReportedValue = blockFunction(argValues, { stackFrame: currentStackFrame.executionContext, target: target, yield: function() { thread.setStatus(Thread.STATUS_YIELD); }, yieldFrame: function() { thread.setStatus(Thread.STATUS_YIELD_FRAME); }, done: function() { thread.setStatus(Thread.STATUS_RUNNING); sequencer.proceedThread(thread); }, startBranch: function (branchNum) { sequencer.stepToBranch(thread, branchNum); }, startHats: function(requestedHat, opt_matchFields, opt_target) { return ( runtime.startHats(requestedHat, opt_matchFields, opt_target) ); }, ioQuery: function (device, func, args) { // Find the I/O device and execute the query/function call. if (runtime.ioDevices[device] && runtime.ioDevices[device][func]) { var devObject = runtime.ioDevices[device]; return devObject[func].call(devObject, args); } } }); if (typeof primitiveReportedValue === 'undefined') { // No value reported - potentially a command block. // Edge-activated hats don't request a glow; all commands do. thread.requestScriptGlowInFrame = true; } // If it's a promise, wait until promise resolves. if (isPromise(primitiveReportedValue)) { if (thread.status === Thread.STATUS_RUNNING) { // Primitive returned a promise; automatically yield thread. thread.setStatus(Thread.STATUS_YIELD); } // Promise handlers primitiveReportedValue.then(function(resolvedValue) { handleReport(resolvedValue); sequencer.proceedThread(thread); }, function(rejectionReason) { // Promise rejected: the primitive had some error. // Log it and proceed. console.warn('Primitive rejected promise: ', rejectionReason); thread.setStatus(Thread.STATUS_RUNNING); sequencer.proceedThread(thread); }); } else if (thread.status === Thread.STATUS_RUNNING) { handleReport(primitiveReportedValue); } }; module.exports = execute; /***/ }, /* 12 */ /***/ function(module, exports, __webpack_require__) { var Timer = __webpack_require__(9); function Clock () { this._projectTimer = new Timer(); this._projectTimer.start(); } Clock.prototype.projectTimer = function () { return this._projectTimer.timeElapsed() / 1000; }; Clock.prototype.resetProjectTimer = function () { this._projectTimer.start(); }; module.exports = Clock; /***/ }, /* 13 */ /***/ function(module, exports, __webpack_require__) { var Cast = __webpack_require__(14); function Keyboard (runtime) { /** * List of currently pressed keys. * @type{Array.} */ this._keysPressed = []; /** * Reference to the owning Runtime. * Can be used, for example, to activate hats. * @type{!Runtime} */ this.runtime = runtime; } /** * Convert a Scratch key name to a DOM keyCode. * @param {Any} keyName Scratch key argument. * @return {number} Key code corresponding to a DOM event. */ Keyboard.prototype._scratchKeyToKeyCode = function (keyName) { if (typeof keyName == 'number') { // Key codes placed in with number blocks. return keyName; } var keyString = Cast.toString(keyName); switch (keyString) { case 'space': return 32; case 'left arrow': return 37; case 'up arrow': return 38; case 'right arrow': return 39; case 'down arrow': return 40; // @todo: Consider adding other special keys here. } // Keys reported by DOM keyCode are upper case. return keyString.toUpperCase().charCodeAt(0); }; Keyboard.prototype._keyCodeToScratchKey = function (keyCode) { if (keyCode >= 48 && keyCode <= 90) { // Standard letter. return String.fromCharCode(keyCode).toLowerCase(); } switch (keyCode) { case 32: return 'space'; case 37: return 'left arrow'; case 38: return 'up arrow'; case 39: return 'right arrow'; case 40: return 'down arrow'; } return null; }; Keyboard.prototype.postData = function (data) { if (data.keyCode) { var index = this._keysPressed.indexOf(data.keyCode); if (data.isDown) { // If not already present, add to the list. if (index < 0) { this._keysPressed.push(data.keyCode); } // Always trigger hats, even if it was already pressed. this.runtime.startHats('event_whenkeypressed', { 'KEY_OPTION': this._keyCodeToScratchKey(data.keyCode) }); this.runtime.startHats('event_whenkeypressed', { 'KEY_OPTION': 'any' }); } else if (index > -1) { // If already present, remove from the list. this._keysPressed.splice(index, 1); } } }; Keyboard.prototype.getKeyIsDown = function (key) { if (key == 'any') { return this._keysPressed.length > 0; } var keyCode = this._scratchKeyToKeyCode(key); return this._keysPressed.indexOf(keyCode) > -1; }; module.exports = Keyboard; /***/ }, /* 14 */ /***/ function(module, exports, __webpack_require__) { var Color = __webpack_require__(15); function Cast () {} /** * @fileoverview * Utilities for casting and comparing Scratch data-types. * Scratch behaves slightly differently from JavaScript in many respects, * and these differences should be encapsulated below. * For example, in Scratch, add(1, join("hello", world")) -> 1. * This is because "hello world" is cast to 0. * In JavaScript, 1 + Number("hello" + "world") would give you NaN. * Use when coercing a value before computation. */ /** * Scratch cast to number. * Treats NaN as 0. * In Scratch 2.0, this is captured by `interp.numArg.` * @param {*} value Value to cast to number. * @return {number} The Scratch-casted number value. */ Cast.toNumber = function (value) { var n = Number(value); if (isNaN(n)) { // Scratch treats NaN as 0, when needed as a number. // E.g., 0 + NaN -> 0. return 0; } return n; }; /** * Scratch cast to boolean. * In Scratch 2.0, this is captured by `interp.boolArg.` * Treats some string values differently from JavaScript. * @param {*} value Value to cast to boolean. * @return {boolean} The Scratch-casted boolean value. */ Cast.toBoolean = function (value) { // Already a boolean? if (typeof value === 'boolean') { return value; } if (typeof value === 'string') { // These specific strings are treated as false in Scratch. if ((value == '') || (value == '0') || (value.toLowerCase() == 'false')) { return false; } // All other strings treated as true. return true; } // Coerce other values and numbers. return Boolean(value); }; /** * Scratch cast to string. * @param {*} value Value to cast to string. * @return {string} The Scratch-casted string value. */ Cast.toString = function (value) { return String(value); }; /** * Cast any Scratch argument to an RGB color object to be used for the renderer. * @param {*} value Value to convert to RGB color object. * @return {Array.} [r,g,b], values between 0-255. */ Cast.toRgbColorList = function (value) { var color; if (typeof value == 'string' && value.substring(0, 1) == '#') { color = Color.hexToRgb(value); } else { color = Color.decimalToRgb(Cast.toNumber(value)); } return [color.r, color.g, color.b]; }; /** * Compare two values, using Scratch cast, case-insensitive string compare, etc. * In Scratch 2.0, this is captured by `interp.compare.` * @param {*} v1 First value to compare. * @param {*} v2 Second value to compare. * @returns {Number} Negative number if v1 < v2; 0 if equal; positive otherwise. */ Cast.compare = function (v1, v2) { var n1 = Number(v1); var n2 = Number(v2); if (isNaN(n1) || isNaN(n2)) { // At least one argument can't be converted to a number. // Scratch compares strings as case insensitive. var s1 = String(v1).toLowerCase(); var s2 = String(v2).toLowerCase(); return s1.localeCompare(s2); } else { // Compare as numbers. return n1 - n2; } }; /** * Determine if a Scratch argument number represents a round integer. * @param {*} val Value to check. * @return {boolean} True if number looks like an integer. */ Cast.isInt = function (val) { // Values that are already numbers. if (typeof val === 'number') { if (isNaN(val)) { // NaN is considered an integer. return true; } // True if it's "round" (e.g., 2.0 and 2). return val == parseInt(val); } else if (typeof val === 'boolean') { // `True` and `false` always represent integer after Scratch cast. return true; } else if (typeof val === 'string') { // If it contains a decimal point, don't consider it an int. return val.indexOf('.') < 0; } return false; }; module.exports = Cast; /***/ }, /* 15 */ /***/ function(module, exports) { function Color () {} /** * Convert a Scratch decimal color to a hex string, #RRGGBB. * @param {number} decimal RGB color as a decimal. * @return {string} RGB color as #RRGGBB hex string. */ Color.decimalToHex = function (decimal) { if (decimal < 0) { decimal += 0xFFFFFF + 1; } var hex = Number(decimal).toString(16); hex = '#' + '000000'.substr(0, 6 - hex.length) + hex; return hex; }; /** * Convert a Scratch decimal color to an RGB color object. * @param {number} decimal RGB color as decimal. * @returns {Object} {r: R, g: G, b: B}, values between 0-255 */ Color.decimalToRgb = function (decimal) { var r = (decimal >> 16) & 0xFF; var g = (decimal >> 8) & 0xFF; var b = decimal & 0xFF; return {r: r, g: g, b: b}; }; /** * Convert a hex color (e.g., F00, #03F, #0033FF) to an RGB color object. * CC-BY-SA Tim Down: * https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb * @param {!string} hex Hex representation of the color. * @return {Object} {r: R, g: G, b: B}, 0-255, or null. */ Color.hexToRgb = function (hex) { var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; hex = hex.replace(shorthandRegex, function(m, r, g, b) { return r + r + g + g + b + b; }); var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; }; /** * Convert an RGB color object to a hex color. * @param {Object} rgb {r: R, g: G, b: B}, values between 0-255. * @return {!string} Hex representation of the color. */ Color.rgbToHex = function (rgb) { return Color.decimalToHex(Color.rgbToDecimal(rgb)); }; /** * Convert an RGB color object to a Scratch decimal color. * @param {Object} rgb {r: R, g: G, b: B}, values between 0-255. * @return {!number} Number representing the color. */ Color.rgbToDecimal = function (rgb) { return (rgb.r << 16) + (rgb.g << 8) + rgb.b; }; /** * Convert a hex color (e.g., F00, #03F, #0033FF) to a decimal color number. * @param {!string} hex Hex representation of the color. * @return {!number} Number representing the color. */ Color.hexToDecimal = function (hex) { return Color.rgbToDecimal(Color.hexToRgb(hex)); }; module.exports = Color; /***/ }, /* 16 */ /***/ function(module, exports, __webpack_require__) { var MathUtil = __webpack_require__(17); function Mouse (runtime) { this._x = 0; this._y = 0; this._isDown = false; /** * Reference to the owning Runtime. * Can be used, for example, to activate hats. * @type{!Runtime} */ this.runtime = runtime; } Mouse.prototype.postData = function(data) { if (data.x) { this._x = data.x - data.canvasWidth / 2; } if (data.y) { this._y = data.y - data.canvasHeight / 2; } if (typeof data.isDown !== 'undefined') { this._isDown = data.isDown; if (this._isDown) { this._activateClickHats(data.x, data.y); } } }; Mouse.prototype._activateClickHats = function (x, y) { if (this.runtime.renderer) { var drawableID = this.runtime.renderer.pick(x, y); for (var i = 0; i < this.runtime.targets.length; i++) { var target = this.runtime.targets[i]; if (target.hasOwnProperty('drawableID') && target.drawableID == drawableID) { this.runtime.startHats('event_whenthisspriteclicked', null, target); return; } } } }; Mouse.prototype.getX = function () { return MathUtil.clamp(this._x, -240, 240); }; Mouse.prototype.getY = function () { return MathUtil.clamp(-this._y, -180, 180); }; Mouse.prototype.getIsDown = function () { return this._isDown; }; module.exports = Mouse; /***/ }, /* 17 */ /***/ function(module, exports) { function MathUtil () {} /** * Convert a value from degrees to radians. * @param {!number} deg Value in degrees. * @return {!number} Equivalent value in radians. */ MathUtil.degToRad = function (deg) { return (Math.PI * (90 - deg)) / 180; }; /** * Convert a value from radians to degrees. * @param {!number} rad Value in radians. * @return {!number} Equivalent value in degrees. */ MathUtil.radToDeg = function (rad) { return rad * 180 / Math.PI; }; /** * Clamp a number between two limits. * If n < min, return min. If n > max, return max. Else, return n. * @param {!number} n Number to clamp. * @param {!number} min Minimum limit. * @param {!number} max Maximum limit. * @return {!number} Value of n clamped to min and max. */ MathUtil.clamp = function (n, min, max) { return Math.min(Math.max(n, min), max); }; /** * Keep a number between two limits, wrapping "extra" into the range. * e.g., wrapClamp(7, 1, 5) == 2 * wrapClamp(0, 1, 5) == 5 * wrapClamp(-11, -10, 6) == 6, etc. * @param {!number} n Number to wrap. * @param {!number} min Minimum limit. * @param {!number} max Maximum limit. * @return {!number} Value of n wrapped between min and max. */ MathUtil.wrapClamp = function (n, min, max) { var range = (max - min) + 1; return n - Math.floor((n - min) / range) * range; }; module.exports = MathUtil; /***/ }, /* 18 */ /***/ function(module, exports, __webpack_require__) { var Cast = __webpack_require__(14); var Promise = __webpack_require__(19); function Scratch3ControlBlocks(runtime) { /** * The runtime instantiating this block package. * @type {Runtime} */ this.runtime = runtime; } /** * Retrieve the block primitives implemented by this package. * @return {Object.} Mapping of opcode to Function. */ Scratch3ControlBlocks.prototype.getPrimitives = function() { return { 'control_repeat': this.repeat, 'control_repeat_until': this.repeatUntil, 'control_forever': this.forever, 'control_wait': this.wait, 'control_if': this.if, 'control_if_else': this.ifElse, 'control_stop': this.stop, 'control_create_clone_of_menu': this.createCloneMenu, 'control_create_clone_of': this.createClone, 'control_delete_this_clone': this.deleteClone }; }; Scratch3ControlBlocks.prototype.getHats = function () { return { 'control_start_as_clone': { restartExistingThreads: false } }; }; Scratch3ControlBlocks.prototype.repeat = function(args, util) { var times = Math.floor(Cast.toNumber(args.TIMES)); // Initialize loop if (util.stackFrame.loopCounter === undefined) { util.stackFrame.loopCounter = times; } // Only execute once per frame. // When the branch finishes, `repeat` will be executed again and // the second branch will be taken, yielding for the rest of the frame. if (!util.stackFrame.executedInFrame) { util.stackFrame.executedInFrame = true; // Decrease counter util.stackFrame.loopCounter--; // If we still have some left, start the branch. if (util.stackFrame.loopCounter >= 0) { util.startBranch(); } } else { util.stackFrame.executedInFrame = false; util.yieldFrame(); } }; Scratch3ControlBlocks.prototype.repeatUntil = function(args, util) { var condition = Cast.toBoolean(args.CONDITION); // Only execute once per frame. // When the branch finishes, `repeat` will be executed again and // the second branch will be taken, yielding for the rest of the frame. if (!util.stackFrame.executedInFrame) { util.stackFrame.executedInFrame = true; // If the condition is true, start the branch. if (!condition) { util.startBranch(); } } else { util.stackFrame.executedInFrame = false; util.yieldFrame(); } }; Scratch3ControlBlocks.prototype.forever = function(args, util) { // Only execute once per frame. // When the branch finishes, `forever` will be executed again and // the second branch will be taken, yielding for the rest of the frame. if (!util.stackFrame.executedInFrame) { util.stackFrame.executedInFrame = true; util.startBranch(); } else { util.stackFrame.executedInFrame = false; util.yieldFrame(); } }; Scratch3ControlBlocks.prototype.wait = function(args) { var duration = Cast.toNumber(args.DURATION); return new Promise(function(resolve) { setTimeout(function() { resolve(); }, 1000 * duration); }); }; Scratch3ControlBlocks.prototype.if = function(args, util) { var condition = Cast.toBoolean(args.CONDITION); // Only execute one time. `if` will be returned to // when the branch finishes, but it shouldn't execute again. if (util.stackFrame.executedInFrame === undefined) { util.stackFrame.executedInFrame = true; if (condition) { util.startBranch(); } } }; Scratch3ControlBlocks.prototype.ifElse = function(args, util) { var condition = Cast.toBoolean(args.CONDITION); // Only execute one time. `ifElse` will be returned to // when the branch finishes, but it shouldn't execute again. if (util.stackFrame.executedInFrame === undefined) { util.stackFrame.executedInFrame = true; if (condition) { util.startBranch(1); } else { util.startBranch(2); } } }; Scratch3ControlBlocks.prototype.stop = function() { // @todo - don't use this.runtime this.runtime.stopAll(); }; // @todo (GH-146): remove. Scratch3ControlBlocks.prototype.createCloneMenu = function (args) { return args.CLONE_OPTION; }; Scratch3ControlBlocks.prototype.createClone = function (args, util) { var cloneTarget; if (args.CLONE_OPTION == '_myself_') { cloneTarget = util.target; } else { cloneTarget = this.runtime.getSpriteTargetByName(args.CLONE_OPTION); } if (!cloneTarget) { return; } var newClone = cloneTarget.makeClone(); if (newClone) { this.runtime.targets.push(newClone); } }; Scratch3ControlBlocks.prototype.deleteClone = function (args, util) { this.runtime.disposeTarget(util.target); this.runtime.stopForTarget(util.target); }; module.exports = Scratch3ControlBlocks; /***/ }, /* 19 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; module.exports = __webpack_require__(20) /***/ }, /* 20 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; module.exports = __webpack_require__(21); __webpack_require__(23); __webpack_require__(24); __webpack_require__(25); __webpack_require__(26); __webpack_require__(28); /***/ }, /* 21 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var asap = __webpack_require__(22); function noop() {} // States: // // 0 - pending // 1 - fulfilled with _value // 2 - rejected with _value // 3 - adopted the state of another promise, _value // // once the state is no longer pending (0) it is immutable // All `_` prefixed properties will be reduced to `_{random number}` // at build time to obfuscate them and discourage their use. // We don't use symbols or Object.defineProperty to fully hide them // because the performance isn't good enough. // to avoid using try/catch inside critical functions, we // extract them to here. var LAST_ERROR = null; var IS_ERROR = {}; function getThen(obj) { try { return obj.then; } catch (ex) { LAST_ERROR = ex; return IS_ERROR; } } function tryCallOne(fn, a) { try { return fn(a); } catch (ex) { LAST_ERROR = ex; return IS_ERROR; } } function tryCallTwo(fn, a, b) { try { fn(a, b); } catch (ex) { LAST_ERROR = ex; return IS_ERROR; } } module.exports = Promise; function Promise(fn) { if (typeof this !== 'object') { throw new TypeError('Promises must be constructed via new'); } if (typeof fn !== 'function') { throw new TypeError('not a function'); } this._45 = 0; this._81 = 0; this._65 = null; this._54 = null; if (fn === noop) return; doResolve(fn, this); } Promise._10 = null; Promise._97 = null; Promise._61 = noop; Promise.prototype.then = function(onFulfilled, onRejected) { if (this.constructor !== Promise) { return safeThen(this, onFulfilled, onRejected); } var res = new Promise(noop); handle(this, new Handler(onFulfilled, onRejected, res)); return res; }; function safeThen(self, onFulfilled, onRejected) { return new self.constructor(function (resolve, reject) { var res = new Promise(noop); res.then(resolve, reject); handle(self, new Handler(onFulfilled, onRejected, res)); }); }; function handle(self, deferred) { while (self._81 === 3) { self = self._65; } if (Promise._10) { Promise._10(self); } if (self._81 === 0) { if (self._45 === 0) { self._45 = 1; self._54 = deferred; return; } if (self._45 === 1) { self._45 = 2; self._54 = [self._54, deferred]; return; } self._54.push(deferred); return; } handleResolved(self, deferred); } function handleResolved(self, deferred) { asap(function() { var cb = self._81 === 1 ? deferred.onFulfilled : deferred.onRejected; if (cb === null) { if (self._81 === 1) { resolve(deferred.promise, self._65); } else { reject(deferred.promise, self._65); } return; } var ret = tryCallOne(cb, self._65); if (ret === IS_ERROR) { reject(deferred.promise, LAST_ERROR); } else { resolve(deferred.promise, ret); } }); } function resolve(self, newValue) { // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure if (newValue === self) { return reject( self, new TypeError('A promise cannot be resolved with itself.') ); } if ( newValue && (typeof newValue === 'object' || typeof newValue === 'function') ) { var then = getThen(newValue); if (then === IS_ERROR) { return reject(self, LAST_ERROR); } if ( then === self.then && newValue instanceof Promise ) { self._81 = 3; self._65 = newValue; finale(self); return; } else if (typeof then === 'function') { doResolve(then.bind(newValue), self); return; } } self._81 = 1; self._65 = newValue; finale(self); } function reject(self, newValue) { self._81 = 2; self._65 = newValue; if (Promise._97) { Promise._97(self, newValue); } finale(self); } function finale(self) { if (self._45 === 1) { handle(self, self._54); self._54 = null; } if (self._45 === 2) { for (var i = 0; i < self._54.length; i++) { handle(self, self._54[i]); } self._54 = null; } } function Handler(onFulfilled, onRejected, promise){ this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; this.onRejected = typeof onRejected === 'function' ? onRejected : null; this.promise = promise; } /** * Take a potentially misbehaving resolver function and make sure * onFulfilled and onRejected are only called once. * * Makes no guarantees about asynchrony. */ function doResolve(fn, promise) { var done = false; var res = tryCallTwo(fn, function (value) { if (done) return; done = true; resolve(promise, value); }, function (reason) { if (done) return; done = true; reject(promise, reason); }) if (!done && res === IS_ERROR) { done = true; reject(promise, LAST_ERROR); } } /***/ }, /* 22 */ /***/ function(module, exports) { /* WEBPACK VAR INJECTION */(function(global) {"use strict"; // Use the fastest means possible to execute a task in its own turn, with // priority over other events including IO, animation, reflow, and redraw // events in browsers. // // An exception thrown by a task will permanently interrupt the processing of // subsequent tasks. The higher level `asap` function ensures that if an // exception is thrown by a task, that the task queue will continue flushing as // soon as possible, but if you use `rawAsap` directly, you are responsible to // either ensure that no exceptions are thrown from your task, or to manually // call `rawAsap.requestFlush` if an exception is thrown. module.exports = rawAsap; function rawAsap(task) { if (!queue.length) { requestFlush(); flushing = true; } // Equivalent to push, but avoids a function call. queue[queue.length] = task; } var queue = []; // Once a flush has been requested, no further calls to `requestFlush` are // necessary until the next `flush` completes. var flushing = false; // `requestFlush` is an implementation-specific method that attempts to kick // off a `flush` event as quickly as possible. `flush` will attempt to exhaust // the event queue before yielding to the browser's own event loop. var requestFlush; // The position of the next task to execute in the task queue. This is // preserved between calls to `flush` so that it can be resumed if // a task throws an exception. var index = 0; // If a task schedules additional tasks recursively, the task queue can grow // unbounded. To prevent memory exhaustion, the task queue will periodically // truncate already-completed tasks. var capacity = 1024; // The flush function processes all tasks that have been scheduled with // `rawAsap` unless and until one of those tasks throws an exception. // If a task throws an exception, `flush` ensures that its state will remain // consistent and will resume where it left off when called again. // However, `flush` does not make any arrangements to be called again if an // exception is thrown. function flush() { while (index < queue.length) { var currentIndex = index; // Advance the index before calling the task. This ensures that we will // begin flushing on the next task the task throws an error. index = index + 1; queue[currentIndex].call(); // Prevent leaking memory for long chains of recursive calls to `asap`. // If we call `asap` within tasks scheduled by `asap`, the queue will // grow, but to avoid an O(n) walk for every task we execute, we don't // shift tasks off the queue after they have been executed. // Instead, we periodically shift 1024 tasks off the queue. if (index > capacity) { // Manually shift all values starting at the index back to the // beginning of the queue. for (var scan = 0, newLength = queue.length - index; scan < newLength; scan++) { queue[scan] = queue[scan + index]; } queue.length -= index; index = 0; } } queue.length = 0; index = 0; flushing = false; } // `requestFlush` is implemented using a strategy based on data collected from // every available SauceLabs Selenium web driver worker at time of writing. // https://docs.google.com/spreadsheets/d/1mG-5UYGup5qxGdEMWkhP6BWCz053NUb2E1QoUTU16uA/edit#gid=783724593 // Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that // have WebKitMutationObserver but not un-prefixed MutationObserver. // Must use `global` instead of `window` to work in both frames and web // workers. `global` is a provision of Browserify, Mr, Mrs, or Mop. var BrowserMutationObserver = global.MutationObserver || global.WebKitMutationObserver; // MutationObservers are desirable because they have high priority and work // reliably everywhere they are implemented. // They are implemented in all modern browsers. // // - Android 4-4.3 // - Chrome 26-34 // - Firefox 14-29 // - Internet Explorer 11 // - iPad Safari 6-7.1 // - iPhone Safari 7-7.1 // - Safari 6-7 if (typeof BrowserMutationObserver === "function") { requestFlush = makeRequestCallFromMutationObserver(flush); // MessageChannels are desirable because they give direct access to the HTML // task queue, are implemented in Internet Explorer 10, Safari 5.0-1, and Opera // 11-12, and in web workers in many engines. // Although message channels yield to any queued rendering and IO tasks, they // would be better than imposing the 4ms delay of timers. // However, they do not work reliably in Internet Explorer or Safari. // Internet Explorer 10 is the only browser that has setImmediate but does // not have MutationObservers. // Although setImmediate yields to the browser's renderer, it would be // preferrable to falling back to setTimeout since it does not have // the minimum 4ms penalty. // Unfortunately there appears to be a bug in Internet Explorer 10 Mobile (and // Desktop to a lesser extent) that renders both setImmediate and // MessageChannel useless for the purposes of ASAP. // https://github.com/kriskowal/q/issues/396 // Timers are implemented universally. // We fall back to timers in workers in most engines, and in foreground // contexts in the following browsers. // However, note that even this simple case requires nuances to operate in a // broad spectrum of browsers. // // - Firefox 3-13 // - Internet Explorer 6-9 // - iPad Safari 4.3 // - Lynx 2.8.7 } else { requestFlush = makeRequestCallFromTimer(flush); } // `requestFlush` requests that the high priority event queue be flushed as // soon as possible. // This is useful to prevent an error thrown in a task from stalling the event // queue if the exception handled by Node.js’s // `process.on("uncaughtException")` or by a domain. rawAsap.requestFlush = requestFlush; // To request a high priority event, we induce a mutation observer by toggling // the text of a text node between "1" and "-1". function makeRequestCallFromMutationObserver(callback) { var toggle = 1; var observer = new BrowserMutationObserver(callback); var node = document.createTextNode(""); observer.observe(node, {characterData: true}); return function requestCall() { toggle = -toggle; node.data = toggle; }; } // The message channel technique was discovered by Malte Ubl and was the // original foundation for this library. // http://www.nonblocking.io/2011/06/windownexttick.html // Safari 6.0.5 (at least) intermittently fails to create message ports on a // page's first load. Thankfully, this version of Safari supports // MutationObservers, so we don't need to fall back in that case. // function makeRequestCallFromMessageChannel(callback) { // var channel = new MessageChannel(); // channel.port1.onmessage = callback; // return function requestCall() { // channel.port2.postMessage(0); // }; // } // For reasons explained above, we are also unable to use `setImmediate` // under any circumstances. // Even if we were, there is another bug in Internet Explorer 10. // It is not sufficient to assign `setImmediate` to `requestFlush` because // `setImmediate` must be called *by name* and therefore must be wrapped in a // closure. // Never forget. // function makeRequestCallFromSetImmediate(callback) { // return function requestCall() { // setImmediate(callback); // }; // } // Safari 6.0 has a problem where timers will get lost while the user is // scrolling. This problem does not impact ASAP because Safari 6.0 supports // mutation observers, so that implementation is used instead. // However, if we ever elect to use timers in Safari, the prevalent work-around // is to add a scroll event listener that calls for a flush. // `setTimeout` does not call the passed callback if the delay is less than // approximately 7 in web workers in Firefox 8 through 18, and sometimes not // even then. function makeRequestCallFromTimer(callback) { return function requestCall() { // We dispatch a timeout with a specified delay of 0 for engines that // can reliably accommodate that request. This will usually be snapped // to a 4 milisecond delay, but once we're flushing, there's no delay // between events. var timeoutHandle = setTimeout(handleTimer, 0); // However, since this timer gets frequently dropped in Firefox // workers, we enlist an interval handle that will try to fire // an event 20 times per second until it succeeds. var intervalHandle = setInterval(handleTimer, 50); function handleTimer() { // Whichever timer succeeds will cancel both timers and // execute the callback. clearTimeout(timeoutHandle); clearInterval(intervalHandle); callback(); } }; } // This is for `asap.js` only. // Its name will be periodically randomized to break any code that depends on // its existence. rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer; // ASAP was originally a nextTick shim included in Q. This was factored out // into this ASAP package. It was later adapted to RSVP which made further // amendments. These decisions, particularly to marginalize MessageChannel and // to capture the MutationObserver implementation in a closure, were integrated // back into ASAP proper. // https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) /***/ }, /* 23 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var Promise = __webpack_require__(21); module.exports = Promise; Promise.prototype.done = function (onFulfilled, onRejected) { var self = arguments.length ? this.then.apply(this, arguments) : this; self.then(null, function (err) { setTimeout(function () { throw err; }, 0); }); }; /***/ }, /* 24 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var Promise = __webpack_require__(21); module.exports = Promise; Promise.prototype['finally'] = function (f) { return this.then(function (value) { return Promise.resolve(f()).then(function () { return value; }); }, function (err) { return Promise.resolve(f()).then(function () { throw err; }); }); }; /***/ }, /* 25 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; //This file contains the ES6 extensions to the core Promises/A+ API var Promise = __webpack_require__(21); module.exports = Promise; /* Static Functions */ var TRUE = valuePromise(true); var FALSE = valuePromise(false); var NULL = valuePromise(null); var UNDEFINED = valuePromise(undefined); var ZERO = valuePromise(0); var EMPTYSTRING = valuePromise(''); function valuePromise(value) { var p = new Promise(Promise._61); p._81 = 1; p._65 = value; return p; } Promise.resolve = function (value) { if (value instanceof Promise) return value; if (value === null) return NULL; if (value === undefined) return UNDEFINED; if (value === true) return TRUE; if (value === false) return FALSE; if (value === 0) return ZERO; if (value === '') return EMPTYSTRING; if (typeof value === 'object' || typeof value === 'function') { try { var then = value.then; if (typeof then === 'function') { return new Promise(then.bind(value)); } } catch (ex) { return new Promise(function (resolve, reject) { reject(ex); }); } } return valuePromise(value); }; Promise.all = function (arr) { var args = Array.prototype.slice.call(arr); return new Promise(function (resolve, reject) { if (args.length === 0) return resolve([]); var remaining = args.length; function res(i, val) { if (val && (typeof val === 'object' || typeof val === 'function')) { if (val instanceof Promise && val.then === Promise.prototype.then) { while (val._81 === 3) { val = val._65; } if (val._81 === 1) return res(i, val._65); if (val._81 === 2) reject(val._65); val.then(function (val) { res(i, val); }, reject); return; } else { var then = val.then; if (typeof then === 'function') { var p = new Promise(then.bind(val)); p.then(function (val) { res(i, val); }, reject); return; } } } args[i] = val; if (--remaining === 0) { resolve(args); } } for (var i = 0; i < args.length; i++) { res(i, args[i]); } }); }; Promise.reject = function (value) { return new Promise(function (resolve, reject) { reject(value); }); }; Promise.race = function (values) { return new Promise(function (resolve, reject) { values.forEach(function(value){ Promise.resolve(value).then(resolve, reject); }); }); }; /* Prototype Methods */ Promise.prototype['catch'] = function (onRejected) { return this.then(null, onRejected); }; /***/ }, /* 26 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; // This file contains then/promise specific extensions that are only useful // for node.js interop var Promise = __webpack_require__(21); var asap = __webpack_require__(27); module.exports = Promise; /* Static Functions */ Promise.denodeify = function (fn, argumentCount) { if ( typeof argumentCount === 'number' && argumentCount !== Infinity ) { return denodeifyWithCount(fn, argumentCount); } else { return denodeifyWithoutCount(fn); } } var callbackFn = ( 'function (err, res) {' + 'if (err) { rj(err); } else { rs(res); }' + '}' ); function denodeifyWithCount(fn, argumentCount) { var args = []; for (var i = 0; i < argumentCount; i++) { args.push('a' + i); } var body = [ 'return function (' + args.join(',') + ') {', 'var self = this;', 'return new Promise(function (rs, rj) {', 'var res = fn.call(', ['self'].concat(args).concat([callbackFn]).join(','), ');', 'if (res &&', '(typeof res === "object" || typeof res === "function") &&', 'typeof res.then === "function"', ') {rs(res);}', '});', '};' ].join(''); return Function(['Promise', 'fn'], body)(Promise, fn); } function denodeifyWithoutCount(fn) { var fnLength = Math.max(fn.length - 1, 3); var args = []; for (var i = 0; i < fnLength; i++) { args.push('a' + i); } var body = [ 'return function (' + args.join(',') + ') {', 'var self = this;', 'var args;', 'var argLength = arguments.length;', 'if (arguments.length > ' + fnLength + ') {', 'args = new Array(arguments.length + 1);', 'for (var i = 0; i < arguments.length; i++) {', 'args[i] = arguments[i];', '}', '}', 'return new Promise(function (rs, rj) {', 'var cb = ' + callbackFn + ';', 'var res;', 'switch (argLength) {', args.concat(['extra']).map(function (_, index) { return ( 'case ' + (index) + ':' + 'res = fn.call(' + ['self'].concat(args.slice(0, index)).concat('cb').join(',') + ');' + 'break;' ); }).join(''), 'default:', 'args[argLength] = cb;', 'res = fn.apply(self, args);', '}', 'if (res &&', '(typeof res === "object" || typeof res === "function") &&', 'typeof res.then === "function"', ') {rs(res);}', '});', '};' ].join(''); return Function( ['Promise', 'fn'], body )(Promise, fn); } Promise.nodeify = function (fn) { return function () { var args = Array.prototype.slice.call(arguments); var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null; var ctx = this; try { return fn.apply(this, arguments).nodeify(callback, ctx); } catch (ex) { if (callback === null || typeof callback == 'undefined') { return new Promise(function (resolve, reject) { reject(ex); }); } else { asap(function () { callback.call(ctx, ex); }) } } } } Promise.prototype.nodeify = function (callback, ctx) { if (typeof callback != 'function') return this; this.then(function (value) { asap(function () { callback.call(ctx, null, value); }); }, function (err) { asap(function () { callback.call(ctx, err); }); }); } /***/ }, /* 27 */ /***/ function(module, exports, __webpack_require__) { "use strict"; // rawAsap provides everything we need except exception management. var rawAsap = __webpack_require__(22); // RawTasks are recycled to reduce GC churn. var freeTasks = []; // We queue errors to ensure they are thrown in right order (FIFO). // Array-as-queue is good enough here, since we are just dealing with exceptions. var pendingErrors = []; var requestErrorThrow = rawAsap.makeRequestCallFromTimer(throwFirstError); function throwFirstError() { if (pendingErrors.length) { throw pendingErrors.shift(); } } /** * Calls a task as soon as possible after returning, in its own event, with priority * over other events like animation, reflow, and repaint. An error thrown from an * event will not interrupt, nor even substantially slow down the processing of * other events, but will be rather postponed to a lower priority event. * @param {{call}} task A callable object, typically a function that takes no * arguments. */ module.exports = asap; function asap(task) { var rawTask; if (freeTasks.length) { rawTask = freeTasks.pop(); } else { rawTask = new RawTask(); } rawTask.task = task; rawAsap(rawTask); } // We wrap tasks with recyclable task objects. A task object implements // `call`, just like a function. function RawTask() { this.task = null; } // The sole purpose of wrapping the task is to catch the exception and recycle // the task object after its single use. RawTask.prototype.call = function () { try { this.task.call(); } catch (error) { if (asap.onerror) { // This hook exists purely for testing purposes. // Its name will be periodically randomized to break any code that // depends on its existence. asap.onerror(error); } else { // In a web browser, exceptions are not fatal. However, to avoid // slowing down the queue of pending tasks, we rethrow the error in a // lower priority turn. pendingErrors.push(error); requestErrorThrow(); } } finally { this.task = null; freeTasks[freeTasks.length] = this; } }; /***/ }, /* 28 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var Promise = __webpack_require__(21); module.exports = Promise; Promise.enableSynchronous = function () { Promise.prototype.isPending = function() { return this.getState() == 0; }; Promise.prototype.isFulfilled = function() { return this.getState() == 1; }; Promise.prototype.isRejected = function() { return this.getState() == 2; }; Promise.prototype.getValue = function () { if (this._81 === 3) { return this._65.getValue(); } if (!this.isFulfilled()) { throw new Error('Cannot get a value of an unfulfilled promise.'); } return this._65; }; Promise.prototype.getReason = function () { if (this._81 === 3) { return this._65.getReason(); } if (!this.isRejected()) { throw new Error('Cannot get a rejection reason of a non-rejected promise.'); } return this._65; }; Promise.prototype.getState = function () { if (this._81 === 3) { return this._65.getState(); } if (this._81 === -1 || this._81 === -2) { return 0; } return this._81; }; }; Promise.disableSynchronous = function() { Promise.prototype.isPending = undefined; Promise.prototype.isFulfilled = undefined; Promise.prototype.isRejected = undefined; Promise.prototype.getValue = undefined; Promise.prototype.getReason = undefined; Promise.prototype.getState = undefined; }; /***/ }, /* 29 */ /***/ function(module, exports, __webpack_require__) { var Cast = __webpack_require__(14); function Scratch3EventBlocks(runtime) { /** * The runtime instantiating this block package. * @type {Runtime} */ this.runtime = runtime; } /** * Retrieve the block primitives implemented by this package. * @return {Object.} Mapping of opcode to Function. */ Scratch3EventBlocks.prototype.getPrimitives = function() { return { 'event_broadcast': this.broadcast, 'event_broadcastandwait': this.broadcastAndWait, 'event_whengreaterthan': this.hatGreaterThanPredicate }; }; Scratch3EventBlocks.prototype.getHats = function () { return { 'event_whenflagclicked': { restartExistingThreads: true }, 'event_whenkeypressed': { restartExistingThreads: false }, 'event_whenthisspriteclicked': { restartExistingThreads: true }, 'event_whenbackdropswitchesto': { restartExistingThreads: true }, 'event_whengreaterthan': { restartExistingThreads: false, edgeActivated: true }, 'event_whenbroadcastreceived': { restartExistingThreads: true } }; }; Scratch3EventBlocks.prototype.hatGreaterThanPredicate = function (args, util) { var option = Cast.toString(args.WHENGREATERTHANMENU).toLowerCase(); var value = Cast.toNumber(args.VALUE); // @todo: Other cases :) if (option == 'timer') { return util.ioQuery('clock', 'projectTimer') > value; } return false; }; Scratch3EventBlocks.prototype.broadcast = function(args, util) { var broadcastOption = Cast.toString(args.BROADCAST_OPTION); util.startHats('event_whenbroadcastreceived', { 'BROADCAST_OPTION': broadcastOption }); }; Scratch3EventBlocks.prototype.broadcastAndWait = function (args, util) { var broadcastOption = Cast.toString(args.BROADCAST_OPTION); // Have we run before, starting threads? if (!util.stackFrame.startedThreads) { // No - start hats for this broadcast. util.stackFrame.startedThreads = util.startHats( 'event_whenbroadcastreceived', { 'BROADCAST_OPTION': broadcastOption } ); if (util.stackFrame.startedThreads.length == 0) { // Nothing was started. return; } } // We've run before; check if the wait is still going on. var instance = this; var waiting = util.stackFrame.startedThreads.some(function(thread) { return instance.runtime.isActiveThread(thread); }); if (waiting) { util.yieldFrame(); } }; module.exports = Scratch3EventBlocks; /***/ }, /* 30 */ /***/ function(module, exports, __webpack_require__) { var Cast = __webpack_require__(14); function Scratch3LooksBlocks(runtime) { /** * The runtime instantiating this block package. * @type {Runtime} */ this.runtime = runtime; } /** * Retrieve the block primitives implemented by this package. * @return {Object.} Mapping of opcode to Function. */ Scratch3LooksBlocks.prototype.getPrimitives = function() { return { 'looks_say': this.say, 'looks_sayforsecs': this.sayforsecs, 'looks_think': this.think, 'looks_thinkforsecs': this.sayforsecs, 'looks_show': this.show, 'looks_hide': this.hide, 'looks_switchcostumeto': this.switchCostume, 'looks_switchbackdropto': this.switchBackdrop, 'looks_switchbackdroptoandwait': this.switchBackdropAndWait, 'looks_nextcostume': this.nextCostume, 'looks_nextbackdrop': this.nextBackdrop, 'looks_changeeffectby': this.changeEffect, 'looks_seteffectto': this.setEffect, 'looks_cleargraphiceffects': this.clearEffects, 'looks_changesizeby': this.changeSize, 'looks_setsizeto': this.setSize, 'looks_size': this.getSize, 'looks_costumeorder': this.getCostumeIndex, 'looks_backdroporder': this.getBackdropIndex, 'looks_backdropname': this.getBackdropName }; }; Scratch3LooksBlocks.prototype.say = function (args, util) { util.target.setSay('say', args.MESSAGE); }; Scratch3LooksBlocks.prototype.sayforsecs = function (args, util) { util.target.setSay('say', args.MESSAGE); return new Promise(function(resolve) { setTimeout(function() { // Clear say bubble and proceed. util.target.setSay(); resolve(); }, 1000 * args.SECS); }); }; Scratch3LooksBlocks.prototype.think = function (args, util) { util.target.setSay('think', args.MESSAGE); }; Scratch3LooksBlocks.prototype.thinkforsecs = function (args, util) { util.target.setSay('think', args.MESSAGE); return new Promise(function(resolve) { setTimeout(function() { // Clear say bubble and proceed. util.target.setSay(); resolve(); }, 1000 * args.SECS); }); }; Scratch3LooksBlocks.prototype.show = function (args, util) { util.target.setVisible(true); }; Scratch3LooksBlocks.prototype.hide = function (args, util) { util.target.setVisible(false); }; /** * Utility function to set the costume or backdrop of a target. * Matches the behavior of Scratch 2.0 for different types of arguments. * @param {!Target} target Target to set costume/backdrop to. * @param {Any} requestedCostume Costume requested, e.g., 0, 'name', etc. * @param {boolean=} opt_zeroIndex Set to zero-index the requestedCostume. * @return {Array.} Any threads started by this switch. */ Scratch3LooksBlocks.prototype._setCostumeOrBackdrop = function (target, requestedCostume, opt_zeroIndex) { if (typeof requestedCostume === 'number') { target.setCostume(opt_zeroIndex ? requestedCostume : requestedCostume - 1); } else { var costumeIndex = target.getCostumeIndexByName(requestedCostume); if (costumeIndex > -1) { target.setCostume(costumeIndex); } else if (costumeIndex == 'previous costume' || costumeIndex == 'previous backdrop') { target.setCostume(target.currentCostume - 1); } else if (costumeIndex == 'next costume' || costumeIndex == 'next backdrop') { target.setCostume(target.currentCostume + 1); } else { var forcedNumber = Cast.toNumber(requestedCostume); if (!isNaN(forcedNumber)) { target.setCostume(opt_zeroIndex ? forcedNumber : forcedNumber - 1); } } } if (target == this.runtime.getTargetForStage()) { // Target is the stage - start hats. var newName = target.sprite.costumes[target.currentCostume].name; return this.runtime.startHats('event_whenbackdropswitchesto', { 'BACKDROP': newName }); } return []; }; Scratch3LooksBlocks.prototype.switchCostume = function (args, util) { this._setCostumeOrBackdrop(util.target, args.COSTUME); }; Scratch3LooksBlocks.prototype.nextCostume = function (args, util) { this._setCostumeOrBackdrop( util.target, util.target.currentCostume + 1, true ); }; Scratch3LooksBlocks.prototype.switchBackdrop = function (args) { this._setCostumeOrBackdrop(this.runtime.getTargetForStage(), args.BACKDROP); }; Scratch3LooksBlocks.prototype.switchBackdropAndWait = function (args, util) { // Have we run before, starting threads? if (!util.stackFrame.startedThreads) { // No - switch the backdrop. util.stackFrame.startedThreads = ( this._setCostumeOrBackdrop( this.runtime.getTargetForStage(), args.BACKDROP ) ); if (util.stackFrame.startedThreads.length == 0) { // Nothing was started. return; } } // We've run before; check if the wait is still going on. var instance = this; var waiting = util.stackFrame.startedThreads.some(function(thread) { return instance.runtime.isActiveThread(thread); }); if (waiting) { util.yieldFrame(); } }; Scratch3LooksBlocks.prototype.nextBackdrop = function () { var stage = this.runtime.getTargetForStage(); this._setCostumeOrBackdrop( stage, stage.currentCostume + 1, true ); }; Scratch3LooksBlocks.prototype.changeEffect = function (args, util) { var effect = Cast.toString(args.EFFECT).toLowerCase(); var change = Cast.toNumber(args.CHANGE); if (!util.target.effects.hasOwnProperty(effect)) return; var newValue = change + util.target.effects[effect]; util.target.setEffect(effect, newValue); }; Scratch3LooksBlocks.prototype.setEffect = function (args, util) { var effect = Cast.toString(args.EFFECT).toLowerCase(); var value = Cast.toNumber(args.VALUE); util.target.setEffect(effect, value); }; Scratch3LooksBlocks.prototype.clearEffects = function (args, util) { util.target.clearEffects(); }; Scratch3LooksBlocks.prototype.changeSize = function (args, util) { var change = Cast.toNumber(args.CHANGE); util.target.setSize(util.target.size + change); }; Scratch3LooksBlocks.prototype.setSize = function (args, util) { var size = Cast.toNumber(args.SIZE); util.target.setSize(size); }; Scratch3LooksBlocks.prototype.getSize = function (args, util) { return util.target.size; }; Scratch3LooksBlocks.prototype.getBackdropIndex = function () { var stage = this.runtime.getTargetForStage(); return stage.currentCostume + 1; }; Scratch3LooksBlocks.prototype.getBackdropName = function () { var stage = this.runtime.getTargetForStage(); return stage.sprite.costumes[stage.currentCostume].name; }; Scratch3LooksBlocks.prototype.getCostumeIndex = function (args, util) { return util.target.currentCostume + 1; }; module.exports = Scratch3LooksBlocks; /***/ }, /* 31 */ /***/ function(module, exports, __webpack_require__) { var Cast = __webpack_require__(14); var MathUtil = __webpack_require__(17); var Timer = __webpack_require__(9); function Scratch3MotionBlocks(runtime) { /** * The runtime instantiating this block package. * @type {Runtime} */ this.runtime = runtime; } /** * Retrieve the block primitives implemented by this package. * @return {Object.} Mapping of opcode to Function. */ Scratch3MotionBlocks.prototype.getPrimitives = function() { return { 'motion_movesteps': this.moveSteps, 'motion_gotoxy': this.goToXY, 'motion_turnright': this.turnRight, 'motion_turnleft': this.turnLeft, 'motion_pointindirection': this.pointInDirection, 'motion_glidesecstoxy': this.glide, 'motion_changexby': this.changeX, 'motion_setx': this.setX, 'motion_changeyby': this.changeY, 'motion_sety': this.setY, 'motion_xposition': this.getX, 'motion_yposition': this.getY, 'motion_direction': this.getDirection }; }; Scratch3MotionBlocks.prototype.moveSteps = function (args, util) { var steps = Cast.toNumber(args.STEPS); var radians = MathUtil.degToRad(util.target.direction); var dx = steps * Math.cos(radians); var dy = steps * Math.sin(radians); util.target.setXY(util.target.x + dx, util.target.y + dy); }; Scratch3MotionBlocks.prototype.goToXY = function (args, util) { var x = Cast.toNumber(args.X); var y = Cast.toNumber(args.Y); util.target.setXY(x, y); }; Scratch3MotionBlocks.prototype.turnRight = function (args, util) { var degrees = Cast.toNumber(args.DEGREES); util.target.setDirection(util.target.direction + degrees); }; Scratch3MotionBlocks.prototype.turnLeft = function (args, util) { var degrees = Cast.toNumber(args.DEGREES); util.target.setDirection(util.target.direction - degrees); }; Scratch3MotionBlocks.prototype.pointInDirection = function (args, util) { var direction = Cast.toNumber(args.DIRECTION); util.target.setDirection(direction); }; Scratch3MotionBlocks.prototype.glide = function (args, util) { if (!util.stackFrame.timer) { // First time: save data for future use. util.stackFrame.timer = new Timer(); util.stackFrame.timer.start(); util.stackFrame.duration = Cast.toNumber(args.SECS); util.stackFrame.startX = util.target.x; util.stackFrame.startY = util.target.y; util.stackFrame.endX = Cast.toNumber(args.X); util.stackFrame.endY = Cast.toNumber(args.Y); if (util.stackFrame.duration <= 0) { // Duration too short to glide. util.target.setXY(util.stackFrame.endX, util.stackFrame.endY); return; } util.yieldFrame(); } else { var timeElapsed = util.stackFrame.timer.timeElapsed(); if (timeElapsed < util.stackFrame.duration * 1000) { // In progress: move to intermediate position. var frac = timeElapsed / (util.stackFrame.duration * 1000); var dx = frac * (util.stackFrame.endX - util.stackFrame.startX); var dy = frac * (util.stackFrame.endY - util.stackFrame.startY); util.target.setXY( util.stackFrame.startX + dx, util.stackFrame.startY + dy ); util.yieldFrame(); } else { // Finished: move to final position. util.target.setXY(util.stackFrame.endX, util.stackFrame.endY); } } }; Scratch3MotionBlocks.prototype.changeX = function (args, util) { var dx = Cast.toNumber(args.DX); util.target.setXY(util.target.x + dx, util.target.y); }; Scratch3MotionBlocks.prototype.setX = function (args, util) { var x = Cast.toNumber(args.X); util.target.setXY(x, util.target.y); }; Scratch3MotionBlocks.prototype.changeY = function (args, util) { var dy = Cast.toNumber(args.DY); util.target.setXY(util.target.x, util.target.y + dy); }; Scratch3MotionBlocks.prototype.setY = function (args, util) { var y = Cast.toNumber(args.Y); util.target.setXY(util.target.x, y); }; Scratch3MotionBlocks.prototype.getX = function (args, util) { return util.target.x; }; Scratch3MotionBlocks.prototype.getY = function (args, util) { return util.target.y; }; Scratch3MotionBlocks.prototype.getDirection = function (args, util) { return util.target.direction; }; module.exports = Scratch3MotionBlocks; /***/ }, /* 32 */ /***/ function(module, exports, __webpack_require__) { var Cast = __webpack_require__(14); function Scratch3OperatorsBlocks(runtime) { /** * The runtime instantiating this block package. * @type {Runtime} */ this.runtime = runtime; } /** * Retrieve the block primitives implemented by this package. * @return {Object.} Mapping of opcode to Function. */ Scratch3OperatorsBlocks.prototype.getPrimitives = function() { return { 'operator_add': this.add, 'operator_subtract': this.subtract, 'operator_multiply': this.multiply, 'operator_divide': this.divide, 'operator_lt': this.lt, 'operator_equals': this.equals, 'operator_gt': this.gt, 'operator_and': this.and, 'operator_or': this.or, 'operator_not': this.not, 'operator_random': this.random, 'operator_join': this.join, 'operator_letter_of': this.letterOf, 'operator_length': this.length, 'operator_mod': this.mod, 'operator_round': this.round, 'operator_mathop': this.mathop }; }; Scratch3OperatorsBlocks.prototype.add = function (args) { return Cast.toNumber(args.NUM1) + Cast.toNumber(args.NUM2); }; Scratch3OperatorsBlocks.prototype.subtract = function (args) { return Cast.toNumber(args.NUM1) - Cast.toNumber(args.NUM2); }; Scratch3OperatorsBlocks.prototype.multiply = function (args) { return Cast.toNumber(args.NUM1) * Cast.toNumber(args.NUM2); }; Scratch3OperatorsBlocks.prototype.divide = function (args) { return Cast.toNumber(args.NUM1) / Cast.toNumber(args.NUM2); }; Scratch3OperatorsBlocks.prototype.lt = function (args) { return Cast.compare(args.OPERAND1, args.OPERAND2) < 0; }; Scratch3OperatorsBlocks.prototype.equals = function (args) { return Cast.compare(args.OPERAND1, args.OPERAND2) == 0; }; Scratch3OperatorsBlocks.prototype.gt = function (args) { return Cast.compare(args.OPERAND1, args.OPERAND2) > 0; }; Scratch3OperatorsBlocks.prototype.and = function (args) { return Cast.toBoolean(args.OPERAND1) && Cast.toBoolean(args.OPERAND2); }; Scratch3OperatorsBlocks.prototype.or = function (args) { return Cast.toBoolean(args.OPERAND1) || Cast.toBoolean(args.OPERAND2); }; Scratch3OperatorsBlocks.prototype.not = function (args) { return !Cast.toBoolean(args.OPERAND); }; Scratch3OperatorsBlocks.prototype.random = function (args) { var nFrom = Cast.toNumber(args.FROM); var nTo = Cast.toNumber(args.TO); var low = nFrom <= nTo ? nFrom : nTo; var high = nFrom <= nTo ? nTo : nFrom; if (low == high) return low; // If both arguments are ints, truncate the result to an int. if (Cast.isInt(args.FROM) && Cast.isInt(args.TO)) { return low + parseInt(Math.random() * ((high + 1) - low)); } return (Math.random() * (high - low)) + low; }; Scratch3OperatorsBlocks.prototype.join = function (args) { return Cast.toString(args.STRING1) + Cast.toString(args.STRING2); }; Scratch3OperatorsBlocks.prototype.letterOf = function (args) { var index = Cast.toNumber(args.LETTER) - 1; var str = Cast.toString(args.STRING); // Out of bounds? if (index < 0 || index >= str.length) { return ''; } return str.charAt(index); }; Scratch3OperatorsBlocks.prototype.length = function (args) { return Cast.toString(args.STRING).length; }; Scratch3OperatorsBlocks.prototype.mod = function (args) { var n = Cast.toNumber(args.NUM1); var modulus = Cast.toNumber(args.NUM2); var result = n % modulus; // Scratch mod is kept positive. if (result / modulus < 0) result += modulus; return result; }; Scratch3OperatorsBlocks.prototype.round = function (args) { return Math.round(Cast.toNumber(args.NUM)); }; Scratch3OperatorsBlocks.prototype.mathop = function (args) { var operator = Cast.toString(args.OPERATOR).toLowerCase(); var n = Cast.toNumber(args.NUM); switch (operator) { case 'abs': return Math.abs(n); case 'floor': return Math.floor(n); case 'ceiling': return Math.ceil(n); case 'sqrt': return Math.sqrt(n); case 'sin': return Math.sin((Math.PI * n) / 180); case 'cos': return Math.cos((Math.PI * n) / 180); case 'tan': return Math.tan((Math.PI * n) / 180); case 'asin': return (Math.asin(n) * 180) / Math.PI; case 'acos': return (Math.acos(n) * 180) / Math.PI; case 'atan': return (Math.atan(n) * 180) / Math.PI; case 'ln': return Math.log(n); case 'log': return Math.log(n) / Math.LN10; case 'e ^': return Math.exp(n); case '10 ^': return Math.pow(10, n); } return 0; }; module.exports = Scratch3OperatorsBlocks; /***/ }, /* 33 */ /***/ function(module, exports, __webpack_require__) { var Cast = __webpack_require__(14); function Scratch3SensingBlocks(runtime) { /** * The runtime instantiating this block package. * @type {Runtime} */ this.runtime = runtime; } /** * Retrieve the block primitives implemented by this package. * @return {Object.} Mapping of opcode to Function. */ Scratch3SensingBlocks.prototype.getPrimitives = function() { return { 'sensing_touchingcolor': this.touchingColor, 'sensing_coloristouchingcolor': this.colorTouchingColor, 'sensing_timer': this.getTimer, 'sensing_resettimer': this.resetTimer, 'sensing_mousex': this.getMouseX, 'sensing_mousey': this.getMouseY, 'sensing_mousedown': this.getMouseDown, 'sensing_keypressed': this.getKeyPressed, 'sensing_current': this.current }; }; Scratch3SensingBlocks.prototype.touchingColor = function (args, util) { var color = Cast.toRgbColorList(args.COLOR); return util.target.isTouchingColor(color); }; Scratch3SensingBlocks.prototype.colorTouchingColor = function (args, util) { var maskColor = Cast.toRgbColorList(args.COLOR); var targetColor = Cast.toRgbColorList(args.COLOR2); return util.target.colorIsTouchingColor(targetColor, maskColor); }; Scratch3SensingBlocks.prototype.getTimer = function (args, util) { return util.ioQuery('clock', 'projectTimer'); }; Scratch3SensingBlocks.prototype.resetTimer = function (args, util) { util.ioQuery('clock', 'resetProjectTimer'); }; Scratch3SensingBlocks.prototype.getMouseX = function (args, util) { return util.ioQuery('mouse', 'getX'); }; Scratch3SensingBlocks.prototype.getMouseY = function (args, util) { return util.ioQuery('mouse', 'getY'); }; Scratch3SensingBlocks.prototype.getMouseDown = function (args, util) { return util.ioQuery('mouse', 'getIsDown'); }; Scratch3SensingBlocks.prototype.current = function (args) { var menuOption = Cast.toString(args.CURRENTMENU).toLowerCase(); var date = new Date(); switch (menuOption) { case 'year': return date.getFullYear(); case 'month': return date.getMonth() + 1; // getMonth is zero-based case 'date': return date.getDate(); case 'dayofweek': return date.getDay() + 1; // getDay is zero-based, Sun=0 case 'hour': return date.getHours(); case 'minute': return date.getMinutes(); case 'second': return date.getSeconds(); } return 0; }; Scratch3SensingBlocks.prototype.getKeyPressed = function (args, util) { return util.ioQuery('keyboard', 'getKeyIsDown', args.KEY_OPTION); }; module.exports = Scratch3SensingBlocks; /***/ }, /* 34 */ /***/ function(module, exports, __webpack_require__) { /** * @fileoverview * Partial implementation of an SB2 JSON importer. * Parses provided JSON and then generates all needed * scratch-vm runtime structures. */ var Blocks = __webpack_require__(35); var Sprite = __webpack_require__(89); var Color = __webpack_require__(15); var uid = __webpack_require__(92); var specMap = __webpack_require__(93); /** * Top-level handler. Parse provided JSON, * and process the top-level object (the stage object). * @param {!string} json SB2-format JSON to load. * @param {!Runtime} runtime Runtime object to load all structures into. */ function sb2import (json, runtime) { parseScratchObject( JSON.parse(json), runtime, true ); } /** * Parse a single "Scratch object" and create all its in-memory VM objects. * @param {!Object} object From-JSON "Scratch object:" sprite, stage, watcher. * @param {!Runtime} runtime Runtime object to load all structures into. * @param {boolean} topLevel Whether this is the top-level object (stage). */ function parseScratchObject (object, runtime, topLevel) { if (!object.hasOwnProperty('objName')) { // Watcher/monitor - skip this object until those are implemented in VM. // @todo return; } // Blocks container for this object. var blocks = new Blocks(); // @todo: For now, load all Scratch objects (stage/sprites) as a Sprite. var sprite = new Sprite(blocks, runtime); // Sprite/stage name from JSON. if (object.hasOwnProperty('objName')) { sprite.name = object.objName; } // Costumes from JSON. if (object.hasOwnProperty('costumes')) { for (var i = 0; i < object.costumes.length; i++) { var costume = object.costumes[i]; // @todo: Make sure all the relevant metadata is being pulled out. sprite.costumes.push({ skin: 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' + costume.baseLayerMD5 + '/get/', name: costume.costumeName, bitmapResolution: costume.bitmapResolution, rotationCenterX: costume.rotationCenterX, rotationCenterY: costume.rotationCenterY }); } } // If included, parse any and all scripts/blocks on the object. if (object.hasOwnProperty('scripts')) { parseScripts(object.scripts, blocks); } // Create the first clone, and load its run-state from JSON. var target = sprite.createClone(); // Add it to the runtime's list of targets. runtime.targets.push(target); if (object.hasOwnProperty('scratchX')) { target.x = object.scratchX; } if (object.hasOwnProperty('scratchY')) { target.y = object.scratchY; } if (object.hasOwnProperty('direction')) { target.direction = object.direction; } if (object.hasOwnProperty('scale')) { // SB2 stores as 1.0 = 100%; we use % in the VM. target.size = object.scale * 100; } if (object.hasOwnProperty('visible')) { target.visible = object.visible; } if (object.hasOwnProperty('currentCostumeIndex')) { target.currentCostume = object.currentCostumeIndex; } target.isStage = topLevel; target.updateAllDrawableProperties(); // The stage will have child objects; recursively process them. if (object.children) { for (var j = 0; j < object.children.length; j++) { parseScratchObject(object.children[j], runtime, false); } } } /** * Parse a Scratch object's scripts into VM blocks. * This should only handle top-level scripts that include X, Y coordinates. * @param {!Object} scripts Scripts object from SB2 JSON. * @param {!Blocks} blocks Blocks object to load parsed blocks into. */ function parseScripts (scripts, blocks) { for (var i = 0; i < scripts.length; i++) { var script = scripts[i]; var scriptX = script[0]; var scriptY = script[1]; var blockList = script[2]; var parsedBlockList = parseBlockList(blockList); if (parsedBlockList[0]) { // Adjust script coordinates to account for // larger block size in scratch-blocks. // @todo: Determine more precisely the right formulas here. parsedBlockList[0].x = scriptX * 1.1; parsedBlockList[0].y = scriptY * 1.1; parsedBlockList[0].topLevel = true; parsedBlockList[0].parent = null; } // Flatten children and create add the blocks. var convertedBlocks = flatten(parsedBlockList); for (var j = 0; j < convertedBlocks.length; j++) { blocks.createBlock(convertedBlocks[j]); } } } /** * Parse any list of blocks from SB2 JSON into a list of VM-format blocks. * Could be used to parse a top-level script, * a list of blocks in a branch (e.g., in forever), * or a list of blocks in an argument (e.g., move [pick random...]). * @param {Array.} blockList SB2 JSON-format block list. * @return {Array.} Scratch VM-format block list. */ function parseBlockList (blockList) { var resultingList = []; var previousBlock = null; // For setting next. for (var i = 0; i < blockList.length; i++) { var block = blockList[i]; var parsedBlock = parseBlock(block); if (previousBlock) { parsedBlock.parent = previousBlock.id; previousBlock.next = parsedBlock.id; } previousBlock = parsedBlock; resultingList.push(parsedBlock); } return resultingList; } /** * Flatten a block tree into a block list. * Children are temporarily stored on the `block.children` property. * @param {Array.} blocks list generated by `parseBlockList`. * @return {Array.} Flattened list to be passed to `blocks.createBlock`. */ function flatten (blocks) { var finalBlocks = []; for (var i = 0; i < blocks.length; i++) { var block = blocks[i]; finalBlocks.push(block); if (block.children) { finalBlocks = finalBlocks.concat(flatten(block.children)); } delete block.children; } return finalBlocks; } /** * Parse a single SB2 JSON-formatted block and its children. * @param {!Object} sb2block SB2 JSON-formatted block. * @return {Object} Scratch VM format block. */ function parseBlock (sb2block) { // First item in block object is the old opcode (e.g., 'forward:'). var oldOpcode = sb2block[0]; // Convert the block using the specMap. See sb2specmap.js. if (!oldOpcode || !specMap[oldOpcode]) { console.warn('Couldn\'t find SB2 block: ', oldOpcode); return; } var blockMetadata = specMap[oldOpcode]; // Block skeleton. var activeBlock = { id: uid(), // Generate a new block unique ID. opcode: blockMetadata.opcode, // Converted, e.g. "motion_movesteps". inputs: {}, // Inputs to this block and the blocks they point to. fields: {}, // Fields on this block and their values. next: null, // Next block. shadow: false, // No shadow blocks in an SB2 by default. children: [] // Store any generated children, flattened in `flatten`. }; // Look at the expected arguments in `blockMetadata.argMap.` // The basic problem here is to turn positional SB2 arguments into // non-positional named Scratch VM arguments. for (var i = 0; i < blockMetadata.argMap.length; i++) { var expectedArg = blockMetadata.argMap[i]; var providedArg = sb2block[i + 1]; // (i = 0 is opcode) // Whether the input is obscuring a shadow. var shadowObscured = false; // Positional argument is an input. if (expectedArg.type == 'input') { // Create a new block and input metadata. var inputUid = uid(); activeBlock.inputs[expectedArg.inputName] = { name: expectedArg.inputName, block: null, shadow: null }; if (typeof providedArg == 'object' && providedArg) { // Block or block list occupies the input. var innerBlocks; if (typeof providedArg[0] == 'object' && providedArg[0]) { // Block list occupies the input. innerBlocks = parseBlockList(providedArg); } else { // Single block occupies the input. innerBlocks = [parseBlock(providedArg)]; } for (var j = 0; j < innerBlocks.length; j++) { innerBlocks[j].parent = activeBlock.id; } // Obscures any shadow. shadowObscured = true; activeBlock.inputs[expectedArg.inputName].block = ( innerBlocks[0].id ); activeBlock.children = ( activeBlock.children.concat(innerBlocks) ); } // Generate a shadow block to occupy the input. if (!expectedArg.inputOp) { // No editable shadow input; e.g., for a boolean. continue; } // Each shadow has a field generated for it automatically. // Value to be filled in the field. var fieldValue = providedArg; // Shadows' field names match the input name, except for these: var fieldName = expectedArg.inputName; if (expectedArg.inputOp == 'math_number' || expectedArg.inputOp == 'math_whole_number' || expectedArg.inputOp == 'math_positive_number' || expectedArg.inputOp == 'math_integer' || expectedArg.inputOp == 'math_angle') { fieldName = 'NUM'; // Fields are given Scratch 2.0 default values if obscured. if (shadowObscured) { fieldValue = 10; } } else if (expectedArg.inputOp == 'text') { fieldName = 'TEXT'; if (shadowObscured) { fieldValue = ''; } } else if (expectedArg.inputOp == 'colour_picker') { // Convert SB2 color to hex. fieldValue = Color.decimalToHex(providedArg); fieldName = 'COLOUR'; if (shadowObscured) { fieldValue = '#990000'; } } var fields = {}; fields[fieldName] = { name: fieldName, value: fieldValue }; activeBlock.children.push({ id: inputUid, opcode: expectedArg.inputOp, inputs: {}, fields: fields, next: null, topLevel: false, parent: activeBlock.id, shadow: true }); activeBlock.inputs[expectedArg.inputName].shadow = inputUid; // If no block occupying the input, alias to the shadow. if (!activeBlock.inputs[expectedArg.inputName].block) { activeBlock.inputs[expectedArg.inputName].block = inputUid; } } else if (expectedArg.type == 'field') { // Add as a field on this block. activeBlock.fields[expectedArg.fieldName] = { name: expectedArg.fieldName, value: providedArg }; } } return activeBlock; } module.exports = sb2import; /***/ }, /* 35 */ /***/ function(module, exports, __webpack_require__) { var adapter = __webpack_require__(36); var xmlEscape = __webpack_require__(88); /** * @fileoverview * Store and mutate the VM block representation, * and handle updates from Scratch Blocks events. */ function Blocks () { /** * All blocks in the workspace. * Keys are block IDs, values are metadata about the block. * @type {Object.} */ this._blocks = {}; /** * All top-level scripts in the workspace. * A list of block IDs that represent scripts (i.e., first block in script). * @type {Array.} */ this._scripts = []; } /** * Blockly inputs that represent statements/branch. * are prefixed with this string. * @const{string} */ Blocks.BRANCH_INPUT_PREFIX = 'SUBSTACK'; /** * Provide an object with metadata for the requested block ID. * @param {!string} blockId ID of block we have stored. * @return {?Object} Metadata about the block, if it exists. */ Blocks.prototype.getBlock = function (blockId) { return this._blocks[blockId]; }; /** * Get all known top-level blocks that start scripts. * @return {Array.} List of block IDs. */ Blocks.prototype.getScripts = function () { return this._scripts; }; /** * Get the next block for a particular block * @param {?string} id ID of block to get the next block for * @return {?string} ID of next block in the sequence */ Blocks.prototype.getNextBlock = function (id) { if (typeof this._blocks[id] === 'undefined') return null; return this._blocks[id].next; }; /** * Get the branch for a particular C-shaped block. * @param {?string} id ID for block to get the branch for. * @param {?number} branchNum Which branch to select (e.g. for if-else). * @return {?string} ID of block in the branch. */ Blocks.prototype.getBranch = function (id, branchNum) { var block = this._blocks[id]; if (typeof block === 'undefined') return null; if (!branchNum) branchNum = 1; var inputName = Blocks.BRANCH_INPUT_PREFIX; if (branchNum > 1) { inputName += branchNum; } // Empty C-block? if (!(inputName in block.inputs)) return null; return block.inputs[inputName].block; }; /** * Get the opcode for a particular block * @param {?string} id ID of block to query * @return {?string} the opcode corresponding to that block */ Blocks.prototype.getOpcode = function (id) { if (typeof this._blocks[id] === 'undefined') return null; return this._blocks[id].opcode; }; /** * Get all fields and their values for a block. * @param {?string} id ID of block to query. * @return {!Object} All fields and their values. */ Blocks.prototype.getFields = function (id) { if (typeof this._blocks[id] === 'undefined') return null; return this._blocks[id].fields; }; /** * Get all non-branch inputs for a block. * @param {?string} id ID of block to query. * @return {!Object} All non-branch inputs and their associated blocks. */ Blocks.prototype.getInputs = function (id) { if (typeof this._blocks[id] === 'undefined') return null; var inputs = {}; for (var input in this._blocks[id].inputs) { // Ignore blocks prefixed with branch prefix. if (input.substring(0, Blocks.BRANCH_INPUT_PREFIX.length) != Blocks.BRANCH_INPUT_PREFIX) { inputs[input] = this._blocks[id].inputs[input]; } } return inputs; }; /** * Get the top-level script for a given block. * @param {?string} id ID of block to query. * @return {?string} ID of top-level script block. */ Blocks.prototype.getTopLevelScript = function (id) { if (typeof this._blocks[id] === 'undefined') return null; var block = this._blocks[id]; while (block.parent !== null) { block = this._blocks[block.parent]; } return block.id; }; // --------------------------------------------------------------------- /** * Create event listener for blocks. Handles validation and serves as a generic * adapter between the blocks and the runtime interface. * @param {Object} e Blockly "block" event * @param {boolean} isFlyout If true, create a listener for flyout events. * @param {?Runtime} opt_runtime Optional runtime to forward click events to. */ Blocks.prototype.blocklyListen = function (e, isFlyout, opt_runtime) { // Validate event if (typeof e !== 'object') return; if (typeof e.blockId !== 'string') return; // UI event: clicked scripts toggle in the runtime. if (e.element === 'stackclick') { if (opt_runtime) { opt_runtime.toggleScript(e.blockId); } return; } // Block create/update/destroy switch (e.type) { case 'create': var newBlocks = adapter(e); // A create event can create many blocks. Add them all. for (var i = 0; i < newBlocks.length; i++) { this.createBlock(newBlocks[i], isFlyout); } break; case 'change': this.changeBlock({ id: e.blockId, element: e.element, name: e.name, value: e.newValue }); break; case 'move': this.moveBlock({ id: e.blockId, oldParent: e.oldParentId, oldInput: e.oldInputName, newParent: e.newParentId, newInput: e.newInputName, newCoordinate: e.newCoordinate }); break; case 'delete': // Don't accept delete events for shadow blocks being obscured. if (this._blocks[e.blockId].shadow) { return; } // Inform any runtime to forget about glows on this script. if (opt_runtime && this._blocks[e.blockId].topLevel) { opt_runtime.quietGlow(e.blockId); } this.deleteBlock({ id: e.blockId }); break; } }; // --------------------------------------------------------------------- /** * Block management: create blocks and scripts from a `create` event * @param {!Object} block Blockly create event to be processed * @param {boolean} opt_isFlyoutBlock Whether the block is in the flyout. */ Blocks.prototype.createBlock = function (block, opt_isFlyoutBlock) { // Does the block already exist? // Could happen, e.g., for an unobscured shadow. if (this._blocks.hasOwnProperty(block.id)) { return; } // Create new block. this._blocks[block.id] = block; // Push block id to scripts array. // Blocks are added as a top-level stack if they are marked as a top-block // (if they were top-level XML in the event) and if they are not // flyout blocks. if (!opt_isFlyoutBlock && block.topLevel) { this._addScript(block.id); } }; /** * Block management: change block field values * @param {!Object} args Blockly change event to be processed */ Blocks.prototype.changeBlock = function (args) { // Validate if (args.element !== 'field') return; if (typeof this._blocks[args.id] === 'undefined') return; if (typeof this._blocks[args.id].fields[args.name] === 'undefined') return; // Update block value this._blocks[args.id].fields[args.name].value = args.value; }; /** * Block management: move blocks from parent to parent * @param {!Object} e Blockly move event to be processed */ Blocks.prototype.moveBlock = function (e) { // Move coordinate changes. if (e.newCoordinate) { this._blocks[e.id].x = e.newCoordinate.x; this._blocks[e.id].y = e.newCoordinate.y; } // Remove from any old parent. if (e.oldParent !== undefined) { var oldParent = this._blocks[e.oldParent]; if (e.oldInput !== undefined && oldParent.inputs[e.oldInput].block === e.id) { // This block was connected to the old parent's input. oldParent.inputs[e.oldInput].block = null; } else if (oldParent.next === e.id) { // This block was connected to the old parent's next connection. oldParent.next = null; } this._blocks[e.id].parent = null; } // Has the block become a top-level block? if (e.newParent === undefined) { this._addScript(e.id); } else { // Remove script, if one exists. this._deleteScript(e.id); // Otherwise, try to connect it in its new place. if (e.newInput !== undefined) { // Moved to the new parent's input. // Don't obscure the shadow block. var oldShadow = null; if (this._blocks[e.newParent].inputs.hasOwnProperty(e.newInput)) { oldShadow = this._blocks[e.newParent].inputs[e.newInput].shadow; } this._blocks[e.newParent].inputs[e.newInput] = { name: e.newInput, block: e.id, shadow: oldShadow }; } else { // Moved to the new parent's next connection. this._blocks[e.newParent].next = e.id; } this._blocks[e.id].parent = e.newParent; } }; /** * Block management: delete blocks and their associated scripts. * @param {!Object} e Blockly delete event to be processed. */ Blocks.prototype.deleteBlock = function (e) { // @todo In runtime, stop threads running on this script. // Get block var block = this._blocks[e.id]; // Delete children if (block.next !== null) { this.deleteBlock({id: block.next}); } // Delete inputs (including branches) for (var input in block.inputs) { // If it's null, the block in this input moved away. if (block.inputs[input].block !== null) { this.deleteBlock({id: block.inputs[input].block}); } // Delete obscured shadow blocks. if (block.inputs[input].shadow !== null && block.inputs[input].shadow !== block.inputs[input].block) { this.deleteBlock({id: block.inputs[input].shadow}); } } // Delete any script starting with this block. this._deleteScript(e.id); // Delete block itself. delete this._blocks[e.id]; }; // --------------------------------------------------------------------- /** * Encode all of `this._blocks` as an XML string usable * by a Blockly/scratch-blocks workspace. * @return {string} String of XML representing this object's blocks. */ Blocks.prototype.toXML = function () { var xmlString = ''; for (var i = 0; i < this._scripts.length; i++) { xmlString += this.blockToXML(this._scripts[i]); } return xmlString + ''; }; /** * Recursively encode an individual block and its children * into a Blockly/scratch-blocks XML string. * @param {!string} blockId ID of block to encode. * @return {string} String of XML representing this block and any children. */ Blocks.prototype.blockToXML = function (blockId) { var block = this._blocks[blockId]; // Encode properties of this block. var tagName = (block.shadow) ? 'shadow' : 'block'; var xy = (block.topLevel) ? ' x="' + block.x +'"' + ' y="' + block.y +'"' : ''; var xmlString = ''; xmlString += '<' + tagName + ' id="' + block.id + '"' + ' type="' + block.opcode + '"' + xy + '>'; // Add any inputs on this block. for (var input in block.inputs) { var blockInput = block.inputs[input]; // Only encode a value tag if the value input is occupied. if (blockInput.block || blockInput.shadow) { xmlString += ''; if (blockInput.block) { xmlString += this.blockToXML(blockInput.block); } if (blockInput.shadow && blockInput.shadow != blockInput.block) { // Obscured shadow. xmlString += this.blockToXML(blockInput.shadow); } xmlString += ''; } } // Add any fields on this block. for (var field in block.fields) { var blockField = block.fields[field]; var value = blockField.value; if (typeof value === 'string') { value = xmlEscape(blockField.value); } xmlString += '' + value + ''; } // Add blocks connected to the next connection. if (block.next) { xmlString += '' + this.blockToXML(block.next) + ''; } xmlString += ''; return xmlString; }; // --------------------------------------------------------------------- /** * Helper to add a stack to `this._scripts`. * @param {?string} topBlockId ID of block that starts the script. */ Blocks.prototype._addScript = function (topBlockId) { var i = this._scripts.indexOf(topBlockId); if (i > -1) return; // Already in scripts. this._scripts.push(topBlockId); // Update `topLevel` property on the top block. this._blocks[topBlockId].topLevel = true; }; /** * Helper to remove a script from `this._scripts`. * @param {?string} topBlockId ID of block that starts the script. */ Blocks.prototype._deleteScript = function (topBlockId) { var i = this._scripts.indexOf(topBlockId); if (i > -1) this._scripts.splice(i, 1); // Update `topLevel` property on the top block. if (this._blocks[topBlockId]) this._blocks[topBlockId].topLevel = false; }; module.exports = Blocks; /***/ }, /* 36 */ /***/ function(module, exports, __webpack_require__) { var html = __webpack_require__(37); /** * Adapter between block creation events and block representation which can be * used by the Scratch runtime. * @param {Object} e `Blockly.events.create` * @return {Array.} List of blocks from this CREATE event. */ module.exports = function (e) { // Validate input if (typeof e !== 'object') return; if (typeof e.xml !== 'object') return; return domToBlocks(html.parseDOM(e.xml.outerHTML)); }; /** * Convert outer blocks DOM from a Blockly CREATE event * to a usable form for the Scratch runtime. * This structure is based on Blockly xml.js:`domToWorkspace` and `domToBlock`. * @param {Element} blocksDOM DOM tree for this event. * @return {Array.} Usable list of blocks from this CREATE event. */ function domToBlocks (blocksDOM) { // At this level, there could be multiple blocks adjacent in the DOM tree. var blocks = {}; for (var i = 0; i < blocksDOM.length; i++) { var block = blocksDOM[i]; if (!block.name || !block.attribs) { continue; } var tagName = block.name.toLowerCase(); if (tagName == 'block' || tagName == 'shadow') { domToBlock(block, blocks, true, null); } } // Flatten blocks object into a list. var blocksList = []; for (var b in blocks) { blocksList.push(blocks[b]); } return blocksList; } /** * Convert and an individual block DOM to the representation tree. * Based on Blockly's `domToBlockHeadless_`. * @param {Element} blockDOM DOM tree for an individual block. * @param {Object} blocks Collection of blocks to add to. * @param {Boolean} isTopBlock Whether blocks at this level are "top blocks." * @param {?string} parent Parent block ID. */ function domToBlock (blockDOM, blocks, isTopBlock, parent) { // Block skeleton. var block = { id: blockDOM.attribs.id, // Block ID opcode: blockDOM.attribs.type, // For execution, "event_whengreenflag". inputs: {}, // Inputs to this block and the blocks they point to. fields: {}, // Fields on this block and their values. next: null, // Next block in the stack, if one exists. topLevel: isTopBlock, // If this block starts a stack. parent: parent, // Parent block ID, if available. shadow: blockDOM.name == 'shadow', // If this represents a shadow/slot. x: blockDOM.attribs.x, // X position of script, if top-level. y: blockDOM.attribs.y // Y position of script, if top-level. }; // Add the block to the representation tree. blocks[block.id] = block; // Process XML children and find enclosed blocks, fields, etc. for (var i = 0; i < blockDOM.children.length; i++) { var xmlChild = blockDOM.children[i]; // Enclosed blocks and shadows var childBlockNode = null; var childShadowNode = null; for (var j = 0; j < xmlChild.children.length; j++) { var grandChildNode = xmlChild.children[j]; if (!grandChildNode.name) { // Non-XML tag node. continue; } var grandChildNodeName = grandChildNode.name.toLowerCase(); if (grandChildNodeName == 'block') { childBlockNode = grandChildNode; } else if (grandChildNodeName == 'shadow') { childShadowNode = grandChildNode; } } // Use shadow block only if there's no real block node. if (!childBlockNode && childShadowNode) { childBlockNode = childShadowNode; } // Not all Blockly-type blocks are handled here, // as we won't be using all of them for Scratch. switch (xmlChild.name.toLowerCase()) { case 'field': // Add the field to this block. var fieldName = xmlChild.attribs.name; var fieldData = ''; if (xmlChild.children.length > 0 && xmlChild.children[0].data) { fieldData = xmlChild.children[0].data; } else { // If the child of the field with a data property // doesn't exist, set the data to an empty string. fieldData = ''; } block.fields[fieldName] = { name: fieldName, value: fieldData }; break; case 'value': case 'statement': // Recursively generate block structure for input block. domToBlock(childBlockNode, blocks, false, block.id); if (childShadowNode && childBlockNode != childShadowNode) { // Also generate the shadow block. domToBlock(childShadowNode, blocks, false, block.id); } // Link this block's input to the child block. var inputName = xmlChild.attribs.name; block.inputs[inputName] = { name: inputName, block: childBlockNode.attribs.id, shadow: childShadowNode ? childShadowNode.attribs.id : null }; break; case 'next': if (!childBlockNode || !childBlockNode.attribs) { // Invalid child block. continue; } // Recursively generate block structure for next block. domToBlock(childBlockNode, blocks, false, block.id); // Link next block to this block. block.next = childBlockNode.attribs.id; break; } } } /***/ }, /* 37 */ /***/ function(module, exports, __webpack_require__) { var Parser = __webpack_require__(38), DomHandler = __webpack_require__(45); function defineProp(name, value){ delete module.exports[name]; module.exports[name] = value; return value; } module.exports = { Parser: Parser, Tokenizer: __webpack_require__(39), ElementType: __webpack_require__(46), DomHandler: DomHandler, get FeedHandler(){ return defineProp("FeedHandler", __webpack_require__(49)); }, get Stream(){ return defineProp("Stream", __webpack_require__(50)); }, get WritableStream(){ return defineProp("WritableStream", __webpack_require__(51)); }, get ProxyHandler(){ return defineProp("ProxyHandler", __webpack_require__(74)); }, get DomUtils(){ return defineProp("DomUtils", __webpack_require__(75)); }, get CollectingHandler(){ return defineProp("CollectingHandler", __webpack_require__(87)); }, // For legacy support DefaultHandler: DomHandler, get RssHandler(){ return defineProp("RssHandler", this.FeedHandler); }, //helper methods parseDOM: function(data, options){ var handler = new DomHandler(options); new Parser(handler, options).end(data); return handler.dom; }, parseFeed: function(feed, options){ var handler = new module.exports.FeedHandler(options); new Parser(handler, options).end(feed); return handler.dom; }, createDomStream: function(cb, options, elementCb){ var handler = new DomHandler(cb, options, elementCb); return new Parser(handler, options); }, // List of all events that the parser emits EVENTS: { /* Format: eventname: number of arguments */ attribute: 2, cdatastart: 0, cdataend: 0, text: 1, processinginstruction: 2, comment: 1, commentend: 0, closetag: 1, opentag: 2, opentagname: 1, error: 1, end: 0 } }; /***/ }, /* 38 */ /***/ function(module, exports, __webpack_require__) { var Tokenizer = __webpack_require__(39); /* Options: xmlMode: Disables the special behavior for script/style tags (false by default) lowerCaseAttributeNames: call .toLowerCase for each attribute name (true if xmlMode is `false`) lowerCaseTags: call .toLowerCase for each tag name (true if xmlMode is `false`) */ /* Callbacks: oncdataend, oncdatastart, onclosetag, oncomment, oncommentend, onerror, onopentag, onprocessinginstruction, onreset, ontext */ var formTags = { input: true, option: true, optgroup: true, select: true, button: true, datalist: true, textarea: true }; var openImpliesClose = { tr : { tr:true, th:true, td:true }, th : { th:true }, td : { thead:true, th:true, td:true }, body : { head:true, link:true, script:true }, li : { li:true }, p : { p:true }, h1 : { p:true }, h2 : { p:true }, h3 : { p:true }, h4 : { p:true }, h5 : { p:true }, h6 : { p:true }, select : formTags, input : formTags, output : formTags, button : formTags, datalist: formTags, textarea: formTags, option : { option:true }, optgroup: { optgroup:true } }; var voidElements = { __proto__: null, area: true, base: true, basefont: true, br: true, col: true, command: true, embed: true, frame: true, hr: true, img: true, input: true, isindex: true, keygen: true, link: true, meta: true, param: true, source: true, track: true, wbr: true, //common self closing svg elements path: true, circle: true, ellipse: true, line: true, rect: true, use: true, stop: true, polyline: true, polygon: true }; var re_nameEnd = /\s|\//; function Parser(cbs, options){ this._options = options || {}; this._cbs = cbs || {}; this._tagname = ""; this._attribname = ""; this._attribvalue = ""; this._attribs = null; this._stack = []; this.startIndex = 0; this.endIndex = null; this._lowerCaseTagNames = "lowerCaseTags" in this._options ? !!this._options.lowerCaseTags : !this._options.xmlMode; this._lowerCaseAttributeNames = "lowerCaseAttributeNames" in this._options ? !!this._options.lowerCaseAttributeNames : !this._options.xmlMode; if(!!this._options.Tokenizer) { Tokenizer = this._options.Tokenizer; } this._tokenizer = new Tokenizer(this._options, this); if(this._cbs.onparserinit) this._cbs.onparserinit(this); } __webpack_require__(3).inherits(Parser, __webpack_require__(2).EventEmitter); Parser.prototype._updatePosition = function(initialOffset){ if(this.endIndex === null){ if(this._tokenizer._sectionStart <= initialOffset){ this.startIndex = 0; } else { this.startIndex = this._tokenizer._sectionStart - initialOffset; } } else this.startIndex = this.endIndex + 1; this.endIndex = this._tokenizer.getAbsoluteIndex(); }; //Tokenizer event handlers Parser.prototype.ontext = function(data){ this._updatePosition(1); this.endIndex--; if(this._cbs.ontext) this._cbs.ontext(data); }; Parser.prototype.onopentagname = function(name){ if(this._lowerCaseTagNames){ name = name.toLowerCase(); } this._tagname = name; if(!this._options.xmlMode && name in openImpliesClose) { for( var el; (el = this._stack[this._stack.length - 1]) in openImpliesClose[name]; this.onclosetag(el) ); } if(this._options.xmlMode || !(name in voidElements)){ this._stack.push(name); } if(this._cbs.onopentagname) this._cbs.onopentagname(name); if(this._cbs.onopentag) this._attribs = {}; }; Parser.prototype.onopentagend = function(){ this._updatePosition(1); if(this._attribs){ if(this._cbs.onopentag) this._cbs.onopentag(this._tagname, this._attribs); this._attribs = null; } if(!this._options.xmlMode && this._cbs.onclosetag && this._tagname in voidElements){ this._cbs.onclosetag(this._tagname); } this._tagname = ""; }; Parser.prototype.onclosetag = function(name){ this._updatePosition(1); if(this._lowerCaseTagNames){ name = name.toLowerCase(); } if(this._stack.length && (!(name in voidElements) || this._options.xmlMode)){ var pos = this._stack.lastIndexOf(name); if(pos !== -1){ if(this._cbs.onclosetag){ pos = this._stack.length - pos; while(pos--) this._cbs.onclosetag(this._stack.pop()); } else this._stack.length = pos; } else if(name === "p" && !this._options.xmlMode){ this.onopentagname(name); this._closeCurrentTag(); } } else if(!this._options.xmlMode && (name === "br" || name === "p")){ this.onopentagname(name); this._closeCurrentTag(); } }; Parser.prototype.onselfclosingtag = function(){ if(this._options.xmlMode || this._options.recognizeSelfClosing){ this._closeCurrentTag(); } else { this.onopentagend(); } }; Parser.prototype._closeCurrentTag = function(){ var name = this._tagname; this.onopentagend(); //self-closing tags will be on the top of the stack //(cheaper check than in onclosetag) if(this._stack[this._stack.length - 1] === name){ if(this._cbs.onclosetag){ this._cbs.onclosetag(name); } this._stack.pop(); } }; Parser.prototype.onattribname = function(name){ if(this._lowerCaseAttributeNames){ name = name.toLowerCase(); } this._attribname = name; }; Parser.prototype.onattribdata = function(value){ this._attribvalue += value; }; Parser.prototype.onattribend = function(){ if(this._cbs.onattribute) this._cbs.onattribute(this._attribname, this._attribvalue); if( this._attribs && !Object.prototype.hasOwnProperty.call(this._attribs, this._attribname) ){ this._attribs[this._attribname] = this._attribvalue; } this._attribname = ""; this._attribvalue = ""; }; Parser.prototype._getInstructionName = function(value){ var idx = value.search(re_nameEnd), name = idx < 0 ? value : value.substr(0, idx); if(this._lowerCaseTagNames){ name = name.toLowerCase(); } return name; }; Parser.prototype.ondeclaration = function(value){ if(this._cbs.onprocessinginstruction){ var name = this._getInstructionName(value); this._cbs.onprocessinginstruction("!" + name, "!" + value); } }; Parser.prototype.onprocessinginstruction = function(value){ if(this._cbs.onprocessinginstruction){ var name = this._getInstructionName(value); this._cbs.onprocessinginstruction("?" + name, "?" + value); } }; Parser.prototype.oncomment = function(value){ this._updatePosition(4); if(this._cbs.oncomment) this._cbs.oncomment(value); if(this._cbs.oncommentend) this._cbs.oncommentend(); }; Parser.prototype.oncdata = function(value){ this._updatePosition(1); if(this._options.xmlMode || this._options.recognizeCDATA){ if(this._cbs.oncdatastart) this._cbs.oncdatastart(); if(this._cbs.ontext) this._cbs.ontext(value); if(this._cbs.oncdataend) this._cbs.oncdataend(); } else { this.oncomment("[CDATA[" + value + "]]"); } }; Parser.prototype.onerror = function(err){ if(this._cbs.onerror) this._cbs.onerror(err); }; Parser.prototype.onend = function(){ if(this._cbs.onclosetag){ for( var i = this._stack.length; i > 0; this._cbs.onclosetag(this._stack[--i]) ); } if(this._cbs.onend) this._cbs.onend(); }; //Resets the parser to a blank state, ready to parse a new HTML document Parser.prototype.reset = function(){ if(this._cbs.onreset) this._cbs.onreset(); this._tokenizer.reset(); this._tagname = ""; this._attribname = ""; this._attribs = null; this._stack = []; if(this._cbs.onparserinit) this._cbs.onparserinit(this); }; //Parses a complete HTML document and pushes it to the handler Parser.prototype.parseComplete = function(data){ this.reset(); this.end(data); }; Parser.prototype.write = function(chunk){ this._tokenizer.write(chunk); }; Parser.prototype.end = function(chunk){ this._tokenizer.end(chunk); }; Parser.prototype.pause = function(){ this._tokenizer.pause(); }; Parser.prototype.resume = function(){ this._tokenizer.resume(); }; //alias for backwards compat Parser.prototype.parseChunk = Parser.prototype.write; Parser.prototype.done = Parser.prototype.end; module.exports = Parser; /***/ }, /* 39 */ /***/ function(module, exports, __webpack_require__) { module.exports = Tokenizer; var decodeCodePoint = __webpack_require__(40), entityMap = __webpack_require__(42), legacyMap = __webpack_require__(43), xmlMap = __webpack_require__(44), i = 0, TEXT = i++, BEFORE_TAG_NAME = i++, //after < IN_TAG_NAME = i++, IN_SELF_CLOSING_TAG = i++, BEFORE_CLOSING_TAG_NAME = i++, IN_CLOSING_TAG_NAME = i++, AFTER_CLOSING_TAG_NAME = i++, //attributes BEFORE_ATTRIBUTE_NAME = i++, IN_ATTRIBUTE_NAME = i++, AFTER_ATTRIBUTE_NAME = i++, BEFORE_ATTRIBUTE_VALUE = i++, IN_ATTRIBUTE_VALUE_DQ = i++, // " IN_ATTRIBUTE_VALUE_SQ = i++, // ' IN_ATTRIBUTE_VALUE_NQ = i++, //declarations BEFORE_DECLARATION = i++, // ! IN_DECLARATION = i++, //processing instructions IN_PROCESSING_INSTRUCTION = i++, // ? //comments BEFORE_COMMENT = i++, IN_COMMENT = i++, AFTER_COMMENT_1 = i++, AFTER_COMMENT_2 = i++, //cdata BEFORE_CDATA_1 = i++, // [ BEFORE_CDATA_2 = i++, // C BEFORE_CDATA_3 = i++, // D BEFORE_CDATA_4 = i++, // A BEFORE_CDATA_5 = i++, // T BEFORE_CDATA_6 = i++, // A IN_CDATA = i++, // [ AFTER_CDATA_1 = i++, // ] AFTER_CDATA_2 = i++, // ] //special tags BEFORE_SPECIAL = i++, //S BEFORE_SPECIAL_END = i++, //S BEFORE_SCRIPT_1 = i++, //C BEFORE_SCRIPT_2 = i++, //R BEFORE_SCRIPT_3 = i++, //I BEFORE_SCRIPT_4 = i++, //P BEFORE_SCRIPT_5 = i++, //T AFTER_SCRIPT_1 = i++, //C AFTER_SCRIPT_2 = i++, //R AFTER_SCRIPT_3 = i++, //I AFTER_SCRIPT_4 = i++, //P AFTER_SCRIPT_5 = i++, //T BEFORE_STYLE_1 = i++, //T BEFORE_STYLE_2 = i++, //Y BEFORE_STYLE_3 = i++, //L BEFORE_STYLE_4 = i++, //E AFTER_STYLE_1 = i++, //T AFTER_STYLE_2 = i++, //Y AFTER_STYLE_3 = i++, //L AFTER_STYLE_4 = i++, //E BEFORE_ENTITY = i++, //& BEFORE_NUMERIC_ENTITY = i++, //# IN_NAMED_ENTITY = i++, IN_NUMERIC_ENTITY = i++, IN_HEX_ENTITY = i++, //X j = 0, SPECIAL_NONE = j++, SPECIAL_SCRIPT = j++, SPECIAL_STYLE = j++; function whitespace(c){ return c === " " || c === "\n" || c === "\t" || c === "\f" || c === "\r"; } function characterState(char, SUCCESS){ return function(c){ if(c === char) this._state = SUCCESS; }; } function ifElseState(upper, SUCCESS, FAILURE){ var lower = upper.toLowerCase(); if(upper === lower){ return function(c){ if(c === lower){ this._state = SUCCESS; } else { this._state = FAILURE; this._index--; } }; } else { return function(c){ if(c === lower || c === upper){ this._state = SUCCESS; } else { this._state = FAILURE; this._index--; } }; } } function consumeSpecialNameChar(upper, NEXT_STATE){ var lower = upper.toLowerCase(); return function(c){ if(c === lower || c === upper){ this._state = NEXT_STATE; } else { this._state = IN_TAG_NAME; this._index--; //consume the token again } }; } function Tokenizer(options, cbs){ this._state = TEXT; this._buffer = ""; this._sectionStart = 0; this._index = 0; this._bufferOffset = 0; //chars removed from _buffer this._baseState = TEXT; this._special = SPECIAL_NONE; this._cbs = cbs; this._running = true; this._ended = false; this._xmlMode = !!(options && options.xmlMode); this._decodeEntities = !!(options && options.decodeEntities); } Tokenizer.prototype._stateText = function(c){ if(c === "<"){ if(this._index > this._sectionStart){ this._cbs.ontext(this._getSection()); } this._state = BEFORE_TAG_NAME; this._sectionStart = this._index; } else if(this._decodeEntities && this._special === SPECIAL_NONE && c === "&"){ if(this._index > this._sectionStart){ this._cbs.ontext(this._getSection()); } this._baseState = TEXT; this._state = BEFORE_ENTITY; this._sectionStart = this._index; } }; Tokenizer.prototype._stateBeforeTagName = function(c){ if(c === "/"){ this._state = BEFORE_CLOSING_TAG_NAME; } else if(c === ">" || this._special !== SPECIAL_NONE || whitespace(c)) { this._state = TEXT; } else if(c === "!"){ this._state = BEFORE_DECLARATION; this._sectionStart = this._index + 1; } else if(c === "?"){ this._state = IN_PROCESSING_INSTRUCTION; this._sectionStart = this._index + 1; } else if(c === "<"){ this._cbs.ontext(this._getSection()); this._sectionStart = this._index; } else { this._state = (!this._xmlMode && (c === "s" || c === "S")) ? BEFORE_SPECIAL : IN_TAG_NAME; this._sectionStart = this._index; } }; Tokenizer.prototype._stateInTagName = function(c){ if(c === "/" || c === ">" || whitespace(c)){ this._emitToken("onopentagname"); this._state = BEFORE_ATTRIBUTE_NAME; this._index--; } }; Tokenizer.prototype._stateBeforeCloseingTagName = function(c){ if(whitespace(c)); else if(c === ">"){ this._state = TEXT; } else if(this._special !== SPECIAL_NONE){ if(c === "s" || c === "S"){ this._state = BEFORE_SPECIAL_END; } else { this._state = TEXT; this._index--; } } else { this._state = IN_CLOSING_TAG_NAME; this._sectionStart = this._index; } }; Tokenizer.prototype._stateInCloseingTagName = function(c){ if(c === ">" || whitespace(c)){ this._emitToken("onclosetag"); this._state = AFTER_CLOSING_TAG_NAME; this._index--; } }; Tokenizer.prototype._stateAfterCloseingTagName = function(c){ //skip everything until ">" if(c === ">"){ this._state = TEXT; this._sectionStart = this._index + 1; } }; Tokenizer.prototype._stateBeforeAttributeName = function(c){ if(c === ">"){ this._cbs.onopentagend(); this._state = TEXT; this._sectionStart = this._index + 1; } else if(c === "/"){ this._state = IN_SELF_CLOSING_TAG; } else if(!whitespace(c)){ this._state = IN_ATTRIBUTE_NAME; this._sectionStart = this._index; } }; Tokenizer.prototype._stateInSelfClosingTag = function(c){ if(c === ">"){ this._cbs.onselfclosingtag(); this._state = TEXT; this._sectionStart = this._index + 1; } else if(!whitespace(c)){ this._state = BEFORE_ATTRIBUTE_NAME; this._index--; } }; Tokenizer.prototype._stateInAttributeName = function(c){ if(c === "=" || c === "/" || c === ">" || whitespace(c)){ this._cbs.onattribname(this._getSection()); this._sectionStart = -1; this._state = AFTER_ATTRIBUTE_NAME; this._index--; } }; Tokenizer.prototype._stateAfterAttributeName = function(c){ if(c === "="){ this._state = BEFORE_ATTRIBUTE_VALUE; } else if(c === "/" || c === ">"){ this._cbs.onattribend(); this._state = BEFORE_ATTRIBUTE_NAME; this._index--; } else if(!whitespace(c)){ this._cbs.onattribend(); this._state = IN_ATTRIBUTE_NAME; this._sectionStart = this._index; } }; Tokenizer.prototype._stateBeforeAttributeValue = function(c){ if(c === "\""){ this._state = IN_ATTRIBUTE_VALUE_DQ; this._sectionStart = this._index + 1; } else if(c === "'"){ this._state = IN_ATTRIBUTE_VALUE_SQ; this._sectionStart = this._index + 1; } else if(!whitespace(c)){ this._state = IN_ATTRIBUTE_VALUE_NQ; this._sectionStart = this._index; this._index--; //reconsume token } }; Tokenizer.prototype._stateInAttributeValueDoubleQuotes = function(c){ if(c === "\""){ this._emitToken("onattribdata"); this._cbs.onattribend(); this._state = BEFORE_ATTRIBUTE_NAME; } else if(this._decodeEntities && c === "&"){ this._emitToken("onattribdata"); this._baseState = this._state; this._state = BEFORE_ENTITY; this._sectionStart = this._index; } }; Tokenizer.prototype._stateInAttributeValueSingleQuotes = function(c){ if(c === "'"){ this._emitToken("onattribdata"); this._cbs.onattribend(); this._state = BEFORE_ATTRIBUTE_NAME; } else if(this._decodeEntities && c === "&"){ this._emitToken("onattribdata"); this._baseState = this._state; this._state = BEFORE_ENTITY; this._sectionStart = this._index; } }; Tokenizer.prototype._stateInAttributeValueNoQuotes = function(c){ if(whitespace(c) || c === ">"){ this._emitToken("onattribdata"); this._cbs.onattribend(); this._state = BEFORE_ATTRIBUTE_NAME; this._index--; } else if(this._decodeEntities && c === "&"){ this._emitToken("onattribdata"); this._baseState = this._state; this._state = BEFORE_ENTITY; this._sectionStart = this._index; } }; Tokenizer.prototype._stateBeforeDeclaration = function(c){ this._state = c === "[" ? BEFORE_CDATA_1 : c === "-" ? BEFORE_COMMENT : IN_DECLARATION; }; Tokenizer.prototype._stateInDeclaration = function(c){ if(c === ">"){ this._cbs.ondeclaration(this._getSection()); this._state = TEXT; this._sectionStart = this._index + 1; } }; Tokenizer.prototype._stateInProcessingInstruction = function(c){ if(c === ">"){ this._cbs.onprocessinginstruction(this._getSection()); this._state = TEXT; this._sectionStart = this._index + 1; } }; Tokenizer.prototype._stateBeforeComment = function(c){ if(c === "-"){ this._state = IN_COMMENT; this._sectionStart = this._index + 1; } else { this._state = IN_DECLARATION; } }; Tokenizer.prototype._stateInComment = function(c){ if(c === "-") this._state = AFTER_COMMENT_1; }; Tokenizer.prototype._stateAfterComment1 = function(c){ if(c === "-"){ this._state = AFTER_COMMENT_2; } else { this._state = IN_COMMENT; } }; Tokenizer.prototype._stateAfterComment2 = function(c){ if(c === ">"){ //remove 2 trailing chars this._cbs.oncomment(this._buffer.substring(this._sectionStart, this._index - 2)); this._state = TEXT; this._sectionStart = this._index + 1; } else if(c !== "-"){ this._state = IN_COMMENT; } // else: stay in AFTER_COMMENT_2 (`--->`) }; Tokenizer.prototype._stateBeforeCdata1 = ifElseState("C", BEFORE_CDATA_2, IN_DECLARATION); Tokenizer.prototype._stateBeforeCdata2 = ifElseState("D", BEFORE_CDATA_3, IN_DECLARATION); Tokenizer.prototype._stateBeforeCdata3 = ifElseState("A", BEFORE_CDATA_4, IN_DECLARATION); Tokenizer.prototype._stateBeforeCdata4 = ifElseState("T", BEFORE_CDATA_5, IN_DECLARATION); Tokenizer.prototype._stateBeforeCdata5 = ifElseState("A", BEFORE_CDATA_6, IN_DECLARATION); Tokenizer.prototype._stateBeforeCdata6 = function(c){ if(c === "["){ this._state = IN_CDATA; this._sectionStart = this._index + 1; } else { this._state = IN_DECLARATION; this._index--; } }; Tokenizer.prototype._stateInCdata = function(c){ if(c === "]") this._state = AFTER_CDATA_1; }; Tokenizer.prototype._stateAfterCdata1 = characterState("]", AFTER_CDATA_2); Tokenizer.prototype._stateAfterCdata2 = function(c){ if(c === ">"){ //remove 2 trailing chars this._cbs.oncdata(this._buffer.substring(this._sectionStart, this._index - 2)); this._state = TEXT; this._sectionStart = this._index + 1; } else if(c !== "]") { this._state = IN_CDATA; } //else: stay in AFTER_CDATA_2 (`]]]>`) }; Tokenizer.prototype._stateBeforeSpecial = function(c){ if(c === "c" || c === "C"){ this._state = BEFORE_SCRIPT_1; } else if(c === "t" || c === "T"){ this._state = BEFORE_STYLE_1; } else { this._state = IN_TAG_NAME; this._index--; //consume the token again } }; Tokenizer.prototype._stateBeforeSpecialEnd = function(c){ if(this._special === SPECIAL_SCRIPT && (c === "c" || c === "C")){ this._state = AFTER_SCRIPT_1; } else if(this._special === SPECIAL_STYLE && (c === "t" || c === "T")){ this._state = AFTER_STYLE_1; } else this._state = TEXT; }; Tokenizer.prototype._stateBeforeScript1 = consumeSpecialNameChar("R", BEFORE_SCRIPT_2); Tokenizer.prototype._stateBeforeScript2 = consumeSpecialNameChar("I", BEFORE_SCRIPT_3); Tokenizer.prototype._stateBeforeScript3 = consumeSpecialNameChar("P", BEFORE_SCRIPT_4); Tokenizer.prototype._stateBeforeScript4 = consumeSpecialNameChar("T", BEFORE_SCRIPT_5); Tokenizer.prototype._stateBeforeScript5 = function(c){ if(c === "/" || c === ">" || whitespace(c)){ this._special = SPECIAL_SCRIPT; } this._state = IN_TAG_NAME; this._index--; //consume the token again }; Tokenizer.prototype._stateAfterScript1 = ifElseState("R", AFTER_SCRIPT_2, TEXT); Tokenizer.prototype._stateAfterScript2 = ifElseState("I", AFTER_SCRIPT_3, TEXT); Tokenizer.prototype._stateAfterScript3 = ifElseState("P", AFTER_SCRIPT_4, TEXT); Tokenizer.prototype._stateAfterScript4 = ifElseState("T", AFTER_SCRIPT_5, TEXT); Tokenizer.prototype._stateAfterScript5 = function(c){ if(c === ">" || whitespace(c)){ this._special = SPECIAL_NONE; this._state = IN_CLOSING_TAG_NAME; this._sectionStart = this._index - 6; this._index--; //reconsume the token } else this._state = TEXT; }; Tokenizer.prototype._stateBeforeStyle1 = consumeSpecialNameChar("Y", BEFORE_STYLE_2); Tokenizer.prototype._stateBeforeStyle2 = consumeSpecialNameChar("L", BEFORE_STYLE_3); Tokenizer.prototype._stateBeforeStyle3 = consumeSpecialNameChar("E", BEFORE_STYLE_4); Tokenizer.prototype._stateBeforeStyle4 = function(c){ if(c === "/" || c === ">" || whitespace(c)){ this._special = SPECIAL_STYLE; } this._state = IN_TAG_NAME; this._index--; //consume the token again }; Tokenizer.prototype._stateAfterStyle1 = ifElseState("Y", AFTER_STYLE_2, TEXT); Tokenizer.prototype._stateAfterStyle2 = ifElseState("L", AFTER_STYLE_3, TEXT); Tokenizer.prototype._stateAfterStyle3 = ifElseState("E", AFTER_STYLE_4, TEXT); Tokenizer.prototype._stateAfterStyle4 = function(c){ if(c === ">" || whitespace(c)){ this._special = SPECIAL_NONE; this._state = IN_CLOSING_TAG_NAME; this._sectionStart = this._index - 5; this._index--; //reconsume the token } else this._state = TEXT; }; Tokenizer.prototype._stateBeforeEntity = ifElseState("#", BEFORE_NUMERIC_ENTITY, IN_NAMED_ENTITY); Tokenizer.prototype._stateBeforeNumericEntity = ifElseState("X", IN_HEX_ENTITY, IN_NUMERIC_ENTITY); //for entities terminated with a semicolon Tokenizer.prototype._parseNamedEntityStrict = function(){ //offset = 1 if(this._sectionStart + 1 < this._index){ var entity = this._buffer.substring(this._sectionStart + 1, this._index), map = this._xmlMode ? xmlMap : entityMap; if(map.hasOwnProperty(entity)){ this._emitPartial(map[entity]); this._sectionStart = this._index + 1; } } }; //parses legacy entities (without trailing semicolon) Tokenizer.prototype._parseLegacyEntity = function(){ var start = this._sectionStart + 1, limit = this._index - start; if(limit > 6) limit = 6; //the max length of legacy entities is 6 while(limit >= 2){ //the min length of legacy entities is 2 var entity = this._buffer.substr(start, limit); if(legacyMap.hasOwnProperty(entity)){ this._emitPartial(legacyMap[entity]); this._sectionStart += limit + 1; return; } else { limit--; } } }; Tokenizer.prototype._stateInNamedEntity = function(c){ if(c === ";"){ this._parseNamedEntityStrict(); if(this._sectionStart + 1 < this._index && !this._xmlMode){ this._parseLegacyEntity(); } this._state = this._baseState; } else if((c < "a" || c > "z") && (c < "A" || c > "Z") && (c < "0" || c > "9")){ if(this._xmlMode); else if(this._sectionStart + 1 === this._index); else if(this._baseState !== TEXT){ if(c !== "="){ this._parseNamedEntityStrict(); } } else { this._parseLegacyEntity(); } this._state = this._baseState; this._index--; } }; Tokenizer.prototype._decodeNumericEntity = function(offset, base){ var sectionStart = this._sectionStart + offset; if(sectionStart !== this._index){ //parse entity var entity = this._buffer.substring(sectionStart, this._index); var parsed = parseInt(entity, base); this._emitPartial(decodeCodePoint(parsed)); this._sectionStart = this._index; } else { this._sectionStart--; } this._state = this._baseState; }; Tokenizer.prototype._stateInNumericEntity = function(c){ if(c === ";"){ this._decodeNumericEntity(2, 10); this._sectionStart++; } else if(c < "0" || c > "9"){ if(!this._xmlMode){ this._decodeNumericEntity(2, 10); } else { this._state = this._baseState; } this._index--; } }; Tokenizer.prototype._stateInHexEntity = function(c){ if(c === ";"){ this._decodeNumericEntity(3, 16); this._sectionStart++; } else if((c < "a" || c > "f") && (c < "A" || c > "F") && (c < "0" || c > "9")){ if(!this._xmlMode){ this._decodeNumericEntity(3, 16); } else { this._state = this._baseState; } this._index--; } }; Tokenizer.prototype._cleanup = function (){ if(this._sectionStart < 0){ this._buffer = ""; this._index = 0; this._bufferOffset += this._index; } else if(this._running){ if(this._state === TEXT){ if(this._sectionStart !== this._index){ this._cbs.ontext(this._buffer.substr(this._sectionStart)); } this._buffer = ""; this._index = 0; this._bufferOffset += this._index; } else if(this._sectionStart === this._index){ //the section just started this._buffer = ""; this._index = 0; this._bufferOffset += this._index; } else { //remove everything unnecessary this._buffer = this._buffer.substr(this._sectionStart); this._index -= this._sectionStart; this._bufferOffset += this._sectionStart; } this._sectionStart = 0; } }; //TODO make events conditional Tokenizer.prototype.write = function(chunk){ if(this._ended) this._cbs.onerror(Error(".write() after done!")); this._buffer += chunk; this._parse(); }; Tokenizer.prototype._parse = function(){ while(this._index < this._buffer.length && this._running){ var c = this._buffer.charAt(this._index); if(this._state === TEXT) { this._stateText(c); } else if(this._state === BEFORE_TAG_NAME){ this._stateBeforeTagName(c); } else if(this._state === IN_TAG_NAME) { this._stateInTagName(c); } else if(this._state === BEFORE_CLOSING_TAG_NAME){ this._stateBeforeCloseingTagName(c); } else if(this._state === IN_CLOSING_TAG_NAME){ this._stateInCloseingTagName(c); } else if(this._state === AFTER_CLOSING_TAG_NAME){ this._stateAfterCloseingTagName(c); } else if(this._state === IN_SELF_CLOSING_TAG){ this._stateInSelfClosingTag(c); } /* * attributes */ else if(this._state === BEFORE_ATTRIBUTE_NAME){ this._stateBeforeAttributeName(c); } else if(this._state === IN_ATTRIBUTE_NAME){ this._stateInAttributeName(c); } else if(this._state === AFTER_ATTRIBUTE_NAME){ this._stateAfterAttributeName(c); } else if(this._state === BEFORE_ATTRIBUTE_VALUE){ this._stateBeforeAttributeValue(c); } else if(this._state === IN_ATTRIBUTE_VALUE_DQ){ this._stateInAttributeValueDoubleQuotes(c); } else if(this._state === IN_ATTRIBUTE_VALUE_SQ){ this._stateInAttributeValueSingleQuotes(c); } else if(this._state === IN_ATTRIBUTE_VALUE_NQ){ this._stateInAttributeValueNoQuotes(c); } /* * declarations */ else if(this._state === BEFORE_DECLARATION){ this._stateBeforeDeclaration(c); } else if(this._state === IN_DECLARATION){ this._stateInDeclaration(c); } /* * processing instructions */ else if(this._state === IN_PROCESSING_INSTRUCTION){ this._stateInProcessingInstruction(c); } /* * comments */ else if(this._state === BEFORE_COMMENT){ this._stateBeforeComment(c); } else if(this._state === IN_COMMENT){ this._stateInComment(c); } else if(this._state === AFTER_COMMENT_1){ this._stateAfterComment1(c); } else if(this._state === AFTER_COMMENT_2){ this._stateAfterComment2(c); } /* * cdata */ else if(this._state === BEFORE_CDATA_1){ this._stateBeforeCdata1(c); } else if(this._state === BEFORE_CDATA_2){ this._stateBeforeCdata2(c); } else if(this._state === BEFORE_CDATA_3){ this._stateBeforeCdata3(c); } else if(this._state === BEFORE_CDATA_4){ this._stateBeforeCdata4(c); } else if(this._state === BEFORE_CDATA_5){ this._stateBeforeCdata5(c); } else if(this._state === BEFORE_CDATA_6){ this._stateBeforeCdata6(c); } else if(this._state === IN_CDATA){ this._stateInCdata(c); } else if(this._state === AFTER_CDATA_1){ this._stateAfterCdata1(c); } else if(this._state === AFTER_CDATA_2){ this._stateAfterCdata2(c); } /* * special tags */ else if(this._state === BEFORE_SPECIAL){ this._stateBeforeSpecial(c); } else if(this._state === BEFORE_SPECIAL_END){ this._stateBeforeSpecialEnd(c); } /* * script */ else if(this._state === BEFORE_SCRIPT_1){ this._stateBeforeScript1(c); } else if(this._state === BEFORE_SCRIPT_2){ this._stateBeforeScript2(c); } else if(this._state === BEFORE_SCRIPT_3){ this._stateBeforeScript3(c); } else if(this._state === BEFORE_SCRIPT_4){ this._stateBeforeScript4(c); } else if(this._state === BEFORE_SCRIPT_5){ this._stateBeforeScript5(c); } else if(this._state === AFTER_SCRIPT_1){ this._stateAfterScript1(c); } else if(this._state === AFTER_SCRIPT_2){ this._stateAfterScript2(c); } else if(this._state === AFTER_SCRIPT_3){ this._stateAfterScript3(c); } else if(this._state === AFTER_SCRIPT_4){ this._stateAfterScript4(c); } else if(this._state === AFTER_SCRIPT_5){ this._stateAfterScript5(c); } /* * style */ else if(this._state === BEFORE_STYLE_1){ this._stateBeforeStyle1(c); } else if(this._state === BEFORE_STYLE_2){ this._stateBeforeStyle2(c); } else if(this._state === BEFORE_STYLE_3){ this._stateBeforeStyle3(c); } else if(this._state === BEFORE_STYLE_4){ this._stateBeforeStyle4(c); } else if(this._state === AFTER_STYLE_1){ this._stateAfterStyle1(c); } else if(this._state === AFTER_STYLE_2){ this._stateAfterStyle2(c); } else if(this._state === AFTER_STYLE_3){ this._stateAfterStyle3(c); } else if(this._state === AFTER_STYLE_4){ this._stateAfterStyle4(c); } /* * entities */ else if(this._state === BEFORE_ENTITY){ this._stateBeforeEntity(c); } else if(this._state === BEFORE_NUMERIC_ENTITY){ this._stateBeforeNumericEntity(c); } else if(this._state === IN_NAMED_ENTITY){ this._stateInNamedEntity(c); } else if(this._state === IN_NUMERIC_ENTITY){ this._stateInNumericEntity(c); } else if(this._state === IN_HEX_ENTITY){ this._stateInHexEntity(c); } else { this._cbs.onerror(Error("unknown _state"), this._state); } this._index++; } this._cleanup(); }; Tokenizer.prototype.pause = function(){ this._running = false; }; Tokenizer.prototype.resume = function(){ this._running = true; if(this._index < this._buffer.length){ this._parse(); } if(this._ended){ this._finish(); } }; Tokenizer.prototype.end = function(chunk){ if(this._ended) this._cbs.onerror(Error(".end() after done!")); if(chunk) this.write(chunk); this._ended = true; if(this._running) this._finish(); }; Tokenizer.prototype._finish = function(){ //if there is remaining data, emit it in a reasonable way if(this._sectionStart < this._index){ this._handleTrailingData(); } this._cbs.onend(); }; Tokenizer.prototype._handleTrailingData = function(){ var data = this._buffer.substr(this._sectionStart); if(this._state === IN_CDATA || this._state === AFTER_CDATA_1 || this._state === AFTER_CDATA_2){ this._cbs.oncdata(data); } else if(this._state === IN_COMMENT || this._state === AFTER_COMMENT_1 || this._state === AFTER_COMMENT_2){ this._cbs.oncomment(data); } else if(this._state === IN_NAMED_ENTITY && !this._xmlMode){ this._parseLegacyEntity(); if(this._sectionStart < this._index){ this._state = this._baseState; this._handleTrailingData(); } } else if(this._state === IN_NUMERIC_ENTITY && !this._xmlMode){ this._decodeNumericEntity(2, 10); if(this._sectionStart < this._index){ this._state = this._baseState; this._handleTrailingData(); } } else if(this._state === IN_HEX_ENTITY && !this._xmlMode){ this._decodeNumericEntity(3, 16); if(this._sectionStart < this._index){ this._state = this._baseState; this._handleTrailingData(); } } else if( this._state !== IN_TAG_NAME && this._state !== BEFORE_ATTRIBUTE_NAME && this._state !== BEFORE_ATTRIBUTE_VALUE && this._state !== AFTER_ATTRIBUTE_NAME && this._state !== IN_ATTRIBUTE_NAME && this._state !== IN_ATTRIBUTE_VALUE_SQ && this._state !== IN_ATTRIBUTE_VALUE_DQ && this._state !== IN_ATTRIBUTE_VALUE_NQ && this._state !== IN_CLOSING_TAG_NAME ){ this._cbs.ontext(data); } //else, ignore remaining data //TODO add a way to remove current tag }; Tokenizer.prototype.reset = function(){ Tokenizer.call(this, {xmlMode: this._xmlMode, decodeEntities: this._decodeEntities}, this._cbs); }; Tokenizer.prototype.getAbsoluteIndex = function(){ return this._bufferOffset + this._index; }; Tokenizer.prototype._getSection = function(){ return this._buffer.substring(this._sectionStart, this._index); }; Tokenizer.prototype._emitToken = function(name){ this._cbs[name](this._getSection()); this._sectionStart = -1; }; Tokenizer.prototype._emitPartial = function(value){ if(this._baseState !== TEXT){ this._cbs.onattribdata(value); //TODO implement the new event } else { this._cbs.ontext(value); } }; /***/ }, /* 40 */ /***/ function(module, exports, __webpack_require__) { var decodeMap = __webpack_require__(41); module.exports = decodeCodePoint; // modified version of https://github.com/mathiasbynens/he/blob/master/src/he.js#L94-L119 function decodeCodePoint(codePoint){ if((codePoint >= 0xD800 && codePoint <= 0xDFFF) || codePoint > 0x10FFFF){ return "\uFFFD"; } if(codePoint in decodeMap){ codePoint = decodeMap[codePoint]; } var output = ""; if(codePoint > 0xFFFF){ codePoint -= 0x10000; output += String.fromCharCode(codePoint >>> 10 & 0x3FF | 0xD800); codePoint = 0xDC00 | codePoint & 0x3FF; } output += String.fromCharCode(codePoint); return output; } /***/ }, /* 41 */ /***/ function(module, exports) { module.exports = { "0": 65533, "128": 8364, "130": 8218, "131": 402, "132": 8222, "133": 8230, "134": 8224, "135": 8225, "136": 710, "137": 8240, "138": 352, "139": 8249, "140": 338, "142": 381, "145": 8216, "146": 8217, "147": 8220, "148": 8221, "149": 8226, "150": 8211, "151": 8212, "152": 732, "153": 8482, "154": 353, "155": 8250, "156": 339, "158": 382, "159": 376 }; /***/ }, /* 42 */ /***/ function(module, exports) { module.exports = { "Aacute": "Á", "aacute": "á", "Abreve": "Ă", "abreve": "ă", "ac": "∾", "acd": "∿", "acE": "∾̳", "Acirc": "Â", "acirc": "â", "acute": "´", "Acy": "А", "acy": "а", "AElig": "Æ", "aelig": "æ", "af": "⁡", "Afr": "𝔄", "afr": "𝔞", "Agrave": "À", "agrave": "à", "alefsym": "ℵ", "aleph": "ℵ", "Alpha": "Α", "alpha": "α", "Amacr": "Ā", "amacr": "ā", "amalg": "⨿", "amp": "&", "AMP": "&", "andand": "⩕", "And": "⩓", "and": "∧", "andd": "⩜", "andslope": "⩘", "andv": "⩚", "ang": "∠", "ange": "⦤", "angle": "∠", "angmsdaa": "⦨", "angmsdab": "⦩", "angmsdac": "⦪", "angmsdad": "⦫", "angmsdae": "⦬", "angmsdaf": "⦭", "angmsdag": "⦮", "angmsdah": "⦯", "angmsd": "∡", "angrt": "∟", "angrtvb": "⊾", "angrtvbd": "⦝", "angsph": "∢", "angst": "Å", "angzarr": "⍼", "Aogon": "Ą", "aogon": "ą", "Aopf": "𝔸", "aopf": "𝕒", "apacir": "⩯", "ap": "≈", "apE": "⩰", "ape": "≊", "apid": "≋", "apos": "'", "ApplyFunction": "⁡", "approx": "≈", "approxeq": "≊", "Aring": "Å", "aring": "å", "Ascr": "𝒜", "ascr": "𝒶", "Assign": "≔", "ast": "*", "asymp": "≈", "asympeq": "≍", "Atilde": "Ã", "atilde": "ã", "Auml": "Ä", "auml": "ä", "awconint": "∳", "awint": "⨑", "backcong": "≌", "backepsilon": "϶", "backprime": "‵", "backsim": "∽", "backsimeq": "⋍", "Backslash": "∖", "Barv": "⫧", "barvee": "⊽", "barwed": "⌅", "Barwed": "⌆", "barwedge": "⌅", "bbrk": "⎵", "bbrktbrk": "⎶", "bcong": "≌", "Bcy": "Б", "bcy": "б", "bdquo": "„", "becaus": "∵", "because": "∵", "Because": "∵", "bemptyv": "⦰", "bepsi": "϶", "bernou": "ℬ", "Bernoullis": "ℬ", "Beta": "Β", "beta": "β", "beth": "ℶ", "between": "≬", "Bfr": "𝔅", "bfr": "𝔟", "bigcap": "⋂", "bigcirc": "◯", "bigcup": "⋃", "bigodot": "⨀", "bigoplus": "⨁", "bigotimes": "⨂", "bigsqcup": "⨆", "bigstar": "★", "bigtriangledown": "▽", "bigtriangleup": "△", "biguplus": "⨄", "bigvee": "⋁", "bigwedge": "⋀", "bkarow": "⤍", "blacklozenge": "⧫", "blacksquare": "▪", "blacktriangle": "▴", "blacktriangledown": "▾", "blacktriangleleft": "◂", "blacktriangleright": "▸", "blank": "␣", "blk12": "▒", "blk14": "░", "blk34": "▓", "block": "█", "bne": "=⃥", "bnequiv": "≡⃥", "bNot": "⫭", "bnot": "⌐", "Bopf": "𝔹", "bopf": "𝕓", "bot": "⊥", "bottom": "⊥", "bowtie": "⋈", "boxbox": "⧉", "boxdl": "┐", "boxdL": "╕", "boxDl": "╖", "boxDL": "╗", "boxdr": "┌", "boxdR": "╒", "boxDr": "╓", "boxDR": "╔", "boxh": "─", "boxH": "═", "boxhd": "┬", "boxHd": "╤", "boxhD": "╥", "boxHD": "╦", "boxhu": "┴", "boxHu": "╧", "boxhU": "╨", "boxHU": "╩", "boxminus": "⊟", "boxplus": "⊞", "boxtimes": "⊠", "boxul": "┘", "boxuL": "╛", "boxUl": "╜", "boxUL": "╝", "boxur": "└", "boxuR": "╘", "boxUr": "╙", "boxUR": "╚", "boxv": "│", "boxV": "║", "boxvh": "┼", "boxvH": "╪", "boxVh": "╫", "boxVH": "╬", "boxvl": "┤", "boxvL": "╡", "boxVl": "╢", "boxVL": "╣", "boxvr": "├", "boxvR": "╞", "boxVr": "╟", "boxVR": "╠", "bprime": "‵", "breve": "˘", "Breve": "˘", "brvbar": "¦", "bscr": "𝒷", "Bscr": "ℬ", "bsemi": "⁏", "bsim": "∽", "bsime": "⋍", "bsolb": "⧅", "bsol": "\\", "bsolhsub": "⟈", "bull": "•", "bullet": "•", "bump": "≎", "bumpE": "⪮", "bumpe": "≏", "Bumpeq": "≎", "bumpeq": "≏", "Cacute": "Ć", "cacute": "ć", "capand": "⩄", "capbrcup": "⩉", "capcap": "⩋", "cap": "∩", "Cap": "⋒", "capcup": "⩇", "capdot": "⩀", "CapitalDifferentialD": "ⅅ", "caps": "∩︀", "caret": "⁁", "caron": "ˇ", "Cayleys": "ℭ", "ccaps": "⩍", "Ccaron": "Č", "ccaron": "č", "Ccedil": "Ç", "ccedil": "ç", "Ccirc": "Ĉ", "ccirc": "ĉ", "Cconint": "∰", "ccups": "⩌", "ccupssm": "⩐", "Cdot": "Ċ", "cdot": "ċ", "cedil": "¸", "Cedilla": "¸", "cemptyv": "⦲", "cent": "¢", "centerdot": "·", "CenterDot": "·", "cfr": "𝔠", "Cfr": "ℭ", "CHcy": "Ч", "chcy": "ч", "check": "✓", "checkmark": "✓", "Chi": "Χ", "chi": "χ", "circ": "ˆ", "circeq": "≗", "circlearrowleft": "↺", "circlearrowright": "↻", "circledast": "⊛", "circledcirc": "⊚", "circleddash": "⊝", "CircleDot": "⊙", "circledR": "®", "circledS": "Ⓢ", "CircleMinus": "⊖", "CirclePlus": "⊕", "CircleTimes": "⊗", "cir": "○", "cirE": "⧃", "cire": "≗", "cirfnint": "⨐", "cirmid": "⫯", "cirscir": "⧂", "ClockwiseContourIntegral": "∲", "CloseCurlyDoubleQuote": "”", "CloseCurlyQuote": "’", "clubs": "♣", "clubsuit": "♣", "colon": ":", "Colon": "∷", "Colone": "⩴", "colone": "≔", "coloneq": "≔", "comma": ",", "commat": "@", "comp": "∁", "compfn": "∘", "complement": "∁", "complexes": "ℂ", "cong": "≅", "congdot": "⩭", "Congruent": "≡", "conint": "∮", "Conint": "∯", "ContourIntegral": "∮", "copf": "𝕔", "Copf": "ℂ", "coprod": "∐", "Coproduct": "∐", "copy": "©", "COPY": "©", "copysr": "℗", "CounterClockwiseContourIntegral": "∳", "crarr": "↵", "cross": "✗", "Cross": "⨯", "Cscr": "𝒞", "cscr": "𝒸", "csub": "⫏", "csube": "⫑", "csup": "⫐", "csupe": "⫒", "ctdot": "⋯", "cudarrl": "⤸", "cudarrr": "⤵", "cuepr": "⋞", "cuesc": "⋟", "cularr": "↶", "cularrp": "⤽", "cupbrcap": "⩈", "cupcap": "⩆", "CupCap": "≍", "cup": "∪", "Cup": "⋓", "cupcup": "⩊", "cupdot": "⊍", "cupor": "⩅", "cups": "∪︀", "curarr": "↷", "curarrm": "⤼", "curlyeqprec": "⋞", "curlyeqsucc": "⋟", "curlyvee": "⋎", "curlywedge": "⋏", "curren": "¤", "curvearrowleft": "↶", "curvearrowright": "↷", "cuvee": "⋎", "cuwed": "⋏", "cwconint": "∲", "cwint": "∱", "cylcty": "⌭", "dagger": "†", "Dagger": "‡", "daleth": "ℸ", "darr": "↓", "Darr": "↡", "dArr": "⇓", "dash": "‐", "Dashv": "⫤", "dashv": "⊣", "dbkarow": "⤏", "dblac": "˝", "Dcaron": "Ď", "dcaron": "ď", "Dcy": "Д", "dcy": "д", "ddagger": "‡", "ddarr": "⇊", "DD": "ⅅ", "dd": "ⅆ", "DDotrahd": "⤑", "ddotseq": "⩷", "deg": "°", "Del": "∇", "Delta": "Δ", "delta": "δ", "demptyv": "⦱", "dfisht": "⥿", "Dfr": "𝔇", "dfr": "𝔡", "dHar": "⥥", "dharl": "⇃", "dharr": "⇂", "DiacriticalAcute": "´", "DiacriticalDot": "˙", "DiacriticalDoubleAcute": "˝", "DiacriticalGrave": "`", "DiacriticalTilde": "˜", "diam": "⋄", "diamond": "⋄", "Diamond": "⋄", "diamondsuit": "♦", "diams": "♦", "die": "¨", "DifferentialD": "ⅆ", "digamma": "ϝ", "disin": "⋲", "div": "÷", "divide": "÷", "divideontimes": "⋇", "divonx": "⋇", "DJcy": "Ђ", "djcy": "ђ", "dlcorn": "⌞", "dlcrop": "⌍", "dollar": "$", "Dopf": "𝔻", "dopf": "𝕕", "Dot": "¨", "dot": "˙", "DotDot": "⃜", "doteq": "≐", "doteqdot": "≑", "DotEqual": "≐", "dotminus": "∸", "dotplus": "∔", "dotsquare": "⊡", "doublebarwedge": "⌆", "DoubleContourIntegral": "∯", "DoubleDot": "¨", "DoubleDownArrow": "⇓", "DoubleLeftArrow": "⇐", "DoubleLeftRightArrow": "⇔", "DoubleLeftTee": "⫤", "DoubleLongLeftArrow": "⟸", "DoubleLongLeftRightArrow": "⟺", "DoubleLongRightArrow": "⟹", "DoubleRightArrow": "⇒", "DoubleRightTee": "⊨", "DoubleUpArrow": "⇑", "DoubleUpDownArrow": "⇕", "DoubleVerticalBar": "∥", "DownArrowBar": "⤓", "downarrow": "↓", "DownArrow": "↓", "Downarrow": "⇓", "DownArrowUpArrow": "⇵", "DownBreve": "̑", "downdownarrows": "⇊", "downharpoonleft": "⇃", "downharpoonright": "⇂", "DownLeftRightVector": "⥐", "DownLeftTeeVector": "⥞", "DownLeftVectorBar": "⥖", "DownLeftVector": "↽", "DownRightTeeVector": "⥟", "DownRightVectorBar": "⥗", "DownRightVector": "⇁", "DownTeeArrow": "↧", "DownTee": "⊤", "drbkarow": "⤐", "drcorn": "⌟", "drcrop": "⌌", "Dscr": "𝒟", "dscr": "𝒹", "DScy": "Ѕ", "dscy": "ѕ", "dsol": "⧶", "Dstrok": "Đ", "dstrok": "đ", "dtdot": "⋱", "dtri": "▿", "dtrif": "▾", "duarr": "⇵", "duhar": "⥯", "dwangle": "⦦", "DZcy": "Џ", "dzcy": "џ", "dzigrarr": "⟿", "Eacute": "É", "eacute": "é", "easter": "⩮", "Ecaron": "Ě", "ecaron": "ě", "Ecirc": "Ê", "ecirc": "ê", "ecir": "≖", "ecolon": "≕", "Ecy": "Э", "ecy": "э", "eDDot": "⩷", "Edot": "Ė", "edot": "ė", "eDot": "≑", "ee": "ⅇ", "efDot": "≒", "Efr": "𝔈", "efr": "𝔢", "eg": "⪚", "Egrave": "È", "egrave": "è", "egs": "⪖", "egsdot": "⪘", "el": "⪙", "Element": "∈", "elinters": "⏧", "ell": "ℓ", "els": "⪕", "elsdot": "⪗", "Emacr": "Ē", "emacr": "ē", "empty": "∅", "emptyset": "∅", "EmptySmallSquare": "◻", "emptyv": "∅", "EmptyVerySmallSquare": "▫", "emsp13": " ", "emsp14": " ", "emsp": " ", "ENG": "Ŋ", "eng": "ŋ", "ensp": " ", "Eogon": "Ę", "eogon": "ę", "Eopf": "𝔼", "eopf": "𝕖", "epar": "⋕", "eparsl": "⧣", "eplus": "⩱", "epsi": "ε", "Epsilon": "Ε", "epsilon": "ε", "epsiv": "ϵ", "eqcirc": "≖", "eqcolon": "≕", "eqsim": "≂", "eqslantgtr": "⪖", "eqslantless": "⪕", "Equal": "⩵", "equals": "=", "EqualTilde": "≂", "equest": "≟", "Equilibrium": "⇌", "equiv": "≡", "equivDD": "⩸", "eqvparsl": "⧥", "erarr": "⥱", "erDot": "≓", "escr": "ℯ", "Escr": "ℰ", "esdot": "≐", "Esim": "⩳", "esim": "≂", "Eta": "Η", "eta": "η", "ETH": "Ð", "eth": "ð", "Euml": "Ë", "euml": "ë", "euro": "€", "excl": "!", "exist": "∃", "Exists": "∃", "expectation": "ℰ", "exponentiale": "ⅇ", "ExponentialE": "ⅇ", "fallingdotseq": "≒", "Fcy": "Ф", "fcy": "ф", "female": "♀", "ffilig": "ffi", "fflig": "ff", "ffllig": "ffl", "Ffr": "𝔉", "ffr": "𝔣", "filig": "fi", "FilledSmallSquare": "◼", "FilledVerySmallSquare": "▪", "fjlig": "fj", "flat": "♭", "fllig": "fl", "fltns": "▱", "fnof": "ƒ", "Fopf": "𝔽", "fopf": "𝕗", "forall": "∀", "ForAll": "∀", "fork": "⋔", "forkv": "⫙", "Fouriertrf": "ℱ", "fpartint": "⨍", "frac12": "½", "frac13": "⅓", "frac14": "¼", "frac15": "⅕", "frac16": "⅙", "frac18": "⅛", "frac23": "⅔", "frac25": "⅖", "frac34": "¾", "frac35": "⅗", "frac38": "⅜", "frac45": "⅘", "frac56": "⅚", "frac58": "⅝", "frac78": "⅞", "frasl": "⁄", "frown": "⌢", "fscr": "𝒻", "Fscr": "ℱ", "gacute": "ǵ", "Gamma": "Γ", "gamma": "γ", "Gammad": "Ϝ", "gammad": "ϝ", "gap": "⪆", "Gbreve": "Ğ", "gbreve": "ğ", "Gcedil": "Ģ", "Gcirc": "Ĝ", "gcirc": "ĝ", "Gcy": "Г", "gcy": "г", "Gdot": "Ġ", "gdot": "ġ", "ge": "≥", "gE": "≧", "gEl": "⪌", "gel": "⋛", "geq": "≥", "geqq": "≧", "geqslant": "⩾", "gescc": "⪩", "ges": "⩾", "gesdot": "⪀", "gesdoto": "⪂", "gesdotol": "⪄", "gesl": "⋛︀", "gesles": "⪔", "Gfr": "𝔊", "gfr": "𝔤", "gg": "≫", "Gg": "⋙", "ggg": "⋙", "gimel": "ℷ", "GJcy": "Ѓ", "gjcy": "ѓ", "gla": "⪥", "gl": "≷", "glE": "⪒", "glj": "⪤", "gnap": "⪊", "gnapprox": "⪊", "gne": "⪈", "gnE": "≩", "gneq": "⪈", "gneqq": "≩", "gnsim": "⋧", "Gopf": "𝔾", "gopf": "𝕘", "grave": "`", "GreaterEqual": "≥", "GreaterEqualLess": "⋛", "GreaterFullEqual": "≧", "GreaterGreater": "⪢", "GreaterLess": "≷", "GreaterSlantEqual": "⩾", "GreaterTilde": "≳", "Gscr": "𝒢", "gscr": "ℊ", "gsim": "≳", "gsime": "⪎", "gsiml": "⪐", "gtcc": "⪧", "gtcir": "⩺", "gt": ">", "GT": ">", "Gt": "≫", "gtdot": "⋗", "gtlPar": "⦕", "gtquest": "⩼", "gtrapprox": "⪆", "gtrarr": "⥸", "gtrdot": "⋗", "gtreqless": "⋛", "gtreqqless": "⪌", "gtrless": "≷", "gtrsim": "≳", "gvertneqq": "≩︀", "gvnE": "≩︀", "Hacek": "ˇ", "hairsp": " ", "half": "½", "hamilt": "ℋ", "HARDcy": "Ъ", "hardcy": "ъ", "harrcir": "⥈", "harr": "↔", "hArr": "⇔", "harrw": "↭", "Hat": "^", "hbar": "ℏ", "Hcirc": "Ĥ", "hcirc": "ĥ", "hearts": "♥", "heartsuit": "♥", "hellip": "…", "hercon": "⊹", "hfr": "𝔥", "Hfr": "ℌ", "HilbertSpace": "ℋ", "hksearow": "⤥", "hkswarow": "⤦", "hoarr": "⇿", "homtht": "∻", "hookleftarrow": "↩", "hookrightarrow": "↪", "hopf": "𝕙", "Hopf": "ℍ", "horbar": "―", "HorizontalLine": "─", "hscr": "𝒽", "Hscr": "ℋ", "hslash": "ℏ", "Hstrok": "Ħ", "hstrok": "ħ", "HumpDownHump": "≎", "HumpEqual": "≏", "hybull": "⁃", "hyphen": "‐", "Iacute": "Í", "iacute": "í", "ic": "⁣", "Icirc": "Î", "icirc": "î", "Icy": "И", "icy": "и", "Idot": "İ", "IEcy": "Е", "iecy": "е", "iexcl": "¡", "iff": "⇔", "ifr": "𝔦", "Ifr": "ℑ", "Igrave": "Ì", "igrave": "ì", "ii": "ⅈ", "iiiint": "⨌", "iiint": "∭", "iinfin": "⧜", "iiota": "℩", "IJlig": "IJ", "ijlig": "ij", "Imacr": "Ī", "imacr": "ī", "image": "ℑ", "ImaginaryI": "ⅈ", "imagline": "ℐ", "imagpart": "ℑ", "imath": "ı", "Im": "ℑ", "imof": "⊷", "imped": "Ƶ", "Implies": "⇒", "incare": "℅", "in": "∈", "infin": "∞", "infintie": "⧝", "inodot": "ı", "intcal": "⊺", "int": "∫", "Int": "∬", "integers": "ℤ", "Integral": "∫", "intercal": "⊺", "Intersection": "⋂", "intlarhk": "⨗", "intprod": "⨼", "InvisibleComma": "⁣", "InvisibleTimes": "⁢", "IOcy": "Ё", "iocy": "ё", "Iogon": "Į", "iogon": "į", "Iopf": "𝕀", "iopf": "𝕚", "Iota": "Ι", "iota": "ι", "iprod": "⨼", "iquest": "¿", "iscr": "𝒾", "Iscr": "ℐ", "isin": "∈", "isindot": "⋵", "isinE": "⋹", "isins": "⋴", "isinsv": "⋳", "isinv": "∈", "it": "⁢", "Itilde": "Ĩ", "itilde": "ĩ", "Iukcy": "І", "iukcy": "і", "Iuml": "Ï", "iuml": "ï", "Jcirc": "Ĵ", "jcirc": "ĵ", "Jcy": "Й", "jcy": "й", "Jfr": "𝔍", "jfr": "𝔧", "jmath": "ȷ", "Jopf": "𝕁", "jopf": "𝕛", "Jscr": "𝒥", "jscr": "𝒿", "Jsercy": "Ј", "jsercy": "ј", "Jukcy": "Є", "jukcy": "є", "Kappa": "Κ", "kappa": "κ", "kappav": "ϰ", "Kcedil": "Ķ", "kcedil": "ķ", "Kcy": "К", "kcy": "к", "Kfr": "𝔎", "kfr": "𝔨", "kgreen": "ĸ", "KHcy": "Х", "khcy": "х", "KJcy": "Ќ", "kjcy": "ќ", "Kopf": "𝕂", "kopf": "𝕜", "Kscr": "𝒦", "kscr": "𝓀", "lAarr": "⇚", "Lacute": "Ĺ", "lacute": "ĺ", "laemptyv": "⦴", "lagran": "ℒ", "Lambda": "Λ", "lambda": "λ", "lang": "⟨", "Lang": "⟪", "langd": "⦑", "langle": "⟨", "lap": "⪅", "Laplacetrf": "ℒ", "laquo": "«", "larrb": "⇤", "larrbfs": "⤟", "larr": "←", "Larr": "↞", "lArr": "⇐", "larrfs": "⤝", "larrhk": "↩", "larrlp": "↫", "larrpl": "⤹", "larrsim": "⥳", "larrtl": "↢", "latail": "⤙", "lAtail": "⤛", "lat": "⪫", "late": "⪭", "lates": "⪭︀", "lbarr": "⤌", "lBarr": "⤎", "lbbrk": "❲", "lbrace": "{", "lbrack": "[", "lbrke": "⦋", "lbrksld": "⦏", "lbrkslu": "⦍", "Lcaron": "Ľ", "lcaron": "ľ", "Lcedil": "Ļ", "lcedil": "ļ", "lceil": "⌈", "lcub": "{", "Lcy": "Л", "lcy": "л", "ldca": "⤶", "ldquo": "“", "ldquor": "„", "ldrdhar": "⥧", "ldrushar": "⥋", "ldsh": "↲", "le": "≤", "lE": "≦", "LeftAngleBracket": "⟨", "LeftArrowBar": "⇤", "leftarrow": "←", "LeftArrow": "←", "Leftarrow": "⇐", "LeftArrowRightArrow": "⇆", "leftarrowtail": "↢", "LeftCeiling": "⌈", "LeftDoubleBracket": "⟦", "LeftDownTeeVector": "⥡", "LeftDownVectorBar": "⥙", "LeftDownVector": "⇃", "LeftFloor": "⌊", "leftharpoondown": "↽", "leftharpoonup": "↼", "leftleftarrows": "⇇", "leftrightarrow": "↔", "LeftRightArrow": "↔", "Leftrightarrow": "⇔", "leftrightarrows": "⇆", "leftrightharpoons": "⇋", "leftrightsquigarrow": "↭", "LeftRightVector": "⥎", "LeftTeeArrow": "↤", "LeftTee": "⊣", "LeftTeeVector": "⥚", "leftthreetimes": "⋋", "LeftTriangleBar": "⧏", "LeftTriangle": "⊲", "LeftTriangleEqual": "⊴", "LeftUpDownVector": "⥑", "LeftUpTeeVector": "⥠", "LeftUpVectorBar": "⥘", "LeftUpVector": "↿", "LeftVectorBar": "⥒", "LeftVector": "↼", "lEg": "⪋", "leg": "⋚", "leq": "≤", "leqq": "≦", "leqslant": "⩽", "lescc": "⪨", "les": "⩽", "lesdot": "⩿", "lesdoto": "⪁", "lesdotor": "⪃", "lesg": "⋚︀", "lesges": "⪓", "lessapprox": "⪅", "lessdot": "⋖", "lesseqgtr": "⋚", "lesseqqgtr": "⪋", "LessEqualGreater": "⋚", "LessFullEqual": "≦", "LessGreater": "≶", "lessgtr": "≶", "LessLess": "⪡", "lesssim": "≲", "LessSlantEqual": "⩽", "LessTilde": "≲", "lfisht": "⥼", "lfloor": "⌊", "Lfr": "𝔏", "lfr": "𝔩", "lg": "≶", "lgE": "⪑", "lHar": "⥢", "lhard": "↽", "lharu": "↼", "lharul": "⥪", "lhblk": "▄", "LJcy": "Љ", "ljcy": "љ", "llarr": "⇇", "ll": "≪", "Ll": "⋘", "llcorner": "⌞", "Lleftarrow": "⇚", "llhard": "⥫", "lltri": "◺", "Lmidot": "Ŀ", "lmidot": "ŀ", "lmoustache": "⎰", "lmoust": "⎰", "lnap": "⪉", "lnapprox": "⪉", "lne": "⪇", "lnE": "≨", "lneq": "⪇", "lneqq": "≨", "lnsim": "⋦", "loang": "⟬", "loarr": "⇽", "lobrk": "⟦", "longleftarrow": "⟵", "LongLeftArrow": "⟵", "Longleftarrow": "⟸", "longleftrightarrow": "⟷", "LongLeftRightArrow": "⟷", "Longleftrightarrow": "⟺", "longmapsto": "⟼", "longrightarrow": "⟶", "LongRightArrow": "⟶", "Longrightarrow": "⟹", "looparrowleft": "↫", "looparrowright": "↬", "lopar": "⦅", "Lopf": "𝕃", "lopf": "𝕝", "loplus": "⨭", "lotimes": "⨴", "lowast": "∗", "lowbar": "_", "LowerLeftArrow": "↙", "LowerRightArrow": "↘", "loz": "◊", "lozenge": "◊", "lozf": "⧫", "lpar": "(", "lparlt": "⦓", "lrarr": "⇆", "lrcorner": "⌟", "lrhar": "⇋", "lrhard": "⥭", "lrm": "‎", "lrtri": "⊿", "lsaquo": "‹", "lscr": "𝓁", "Lscr": "ℒ", "lsh": "↰", "Lsh": "↰", "lsim": "≲", "lsime": "⪍", "lsimg": "⪏", "lsqb": "[", "lsquo": "‘", "lsquor": "‚", "Lstrok": "Ł", "lstrok": "ł", "ltcc": "⪦", "ltcir": "⩹", "lt": "<", "LT": "<", "Lt": "≪", "ltdot": "⋖", "lthree": "⋋", "ltimes": "⋉", "ltlarr": "⥶", "ltquest": "⩻", "ltri": "◃", "ltrie": "⊴", "ltrif": "◂", "ltrPar": "⦖", "lurdshar": "⥊", "luruhar": "⥦", "lvertneqq": "≨︀", "lvnE": "≨︀", "macr": "¯", "male": "♂", "malt": "✠", "maltese": "✠", "Map": "⤅", "map": "↦", "mapsto": "↦", "mapstodown": "↧", "mapstoleft": "↤", "mapstoup": "↥", "marker": "▮", "mcomma": "⨩", "Mcy": "М", "mcy": "м", "mdash": "—", "mDDot": "∺", "measuredangle": "∡", "MediumSpace": " ", "Mellintrf": "ℳ", "Mfr": "𝔐", "mfr": "𝔪", "mho": "℧", "micro": "µ", "midast": "*", "midcir": "⫰", "mid": "∣", "middot": "·", "minusb": "⊟", "minus": "−", "minusd": "∸", "minusdu": "⨪", "MinusPlus": "∓", "mlcp": "⫛", "mldr": "…", "mnplus": "∓", "models": "⊧", "Mopf": "𝕄", "mopf": "𝕞", "mp": "∓", "mscr": "𝓂", "Mscr": "ℳ", "mstpos": "∾", "Mu": "Μ", "mu": "μ", "multimap": "⊸", "mumap": "⊸", "nabla": "∇", "Nacute": "Ń", "nacute": "ń", "nang": "∠⃒", "nap": "≉", "napE": "⩰̸", "napid": "≋̸", "napos": "ʼn", "napprox": "≉", "natural": "♮", "naturals": "ℕ", "natur": "♮", "nbsp": " ", "nbump": "≎̸", "nbumpe": "≏̸", "ncap": "⩃", "Ncaron": "Ň", "ncaron": "ň", "Ncedil": "Ņ", "ncedil": "ņ", "ncong": "≇", "ncongdot": "⩭̸", "ncup": "⩂", "Ncy": "Н", "ncy": "н", "ndash": "–", "nearhk": "⤤", "nearr": "↗", "neArr": "⇗", "nearrow": "↗", "ne": "≠", "nedot": "≐̸", "NegativeMediumSpace": "​", "NegativeThickSpace": "​", "NegativeThinSpace": "​", "NegativeVeryThinSpace": "​", "nequiv": "≢", "nesear": "⤨", "nesim": "≂̸", "NestedGreaterGreater": "≫", "NestedLessLess": "≪", "NewLine": "\n", "nexist": "∄", "nexists": "∄", "Nfr": "𝔑", "nfr": "𝔫", "ngE": "≧̸", "nge": "≱", "ngeq": "≱", "ngeqq": "≧̸", "ngeqslant": "⩾̸", "nges": "⩾̸", "nGg": "⋙̸", "ngsim": "≵", "nGt": "≫⃒", "ngt": "≯", "ngtr": "≯", "nGtv": "≫̸", "nharr": "↮", "nhArr": "⇎", "nhpar": "⫲", "ni": "∋", "nis": "⋼", "nisd": "⋺", "niv": "∋", "NJcy": "Њ", "njcy": "њ", "nlarr": "↚", "nlArr": "⇍", "nldr": "‥", "nlE": "≦̸", "nle": "≰", "nleftarrow": "↚", "nLeftarrow": "⇍", "nleftrightarrow": "↮", "nLeftrightarrow": "⇎", "nleq": "≰", "nleqq": "≦̸", "nleqslant": "⩽̸", "nles": "⩽̸", "nless": "≮", "nLl": "⋘̸", "nlsim": "≴", "nLt": "≪⃒", "nlt": "≮", "nltri": "⋪", "nltrie": "⋬", "nLtv": "≪̸", "nmid": "∤", "NoBreak": "⁠", "NonBreakingSpace": " ", "nopf": "𝕟", "Nopf": "ℕ", "Not": "⫬", "not": "¬", "NotCongruent": "≢", "NotCupCap": "≭", "NotDoubleVerticalBar": "∦", "NotElement": "∉", "NotEqual": "≠", "NotEqualTilde": "≂̸", "NotExists": "∄", "NotGreater": "≯", "NotGreaterEqual": "≱", "NotGreaterFullEqual": "≧̸", "NotGreaterGreater": "≫̸", "NotGreaterLess": "≹", "NotGreaterSlantEqual": "⩾̸", "NotGreaterTilde": "≵", "NotHumpDownHump": "≎̸", "NotHumpEqual": "≏̸", "notin": "∉", "notindot": "⋵̸", "notinE": "⋹̸", "notinva": "∉", "notinvb": "⋷", "notinvc": "⋶", "NotLeftTriangleBar": "⧏̸", "NotLeftTriangle": "⋪", "NotLeftTriangleEqual": "⋬", "NotLess": "≮", "NotLessEqual": "≰", "NotLessGreater": "≸", "NotLessLess": "≪̸", "NotLessSlantEqual": "⩽̸", "NotLessTilde": "≴", "NotNestedGreaterGreater": "⪢̸", "NotNestedLessLess": "⪡̸", "notni": "∌", "notniva": "∌", "notnivb": "⋾", "notnivc": "⋽", "NotPrecedes": "⊀", "NotPrecedesEqual": "⪯̸", "NotPrecedesSlantEqual": "⋠", "NotReverseElement": "∌", "NotRightTriangleBar": "⧐̸", "NotRightTriangle": "⋫", "NotRightTriangleEqual": "⋭", "NotSquareSubset": "⊏̸", "NotSquareSubsetEqual": "⋢", "NotSquareSuperset": "⊐̸", "NotSquareSupersetEqual": "⋣", "NotSubset": "⊂⃒", "NotSubsetEqual": "⊈", "NotSucceeds": "⊁", "NotSucceedsEqual": "⪰̸", "NotSucceedsSlantEqual": "⋡", "NotSucceedsTilde": "≿̸", "NotSuperset": "⊃⃒", "NotSupersetEqual": "⊉", "NotTilde": "≁", "NotTildeEqual": "≄", "NotTildeFullEqual": "≇", "NotTildeTilde": "≉", "NotVerticalBar": "∤", "nparallel": "∦", "npar": "∦", "nparsl": "⫽⃥", "npart": "∂̸", "npolint": "⨔", "npr": "⊀", "nprcue": "⋠", "nprec": "⊀", "npreceq": "⪯̸", "npre": "⪯̸", "nrarrc": "⤳̸", "nrarr": "↛", "nrArr": "⇏", "nrarrw": "↝̸", "nrightarrow": "↛", "nRightarrow": "⇏", "nrtri": "⋫", "nrtrie": "⋭", "nsc": "⊁", "nsccue": "⋡", "nsce": "⪰̸", "Nscr": "𝒩", "nscr": "𝓃", "nshortmid": "∤", "nshortparallel": "∦", "nsim": "≁", "nsime": "≄", "nsimeq": "≄", "nsmid": "∤", "nspar": "∦", "nsqsube": "⋢", "nsqsupe": "⋣", "nsub": "⊄", "nsubE": "⫅̸", "nsube": "⊈", "nsubset": "⊂⃒", "nsubseteq": "⊈", "nsubseteqq": "⫅̸", "nsucc": "⊁", "nsucceq": "⪰̸", "nsup": "⊅", "nsupE": "⫆̸", "nsupe": "⊉", "nsupset": "⊃⃒", "nsupseteq": "⊉", "nsupseteqq": "⫆̸", "ntgl": "≹", "Ntilde": "Ñ", "ntilde": "ñ", "ntlg": "≸", "ntriangleleft": "⋪", "ntrianglelefteq": "⋬", "ntriangleright": "⋫", "ntrianglerighteq": "⋭", "Nu": "Ν", "nu": "ν", "num": "#", "numero": "№", "numsp": " ", "nvap": "≍⃒", "nvdash": "⊬", "nvDash": "⊭", "nVdash": "⊮", "nVDash": "⊯", "nvge": "≥⃒", "nvgt": ">⃒", "nvHarr": "⤄", "nvinfin": "⧞", "nvlArr": "⤂", "nvle": "≤⃒", "nvlt": "<⃒", "nvltrie": "⊴⃒", "nvrArr": "⤃", "nvrtrie": "⊵⃒", "nvsim": "∼⃒", "nwarhk": "⤣", "nwarr": "↖", "nwArr": "⇖", "nwarrow": "↖", "nwnear": "⤧", "Oacute": "Ó", "oacute": "ó", "oast": "⊛", "Ocirc": "Ô", "ocirc": "ô", "ocir": "⊚", "Ocy": "О", "ocy": "о", "odash": "⊝", "Odblac": "Ő", "odblac": "ő", "odiv": "⨸", "odot": "⊙", "odsold": "⦼", "OElig": "Œ", "oelig": "œ", "ofcir": "⦿", "Ofr": "𝔒", "ofr": "𝔬", "ogon": "˛", "Ograve": "Ò", "ograve": "ò", "ogt": "⧁", "ohbar": "⦵", "ohm": "Ω", "oint": "∮", "olarr": "↺", "olcir": "⦾", "olcross": "⦻", "oline": "‾", "olt": "⧀", "Omacr": "Ō", "omacr": "ō", "Omega": "Ω", "omega": "ω", "Omicron": "Ο", "omicron": "ο", "omid": "⦶", "ominus": "⊖", "Oopf": "𝕆", "oopf": "𝕠", "opar": "⦷", "OpenCurlyDoubleQuote": "“", "OpenCurlyQuote": "‘", "operp": "⦹", "oplus": "⊕", "orarr": "↻", "Or": "⩔", "or": "∨", "ord": "⩝", "order": "ℴ", "orderof": "ℴ", "ordf": "ª", "ordm": "º", "origof": "⊶", "oror": "⩖", "orslope": "⩗", "orv": "⩛", "oS": "Ⓢ", "Oscr": "𝒪", "oscr": "ℴ", "Oslash": "Ø", "oslash": "ø", "osol": "⊘", "Otilde": "Õ", "otilde": "õ", "otimesas": "⨶", "Otimes": "⨷", "otimes": "⊗", "Ouml": "Ö", "ouml": "ö", "ovbar": "⌽", "OverBar": "‾", "OverBrace": "⏞", "OverBracket": "⎴", "OverParenthesis": "⏜", "para": "¶", "parallel": "∥", "par": "∥", "parsim": "⫳", "parsl": "⫽", "part": "∂", "PartialD": "∂", "Pcy": "П", "pcy": "п", "percnt": "%", "period": ".", "permil": "‰", "perp": "⊥", "pertenk": "‱", "Pfr": "𝔓", "pfr": "𝔭", "Phi": "Φ", "phi": "φ", "phiv": "ϕ", "phmmat": "ℳ", "phone": "☎", "Pi": "Π", "pi": "π", "pitchfork": "⋔", "piv": "ϖ", "planck": "ℏ", "planckh": "ℎ", "plankv": "ℏ", "plusacir": "⨣", "plusb": "⊞", "pluscir": "⨢", "plus": "+", "plusdo": "∔", "plusdu": "⨥", "pluse": "⩲", "PlusMinus": "±", "plusmn": "±", "plussim": "⨦", "plustwo": "⨧", "pm": "±", "Poincareplane": "ℌ", "pointint": "⨕", "popf": "𝕡", "Popf": "ℙ", "pound": "£", "prap": "⪷", "Pr": "⪻", "pr": "≺", "prcue": "≼", "precapprox": "⪷", "prec": "≺", "preccurlyeq": "≼", "Precedes": "≺", "PrecedesEqual": "⪯", "PrecedesSlantEqual": "≼", "PrecedesTilde": "≾", "preceq": "⪯", "precnapprox": "⪹", "precneqq": "⪵", "precnsim": "⋨", "pre": "⪯", "prE": "⪳", "precsim": "≾", "prime": "′", "Prime": "″", "primes": "ℙ", "prnap": "⪹", "prnE": "⪵", "prnsim": "⋨", "prod": "∏", "Product": "∏", "profalar": "⌮", "profline": "⌒", "profsurf": "⌓", "prop": "∝", "Proportional": "∝", "Proportion": "∷", "propto": "∝", "prsim": "≾", "prurel": "⊰", "Pscr": "𝒫", "pscr": "𝓅", "Psi": "Ψ", "psi": "ψ", "puncsp": " ", "Qfr": "𝔔", "qfr": "𝔮", "qint": "⨌", "qopf": "𝕢", "Qopf": "ℚ", "qprime": "⁗", "Qscr": "𝒬", "qscr": "𝓆", "quaternions": "ℍ", "quatint": "⨖", "quest": "?", "questeq": "≟", "quot": "\"", "QUOT": "\"", "rAarr": "⇛", "race": "∽̱", "Racute": "Ŕ", "racute": "ŕ", "radic": "√", "raemptyv": "⦳", "rang": "⟩", "Rang": "⟫", "rangd": "⦒", "range": "⦥", "rangle": "⟩", "raquo": "»", "rarrap": "⥵", "rarrb": "⇥", "rarrbfs": "⤠", "rarrc": "⤳", "rarr": "→", "Rarr": "↠", "rArr": "⇒", "rarrfs": "⤞", "rarrhk": "↪", "rarrlp": "↬", "rarrpl": "⥅", "rarrsim": "⥴", "Rarrtl": "⤖", "rarrtl": "↣", "rarrw": "↝", "ratail": "⤚", "rAtail": "⤜", "ratio": "∶", "rationals": "ℚ", "rbarr": "⤍", "rBarr": "⤏", "RBarr": "⤐", "rbbrk": "❳", "rbrace": "}", "rbrack": "]", "rbrke": "⦌", "rbrksld": "⦎", "rbrkslu": "⦐", "Rcaron": "Ř", "rcaron": "ř", "Rcedil": "Ŗ", "rcedil": "ŗ", "rceil": "⌉", "rcub": "}", "Rcy": "Р", "rcy": "р", "rdca": "⤷", "rdldhar": "⥩", "rdquo": "”", "rdquor": "”", "rdsh": "↳", "real": "ℜ", "realine": "ℛ", "realpart": "ℜ", "reals": "ℝ", "Re": "ℜ", "rect": "▭", "reg": "®", "REG": "®", "ReverseElement": "∋", "ReverseEquilibrium": "⇋", "ReverseUpEquilibrium": "⥯", "rfisht": "⥽", "rfloor": "⌋", "rfr": "𝔯", "Rfr": "ℜ", "rHar": "⥤", "rhard": "⇁", "rharu": "⇀", "rharul": "⥬", "Rho": "Ρ", "rho": "ρ", "rhov": "ϱ", "RightAngleBracket": "⟩", "RightArrowBar": "⇥", "rightarrow": "→", "RightArrow": "→", "Rightarrow": "⇒", "RightArrowLeftArrow": "⇄", "rightarrowtail": "↣", "RightCeiling": "⌉", "RightDoubleBracket": "⟧", "RightDownTeeVector": "⥝", "RightDownVectorBar": "⥕", "RightDownVector": "⇂", "RightFloor": "⌋", "rightharpoondown": "⇁", "rightharpoonup": "⇀", "rightleftarrows": "⇄", "rightleftharpoons": "⇌", "rightrightarrows": "⇉", "rightsquigarrow": "↝", "RightTeeArrow": "↦", "RightTee": "⊢", "RightTeeVector": "⥛", "rightthreetimes": "⋌", "RightTriangleBar": "⧐", "RightTriangle": "⊳", "RightTriangleEqual": "⊵", "RightUpDownVector": "⥏", "RightUpTeeVector": "⥜", "RightUpVectorBar": "⥔", "RightUpVector": "↾", "RightVectorBar": "⥓", "RightVector": "⇀", "ring": "˚", "risingdotseq": "≓", "rlarr": "⇄", "rlhar": "⇌", "rlm": "‏", "rmoustache": "⎱", "rmoust": "⎱", "rnmid": "⫮", "roang": "⟭", "roarr": "⇾", "robrk": "⟧", "ropar": "⦆", "ropf": "𝕣", "Ropf": "ℝ", "roplus": "⨮", "rotimes": "⨵", "RoundImplies": "⥰", "rpar": ")", "rpargt": "⦔", "rppolint": "⨒", "rrarr": "⇉", "Rrightarrow": "⇛", "rsaquo": "›", "rscr": "𝓇", "Rscr": "ℛ", "rsh": "↱", "Rsh": "↱", "rsqb": "]", "rsquo": "’", "rsquor": "’", "rthree": "⋌", "rtimes": "⋊", "rtri": "▹", "rtrie": "⊵", "rtrif": "▸", "rtriltri": "⧎", "RuleDelayed": "⧴", "ruluhar": "⥨", "rx": "℞", "Sacute": "Ś", "sacute": "ś", "sbquo": "‚", "scap": "⪸", "Scaron": "Š", "scaron": "š", "Sc": "⪼", "sc": "≻", "sccue": "≽", "sce": "⪰", "scE": "⪴", "Scedil": "Ş", "scedil": "ş", "Scirc": "Ŝ", "scirc": "ŝ", "scnap": "⪺", "scnE": "⪶", "scnsim": "⋩", "scpolint": "⨓", "scsim": "≿", "Scy": "С", "scy": "с", "sdotb": "⊡", "sdot": "⋅", "sdote": "⩦", "searhk": "⤥", "searr": "↘", "seArr": "⇘", "searrow": "↘", "sect": "§", "semi": ";", "seswar": "⤩", "setminus": "∖", "setmn": "∖", "sext": "✶", "Sfr": "𝔖", "sfr": "𝔰", "sfrown": "⌢", "sharp": "♯", "SHCHcy": "Щ", "shchcy": "щ", "SHcy": "Ш", "shcy": "ш", "ShortDownArrow": "↓", "ShortLeftArrow": "←", "shortmid": "∣", "shortparallel": "∥", "ShortRightArrow": "→", "ShortUpArrow": "↑", "shy": "­", "Sigma": "Σ", "sigma": "σ", "sigmaf": "ς", "sigmav": "ς", "sim": "∼", "simdot": "⩪", "sime": "≃", "simeq": "≃", "simg": "⪞", "simgE": "⪠", "siml": "⪝", "simlE": "⪟", "simne": "≆", "simplus": "⨤", "simrarr": "⥲", "slarr": "←", "SmallCircle": "∘", "smallsetminus": "∖", "smashp": "⨳", "smeparsl": "⧤", "smid": "∣", "smile": "⌣", "smt": "⪪", "smte": "⪬", "smtes": "⪬︀", "SOFTcy": "Ь", "softcy": "ь", "solbar": "⌿", "solb": "⧄", "sol": "/", "Sopf": "𝕊", "sopf": "𝕤", "spades": "♠", "spadesuit": "♠", "spar": "∥", "sqcap": "⊓", "sqcaps": "⊓︀", "sqcup": "⊔", "sqcups": "⊔︀", "Sqrt": "√", "sqsub": "⊏", "sqsube": "⊑", "sqsubset": "⊏", "sqsubseteq": "⊑", "sqsup": "⊐", "sqsupe": "⊒", "sqsupset": "⊐", "sqsupseteq": "⊒", "square": "□", "Square": "□", "SquareIntersection": "⊓", "SquareSubset": "⊏", "SquareSubsetEqual": "⊑", "SquareSuperset": "⊐", "SquareSupersetEqual": "⊒", "SquareUnion": "⊔", "squarf": "▪", "squ": "□", "squf": "▪", "srarr": "→", "Sscr": "𝒮", "sscr": "𝓈", "ssetmn": "∖", "ssmile": "⌣", "sstarf": "⋆", "Star": "⋆", "star": "☆", "starf": "★", "straightepsilon": "ϵ", "straightphi": "ϕ", "strns": "¯", "sub": "⊂", "Sub": "⋐", "subdot": "⪽", "subE": "⫅", "sube": "⊆", "subedot": "⫃", "submult": "⫁", "subnE": "⫋", "subne": "⊊", "subplus": "⪿", "subrarr": "⥹", "subset": "⊂", "Subset": "⋐", "subseteq": "⊆", "subseteqq": "⫅", "SubsetEqual": "⊆", "subsetneq": "⊊", "subsetneqq": "⫋", "subsim": "⫇", "subsub": "⫕", "subsup": "⫓", "succapprox": "⪸", "succ": "≻", "succcurlyeq": "≽", "Succeeds": "≻", "SucceedsEqual": "⪰", "SucceedsSlantEqual": "≽", "SucceedsTilde": "≿", "succeq": "⪰", "succnapprox": "⪺", "succneqq": "⪶", "succnsim": "⋩", "succsim": "≿", "SuchThat": "∋", "sum": "∑", "Sum": "∑", "sung": "♪", "sup1": "¹", "sup2": "²", "sup3": "³", "sup": "⊃", "Sup": "⋑", "supdot": "⪾", "supdsub": "⫘", "supE": "⫆", "supe": "⊇", "supedot": "⫄", "Superset": "⊃", "SupersetEqual": "⊇", "suphsol": "⟉", "suphsub": "⫗", "suplarr": "⥻", "supmult": "⫂", "supnE": "⫌", "supne": "⊋", "supplus": "⫀", "supset": "⊃", "Supset": "⋑", "supseteq": "⊇", "supseteqq": "⫆", "supsetneq": "⊋", "supsetneqq": "⫌", "supsim": "⫈", "supsub": "⫔", "supsup": "⫖", "swarhk": "⤦", "swarr": "↙", "swArr": "⇙", "swarrow": "↙", "swnwar": "⤪", "szlig": "ß", "Tab": "\t", "target": "⌖", "Tau": "Τ", "tau": "τ", "tbrk": "⎴", "Tcaron": "Ť", "tcaron": "ť", "Tcedil": "Ţ", "tcedil": "ţ", "Tcy": "Т", "tcy": "т", "tdot": "⃛", "telrec": "⌕", "Tfr": "𝔗", "tfr": "𝔱", "there4": "∴", "therefore": "∴", "Therefore": "∴", "Theta": "Θ", "theta": "θ", "thetasym": "ϑ", "thetav": "ϑ", "thickapprox": "≈", "thicksim": "∼", "ThickSpace": "  ", "ThinSpace": " ", "thinsp": " ", "thkap": "≈", "thksim": "∼", "THORN": "Þ", "thorn": "þ", "tilde": "˜", "Tilde": "∼", "TildeEqual": "≃", "TildeFullEqual": "≅", "TildeTilde": "≈", "timesbar": "⨱", "timesb": "⊠", "times": "×", "timesd": "⨰", "tint": "∭", "toea": "⤨", "topbot": "⌶", "topcir": "⫱", "top": "⊤", "Topf": "𝕋", "topf": "𝕥", "topfork": "⫚", "tosa": "⤩", "tprime": "‴", "trade": "™", "TRADE": "™", "triangle": "▵", "triangledown": "▿", "triangleleft": "◃", "trianglelefteq": "⊴", "triangleq": "≜", "triangleright": "▹", "trianglerighteq": "⊵", "tridot": "◬", "trie": "≜", "triminus": "⨺", "TripleDot": "⃛", "triplus": "⨹", "trisb": "⧍", "tritime": "⨻", "trpezium": "⏢", "Tscr": "𝒯", "tscr": "𝓉", "TScy": "Ц", "tscy": "ц", "TSHcy": "Ћ", "tshcy": "ћ", "Tstrok": "Ŧ", "tstrok": "ŧ", "twixt": "≬", "twoheadleftarrow": "↞", "twoheadrightarrow": "↠", "Uacute": "Ú", "uacute": "ú", "uarr": "↑", "Uarr": "↟", "uArr": "⇑", "Uarrocir": "⥉", "Ubrcy": "Ў", "ubrcy": "ў", "Ubreve": "Ŭ", "ubreve": "ŭ", "Ucirc": "Û", "ucirc": "û", "Ucy": "У", "ucy": "у", "udarr": "⇅", "Udblac": "Ű", "udblac": "ű", "udhar": "⥮", "ufisht": "⥾", "Ufr": "𝔘", "ufr": "𝔲", "Ugrave": "Ù", "ugrave": "ù", "uHar": "⥣", "uharl": "↿", "uharr": "↾", "uhblk": "▀", "ulcorn": "⌜", "ulcorner": "⌜", "ulcrop": "⌏", "ultri": "◸", "Umacr": "Ū", "umacr": "ū", "uml": "¨", "UnderBar": "_", "UnderBrace": "⏟", "UnderBracket": "⎵", "UnderParenthesis": "⏝", "Union": "⋃", "UnionPlus": "⊎", "Uogon": "Ų", "uogon": "ų", "Uopf": "𝕌", "uopf": "𝕦", "UpArrowBar": "⤒", "uparrow": "↑", "UpArrow": "↑", "Uparrow": "⇑", "UpArrowDownArrow": "⇅", "updownarrow": "↕", "UpDownArrow": "↕", "Updownarrow": "⇕", "UpEquilibrium": "⥮", "upharpoonleft": "↿", "upharpoonright": "↾", "uplus": "⊎", "UpperLeftArrow": "↖", "UpperRightArrow": "↗", "upsi": "υ", "Upsi": "ϒ", "upsih": "ϒ", "Upsilon": "Υ", "upsilon": "υ", "UpTeeArrow": "↥", "UpTee": "⊥", "upuparrows": "⇈", "urcorn": "⌝", "urcorner": "⌝", "urcrop": "⌎", "Uring": "Ů", "uring": "ů", "urtri": "◹", "Uscr": "𝒰", "uscr": "𝓊", "utdot": "⋰", "Utilde": "Ũ", "utilde": "ũ", "utri": "▵", "utrif": "▴", "uuarr": "⇈", "Uuml": "Ü", "uuml": "ü", "uwangle": "⦧", "vangrt": "⦜", "varepsilon": "ϵ", "varkappa": "ϰ", "varnothing": "∅", "varphi": "ϕ", "varpi": "ϖ", "varpropto": "∝", "varr": "↕", "vArr": "⇕", "varrho": "ϱ", "varsigma": "ς", "varsubsetneq": "⊊︀", "varsubsetneqq": "⫋︀", "varsupsetneq": "⊋︀", "varsupsetneqq": "⫌︀", "vartheta": "ϑ", "vartriangleleft": "⊲", "vartriangleright": "⊳", "vBar": "⫨", "Vbar": "⫫", "vBarv": "⫩", "Vcy": "В", "vcy": "в", "vdash": "⊢", "vDash": "⊨", "Vdash": "⊩", "VDash": "⊫", "Vdashl": "⫦", "veebar": "⊻", "vee": "∨", "Vee": "⋁", "veeeq": "≚", "vellip": "⋮", "verbar": "|", "Verbar": "‖", "vert": "|", "Vert": "‖", "VerticalBar": "∣", "VerticalLine": "|", "VerticalSeparator": "❘", "VerticalTilde": "≀", "VeryThinSpace": " ", "Vfr": "𝔙", "vfr": "𝔳", "vltri": "⊲", "vnsub": "⊂⃒", "vnsup": "⊃⃒", "Vopf": "𝕍", "vopf": "𝕧", "vprop": "∝", "vrtri": "⊳", "Vscr": "𝒱", "vscr": "𝓋", "vsubnE": "⫋︀", "vsubne": "⊊︀", "vsupnE": "⫌︀", "vsupne": "⊋︀", "Vvdash": "⊪", "vzigzag": "⦚", "Wcirc": "Ŵ", "wcirc": "ŵ", "wedbar": "⩟", "wedge": "∧", "Wedge": "⋀", "wedgeq": "≙", "weierp": "℘", "Wfr": "𝔚", "wfr": "𝔴", "Wopf": "𝕎", "wopf": "𝕨", "wp": "℘", "wr": "≀", "wreath": "≀", "Wscr": "𝒲", "wscr": "𝓌", "xcap": "⋂", "xcirc": "◯", "xcup": "⋃", "xdtri": "▽", "Xfr": "𝔛", "xfr": "𝔵", "xharr": "⟷", "xhArr": "⟺", "Xi": "Ξ", "xi": "ξ", "xlarr": "⟵", "xlArr": "⟸", "xmap": "⟼", "xnis": "⋻", "xodot": "⨀", "Xopf": "𝕏", "xopf": "𝕩", "xoplus": "⨁", "xotime": "⨂", "xrarr": "⟶", "xrArr": "⟹", "Xscr": "𝒳", "xscr": "𝓍", "xsqcup": "⨆", "xuplus": "⨄", "xutri": "△", "xvee": "⋁", "xwedge": "⋀", "Yacute": "Ý", "yacute": "ý", "YAcy": "Я", "yacy": "я", "Ycirc": "Ŷ", "ycirc": "ŷ", "Ycy": "Ы", "ycy": "ы", "yen": "¥", "Yfr": "𝔜", "yfr": "𝔶", "YIcy": "Ї", "yicy": "ї", "Yopf": "𝕐", "yopf": "𝕪", "Yscr": "𝒴", "yscr": "𝓎", "YUcy": "Ю", "yucy": "ю", "yuml": "ÿ", "Yuml": "Ÿ", "Zacute": "Ź", "zacute": "ź", "Zcaron": "Ž", "zcaron": "ž", "Zcy": "З", "zcy": "з", "Zdot": "Ż", "zdot": "ż", "zeetrf": "ℨ", "ZeroWidthSpace": "​", "Zeta": "Ζ", "zeta": "ζ", "zfr": "𝔷", "Zfr": "ℨ", "ZHcy": "Ж", "zhcy": "ж", "zigrarr": "⇝", "zopf": "𝕫", "Zopf": "ℤ", "Zscr": "𝒵", "zscr": "𝓏", "zwj": "‍", "zwnj": "‌" }; /***/ }, /* 43 */ /***/ function(module, exports) { module.exports = { "Aacute": "Á", "aacute": "á", "Acirc": "Â", "acirc": "â", "acute": "´", "AElig": "Æ", "aelig": "æ", "Agrave": "À", "agrave": "à", "amp": "&", "AMP": "&", "Aring": "Å", "aring": "å", "Atilde": "Ã", "atilde": "ã", "Auml": "Ä", "auml": "ä", "brvbar": "¦", "Ccedil": "Ç", "ccedil": "ç", "cedil": "¸", "cent": "¢", "copy": "©", "COPY": "©", "curren": "¤", "deg": "°", "divide": "÷", "Eacute": "É", "eacute": "é", "Ecirc": "Ê", "ecirc": "ê", "Egrave": "È", "egrave": "è", "ETH": "Ð", "eth": "ð", "Euml": "Ë", "euml": "ë", "frac12": "½", "frac14": "¼", "frac34": "¾", "gt": ">", "GT": ">", "Iacute": "Í", "iacute": "í", "Icirc": "Î", "icirc": "î", "iexcl": "¡", "Igrave": "Ì", "igrave": "ì", "iquest": "¿", "Iuml": "Ï", "iuml": "ï", "laquo": "«", "lt": "<", "LT": "<", "macr": "¯", "micro": "µ", "middot": "·", "nbsp": " ", "not": "¬", "Ntilde": "Ñ", "ntilde": "ñ", "Oacute": "Ó", "oacute": "ó", "Ocirc": "Ô", "ocirc": "ô", "Ograve": "Ò", "ograve": "ò", "ordf": "ª", "ordm": "º", "Oslash": "Ø", "oslash": "ø", "Otilde": "Õ", "otilde": "õ", "Ouml": "Ö", "ouml": "ö", "para": "¶", "plusmn": "±", "pound": "£", "quot": "\"", "QUOT": "\"", "raquo": "»", "reg": "®", "REG": "®", "sect": "§", "shy": "­", "sup1": "¹", "sup2": "²", "sup3": "³", "szlig": "ß", "THORN": "Þ", "thorn": "þ", "times": "×", "Uacute": "Ú", "uacute": "ú", "Ucirc": "Û", "ucirc": "û", "Ugrave": "Ù", "ugrave": "ù", "uml": "¨", "Uuml": "Ü", "uuml": "ü", "Yacute": "Ý", "yacute": "ý", "yen": "¥", "yuml": "ÿ" }; /***/ }, /* 44 */ /***/ function(module, exports) { module.exports = { "amp": "&", "apos": "'", "gt": ">", "lt": "<", "quot": "\"" }; /***/ }, /* 45 */ /***/ function(module, exports, __webpack_require__) { var ElementType = __webpack_require__(46); var re_whitespace = /\s+/g; var NodePrototype = __webpack_require__(47); var ElementPrototype = __webpack_require__(48); function DomHandler(callback, options, elementCB){ if(typeof callback === "object"){ elementCB = options; options = callback; callback = null; } else if(typeof options === "function"){ elementCB = options; options = defaultOpts; } this._callback = callback; this._options = options || defaultOpts; this._elementCB = elementCB; this.dom = []; this._done = false; this._tagStack = []; this._parser = this._parser || null; } //default options var defaultOpts = { normalizeWhitespace: false, //Replace all whitespace with single spaces withStartIndices: false, //Add startIndex properties to nodes }; DomHandler.prototype.onparserinit = function(parser){ this._parser = parser; }; //Resets the handler back to starting state DomHandler.prototype.onreset = function(){ DomHandler.call(this, this._callback, this._options, this._elementCB); }; //Signals the handler that parsing is done DomHandler.prototype.onend = function(){ if(this._done) return; this._done = true; this._parser = null; this._handleCallback(null); }; DomHandler.prototype._handleCallback = DomHandler.prototype.onerror = function(error){ if(typeof this._callback === "function"){ this._callback(error, this.dom); } else { if(error) throw error; } }; DomHandler.prototype.onclosetag = function(){ //if(this._tagStack.pop().name !== name) this._handleCallback(Error("Tagname didn't match!")); var elem = this._tagStack.pop(); if(this._elementCB) this._elementCB(elem); }; DomHandler.prototype._addDomElement = function(element){ var parent = this._tagStack[this._tagStack.length - 1]; var siblings = parent ? parent.children : this.dom; var previousSibling = siblings[siblings.length - 1]; element.next = null; if(this._options.withStartIndices){ element.startIndex = this._parser.startIndex; } if (this._options.withDomLvl1) { element.__proto__ = element.type === "tag" ? ElementPrototype : NodePrototype; } if(previousSibling){ element.prev = previousSibling; previousSibling.next = element; } else { element.prev = null; } siblings.push(element); element.parent = parent || null; }; DomHandler.prototype.onopentag = function(name, attribs){ var element = { type: name === "script" ? ElementType.Script : name === "style" ? ElementType.Style : ElementType.Tag, name: name, attribs: attribs, children: [] }; this._addDomElement(element); this._tagStack.push(element); }; DomHandler.prototype.ontext = function(data){ //the ignoreWhitespace is officially dropped, but for now, //it's an alias for normalizeWhitespace var normalize = this._options.normalizeWhitespace || this._options.ignoreWhitespace; var lastTag; if(!this._tagStack.length && this.dom.length && (lastTag = this.dom[this.dom.length-1]).type === ElementType.Text){ if(normalize){ lastTag.data = (lastTag.data + data).replace(re_whitespace, " "); } else { lastTag.data += data; } } else { if( this._tagStack.length && (lastTag = this._tagStack[this._tagStack.length - 1]) && (lastTag = lastTag.children[lastTag.children.length - 1]) && lastTag.type === ElementType.Text ){ if(normalize){ lastTag.data = (lastTag.data + data).replace(re_whitespace, " "); } else { lastTag.data += data; } } else { if(normalize){ data = data.replace(re_whitespace, " "); } this._addDomElement({ data: data, type: ElementType.Text }); } } }; DomHandler.prototype.oncomment = function(data){ var lastTag = this._tagStack[this._tagStack.length - 1]; if(lastTag && lastTag.type === ElementType.Comment){ lastTag.data += data; return; } var element = { data: data, type: ElementType.Comment }; this._addDomElement(element); this._tagStack.push(element); }; DomHandler.prototype.oncdatastart = function(){ var element = { children: [{ data: "", type: ElementType.Text }], type: ElementType.CDATA }; this._addDomElement(element); this._tagStack.push(element); }; DomHandler.prototype.oncommentend = DomHandler.prototype.oncdataend = function(){ this._tagStack.pop(); }; DomHandler.prototype.onprocessinginstruction = function(name, data){ this._addDomElement({ name: name, data: data, type: ElementType.Directive }); }; module.exports = DomHandler; /***/ }, /* 46 */ /***/ function(module, exports) { //Types of elements found in the DOM module.exports = { Text: "text", //Text Directive: "directive", // Comment: "comment", // Script: "script", //