<' + '/script>\n?'), '');
+ }
+ state.add--;
+ }
+
+ if (isCssFile(url)) {
+ resource = '<' + 'link href="' + url + '"' + attrList + ' />';
+ } else {
+ resource = '<' + 'script src="' + url + '"' + attrList + '><' + '/script>';
+ }
+
+ if (isJadeActive()) {
+ resource = isCssFile(url) ? htmlLinkToJade(resource) : htmlScriptToJade(resource);
+ }
+
+ html.push(resource);
+
+ state.add++;
+ }
+
+ if (isJadeActive()) {
+ // always append Jade at the end, it's just easier that way...okay?
+ var indent = (code.match(/html.*\n(\s*)\S?/i) || [,])[1];
+ code = code.trim() + '\n' + indent + html.join('\n' + indent).trim();
+ } else {
+ if (code.indexOf('/i, '\n' + html.join('\n'));
+ } else { // add to the start of the doc
+ code = html.join('\n') + code;
+ }
+ }
+
+ editors.html.setCode(code);
+ editors.html.editor.setCursor({ line: state.line + state.add, ch: state.character });
+
+}
+
+function insertSnippet(snippet) {
+ var code = editors.html.getCode(),
+ state = { line: editors.html.editor.currentLine(),
+ character: editors.html.editor.getCursor().ch,
+ add: 0
+ };
+
+ if (code.indexOf('/i, snippet + '\n');
+ } else { // add to the start of the doc
+ code = snippet + '\n' + code;
+ }
+
+ editors.html.setCode(code);
+ editors.html.editor.setCursor({ line: state.line + state.add, ch: state.character });
+}
+
+function createHTMLToJadeTagConverter(tagName, attribute, suffix){
+ var regExToGrabResource = new RegExp(attribute+'=(\'|").+.'+suffix+'\\1');
+ return function(html){
+ var resource = html.match(regExToGrabResource);
+ return tagName+'('+resource[0]+')';
+ };
+}
+
+var htmlScriptToJade = createHTMLToJadeTagConverter('script', 'src', 'js');
+// Dirty, but good enough for now, parse the link and add commas between attributes;
+var htmlLinkToJade = (function(){
+ var parseLink = createHTMLToJadeTagConverter('link', 'href', 'css');
+ return function(html){
+ var jadeLink = parseLink(html);
+ return jadeLink.split('" ').join('",');
+ };
+}());
+
+function isJadeActive(){
+ return jsbin.state.processors.html === 'jade';
+}
+
+function isCssFile(url) {
+ return (url.length - (url.lastIndexOf('.css') + 4) === 0);
+}
+;(function () {
+ 'use strict';
+
+ /*globals $, jsbin, CodeMirror, template, ternDefinitions, ternBasicDefs */
+ if (!jsbin.settings.addons.tern) {
+ return;
+ }
+
+ var ternServer;
+ var ternLoaded = {};
+
+ var initTern = function(editor, defs){
+ var keyMap = {
+ 'Ctrl-Q': function(cm) { ternServer.selectName(cm); },
+ 'Ctrl-I': function(cm) { ternServer.showType(cm); },
+ 'Ctrl-Space': function(cm) { ternServer.complete(cm); }
+ };
+ if (typeof defs === 'undefined') {
+ defs = [];
+ }
+ ternServer = new CodeMirror.TernServer({
+ defs: defs,
+ useWorker: false,
+ cm: editor
+ });
+ editor.addKeyMap(keyMap);
+ editor.on('cursorActivity', function(cm) { ternServer.updateArgHints(cm); });
+ };
+
+ var addTernDefinition = function(def) {
+ if (typeof ternServer === 'object') {
+ ternServer.options.defs.push(def);
+ ternServer = new CodeMirror.TernServer({
+ defs: ternServer.options.defs,
+ useWorker: ternServer.options.useWorker,
+ tooltipType: ternServer.options.tooltipType,
+ cm: ternServer.options.cm
+ });
+ }
+ };
+
+ // Load the json defition of the library
+ var loadTernDefinition = function(name, file) {
+ if (!ternLoaded[name]) {
+ $.ajax({
+ url: file,
+ dataType: 'json',
+ success: function(data) {
+ addTernDefinition(data);
+ ternLoaded[name] = true;
+ }
+ });
+ }
+ };
+
+ // Load the actual js library
+ var loadTernFile = function(name, file) {
+ if (!ternLoaded[name]) {
+ $.ajax({
+ url: file,
+ dataType: 'script',
+ success: function(data) {
+ ternServer.server.addFile(name, data);
+ ternLoaded[name] = true;
+ }
+ });
+ }
+ };
+
+ var loadTern = function(editor) {
+ initTern(editor, ternBasicDefs);
+ ternLoaded.ecma5 = true;
+ ternLoaded.browser = true;
+ };
+
+ var searchTernDefinition = function(htmlCode) {
+ for (var i = 0; i < ternDefinitions.length; i++) {
+ if (ternDefinitions[i].match.test(htmlCode)) {
+ if (ternDefinitions[i].type === 'def') {
+ loadTernDefinition(ternDefinitions[i].name, ternDefinitions[i].file);
+ } else {
+ loadTernFile(ternDefinitions[i].name, ternDefinitions[i].file);
+ }
+ }
+ }
+ };
+
+ // Overwrite the autocomplete function to use tern
+ CodeMirror.commands.autocomplete = function(cm) {
+ if (CodeMirror.snippets(cm) === CodeMirror.Pass) {
+ var pos = cm.getCursor();
+ var tok = cm.getTokenAt(pos);
+ var indent = '';
+ if (cm.options.indentWithTabs) {
+ indent = '\t';
+ } else {
+ indent = new Array(cm.options.indentUnit * 1 + 1).join(' ');
+ }
+
+ if (tok.string === ';') {
+ return cm.replaceRange(indent, pos);
+ }
+ if (tok.string.trim() !== '') {
+ return ternServer.complete(cm);
+ }
+ return cm.replaceRange(indent, pos);
+ }
+ };
+
+ CodeMirror.startTern = function() {
+ loadTern(jsbin.panels.panels.javascript.editor);
+ searchTernDefinition(template.html);
+
+ $('#library').bind('change', function () {
+ searchTernDefinition(jsbin.panels.panels.html.getCode());
+ });
+ };
+
+})();;(function () {
+ 'use strict';
+ /*globals $, jsbin, CodeMirror*/
+
+ var defaults = {
+ closebrackets: true,
+ highlight: false,
+ vim: false,
+ emacs: false,
+ trailingspace: false,
+ fold: false,
+ sublime: false,
+ tern: false,
+ activeline: true,
+ matchbrackets: false
+ };
+
+ if (!jsbin.settings.addons) {
+ jsbin.settings.addons = defaults;
+ }
+
+ var detailsSupport = 'open' in document.createElement('details');
+
+ var settingsHints = {};
+ var settingsHintShow = {};
+ var hintShow = {
+ console: true,
+ line: false,
+ under: false,
+ gutter: false
+ };
+ // css must go last for the moment due to CSSLint creating the
+ // global variable 'exports'
+ ['js', 'html', 'coffeescript', 'css'].forEach(function (val) {
+ var h = val + 'hint';
+ var d = false;
+ if (val === 'js') {
+ d = true;
+ }
+ settingsHints[h] = (jsbin.settings[h] !== undefined) ? jsbin.settings[h] : d;
+ });
+
+ settingsHintShow = $.extend({}, hintShow, jsbin.settings.hintShow);
+ settingsHintShow.tooltip = settingsHintShow.gutter;
+ var settingsAddons = $.extend({}, jsbin.settings.addons, settingsHints);
+
+ var addons = {
+ closebrackets: {
+ url: '/js/vendor/codemirror4/addon/edit/closebrackets.js',
+ test: defaultTest('autoCloseBrackets'),
+ done: function (cm) {
+ setOption(cm, 'autoCloseBrackets', true);
+ }
+ },
+ highlight: {
+ url: '/js/vendor/codemirror4/addon/search/match-highlighter.js',
+ test: defaultTest('highlightSelectionMatches'),
+ done: function (cm) {
+ setOption(cm, 'highlightSelectionMatches', true);
+ }
+ },
+ vim: {
+ url: [
+ '/js/vendor/codemirror4/addon/dialog/dialog.css',
+ '/js/vendor/codemirror4/keymap/vim.js',
+ '/js/vendor/codemirror4/addon/dialog/dialog.js'
+ ],
+ test: defaultTest('vimMode'),
+ done: function (cm) {
+ setOption(cm, 'vimMode', true);
+ setOption(cm, 'showCursorWhenSelecting', true);
+ }
+ },
+ emacs: {
+ url: [
+ '/js/vendor/codemirror4/addon/dialog/dialog.css',
+ '/js/vendor/codemirror4/keymap/emacs.js',
+ '/js/vendor/codemirror4/addon/dialog/dialog.js',
+ '/js/vendor/codemirror4/addon/search/search.js'
+ ],
+ test: function () {
+ return jsbin.panels.panels.javascript.editor.openDialog &&
+ CodeMirror.commands.find &&
+ CodeMirror.keyMap.emacs;
+ },
+ done: function (cm) {
+ setOption(cm, 'keyMap', 'emacs');
+ }
+ },
+ matchtags: {
+ url: [
+ '/js/vendor/codemirror4/addon/fold/xml-fold.js',
+ '/js/vendor/codemirror4/addon/edit/matchtags.js'
+ ],
+ test: function () {
+ return CodeMirror.scanForClosingTag &&
+ CodeMirror.optionHandlers.matchTags;
+ },
+ done: function (cm) {
+ setOption(cm, 'matchTags', { bothTags: true });
+ cm.addKeyMap({'Ctrl-J': 'toMatchingTag' });
+ }
+ },
+ trailingspace: {
+ url: '/js/vendor/codemirror4/addon/edit/trailingspace.js',
+ test: defaultTest('showTrailingSpace'),
+ done: function (cm) {
+ setOption(cm, 'showTrailingSpace', true);
+ }
+ },
+ fold: {
+ url: [
+ '/js/vendor/codemirror4/addon/fold/foldgutter.css',
+ '/js/vendor/codemirror4/addon/fold/foldcode.js',
+ '/js/vendor/codemirror4/addon/fold/foldgutter.js',
+ '/js/vendor/codemirror4/addon/fold/brace-fold.js',
+ '/js/vendor/codemirror4/addon/fold/xml-fold.js',
+ '/js/vendor/codemirror4/addon/fold/comment-fold.js'
+ ],
+ test: function () {
+ return CodeMirror.helpers.fold &&
+ CodeMirror.optionHandlers.foldGutter &&
+ CodeMirror.optionHandlers.gutters;
+ },
+ done: function (cm) {
+ $body.addClass('code-fold');
+ cm.addKeyMap({'Ctrl-Q': function (cm) {
+ cm.foldCode(cm.getCursor());
+ }});
+ setOption(cm, 'foldGutter', true);
+ var gutters = cm.getOption('gutters');
+ gutters.push('CodeMirror-linenumbers');
+ gutters.push('CodeMirror-foldgutter');
+ setOption(cm, 'gutters', gutters);
+ }
+ },
+ sublime: {
+ url: [
+ '/js/vendor/codemirror4/addon/dialog/dialog.css',
+ '/js/vendor/codemirror4/keymap/sublime.js',
+ '/js/vendor/codemirror4/addon/dialog/dialog.js',
+ '/js/vendor/codemirror4/addon/search/search.js'
+ ],
+ test: function () {
+ return jsbin.panels.panels.javascript.editor.openDialog &&
+ CodeMirror.commands.find &&
+ CodeMirror.keyMap.sublime;
+ },
+ done: function (cm) {
+ setOption(cm, 'keyMap', 'sublime');
+ // Keys that CodeMirror should never take over
+ var cmd = $.browser.platform === 'mac' ? 'Cmd' : 'Ctrl';
+ delete CodeMirror.keyMap['sublime'][cmd + '-L'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-T'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-W'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-J'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-R'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-Enter'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-Up'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-Down'];
+ cm.removeKeyMap('noEmmet');
+ }
+ },
+ tern: {
+ url: [
+ '/js/vendor/codemirror4/addon/dialog/dialog.css',
+ '/js/vendor/codemirror4/addon/hint/show-hint.css',
+ '/js/vendor/codemirror4/addon/tern/tern.css',
+ '/js/vendor/codemirror4/addon/hint/show-hint.js',
+ '/js/vendor/codemirror4/addon/dialog/dialog.js',
+ '/js/prod/addon-tern-' + jsbin.version + '.min.js'
+ ],
+ test: function () {
+ return jsbin.panels.panels.javascript.editor.openDialog &&
+ (typeof window.ternBasicDefs !== 'undefined') &&
+ CodeMirror.showHint &&
+ CodeMirror.TernServer &&
+ CodeMirror.startTern;
+ },
+ done: function () {
+ CodeMirror.startTern();
+ }
+ },
+ activeline: {
+ url: [
+ '/js/vendor/codemirror4/addon/selection/active-line.js'
+ ],
+ test: function() {
+ return (typeof CodeMirror.defaults.styleActiveLine !== 'undefined');
+ },
+ done: function(cm) {
+ setOption(cm, 'styleActiveLine', true);
+ }
+ },
+ matchbrackets: {
+ url: [],
+ test: function() {
+ return (typeof CodeMirror.defaults.matchBrackets !== 'undefined');
+ },
+ done: function(cm) {
+ setOption(cm, 'matchBrackets', true);
+ }
+ },
+ csshint: {
+ url: [
+ '/js/vendor/csslint/csslint.min.js',
+ '/js/vendor/cm_addons/lint/css-lint.js'
+ ],
+ test: function() {
+ return hintingTest('css') &&
+ (typeof CSSLint !== 'undefined');
+ },
+ done: function(cm) {
+ if (cm.getOption('mode') !== 'css') {
+ return;
+ }
+ hintingDone(cm);
+ }
+ },
+ jshint: {
+ url: [],
+ test: function() {
+ return hintingTest('javascript') &&
+ (typeof JSHINT !== 'undefined');
+ },
+ done: function(cm) {
+ if (cm.getOption('mode') !== 'javascript') {
+ return;
+ }
+ hintingDone(cm, {
+ 'eqnull': true
+ });
+ }
+ },
+ htmlhint: {
+ url: [
+ '/js/vendor/htmlhint/htmlhint.js',
+ '/js/vendor/cm_addons/lint/html-lint.js'
+ ],
+ test: function() {
+ return hintingTest('htmlmixed') &&
+ (typeof HTMLHint !== 'undefined');
+ },
+ done: function(cm) {
+ if (cm.getOption('mode') !== 'htmlmixed') {
+ return;
+ }
+ hintingDone(cm);
+ }
+ },
+ coffeescripthint: {
+ url: [
+ '/js/vendor/coffeelint/coffeelint.min.js',
+ '/js/vendor/cm_addons/lint/coffeescript-lint.js'
+ ],
+ test: function() {
+ return hintingTest('coffeescript') &&
+ (typeof coffeelint !== 'undefined');
+ },
+ done: function(cm) {
+ if (cm.getOption('mode') !== 'coffeescript') {
+ return;
+ }
+ hintingDone(cm);
+ }
+ }
+ };
+
+ // begin loading user addons
+
+
+ var $body = $('body');
+
+ function load(url) {
+ if (url.indexOf('http') !== 0) {
+ url = jsbin.static + url;
+ }
+
+ if (url.slice(-3) === '.js') {
+ return $.ajax({
+ url: url + '?' + jsbin.version, // manual cache busting
+ dataType: 'script',
+ cache: true
+ });
+ } else if (url.slice(-4) === '.css') {
+ var d = $.Deferred();
+ setTimeout(function () {
+ $body.append(' ');
+ d.resolve();
+ }, 0);
+ return d;
+ }
+ }
+
+ function ready(test) {
+ var d = $.Deferred();
+ var timer = null;
+
+ if (test()) {
+ d.resolve();
+ } else {
+ timer = setInterval(function () {
+ if (test()) {
+ clearInterval(timer);
+ d.resolve();
+ }
+ }, 100);
+ }
+
+ return d;
+ }
+
+ function setOption(cm, option, value) {
+ cm.setOption(option, value);
+ }
+
+ function defaultTest(prop) {
+ return function () {
+ return (typeof CodeMirror.optionHandlers[prop] !== 'undefined');
+ };
+ }
+
+ function hintingTest(mode) {
+ return (typeof CodeMirror.defaults.lint !== 'undefined') &&
+ CodeMirror.helpers.lint &&
+ CodeMirror.helpers.lint[mode] &&
+ CodeMirror.optionHandlers.lint;
+ }
+
+ window.hintingDone = function(cm, defhintOptions) {
+ var mode = cm.getOption('mode');
+ if (mode === 'javascript') {
+ mode = 'js';
+ }
+ if (mode === 'htmlmixed') {
+ mode = 'html';
+ }
+ var opt = $.extend({}, settingsHintShow);
+ opt.consoleParent = cm.getWrapperElement().parentNode.parentNode;
+ setOption(cm, 'lintOpt', opt);
+ setOption(cm, 'lintRules', $.extend({}, defhintOptions, jsbin.settings[mode + 'hintOptions']));
+ if (opt.gutter) {
+ var gutters = cm.getOption('gutters');
+ if (gutters.indexOf('CodeMirror-lint-markers') === -1) {
+ gutters.push('CodeMirror-lint-markers');
+ setOption(cm, 'gutters', gutters);
+ }
+ setOption(cm, 'lint', true);
+ var ln = cm.getOption('lineNumbers');
+ setOption(cm, 'lineNumbers', !ln);
+ setOption(cm, 'lineNumbers', ln);
+ } else {
+ setOption(cm, 'lint', true);
+ }
+ if (opt.console) {
+ $document.trigger('sizeeditors');
+ $(cm.consolelint.head).on('click', function() {
+ if (!detailsSupport) {
+ $(this).nextAll().toggle();
+ }
+ // trigger a resize after the click has completed and the details is close
+ setTimeout(function () {
+ $document.trigger('sizeeditors');
+ }, 10);
+ });
+ }
+ }
+
+ var options = Object.keys(settingsAddons);
+
+ function loadAddon(key) {
+ var addon = addons[key];
+ if (addon && settingsAddons[key]) {
+ if (typeof addon.url === 'string') {
+ addon.url = [addon.url];
+ }
+
+ // dirty jQuery way of doing .done on an array of promises
+ $.when.call($, addon.url.map(load)).done(function () {
+ if (addon.done) {
+ ready(addon.test).then(function () {
+ jsbin.panels.allEditors(function (panel) {
+ if (panel.editor) {
+ addon.done(panel.editor);
+ }
+ });
+ });
+ }
+ });
+ }
+ }
+
+ options.forEach(loadAddon);
+
+ // External method to realod all the addons
+ window.reloadAddons = function(arr) {
+ if (arr) {
+ arr.forEach(loadAddon);
+ } else {
+ options.forEach(loadAddon);
+ }
+ };
+
+ // External method to realod the selected addon
+ // may be useful in the future
+ // window.reloadSelectedAddon = function(addon) {
+ // if (options.indexOf(addon) !== -1) {
+ // loadAddon(addon);
+ // }
+ // };
+
+})();;;(function () {
+ var $body = $('body'),
+ loaded = false,
+ $history; // set in hookUserHistory()
+
+ $document.on('history:open', function () {
+ if ($history && jsbin.panels.getVisible().length === 0) {
+ $history.appendTo('body');
+ }
+ }).on('history:close', function () {
+ if ($history === null) {
+ $history = $('#history').detach();
+ }
+ });
+
+ var loadList = function () {
+ if (loaded) return;
+
+ if ($('html').hasClass('public-listing')) {
+ hookUserHistory();
+ } else {
+ $.ajax({
+ dataType: 'html',
+ url: jsbin.root + '/list',
+ error: function () {
+ $('#history').remove();
+ setTimeout(loadList, 500);
+ },
+ success: function (html) {
+ $('#history').remove();
+ $body.append(html);
+ hookUserHistory();
+ loaded = true;
+ }
+ });
+ }
+ };
+
+ var updatePreview = function(url, $iframe) {
+ $iframe.attr('src', url + '/quiet');
+ $iframe.removeAttr('hidden');
+ };
+
+ var updateViewing = function (url, $viewing) {
+ $viewing.text(url);
+ };
+
+ var updateLayout = function ($tbodys, archiveMode) {
+ var $parent = $tbodys.parent();
+ $tbodys
+ .detach()
+ .each(function () {
+ var $tbody = $(this),
+ filter = archiveMode ? '.archived' : ':not(.archived)',
+ $trs = $('tr' + filter, $tbody).filter(':not(.spacer)');
+ if ($trs.length > 0) {
+ $trs.filter('.first').removeClass('first');
+ $tbody.removeClass('hidden');
+ $trs.first().addClass('first');
+ } else {
+ $tbody.addClass('hidden');
+ }
+ })
+ .appendTo($parent);
+ };
+
+ var hookUserHistory = function () {
+ // Loading the HTML from the server may have failed
+ $history = $('#history').detach();
+ if (!$history.length) return $history;
+
+ // Cache some useful elements
+ var $iframe = $('iframe', $history),
+ $viewing = $('#viewing', $history),
+ $bins = $history,
+ $tbodys = $('tbody', $history),
+ $trs = $('tr', $history),
+ $created = $('td.created a', $history),
+ $toggle = $('.toggle_archive', $history),
+ current = null,
+ hoverTimer = null,
+ layoutTimer = null;
+
+ // Load bin from data-edit-url attribute when user clicks on a row
+ $bins.delegate('tr:not(.spacer)', 'click', function () {
+ if (event.shiftKey || event.metaKey) return;
+ window.location = this.getAttribute('data-edit-url');
+ });
+
+ // Archive & un-archive click handlers
+ $bins.delegate('.archive, .unarchive', 'click', function (e) {
+ var $this = $(this),
+ $row = $this.parents('tr');
+ // Instantly update this row and the page layout
+ $row.toggleClass('archived');
+
+ analytics[this.pathname.indexOf('unarchive') === -1 ? 'archive' : 'unarchive'](jsbin.root + $row.data('url'));
+
+ updateLayout($tbodys, $history.hasClass('archive_mode'));
+ // Then send the update to the server
+ $.ajax({
+ type: 'POST',
+ url: $this.attr('href'),
+ error: function () {
+ // Undo if something went wrong
+ alert("Something went wrong, please try again");
+ $row.toggleClass('archived');
+ updateLayout($tbodys, $history.hasClass('archive_mode'));
+ },
+ success: function () {}
+ });
+ return false;
+ });
+
+ // Handle toggling of archive view
+ $toggle.change(function () {
+ $history.toggleClass('archive_mode');
+ var archive = $history.hasClass('archive_mode');
+ analytics.archiveView(archive);
+ updateLayout($tbodys, archive);
+ });
+
+
+ // Load a preview on tr mouseover (delayed by 400ms)
+ $bins.delegate('tr', 'mouseover', function (event) {
+ var $this = $(this),
+ url = $this.attr('data-url');
+ clearTimeout(hoverTimer);
+ if (!$this.hasClass('spacer') && current !== url) {
+ hoverTimer = setTimeout(function () {
+ $trs.removeClass('selected');
+ $this.addClass('selected');
+ current = url;
+ updatePreview(url, $iframe);
+ updateViewing(url, $viewing);
+ }, 400);
+ }
+ return false;
+ });
+
+ // Update the time every 30 secs
+ // Need to replace Z in ISO8601 timestamp with +0000 so prettyDate() doesn't
+ // completely remove it (and parse the date using the local timezone).
+ $('a[pubdate]', $history).attr('pubdate', function (i, val) {
+ return val.replace('Z', '+0000');
+ }).prettyDate();
+ setInterval(function(){
+ $created.prettyDate();
+ }, 30 * 1000);
+
+ // Update the layout straign away
+ setTimeout(function () {
+ updateLayout($tbodys, false);
+ }, 0);
+
+ $document.trigger('history:open');
+
+ return $history;
+ };
+
+ // inside a ready call because history DOM is rendered *after* our JS to improve load times.
+ $(document).on('jsbinReady', function () {
+ if (jsbin.embed) return;
+
+ var $panelButtons = $('#panels a'),
+ $homebtn = $('.homebtn'),
+ panelsVisible = $body.hasClass('panelsVisible');
+
+ var panelCloseIntent = function() {
+ var activeCount = $panelButtons.filter('.active').length;
+ if (activeCount === 1 && $(this).hasClass('active')) {
+ loadList();
+ }
+ };
+
+ // this code attempts to only call the list ajax request only if
+ // the user should want to see the list page - most users will
+ // jump in and jump out of jsbin, and never see this page,
+ // so let's not send this ajax request.
+ //
+ // The list should be loaded when:
+ // - user hovers the home button
+ // - they close all the panels
+ // - they arrive at the page with no panels open
+
+ $homebtn.on('click', loadList);
+ $panelButtons.on('mousedown', panelCloseIntent);
+
+ if (!panelsVisible) {
+ loadList();
+ }
+
+ });
+
+}());
+;var loginVisible = false,
+ dropdownOpen = false,
+ keyboardHelpVisible = false,
+ urlHelpVisible = false;
+
+$document.keydown(function (event) {
+ if (event.which == 27) {//} || (keyboardHelpVisible && event.which == 191 && event.shiftKey && event.metaKey)) {
+ hideOpen();
+ }
+});
+
+function hideOpen() {
+ if (urlHelpVisible) {
+ $body.removeClass('urlHelp');
+ urlHelpVisible = false;
+ analytics.closeMenu('help');
+ } else if (keyboardHelpVisible) {
+ $body.removeClass('keyboardHelp');
+ keyboardHelpVisible = false;
+ analytics.closeMenu('keyboardHelp');
+ } else if (dropdownOpen) {
+ var open = $('.menu.open').removeClass('open');
+ analytics.closeMenu(open.find('.button')[0].hash.substring(1));
+ dropdownOpen = false;
+ } else if (loginVisible) {
+ $('#login').hide();
+ analytics.closeMenu('login');
+ loginVisible = false;
+ }
+}
+
+$document.delegate('.modal', 'click', function (event) {
+ if ($(event.target).is('.modal')) {
+ hideOpen();
+ }
+});;var githubIssue = (function () {
+/*global $:true, jsbin:true */
+ 'use strict';
+
+ function githubIssue() {
+ var url = 'http://github.com/jsbin/jsbin/issues/new';
+ var body = ['Please provide any additional information, record a screencast ',
+ 'with http://quickcast.io or http://screenr.com and attach a screenshot ',
+ 'if possible.\n\n**JS Bin info**\n\n* [%url%](%url%)\n* ',
+ window.navigator.userAgent + '\n',
+ (jsbin.user && jsbin.user.name ? '* ' + jsbin.user.name : ''),
+ '\n'].join('');
+
+ return url + '?body=' + encodeURIComponent(body.replace(/%url%/g, jsbin.getURL()));
+ }
+
+ var $newissue = $('#newissue');
+
+ $('#help').parent().on('open', function () {
+ $newissue.attr('href', githubIssue());
+ });
+
+ return githubIssue;
+})();;$('#download').click(function (event) {
+ event.preventDefault();
+ window.location = jsbin.getURL() + '/download';
+ analytics.download();
+});
+;/* global $ */
+
+$('form.login').submit(function (event) {
+ 'use strict';
+ event.preventDefault();
+
+ var form = $(this),
+ name = form.find('input[name=username]').val(),
+ key = form.find('input[name=password]').val(),
+ email = form.find('input[name=email]').val(),
+ $loginFeedback = form.find('.loginFeedback');
+
+
+ // jsbin.settings.home = name; // will save later
+ $loginFeedback.show().text('Checking...');
+
+ $.ajax({
+ url: form.attr('action'),
+ data: { username: name, key: key, email: email },
+ type: 'POST',
+ dataType: 'json',
+ complete: function (jqXHR) {
+ var data = $.parseJSON(jqXHR.responseText) || {};
+ // cookie is required to share with the server so we can do a redirect on new bin
+ if (jqXHR.status === 200) {
+ if (data.avatar) {
+ $('a.avatar').find('img').remove().end().prepend(' ');
+ }
+ if (data.message) {
+ $loginFeedback.text(data.message);
+ } else {
+ window.location = window.location.pathname + window.location.search;
+ }
+ } else {
+ analytics.login(false);
+ $loginFeedback.text(data.message || ('"' + name + '" has already been taken. Please either double check the password, or choose another username.'));
+ }
+ }
+ });
+});
+;(function () {
+
+ var $html = $(document.documentElement),
+ $tip = $('#tip'),
+ $tipContent = $('p', $tip),
+ tipTimeout;
+
+ var removeTip = function (cb) {
+ $html.removeClass('showtip');
+ $tip.removeClass();
+ $tipContent.html('');
+ $(window).resize();
+ cb && setTimeout(cb, 0);
+ };
+
+ var setTip = function (data) {
+ clearTimeout(tipTimeout);
+ $tipContent.html(data.content);
+ $tip.removeClass().addClass(data.type || 'info');
+ $html.addClass('showtip');
+ if (!data.autohide) return;
+ tipTimeout = setTimeout(function () {
+ removeTip();
+ }, parseInt(data.autohide, 10) || 5 * 1000);
+ };
+
+ /**
+ * Trigger a tip to be shown.
+ *
+ * $document.trigger('tip', 'You have an infinite loop in your HTML.');
+ *
+ * $document.trigger('tip', {
+ * type: 'error',
+ * content: 'Do you even Javascript?',
+ * autohide: 8000
+ * });
+ */
+ $document.on('tip', function (event, data) {
+ var tipData = data;
+ if (typeof data === 'string') {
+ tipData = {};
+ tipData.content = data;
+ tipData.type = 'info';
+ }
+ // If the content and the type haven't changed, just set it again.
+ if ($tipContent.html() === tipData.content &&
+ $tip.hasClass(tipData.type)) return setTip(data);
+ removeTip(function () {
+ setTip(tipData);
+ });
+ });
+
+ $('#tip').on('click', 'a.dismiss', function () {
+ removeTip();
+ return false;
+ });
+
+ // Escape
+ $document.keydown(function (event) {
+ if (event.which == 27) {
+ removeTip();
+ }
+ });
+
+}());;var saving = {
+ todo: {
+ html: false,
+ css: false,
+ javascript: false
+ },
+ _inprogress: false,
+ inprogress: function (inprogress) {
+ if (typeof inprogress === 'undefined') {
+ return saving._inprogress;
+ }
+
+ saving._inprogress = inprogress;
+ if (inprogress === false) {
+ var panels = ['html','css','javascript'],
+ todo;
+
+ var save = function () {
+ var todo = panels.pop();
+ if (todo && saving.todo[todo]) {
+ saving._inprogress = true;
+ updateCode(todo, save);
+ saving.todo[todo] = false;
+ } else if (todo) {
+ save();
+ }
+ };
+
+ save();
+ }
+ }
+};
+
+// to allow for download button to be introduced via beta feature
+$('a.save').click(function (event) {
+ event.preventDefault();
+
+ analytics.milestone();
+ // if save is disabled, hitting save will trigger a reload
+ var ajax = true;
+ if (jsbin.saveDisabled === true) {
+ ajax = false;
+ }
+ saveCode('save', ajax);
+
+ return false;
+});
+
+var $shareLinks = $('#share .link');
+
+$panelCheckboxes = $('#sharemenu #sharepanels input');
+
+function updateSavedState() {
+ 'use strict';
+ var mapping = {
+ live: 'output',
+ javascript: 'js',
+ css: 'css',
+ html: 'html',
+ console: 'console'
+ };
+ var query = $panelCheckboxes.filter(':checked').map(function () {
+ return mapping[this.getAttribute('data-panel')];
+ }).get().join(',');
+ $shareLinks.each(function () {
+ var path = this.getAttribute('data-path');
+ var url = jsbin.getURL(false, path === '/') + path + (query && this.id !== 'livepreview' ? '?' + query : ''),
+ nodeName = this.nodeName;
+ var hash = panels.getHighlightLines();
+
+ if (hash) {
+ hash = '#' + hash;
+ }
+
+ if (nodeName === 'A') {
+ this.href = url;
+ } else if (nodeName === 'INPUT') {
+ this.value = url;
+ if (path === '/edit') {
+ this.value += hash;
+ }
+ } else if (nodeName === 'TEXTAREA') {
+ this.value = ('' + documentTitle + ' <' + 'script src="' + jsbin.static + '/js/embed.js"><' + '/script>').replace(/<>"&/g, function (m) {
+ return {
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ '&': '&'
+ }[m];
+ });
+ }
+ });
+}
+
+$('#sharemenu').bind('open', function () {
+ updateSavedState();
+});
+
+$document.on('saved', function () {
+ updateSavedState();
+ $shareLinks.closest('.menu').removeClass('hidden');
+
+ $('#jsbinurl').attr('href', jsbin.getURL()).removeClass('hidden');
+ $('#clone').removeClass('hidden');
+});
+
+var saveChecksum = jsbin.state.checksum || sessionStorage.getItem('checksum') || false;
+
+// store it back on state
+jsbin.state.checksum = saveChecksum;
+
+if (saveChecksum) {
+ // remove the disabled class, but also remove the cancelling event handlers
+ $('#share div.disabled').removeClass('disabled').unbind('click mousedown mouseup');
+} else {
+ $('#share div.disabled').one('click', function (event) {
+ event.preventDefault();
+ $('a.save').click();
+ });
+}
+
+$document.one('saved', function () {
+ $('#share div.disabled').removeClass('disabled').unbind('click mousedown mouseup');
+});
+
+function onSaveError(jqXHR, panelId) {
+ if (jqXHR.status === 413) {
+ // Hijack the tip label to show an error message.
+ $('#tip p').html('Sorry this bin is too large for us to save');
+ $(document.documentElement).addClass('showtip');
+ } else if (jqXHR.status === 403) {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'I think there\'s something wrong with your session and I\'m unable to save. Refresh to fix this , you will not lose your code.'
+ });
+ } else if (panelId) {
+ if (panelId) savingLabels[panelId].text('Saving...').animate({ opacity: 1 }, 100);
+ window._console.error({message: 'Warning: Something went wrong while saving. Your most recent work is not saved.'});
+ }
+}
+
+
+
+// only start live saving it they're allowed to (whereas save is disabled if they're following)
+if (!jsbin.saveDisabled) {
+ $('.code.panel .label .name').append('Saved ');
+
+ var savingLabels = {
+ html: $('.panel.html .name span'),
+ javascript: $('.panel.javascript .name span'),
+ css: $('.panel.css .name span')
+ };
+
+ $document.bind('jsbinReady', function () {
+ jsbin.panels.allEditors(function (panel) {
+ panel.on('processor', function () {
+ // if the url doesn't match the root - i.e. they've actually saved something then save on processor change
+ if (jsbin.root !== jsbin.getURL()) {
+ $document.trigger('codeChange', [{ panelId: panel.id }]);
+ }
+ });
+ });
+
+ $document.bind('codeChange', function (event, data) {
+ // savingLabels[data.panelId].text('Saving');
+ if (savingLabels[data.panelId]) {
+ savingLabels[data.panelId].css({ 'opacity': 0 }).stop(true, true);
+ }
+ });
+
+ $document.bind('saveComplete', throttle(function (event, data) {
+ // show saved, then revert out animation
+ savingLabels[data.panelId]
+ .text('Saved')
+ .stop(true, true)
+ .animate({ opacity: 1 }, 100)
+ .delay(1200)
+ .animate({ opacity: 0 }, 500);
+ }, 500));
+
+ $document.bind('codeChange', throttle(function (event, data) {
+ if (!data.panelId) {
+ return;
+ }
+
+ if (jsbin.state.deleted) {
+ return;
+ }
+
+ var panelId = data.panelId;
+
+ jsbin.panels.savecontent();
+
+ if (saving.inprogress()) {
+ // queue up the request and wait
+ saving.todo[panelId] = true;
+ return;
+ }
+
+ saving.inprogress(true);
+
+ // We force a full save if there's no checksum OR if there's no bin code/url
+ if (!saveChecksum || !jsbin.state.code) {
+ // create the bin and when the response comes back update the url
+ saveCode('save', true);
+ } else {
+ updateCode(panelId);
+ }
+ }, 250));
+ });
+} else {
+ $document.one('jsbinReady', function () {
+ var shown = false;
+ if (!jsbin.embed && !jsbin.sandbox) {
+ $document.on('codeChange', function (event, data) {
+ if (!data.onload && !shown && data.origin !== 'setValue') {
+ shown = true;
+ var ismac = navigator.userAgent.indexOf(' Mac ') !== -1;
+ var cmd = ismac ? '⌘' : 'ctrl';
+ var shift = ismac ? '⇧' : 'shift';
+ var plus = ismac ? '' : '+';
+
+ $document.trigger('tip', {
+ type: 'notification',
+ content: 'You\'re currently viewing someone else\'s live stream, but you can clone your own copy (' + cmd + plus + shift + plus + 'S) at any time to save your edits'
+ });
+ }
+ });
+ }
+ });
+}
+
+function compressKeys(keys, obj) {
+ obj.compressed = keys;
+ keys.split(',').forEach(function (key) {
+ obj[key] = LZString.compressToUTF16(obj[key]);
+ });
+}
+
+function updateCode(panelId, callback) {
+ var panelSettings = {};
+
+ if (jsbin.state.processors) {
+ panelSettings.processors = jsbin.state.processors;
+ }
+
+ var data = {
+ code: jsbin.state.code,
+ revision: jsbin.state.revision,
+ method: 'update',
+ panel: panelId,
+ content: editors[panelId].getCode(),
+ checksum: saveChecksum,
+ settings: JSON.stringify(panelSettings),
+ };
+
+ if (jsbin.settings.useCompression) {
+ compressKeys('content', data);
+ }
+
+ $.ajax({
+ url: jsbin.getURL() + '/save',
+ data: data,
+ type: 'post',
+ dataType: 'json',
+ headers: {'Accept': 'application/json'},
+ success: function (data) {
+ $document.trigger('saveComplete', { panelId: panelId });
+ if (data.error) {
+ saveCode('save', true, function (data) {
+ // savedAlready = data.checksum;
+ });
+ }
+ },
+ error: function (jqXHR) {
+ onSaveError(jqXHR, panelId);
+ },
+ complete: function () {
+ saving.inprogress(false);
+ callback && callback();
+ }
+ });
+}
+
+$('a.clone').click(function (event) {
+ event.preventDefault();
+
+ // save our panel layout - assumes our user is happy with this layout
+ jsbin.panels.save();
+ analytics.clone();
+
+ var $form = setupform('save,new');
+ $form.submit();
+
+ return false;
+});
+
+function setupform(method) {
+var $form = $('form#saveform').empty()
+ .append(' ')
+ .append(' ')
+ .append(' ')
+ .append(' ')
+ .append(' ')
+ .append(' ');
+
+ var settings = {};
+
+ if (jsbin.state.processors) {
+ settings.processors = jsbin.state.processors;
+ }
+
+ // this prevents new revisions forking off the welcome bin
+ // because it's looking silly!
+ if (jsbin.state.code === 'welcome') {
+ $form.attr('action', '/save');
+ }
+
+ $form.find('input[name=settings]').val(JSON.stringify(settings));
+ $form.find('input[name=javascript]').val(editors.javascript.getCode());
+ $form.find('input[name=css]').val(editors.css.getCode());
+ $form.find('input[name=html]').val(editors.html.getCode());
+ $form.find('input[name=method]').val(method);
+
+ return $form;
+}
+
+function pad(n){
+ return n<10 ? '0'+n : n
+}
+
+function ISODateString(d){
+ return d.getFullYear()+'-'
+ + pad(d.getMonth()+1)+'-'
+ + pad(d.getDate())+'T'
+ + pad(d.getHours())+':'
+ + pad(d.getMinutes())+':'
+ + pad(d.getSeconds())+'Z'
+}
+
+function saveCode(method, ajax, ajaxCallback) {
+ // create form and post to it
+ var $form = setupform(method);
+ // save our panel layout - assumes our user is happy with this layout
+ jsbin.panels.save();
+ jsbin.panels.saveOnExit = true;
+
+ var data = $form.serializeArray().reduce(function(obj, data) {
+ obj[data.name] = data.value;
+ return obj;
+ }, {});
+
+ if (jsbin.settings.useCompression) {
+ compressKeys('html,css,javascript', data);
+ }
+
+ if (ajax) {
+ $.ajax({
+ url: $form.attr('action'),
+ data: data,
+ dataType: 'json',
+ type: 'post',
+ headers: {'Accept': 'application/json'},
+ success: function (data) {
+ var $binGroup,
+ edit;
+
+ $form.attr('action', data.url + '/save');
+ if (ajaxCallback) {
+ ajaxCallback(data);
+ }
+
+ sessionStorage.setItem('checksum', data.checksum);
+ saveChecksum = data.checksum;
+
+ jsbin.state.checksum = saveChecksum;
+ jsbin.state.code = data.code;
+ jsbin.state.revision = data.revision;
+ jsbin.state.metadata = { name: jsbin.user.name };
+
+ // getURL(true) gets the jsbin without the root attached
+ // $binGroup = $('#history tr[data-url="' + jsbin.getURL(true) + '"]');
+ // edit = data.edit.replace(location.protocol + '//' + window.location.host, '') + window.location.search;
+ // $binGroup.find('td.url a span.first').removeClass('first');
+ // $binGroup.before('' + data.code + '/ ' + data.revision + '/Just now ' + data.title + ' ');
+
+
+ if (window.history && window.history.pushState) {
+ // updateURL(edit);
+ var hash = panels.getHighlightLines();
+ if (hash) hash = '#' + hash;
+ window.history.pushState(null, '', jsbin.getURL() + '/edit' + hash);
+ sessionStorage.setItem('url', jsbin.getURL());
+ } else {
+ window.location.hash = data.edit;
+ }
+
+ $document.trigger('saved');
+ },
+ error: function (jqXHR) {
+ onSaveError(jqXHR, null);
+ },
+ complete: function () {
+ saving.inprogress(false);
+ }
+ });
+ } else {
+ $form.submit();
+ }
+}
+
+/**
+ * Returns the similar part of two strings
+ * @param {String} a first string
+ * @param {String} b second string
+ * @return {String} common substring
+ */
+function sameStart(a, b) {
+ if (a == b) return a;
+
+ var tmp = b.slice(0, 1);
+ while (a.indexOf(b.slice(0, tmp.length + 1)) === 0) {
+ tmp = b.slice(0, tmp.length + 1);
+ }
+
+ return tmp;
+}
+
+/*
+
+// refresh the window when we popstate, because for now we don't do an xhr to
+// inject the panel content...yet.
+window.onpopstate = function onpopstate(event) {
+ // ignore the first popstate event, because that comes from the browser...
+ if (!onpopstate.first) window.location.reload();
+ else onpopstate.first = false;
+};
+
+onpopstate.first = true;
+
+function updateURL(path) {
+ var old = location.pathname,
+ back = true,
+ same = sameStart(old, path);
+ sameAt = same.length;
+
+ if (updateURL.timer) window.cancelAnimationFrame(updateURL.timer);
+
+ var run = function () {
+ if (location.pathname !== path) {
+ updateURL.timer = window.requestAnimationFrame(run);
+ }
+
+ if (location.pathname !== same) {
+ if (back) {
+ history.replaceState({ path: path }, '', location.pathname.slice(0, -1));
+ } else {
+ history.replaceState({ path: path }, '', path.slice(0, location.pathname.length + 1));
+ }
+ } else {
+ back = false;
+ history.replaceState({ path: path }, '', path.slice(0, sameAt + 2));
+ }
+ };
+
+ history.pushState({ path: path }, '', location.pathname.slice(0, -1));
+
+ run();
+}
+
+*/
+;var $startingpoint = $('a.startingpoint').click(function (event) {
+ event.preventDefault();
+ if (localStorage) {
+ analytics.saveTemplate();
+ localStorage.setItem('saved-javascript', editors.javascript.getCode());
+ localStorage.setItem('saved-html', editors.html.getCode());
+ localStorage.setItem('saved-css', editors.css.getCode());
+
+ $document.trigger('tip', {
+ type: 'notification',
+ content: 'Starting template updated and saved',
+ autohide: 3000
+ });
+ } else {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'Saving templates isn\'t supported in this browser I\'m afraid. Sorry'
+ });
+ }
+ return false;
+});
+
+// if (localStorage && localStorage['saved-html']) {
+ // $startingpoint.append('')
+// }
+
+$('a.disabled').on('click mousedown mouseup', function (event) {
+ event.stopImmediatePropagation();
+ return false;
+});
+
+$('#loginbtn').click(function () {
+ analytics.login();
+ $(this).toggleClass('open');
+ // $('#login').show();
+ // loginVisible = true;
+ // return false;
+});
+
+$('a.logout').click(function (event) {
+ event.preventDefault();
+
+ // We submit a form here because I can't work out how to style the button
+ // element in the form to look the same as the anchor. Ideally we would
+ // remove that and just let the form submit itself...
+ $(this.hash).submit();
+ // Clear session storage so private bins wont be cached.
+ for (i = 0; i < sessionStorage.length; i++) {
+ key = sessionStorage.key(i);
+ if (key.indexOf('jsbin.content.') === 0) {
+ sessionStorage.removeItem(key);
+ }
+ }
+});
+
+$('.homebtn').click(function (event, data) {
+ if (this.id === 'avatar') {
+ analytics.openFromAvatar();
+ } else if (this.id === 'profile') {
+ analytics.openFromAvatar();
+ $(this).closest('.open').removeClass('open');
+ } else {
+ analytics.open(data);
+ }
+
+ jsbin.panels.hideAll();
+ return false;
+});
+
+var $lockrevision = $('.lockrevision').on('click', function (event) {
+ event.preventDefault();
+ if (!$lockrevision.data('lock')) {
+ analytics.lock();
+ $lockrevision.removeClass('icon-unlocked').addClass('icon-lock');
+ $lockrevision.html('This bin is now locked from further changes ');
+ $lockrevision.data('locked', true);
+ saveChecksum = false;
+ $document.trigger('locked');
+ }
+ return false;
+}).on('mouseup', function () {
+ return false;
+});
+
+$document.on('saved', function () {
+ $lockrevision.removeClass('icon-lock').addClass('icon-unlocked').data('locked', false);
+ $lockrevision.html('Click to lock and prevent further changes ');
+});
+
+$('#share input[type=text], #share textarea').on('beforecopy', function (event) {
+ analytics.share('copy', this.getAttribute('data-path').substring(1) || 'output');
+});
+
+var $panelCheckboxes = $('#sharepanels input').on('change click', updateSavedState);
+$('#sharemenu').bind('open', function () {
+ // analytics.openShare();
+ // $lockrevision.removeClass('icon-unlock').addClass('icon-lock');
+
+ $panelCheckboxes.attr('checked', false);
+ jsbin.panels.getVisible().forEach(function (panel) {
+ $panelCheckboxes.filter('[data-panel="' + panel.id + '"]').attr('checked', true).change();
+ });
+
+});
+
+var dropdownOpen = false,
+ onhover = false,
+ menuDown = false;
+
+function opendropdown(el) {
+ var menu;
+ if (!dropdownOpen) {
+ menu = $(el).closest('.menu').addClass('open').trigger('open');
+ // $body.addClass('menuinfo');
+ analytics.openMenu(el.hash.substring(1));
+ var input = menu.find(':text:visible:first').focus()[0];
+ if (input) setTimeout(function () {
+ input.select();
+ }, 0);
+ dropdownOpen = el;
+ }
+}
+
+function closedropdown() {
+ menuDown = false;
+ if (dropdownOpen) {
+ dropdownButtons.closest('.menu').removeClass('open').trigger('close');
+ // $body.removeClass('menuinfo');
+ dropdownOpen = false;
+ onhover = false;
+ }
+}
+
+var dropdownButtons = $('.button-dropdown, .button-open').mousedown(function (e) {
+ $dropdownLinks.removeClass('hover');
+ if (dropdownOpen && dropdownOpen !== this) {
+ closedropdown();
+ }
+ if (!dropdownOpen) {
+ menuDown = true;
+ opendropdown(this);
+ }
+ e.preventDefault();
+ return false;
+}).mouseup(function () {
+ if (menuDown) return false;
+}).click(function () {
+ if (!menuDown) {
+ analytics.closeMenu(this.hash.substring(1));
+ closedropdown();
+ }
+ menuDown = false;
+ return false;
+});
+
+$('#actionmenu').click(function () {
+ dropdownOpen = true;
+});
+
+var ignoreUp = false;
+$body.bind('mousedown', function (event) {
+ if (dropdownOpen) {
+ if ($(event.target).closest('.menu').length) {
+ ignoreUp = true;
+ }
+ }
+}).bind('click mouseup', function (event) {
+ if (dropdownOpen && !ignoreUp) {
+ if (!$(event.target).closest('.menu').length) {
+ closedropdown();
+ return false;
+ }
+ }
+ ignoreUp = false;
+});
+
+var fromClick = false;
+var $dropdownLinks = $('.dropdownmenu a, .dropdownmenu .button').mouseup(function () {
+ setTimeout(closedropdown, 0);
+ analytics.selectMenu(this.getAttribute('data-label') || this.hash.substring(1) || this.href);
+ if (!fromClick) {
+ if (this.hostname === window.location.hostname) {
+ if ($(this).triggerHandler('click') !== false) {
+ window.location = this.href;
+ }
+ } else {
+ if (this.getAttribute('target')) {
+ window.open(this.href);
+ } else {
+ window.location = this.href;
+ }
+ }
+ }
+ fromClick = false;
+}).mouseover(function () {
+ $dropdownLinks.removeClass('hover');
+ $(this).addClass('hover');
+}).mousedown(function () {
+ fromClick = true;
+});
+
+$('#jsbinurl').click(function (e) {
+ setTimeout(function () {
+ jsbin.panels.panels.live.hide();
+ }, 0);
+});
+
+$('#runwithalerts').click(function (event, data) {
+ analytics.run(data);
+ if (editors.console.visible) {
+ editors.console.render(true);
+ } else {
+ renderLivePreview(true);
+ }
+ return false;
+});
+
+$('#runconsole').click(function () {
+ analytics.runconsole();
+ editors.console.render(true);
+ return false;
+});
+
+$('#clearconsole').click(function () {
+ jsconsole.clear();
+ return false;
+});
+
+$('#showhelp').click(function () {
+ $body.toggleClass('keyboardHelp');
+ keyboardHelpVisible = $body.is('.keyboardHelp');
+ if (keyboardHelpVisible) {
+ // analytics.help('keyboard');
+ }
+ return false;
+});
+
+$('#showurls').click(function () {
+ $body.toggleClass('urlHelp');
+ urlHelpVisible = $body.is('.urlHelp');
+ if (urlHelpVisible) {
+ // analytics.urls();
+ }
+ return false;
+});
+
+$('.code.panel > .label > span.name').dblclick(function () {
+ jsbin.panels.allEditors(function (panel) {
+ var lineNumbers = !panel.editor.getOption('lineNumbers');
+ panel.editor.setOption('lineNumbers', lineNumbers);
+ jsbin.settings.editor.lineNumbers = lineNumbers;
+ });
+});
+
+$('#createnew').click(function (event) {
+ event.preventDefault();
+ var i, key;
+ analytics.createNew();
+ // FIXME this is out and out [cr]lazy....
+ jsbin.panels.savecontent = function(){};
+ for (i = 0; i < sessionStorage.length; i++) {
+ key = sessionStorage.key(i);
+ if (key.indexOf('jsbin.content.') === 0) {
+ sessionStorage.removeItem(key);
+ }
+ }
+
+ // clear out the write checksum too
+ sessionStorage.removeItem('checksum');
+
+ jsbin.panels.saveOnExit = true;
+
+ // first try to restore their default panels
+ jsbin.panels.restore();
+
+ // if nothing was shown, show html & live
+ setTimeout(function () {
+ if (jsbin.panels.getVisible().length === 0) {
+ jsbin.panels.panels.html.show();
+ jsbin.panels.panels.live.show();
+ }
+ window.location = jsbin.root;
+ }, 0);
+});
+
+var $privateButton = $('#control a.visibilityToggle#private');
+var $publicButton = $('#control a.visibilityToggle#public');
+
+var $visibilityButtons = $('#control a.visibilityToggle').click(function(event) {
+ event.preventDefault();
+
+ var visibility = $(this).data('vis');
+
+ $.ajax({
+ url: jsbin.getURL() + '/' + visibility,
+ type: 'post',
+ success: function (data) {
+
+ $document.trigger('tip', {
+ type: 'notification',
+ content: 'This bin is now ' + visibility,
+ autohide: 6000
+ });
+
+ $visibilityButtons.css('display', 'none');
+
+ if (visibility === 'public') {
+ $privateButton.css('display', 'block');
+ } else {
+ $publicButton.css('display', 'block');
+ }
+
+ }
+ });
+});
+
+$('form.login').closest('.menu').bind('close', function () {
+ $(this).find('.loginFeedback').empty().hide();
+ $('#login').removeClass('forgot');
+});
+
+$('#lostpass').click(function (e) {
+ $('#login').addClass('forgot').find('input[name=email]').focus();
+ return false;
+});
+
+jsbin.settings.includejs = jsbin.settings.includejs === undefined ? true : jsbin.settings.includejs;
+
+$('#enablejs').change(function () {
+ jsbin.settings.includejs = this.checked;
+ analytics.enableLiveJS(jsbin.settings.includejs);
+ editors.live.render();
+}).attr('checked', jsbin.settings.includejs);
+
+if (jsbin.settings.hideheader) {
+ $body.addClass('hideheader');
+}
+
+var cancelUp = false;
+$('form input, form textarea').focus(function () {
+ this.select();
+ cancelUp = true;
+}).mouseup(function () {
+ if (cancelUp) {
+ cancelUp = false;
+ return false;
+ }
+});
+
+if (window.location.hash) {
+ $('a[href$="' + window.location.hash + '"]').mousedown();
+}
+
+var ismac = navigator.userAgent.indexOf(' Mac ') !== -1,
+ mackeys = {
+ 'ctrl': '⌘',
+ 'shift': '⇧',
+ 'del': '⌫'
+ };
+
+$('#control').find('a[data-shortcut]').each(function () {
+ var $this = $(this),
+ data = $this.data();
+
+ var key = data.shortcut;
+ if (ismac) {
+ key = key.replace(/ctrl/i, mackeys.ctrl).replace(/shift/, mackeys.shift).replace(/del/, mackeys.del).replace(/\+/g, '').toUpperCase();
+ }
+
+ $this.append('' + key + ' ');
+});
+
+(function () {
+
+var re = {
+ head: //i,
+ metaContent: /content=".*?"/i
+};
+
+var metatag = ' \n';
+
+$('#addmeta').click(function () {
+ // if not - insert
+ //
+ // if meta description is in the HTML, highlight it
+ var editor = jsbin.panels.panels.html,
+ cm = editor.editor,
+ html = editor.getCode();
+
+ if (!re.meta.test(html)) {
+ if (re.head.test(html)) {
+ html = html.replace(re.head, '' + jsbin.shareRoot + ''
+ });
+ },
+ error: function (xhr) {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'There was a problem publishing to your vanity URL. Can you try again or file a new issue ?'
+ });
+ }
+ })
+});
+
+$('a.deletebin').on('click', function (e) {
+ e.preventDefault();
+ if (confirm('Delete this bin?')) {
+ analytics['delete']();
+ $.ajax({
+ type: 'post',
+ url: jsbin.getURL() + '/delete',
+ data: { checksum: jsbin.state.checksum },
+ success: function () {
+ jsbin.state.deleted = true;
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'This bin is now deleted. You can continue to edit, but once you leave the bin can\'t be retrieved'
+ });
+ },
+ error: function (xhr) {
+ if (xhr.status === 403) {
+ $document.trigger('tip', {
+ content: 'You don\'t own this bin, so you can\'t delete it.',
+ autohide: 5000
+ });
+ }
+ }
+ });
+
+ }
+});
+
+$('a.archivebin').on('click', function (e) {
+ e.preventDefault();
+ archive();
+});
+
+$('a.unarchivebin').on('click', function (e) {
+ e.preventDefault();
+ archive(false);
+});
+
+}());
+;function allowDrop(holder) {
+ holder.ondragover = function () {
+ return false;
+ };
+
+ holder.ondragend = function () {
+ return false;
+ };
+
+ var jstypes = {
+ 'javascript': 1,
+ 'coffeescript': 1,
+ 'coffee': 1,
+ 'js' :1
+ },
+ csstypes = {
+ 'css': 1,
+ 'less': 1,
+ 'sass': 1
+ };
+
+ holder.ondrop = function (e) {
+ e.preventDefault();
+
+ var file = e.dataTransfer.files[0],
+ reader = new FileReader();
+ reader.onload = function (event) {
+ // put JS in the JavaScript panel
+ var type = file.type ? file.type.toLowerCase().replace(/^(text|application)\//, '') : file.name.toLowerCase().replace(/.*\./g, ''),
+ panelId = 'html',
+ panel = editors[panelId],
+ syncCode = event.target.result,
+ scroller = null;
+
+ if (jstypes[type]) {
+ panelId = 'javascript';
+ } else if (csstypes[type]) {
+ panelId = 'css';
+ }
+
+ panel = editors[panelId];
+ scroller = panel.editor.scroller;
+
+ panel.setCode(event.target.result);
+ panel.show();
+
+ try {
+ // now kick off - basically just doing a copy and paste job from @wookiehangover - thanks man! :)
+ var worker = new Worker(jsbin.root + '/js/editors/sync-worker.js');
+
+ // pass the worker the file object
+ worker.postMessage(file);
+
+ panel.$el.find('> .label').append(' (live: edit & save in your fav editor) ');
+
+ // bind onmessage handler
+ worker.onmessage = function (event) {
+ var top = scroller.scrollTop;
+ panel.setCode(event.data.body);
+ scroller.scrollTop = top;
+ syncCode = event.data.body;
+ };
+
+ /* FIXME for now, there's a bug in CodeMirror 2 whereby binding the
+ onKeyEvent causes all cursor keys to be ate :( */
+ // panel.editor.setOption('onKeyEvent', function (event) {
+ // if (syncCode !== panel.editor.getCode()) {
+ // worker.terminate();
+ // console.log('terminate');
+ // panel.$el.find('> .label small').remove();
+ // panel.editor.setOption('onKeyEvent', function () { return true });
+ // }
+ // return event;
+ // });
+ } catch (e) {
+ // fail on the awesomeness...oh well
+ }
+ };
+
+ reader.readAsText(file);
+
+ return false;
+ };
+}
+
+// test for dnd and file api first
+if (!!(window.File && window.FileList && window.FileReader)) allowDrop(document.body);
+;var Gist = (function () { // jshint ignore:line
+ /*global $:true, jsbin:true, processors:true, $document*/
+ 'use strict';
+
+ // Only allow gist import/export if CORS is supported
+ var CORS = !!('withCredentials' in new XMLHttpRequest() ||
+ typeof XDomainRequest !== 'undefined');
+ if (!CORS) {
+ return $(function () {
+ $('#export-as-gist').remove();
+ });
+ }
+
+ var Gist = function (id) {
+ var gist = this,
+ token = '';
+ gist.code = {};
+ if (jsbin.user && jsbin.user.github_token) { // jshint ignore:line
+ token = '?access_token=' + jsbin.user.github_token; // jshint ignore:line
+ }
+ $.get('https://api.github.com/gists/' + id + token, function (data) {
+ if (!data) {return;}
+ $.each(data.files, function (fileName, fileData) {
+ var ext = fileName.split('.').slice(-1).join('');
+ gist.code[ext] = fileData.content;
+ });
+ gist.setCode();
+ });
+ return this;
+ };
+
+ Gist.prototype.setCode = function () {
+ var gist = this;
+ $.each(gist.code, function (ext, data) {
+ var processorInit = jsbin.processors.findByExtension(ext),
+ target = processorInit.target || processorInit.id,
+ panel = jsbin.panels.panels[target];
+ if (!panel) {return;}
+ processors.set(target, processorInit.id);
+ jsbin.saveDisabled = true;
+ panel.setCode(data);
+ jsbin.saveDisabled = false;
+ });
+ };
+
+ /**
+ * Export as gist
+ */
+
+ $('a.export-as-gist').click(function () {
+ var gist = {
+ public: true,
+ files: {}
+ };
+ var panels = [
+ { panel: 'html' },
+ { panel: 'css' },
+ { panel: 'javascript', extension: 'js' }
+ ];
+
+ // Add files to gist for each panel
+ panels.forEach(function (data) {
+ var code;
+ try {
+ code = jsbin.panels.panels[data.panel].getCode();
+ } catch(e) {}
+ if (!code || !code.length) {return;}
+ // Figure out what the file extension should be according to the processor
+ var ext = data.extension || data.panel,
+ processor = jsbin.panels.panels[data.panel].processor;
+ if (processor && processor.extensions) {
+ ext = processor.extensions[0] || processor.name;
+ }
+ // Build a file name
+ var file = ['jsbin', (jsbin.state.code || 'untitled'), ext].join('.');
+ gist.files[file] = {
+ content: code
+ };
+ });
+
+ var token = '';
+ if (jsbin.user && jsbin.user.github_token) { // jshint ignore:line
+ token = '?access_token=' + jsbin.user.github_token; // jshint ignore:line
+ }
+
+ $.ajax({
+ type: 'POST',
+ url: 'https://api.github.com/gists' + token,
+ data: JSON.stringify(gist),
+ dataType: 'json',
+ crossDomain: true,
+ success: function (data) {
+ $document.trigger('tip', {
+ type: 'notification',
+ content: 'Gist created! Open in new tab. ' // jshint ignore:line
+ });
+ },
+ error: function (xhr, status) {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'Error: ' + status
+ });
+ }
+ });
+ // return false becuase there's weird even stuff going on. ask @rem.
+ return false;
+ });
+
+ return Gist;
+
+}());
+;function spinner(element) {
+ 'use strict';
+ var c = element || document.createElement('canvas');
+ if (!c.getContext) {
+ return false;
+ }
+ var ctx = c.getContext('2d');
+
+ var rafID = null;
+
+ c.height = c.width = 11;
+
+ var TORADIAN = Math.PI / 180;
+ var w = c.width;
+ var h = c.height;
+ var deg = 0;
+ var r = 4;
+ var speed = 4;
+ var tailspeed = 1/7;
+
+ ctx.strokeStyle = 'rgba(0,0,0,.5)';
+ ctx.lineWidth = 1.5;
+
+ var last = true;
+ function draw() {
+ rafID = window.requestAnimationFrame(draw);
+
+ deg += speed;
+
+ var start = ((deg * tailspeed)) % 360; // A / TAIL
+ var end = deg % 360; // B / HEAD
+ var flip = end === start;
+
+ if (flip) {
+ last = !last;
+ // this prevents a single blank frame when
+ // the start and end have the same value
+ start -= 1;
+ }
+
+ ctx.fillStyle = 'white';
+ ctx.strokeStyle = '#111';
+ ctx.fillRect(w/2 - r*2, h/2 - r*2, r * 4, r * 4);
+ ctx.beginPath();
+ ctx.arc(w/2 + 0.5, h/2 + 0.5, r, start * TORADIAN, end * TORADIAN, last);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#999';
+ ctx.beginPath();
+ ctx.arc(w/2 + 0.5, h/2 + 0.5, r, end * TORADIAN, start * TORADIAN, last);
+ ctx.stroke();
+
+ ctx.closePath();
+
+ }
+
+ return {
+ element: c,
+ start: draw,
+ stop: function () {
+ window.cancelAnimationFrame(rafID);
+ }
+ };
+};(function () {
+ /*global $:true, jsbin:true, prettyDate:true, EventSource:true, throttle:true, $document:true*/
+ 'use strict';
+
+ // don't insert this on embeded views
+ if (jsbin.embed) {
+ return;
+ }
+
+ var $template = $('#infocard'); // donkey way of cloning from template
+ var $header = $template.find('header');
+ var canvas = $header.find('canvas')[0];
+ var s = spinner(canvas);
+
+ if ($template.length === 0) {
+ return;
+ }
+
+ function updateInfoCard(event) {
+ var meta = jsbin.state.metadata || {};
+ var classes = [];
+ var es = null;
+ var owner = false;
+
+ if (meta.name) {
+ $header.find('.name b').html(meta.name);
+ $header.find('img').attr('src', meta.avatar);
+ classes.push(meta.name);
+ }
+
+ if (jsbin.state.checksum || (jsbin.user && (meta.name === jsbin.user.name))) {
+ owner = true;
+ classes.push('author');
+ }
+
+ if (s) {
+ s.stop();
+ }
+
+ if (!jsbin.state.streaming || owner === true) {
+ $header.find('time').html(event ? 'just now' : prettyDate(meta.last_updated));
+ } else if (owner === false) {
+ $header.find('time').html('Streaming');
+ classes.push('streaming');
+ if (s) {
+ s.start();
+ }
+ }
+
+ if (!jsbin.checksum) {
+ classes.push('meta');
+ }
+
+ if (meta.pro) {
+ classes.push('pro');
+ }
+
+ $header.find('.visibility').text(meta.visibility);
+
+ if (meta.visibility === 'private') {
+ classes.push('private');
+ } else if (meta.visibility === 'public') {
+ classes.push('public');
+ } // TODO handle team
+
+ if (jsbin.state.code) {
+ $template.addClass(classes.join(' ')).parent().removeAttr('hidden');
+
+ $header.click(function (e) {
+ e.preventDefault();
+ $template.toggleClass('open');
+ });
+
+ var viewers = 0;
+
+ if (jsbin.state.streaming) {
+ if (window.EventSource && owner) {
+ listenStats();
+ var url = jsbin.getURL();
+ $document.on('saved', function () {
+ var newurl = window.location.toString();
+ if (url !== newurl) {
+ es.close();
+ listenStats();
+ }
+ });
+ } else if (jsbin.saveDisabled === true && window.location.pathname.slice(-5) === '/edit') {
+ $.getScript(jsbin.static + '/js/spike.js?' + jsbin.version);
+ $document.on('stats', throttle(updateStats, 1000));
+ }
+ }
+ }
+
+ function updateStats(event, _data) {
+ var data = _data ? JSON.parse(_data) : JSON.parse(event.data);
+
+ if (data.connections > 0 && viewers === 0) {
+ $template.addClass('viewers');
+ }
+
+ if (viewers !== data.connections) {
+ var $b = $header.find('.viewers b').removeClass('up down').html('' + data.connections + ' ' + viewers + ' ' + data.connections + ' '),
+ c = viewers > data.connections ? 'down' : 'up';
+ setTimeout(function () {
+ $b.addClass(c);
+ }, 0);
+ }
+
+ viewers = data.connections;
+
+ if (viewers === 0) {
+ setTimeout(function () {
+ $template.removeClass('viewers');
+ }, 250);
+ }
+
+ }
+
+ function listenStats() {
+ es = new EventSource(jsbin.getURL() + '/stats?checksum=' + jsbin.state.checksum);
+ es.addEventListener('stats', throttle(updateStats, 1000));
+ }
+ }
+
+ updateInfoCard();
+ $document.bind('saved', updateInfoCard);
+})();
+;(function () {
+ 'use strict';
+
+ function getExpires() {
+ var d = new Date();
+
+ // expires in 1 hour from now
+ d.setTime(+d + 1000 * 60 * 60);
+ return d.toUTCString();
+ }
+
+ function save() {
+ var url = jsbin.getURL(true) + '/edit';
+ if (url) {
+ document.cookie = 'last=' + encodeURIComponent(url) + '; expires=' + getExpires() + '; path=/';
+ } else {
+ // expire cookie
+ document.cookie = 'last=""; expires=-1; path=/';
+ }
+ }
+
+ function readCookie(name) {
+ var nameEQ = name + '=';
+ var ca = document.cookie.split(';');
+ for(var i=0;i < ca.length;i++) {
+ var c = ca[i];
+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
+ }
+ return null;
+ }
+
+ function updateBackButton() {
+ var el = document.getElementById('back');
+ var back = readCookie('last');
+
+ if (el && back !== null && back !== '%2Fedit') {
+ el.href = decodeURIComponent(back);
+ }
+ }
+
+ // save the bin url when the bin is saved, changed and when we load first time
+ if (jsbin && jsbin.getURL) {
+ $document.on('saved', save);
+ save();
+ } else {
+ updateBackButton();
+ }
+})();;function archive(unarchive) {
+ /*global jsbin, $, $document, analytics*/
+ 'use strict';
+ var type = unarchive === false ? 'unarchive' : 'archive';
+ var text = unarchive === false ? 'restore from archive' : 'archiving';
+ analytics[type](jsbin.getURL());
+ if (!jsbin.user.name) {
+ $document.trigger('tip', {
+ type: 'notication',
+ content: 'You must be logged in and the owner of the bin to archive.'
+ });
+ } else if (jsbin.owner()) {
+ $.ajax({
+ type: 'POST',
+ url: jsbin.getURL() + '/' + type,
+ error: function () {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'The ' + text + ' failed. If this continues, please can you file an issue?'
+ });
+ },
+ success: function () {
+ jsbin.state.metadata.archive = unarchive !== false;
+ updateArchiveMenu();
+ $document.trigger('tip', {
+ type: 'notication',
+ autohide: 5000,
+ content: 'This bin is now ' + (unarchive === false ? 'restored from the archive.' : 'archived.')
+ });
+ }
+ });
+ } else {
+ $document.trigger('tip', {
+ type: 'notication',
+ content: 'The ' + text + ' failed. You can only archive bins that you own.'
+ });
+ }
+}
+
+function updateArchiveMenu() {
+ if (jsbin.state.metadata && jsbin.state.metadata.archive) {
+ $('a.archivebin').hide();
+ $('a.unarchivebin').show();
+ } else {
+ $('a.archivebin').show();
+ $('a.unarchivebin').hide();
+ }
+}
+
+updateArchiveMenu();
+
+var unarchive = archive.bind(null, false);;(function () {
+ /*global jsbin, $, $body, $document, analytics, settings*/
+ 'use strict';
+
+ if (!$('#toppanel').length) {
+ return;
+ }
+
+ if (jsbin.settings.gui === undefined) {
+ jsbin.settings.gui = {};
+ }
+ if (jsbin.settings.gui.toppanel === undefined) {
+ jsbin.settings.gui.toppanel = true;
+ localStorage.setItem('settings', JSON.stringify(jsbin.settings));
+ }
+
+ if ($body.hasClass('toppanel') && jsbin.settings.gui.toppanel === false) {
+ $body.addClass('toppanel-close');
+ $body.removeClass('toppanel');
+ }
+
+ // analytics for panel state
+ analytics.welcomePanelState(jsbin.settings.gui.toppanel);
+
+ var removeToppanel = function() {
+ jsbin.settings.gui.toppanel = false;
+ settings.save();
+ $body.addClass('toppanel-close');
+ $body.removeClass('toppanel');
+ };
+
+ var showToppanel = function() {
+ jsbin.settings.gui.toppanel = true;
+ settings.save();
+ $body.removeClass('toppanel-close');
+ $body.addClass('toppanel');
+ };
+
+ // to remove
+ var goSlow = function(e) {
+ $body.removeClass('toppanel-slow');
+ if (e.shiftKey) {
+ $body.addClass('toppanel-slow');
+ }
+ };
+
+ $('.toppanel-hide').click(function(event) {
+ event.preventDefault();
+ goSlow(event);
+ removeToppanel();
+ });
+ $('.toppanel-logo').click(function(event) {
+ event.preventDefault();
+ goSlow(event);
+ showToppanel();
+ });
+ $document.keydown(function (event) {
+ if (event.which === 27) {
+ if ($body.hasClass('toppanel')) {
+ removeToppanel();
+ }
+ }
+ });
+
+ // analytics for links
+ $('#toppanel').find('.toppanel-link').mousedown(function() {
+ analytics.welcomePanelLink(this.href);
+ });
+
+}());;// if a gist has been requested, lazy load the gist library and plug it in
+if (/gist\/.*/.test(window.location.pathname)) {
+ window.editors = editors; // needs to be global when the callback triggers to set the content
+ loadGist = function () {
+ window.gist = new Gist(window.location.pathname.replace(/.*\/([^/]+)$/, "$1"));
+ };
+
+ if (editors.ready) {
+ loadGist();
+ } else {
+ $document.on('jsbinReady', loadGist);
+ }
+}
+
+// prevent the app from accidently getting scrolled out of view
+if (!jsbin.mobile) document.body.onscroll = window.onscroll = function () {
+ if (document.body.scrollTop !== 0) {
+ window.scrollTo(0,0);
+ }
+ return false;
+};
+
+window.CodeMirror = CodeMirror; // fix to allow code mirror to break naturally
+
+// These are keys that CodeMirror (and Emmet) should never take over
+// ref: https://gist.github.com/rodneyrehm/5213304
+if (CodeMirror.keyMap && CodeMirror.keyMap['default']) {
+ var cmd = $.browser.platform === 'mac' ? 'Cmd' : 'Ctrl';
+ delete CodeMirror.keyMap['default'][cmd + '-L'];
+ delete CodeMirror.keyMap['default'][cmd + '-T'];
+ delete CodeMirror.keyMap['default'][cmd + '-W'];
+ delete CodeMirror.keyMap['default'][cmd + '-J'];
+ delete CodeMirror.keyMap['default'][cmd + '-R'];
+}
+
+var link = document.createElement('link');
+link.rel = 'stylesheet';
+link.href = jsbin['static'] + '/css/font.css?' + jsbin.version;
+link.type = 'text/css';
+document.getElementsByTagName('head')[0].appendChild(link);
+
+if (jsbin.embed) {
+ analytics.embed();
+};}
\ No newline at end of file
diff --git a/public/js/prod/jsbin-3.15.3.min.js b/public/js/prod/jsbin-3.15.3.min.js
new file mode 100644
index 00000000..b3390d02
--- /dev/null
+++ b/public/js/prod/jsbin-3.15.3.min.js
@@ -0,0 +1,20 @@
+/*! jsbin - v3.15.3 - 2014-07-03 */
+function start(template,jsbin,window,document,undefined){function prettyDate(a){var b=new Date((a||"").replace(/-/g,"/").replace(/[TZ]/g," ")),c=((new Date).getTime()-b.getTime())/1e3,d=Math.floor(c/86400);if(!(isNaN(d)||0>d||d>=31))return 0==d&&(60>c&&"just now"||120>c&&"1 minute ago"||3600>c&&Math.floor(c/60)+" minutes ago"||7200>c&&"1 hour ago"||86400>c&&Math.floor(c/3600)+" hours ago")||1==d&&"Yesterday"||7>d&&d+" days ago"||31>d&&Math.ceil(d/7)+" weeks ago"}function hasStore(a){try{return a in window&&null!==window[a]}catch(b){return!1}}function throttle(a,b){var c=function(){var d=this,e=arguments;c.cancel(),c.timer=setTimeout(function(){a.apply(d,e)},b)};return c.cancel=function(){clearTimeout(c.timer)},c}function escapeHTML(a){return String(a).replace(/&(?!\w+;)/g,"&").replace(//g,">").replace(/"/g,""")}function dedupe(a){var b,c,d,e={},f=[],g=Object.prototype.hasOwnProperty;for(b=0,d=a.length;d>b;b+=1)c=a[b],g.call(e,c)||(e[c]=1,f.push(c));return f}function exposeSettings(){"use strict";if(window.jsbin instanceof Node||!window.jsbin){if(window.jsbin={"static":jsbin["static"]},jsbin.state.metadata&&jsbin.user&&jsbin.state.metadata.name===jsbin.user.name&&jsbin.user.name)return window.jsbin.settings=jsbin.settings,void 0;var a="o"+(1*Math.random()).toString(32).slice(2);Object.defineProperty(window,a,{get:function(){window.jsbin.settings=jsbin.settings,console.log("jsbin.settings can how be modified on the console")}}),console.log("To edit settings, type this string into the console: "+a)}}function objectValue(a,b){var c=a.split("."),d=c.length,e=1,f=b||window,g=f[a];try{if(f[c[0]]!==undefined)for(f=f[c[0]];d>e&&f[c[e]]!==undefined;e++)e===d-1&&(g=f[c[e]]),f=f[c[e]]}catch(h){g=undefined}return g}function sendReload(){saveChecksum&&$.ajax({url:jsbin.getURL()+"/reload",data:{code:jsbin.state.code,revision:jsbin.state.revision,checksum:saveChecksum},type:"post"})}function codeChangeLive(a,b){clearTimeout(deferredLiveRender);var c,d,e=jsbin.panels.panels.live;jsbin.panels.ready&&(jsbin.settings.includejs===!1&&"javascript"===b.panelId||e.visible&&(!jsbin.lameEditor&&jsbin.panels.focused&&"javascript"===jsbin.panels.focused.id?(c=jsbin.panels.focused.editor,d=c.getLine(c.getCursor().line),ignoreDuringLive.test(d)===!0?(throttledPreview.cancel(),deferredLiveRender=setTimeout(function(){codeChangeLive(a,b)},1e3)):throttledPreview()):throttledPreview()))}function enableAltUse(){jsbin.settings.keys||(jsbin.settings.keys={}),jsbin.settings.keys.useAlt=this.checked}function keycontrol(a){a=normalise(a);var b={};jsbin.panels.focused&&jsbin.panels.focused.editor?b=jsbin.panels.focused.editor:jsbin.panels.focused&&(b=jsbin.panels.focused);var c={css:1,javascript:1,html:1}[b.id],d=!1,e=customKeys.useAlt?a.altKey:!a.altKey;if("keydown"===a.type){if(c&&a.metaKey&&13===a.which&&(editors.console.visible&&!editors.live.visible?(d=!0,$("#runconsole").trigger("click","keyboard")):editors.live.visible?($("#runwithalerts").trigger("click","keyboard"),d=!0):($("#runwithalerts").trigger("click","keyboard"),d=!0),d?a.stop():sendReload()),panelShortcuts[a.which]!==undefined&&a.metaKey&&e)if(jsbin.panels.focused.id===panelShortcuts[a.which])jsbin.panels.hide(panelShortcuts[a.which]),a.stop();else if(jsbin.panels.show(panelShortcuts[a.which]),a.stop(),!(customKeys.useAlt||jsbin.settings.keys&&jsbin.settings.keys.seenWarning)){var f="mac"===$.browser.platform?"cmd":"ctrl";jsbin.settings.keys||(jsbin.settings.keys={}),jsbin.settings.keys.seenWarning=!0,$document.trigger("tip",{type:"notification",content:' Turn this off . Reserve '+f+"+[n] for switching browser tabs and use "+f+"+alt +[n] to switch JS Bin panels. You can access this any time in Help→Keyboard "}),$("#tip").delegate("input.enablealt","click",function(){enableAltUse.call(this),window.location.reload()})}if(191===a.which&&a.metaKey&&a.shiftKey)$body.toggleClass("keyboardHelp"),keyboardHelpVisible=$body.is(".keyboardHelp"),keyboardHelpVisible&&analytics.track("keyboard","select","help"),a.stop();else if(27===a.which&&keyboardHelpVisible)$body.removeClass("keyboardHelp"),keyboardHelpVisible=!1,a.stop();else if(27===a.which&&jsbin.panels.focused&&c);else if(190===a.which&&e&&a.metaKey&&"html"===b.id){if(b.somethingSelected())return;var g=b.getCursor(!1),h=b.getTokenAt(g),i=h;/^[\w$_]*$/.test(h.string)||(h=i={start:g.ch,end:g.ch,string:"",state:h.state,className:"."===h.string?"js-property":null}),b.replaceRange(""+h.state.htmlState.context.tagName+">",{line:g.line,ch:h.end},{line:g.line,ch:h.end}),a.stop()}else if(188===a.which&&a.ctrlKey&&a.shiftKey&&c)return a.stop(),startTagComplete(b)}return a.stopping?!1:void 0}function normalise(a){var b={type:a.type,which:a.which,metaKey:a.metaKey,shiftKey:a.shiftKey,ctrlKey:a.ctrlKey,altKey:a.altKey,orig:a};null!==a.which||null===a.charCode&&null===a.keyCode||(b.which=null!==a.charCode?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(b.metaKey=a.ctrlKey),0===a.which&&a.ctrlKey===!0&&a.shiftKey===!0&&"keydown"===a.type&&(b.which=191);var c=a.stop;return b.stop=function(){b.stopping=!0,c&&c.call(a)},b}function upgradeConsolePanel(a){a.$el.click(function(a){$(a.target).closest("#output").length||jsconsole.focus()}),a.reset=function(){jsconsole.reset()},a.settings.render=function(a){var b=editors.html.render().trim();if(""===b){var c=editors.javascript.render().trim(),d=getPreparedCode().replace(//,"").replace(/<\/pre>/,"");renderer.postMessage("render",{source:""}),setTimeout(function(){jsconsole.run({echo:c,cmd:d})},0)}else renderLivePreview(a||!1)},a.settings.show=function(){jsconsole.clear(),setTimeout(function(){editors.console.ready&&!jsbin.embed&&jsconsole.focus()},0)},a.settings.hide=function(){!editors.live.visible},$document.one("jsbinReady",function(){var a=function(){$("#runconsole")[this.visible?"hide":"show"]()};jsbin.panels.panels.live.on("show",a).on("hide",a),jsbin.panels.panels.live.visible&&$("#runconsole").hide()})}function populateEditor(a,b){if(a.codeSet)f=!0;else{var c=sessionStorage.getItem("jsbin.content."+b),d=localStorage.getItem("saved-"+b),e=sessionStorage.getItem("url"),f=!1;e===jsbin.getURL()||jsbin.state.checksum||(sessionStorage.removeItem("checksum"),saveChecksum=!1),template&&c==template[b]?a.setCode(c):c&&e==jsbin.getURL()?(a.setCode(c),f=c!=d&&c!=template[b]):template.post||null===d||/edit/.test(window.location)||window.location.search?a.setCode(template[b]):a.setCode(d)}f&&$document.trigger("codeChange",[{revert:!1,onload:!0}])}function getQuery(a){var b="&",c="=",d={},e=/\+/g;a=a.split(b);var f=1e3,g=a.length;f>0&&g>f&&(g=f);for(var h=0;g>h;++h){var i,j,k,l,m=a[h].replace(e,"%20"),n=m.indexOf(c);n>=0?(i=m.substr(0,n),j=m.substr(n+1)):(i=m,j="");try{k=decodeURIComponent(i),l=decodeURIComponent(j)}catch(o){k=i,l=j}(window.hasOwnProperty?window.hasOwnProperty(d,k):d.hasOwnProperty(k))?$.isArray(d[k])?d[k].push(l):d[k]=[d[k],l]:d[k]=l}return d}function insertResources(a){$.isArray(a)||(a=[a]);var b,c,d,e=0,f=a.length,g="",h=editors.html.getCode(),i={line:editors.html.editor.currentLine(),character:editors.html.editor.getCursor().ch,add:0},j=[],k="",l={},m={rel:"stylesheet",type:"text/css"};for(e=0;f>e;e++){g=a[e],$.isPlainObject(g)?(d=g,g=g.url,delete d.url):d={},k=g.split("/").pop(),d=$.extend({},isCssFile(k)?m:l,d),c="";for(var n in d)c+=" "+n+'="'+d[n]+'"';k&&h.indexOf(k+'"')&&(h=isCssFile(k)?h.replace(new RegExp(' \n?'),""):h.replace(new RegExp('<'+"/script>\n?"),""),i.add--),b=isCssFile(g)?' ":'\n"+g}if(a.console.test(d)){var m="window.runnerWindow.proxyConsole.";d=d.replace(a.console,function(a,b,c,e){var f=d.lastIndexOf("'},{url:["http://jashkenas.github.io/underscore/underscore-min.js","http://jashkenas.github.io/backbone/backbone-min.js"],label:"Backbone latest"},{url:["http://jashkenas.github.io/underscore/underscore-min.js","http://jashkenas.github.io/backbone/backbone-min.js","http://marionettejs.com/downloads/backbone.marionette.min.js"],label:"MarionetteJS latest"},{url:"http://cdnjs.cloudflare.com/ajax/libs/bonsai/0.4/bonsai.min.js",label:"Bonsai 0.4.latest"},{url:"http://jashkenas.github.io/coffee-script/extras/coffee-script.js",label:"CoffeeScript"},{url:["http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js","http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js","http://builds.emberjs.com.s3.amazonaws.com/tags/v1.0.0/ember.js"],label:"Ember.js 1.0.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/es5-shim/2.0.8/es5-shim.min.js",label:"ES5 shim 2.0.8"},{url:["http://extjs.cachefly.net/ext-3.1.0/resources/css/ext-all.css","http://cdnjs.cloudflare.com/ajax/libs/ext-core/3.1.0/ext-core.min.js"],label:"ext-core 3.1.0"},{url:["http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/css/normalize.min.css","http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/css/foundation.min.css","http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/js/vendor/jquery.min.js","http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/js/foundation.min.js"],label:"Foundation 5.0.3"},{url:"http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js",label:"Handlebars.js 1.0.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js",label:"Knockout 3.0.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/less.js/1.3.3/less.min.js",label:"Less 1.3.3"},{url:"http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js",label:"Lo-Dash 2.4.1"},{url:"http://modernizr.com/downloads/modernizr-latest.js",label:"Modernizr Development latest"},{url:["http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js","http://cdnjs.cloudflare.com/ajax/libs/detectizr/1.5.0/detectizr.min.js"],label:"Detectizr 1.5.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js",label:"Prefixfree 1.0.7"},{url:"http://cdnjs.cloudflare.com/ajax/libs/processing.js/1.4.1/processing-api.min.js",label:"Processing 1.4.1"},{url:"http://d3js.org/d3.v3.min.js",label:"D3 3.x"},{url:"//code.highcharts.com/highcharts.js",label:"Highcharts latest"},{url:"http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js",label:"Raphaël 2.1.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/sammy.js/0.7.4/sammy.min.js",label:"Sammy 0.7.4"},{url:["http://cdn.sencha.io/touch/1.1.0/resources/css/sencha-touch.css","http://cdn.sencha.io/touch/1.1.0/sencha-touch.js"],label:"Sencha Touch"},{url:[jsbin.static+"/js/vendor/traceur.js"],label:"Traceur"},{url:"http://remy.github.io/twitterlib/twitterlib.min.js",label:"TwitterLib"},{url:"http://jashkenas.github.io/underscore/underscore-min.js",label:"underscore"},{url:["http://code.jquery.com/jquery.min.js","//canjs.com/release/2.0.3/can.jquery.min.js"],label:"CanJS 2.0.3"},{url:["http://cdnjs.cloudflare.com/ajax/libs/three.js/r61/three.min.js"],label:"Three.js r61"},{url:["http://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.2/html5shiv.js"],label:"HTML5 shiv"},{url:["http://lungo.tapquo.com/demo/components/lungo/lungo.css","http://lungo.tapquo.com/demo/components/lungo/lungo.theme.css","http://lungo.tapquo.com/demo/components/lungo/lungo.icon.css","http://lungo.tapquo.com/demo/components/quojs/quo.js","http://lungo.tapquo.com/demo/components/lungo/lungo.js"],label:"Lungo"},{url:["//cdnjs.cloudflare.com/ajax/libs/polymer/0.3.3/platform.js","//cdnjs.cloudflare.com/ajax/libs/polymer/0.3.3/polymer.js"],label:"Polymer 0.3.3"},{url:"//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css",label:"Font Awesome 4.0.3"},{url:"//cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.12/paper.js",label:"Paper.js 0.9.12"},{url:{url:"https://openui5.hana.ondemand.com/resources/sap-ui-core.js",id:"sap-ui-bootstrap","data-sap-ui-theme":"sap_bluecrystal","data-sap-ui-libs":"sap.m"},label:"OpenUI5 1.18.8 Mobile BlueCrystal"},{url:"http://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.7/TweenMax.min.js",label:"GSAP 1.11.7"},{url:"//cdnjs.cloudflare.com/ajax/libs/phaser/2.0.5/phaser.min.js",label:"Phaser 2.0.5"}];window.libraries=libraries,libraries.userSpecified=JSON.parse(localStorage.getItem("libraries")||"[]");for(var i=0;ib;b++)"Custom"===libraries[b].group&&(libraries.splice(b,1),a--);$("#library").trigger("init")};var $library=$("#library"),groups={};$library.bind("init",function(){var a=0,b=0,c={},d=[],e={},f="",g="";for(groups={},$library.empty(),a=0;aNone'];for(a=0;a-------------'),b=0;b'+c.label+"");$library.html(h.join(""))}).trigger("init"),$library.bind("change",function(){if(this.value){var a=this.value.split(":"),b=groups[a[0]],c=b.libraries[a[1]];analytics.library("select",b.libraries[a[1]].label),insertResources(c.url),c.snippet&&insertSnippet(c.snippet)}}).on("click",function(){analytics.library("open")});var htmlScriptToJade=createHTMLToJadeTagConverter("script","src","js"),htmlLinkToJade=function(){var a=createHTMLToJadeTagConverter("link","href","css");return function(b){var c=a(b);return c.split('" ').join('",')}}();!function(){"use strict";if(jsbin.settings.addons.tern){var a,b={},c=function(b,c){var d={"Ctrl-Q":function(b){a.selectName(b)},"Ctrl-I":function(b){a.showType(b)},"Ctrl-Space":function(b){a.complete(b)}};"undefined"==typeof c&&(c=[]),a=new CodeMirror.TernServer({defs:c,useWorker:!1,cm:b}),b.addKeyMap(d),b.on("cursorActivity",function(b){a.updateArgHints(b)})},d=function(b){"object"==typeof a&&(a.options.defs.push(b),a=new CodeMirror.TernServer({defs:a.options.defs,useWorker:a.options.useWorker,tooltipType:a.options.tooltipType,cm:a.options.cm}))},e=function(a,c){b[a]||$.ajax({url:c,dataType:"json",success:function(c){d(c),b[a]=!0}})},f=function(c,d){b[c]||$.ajax({url:d,dataType:"script",success:function(d){a.server.addFile(c,d),b[c]=!0}})},g=function(a){c(a,ternBasicDefs),b.ecma5=!0,b.browser=!0},h=function(a){for(var b=0;b'),b.resolve()},0),b}}function b(a){var b=$.Deferred(),c=null;return a()?b.resolve():c=setInterval(function(){a()&&(clearInterval(c),b.resolve())},100),b}function c(a,b,c){a.setOption(b,c)}function d(a){return function(){return"undefined"!=typeof CodeMirror.optionHandlers[a]}}function e(a){return"undefined"!=typeof CodeMirror.defaults.lint&&CodeMirror.helpers.lint&&CodeMirror.helpers.lint[a]&&CodeMirror.optionHandlers.lint}function f(c){var d=m[c];d&&l[c]&&("string"==typeof d.url&&(d.url=[d.url]),$.when.call($,d.url.map(a)).done(function(){d.done&&b(d.test).then(function(){jsbin.panels.allEditors(function(a){a.editor&&d.done(a.editor)})})}))}var g={closebrackets:!0,highlight:!1,vim:!1,emacs:!1,trailingspace:!1,fold:!1,sublime:!1,tern:!1,activeline:!0,matchbrackets:!1};jsbin.settings.addons||(jsbin.settings.addons=g);var h="open"in document.createElement("details"),i={},j={},k={console:!0,line:!1,under:!1,gutter:!1};["js","html","coffeescript","css"].forEach(function(a){var b=a+"hint",c=!1;"js"===a&&(c=!0),i[b]=jsbin.settings[b]!==undefined?jsbin.settings[b]:c}),j=$.extend({},k,jsbin.settings.hintShow),j.tooltip=j.gutter;var l=$.extend({},jsbin.settings.addons,i),m={closebrackets:{url:"/js/vendor/codemirror4/addon/edit/closebrackets.js",test:d("autoCloseBrackets"),done:function(a){c(a,"autoCloseBrackets",!0)}},highlight:{url:"/js/vendor/codemirror4/addon/search/match-highlighter.js",test:d("highlightSelectionMatches"),done:function(a){c(a,"highlightSelectionMatches",!0)}},vim:{url:["/js/vendor/codemirror4/addon/dialog/dialog.css","/js/vendor/codemirror4/keymap/vim.js","/js/vendor/codemirror4/addon/dialog/dialog.js"],test:d("vimMode"),done:function(a){c(a,"vimMode",!0),c(a,"showCursorWhenSelecting",!0)}},emacs:{url:["/js/vendor/codemirror4/addon/dialog/dialog.css","/js/vendor/codemirror4/keymap/emacs.js","/js/vendor/codemirror4/addon/dialog/dialog.js","/js/vendor/codemirror4/addon/search/search.js"],test:function(){return jsbin.panels.panels.javascript.editor.openDialog&&CodeMirror.commands.find&&CodeMirror.keyMap.emacs},done:function(a){c(a,"keyMap","emacs")}},matchtags:{url:["/js/vendor/codemirror4/addon/fold/xml-fold.js","/js/vendor/codemirror4/addon/edit/matchtags.js"],test:function(){return CodeMirror.scanForClosingTag&&CodeMirror.optionHandlers.matchTags},done:function(a){c(a,"matchTags",{bothTags:!0}),a.addKeyMap({"Ctrl-J":"toMatchingTag"})}},trailingspace:{url:"/js/vendor/codemirror4/addon/edit/trailingspace.js",test:d("showTrailingSpace"),done:function(a){c(a,"showTrailingSpace",!0)}},fold:{url:["/js/vendor/codemirror4/addon/fold/foldgutter.css","/js/vendor/codemirror4/addon/fold/foldcode.js","/js/vendor/codemirror4/addon/fold/foldgutter.js","/js/vendor/codemirror4/addon/fold/brace-fold.js","/js/vendor/codemirror4/addon/fold/xml-fold.js","/js/vendor/codemirror4/addon/fold/comment-fold.js"],test:function(){return CodeMirror.helpers.fold&&CodeMirror.optionHandlers.foldGutter&&CodeMirror.optionHandlers.gutters},done:function(a){n.addClass("code-fold"),a.addKeyMap({"Ctrl-Q":function(a){a.foldCode(a.getCursor())}}),c(a,"foldGutter",!0);var b=a.getOption("gutters");b.push("CodeMirror-linenumbers"),b.push("CodeMirror-foldgutter"),c(a,"gutters",b)}},sublime:{url:["/js/vendor/codemirror4/addon/dialog/dialog.css","/js/vendor/codemirror4/keymap/sublime.js","/js/vendor/codemirror4/addon/dialog/dialog.js","/js/vendor/codemirror4/addon/search/search.js"],test:function(){return jsbin.panels.panels.javascript.editor.openDialog&&CodeMirror.commands.find&&CodeMirror.keyMap.sublime},done:function(a){c(a,"keyMap","sublime");var b="mac"===$.browser.platform?"Cmd":"Ctrl";delete CodeMirror.keyMap.sublime[b+"-L"],delete CodeMirror.keyMap.sublime[b+"-T"],delete CodeMirror.keyMap.sublime[b+"-W"],delete CodeMirror.keyMap.sublime[b+"-J"],delete CodeMirror.keyMap.sublime[b+"-R"],delete CodeMirror.keyMap.sublime[b+"-Enter"],delete CodeMirror.keyMap.sublime[b+"-Up"],delete CodeMirror.keyMap.sublime[b+"-Down"],a.removeKeyMap("noEmmet")}},tern:{url:["/js/vendor/codemirror4/addon/dialog/dialog.css","/js/vendor/codemirror4/addon/hint/show-hint.css","/js/vendor/codemirror4/addon/tern/tern.css","/js/vendor/codemirror4/addon/hint/show-hint.js","/js/vendor/codemirror4/addon/dialog/dialog.js","/js/prod/addon-tern-"+jsbin.version+".min.js"],test:function(){return jsbin.panels.panels.javascript.editor.openDialog&&"undefined"!=typeof window.ternBasicDefs&&CodeMirror.showHint&&CodeMirror.TernServer&&CodeMirror.startTern},done:function(){CodeMirror.startTern()}},activeline:{url:["/js/vendor/codemirror4/addon/selection/active-line.js"],test:function(){return"undefined"!=typeof CodeMirror.defaults.styleActiveLine},done:function(a){c(a,"styleActiveLine",!0)}},matchbrackets:{url:[],test:function(){return"undefined"!=typeof CodeMirror.defaults.matchBrackets},done:function(a){c(a,"matchBrackets",!0)}},csshint:{url:["/js/vendor/csslint/csslint.min.js","/js/vendor/cm_addons/lint/css-lint.js"],test:function(){return e("css")&&"undefined"!=typeof CSSLint},done:function(a){"css"===a.getOption("mode")&&hintingDone(a)}},jshint:{url:[],test:function(){return e("javascript")&&"undefined"!=typeof JSHINT},done:function(a){"javascript"===a.getOption("mode")&&hintingDone(a,{eqnull:!0})}},htmlhint:{url:["/js/vendor/htmlhint/htmlhint.js","/js/vendor/cm_addons/lint/html-lint.js"],test:function(){return e("htmlmixed")&&"undefined"!=typeof HTMLHint},done:function(a){"htmlmixed"===a.getOption("mode")&&hintingDone(a)}},coffeescripthint:{url:["/js/vendor/coffeelint/coffeelint.min.js","/js/vendor/cm_addons/lint/coffeescript-lint.js"],test:function(){return e("coffeescript")&&"undefined"!=typeof coffeelint},done:function(a){"coffeescript"===a.getOption("mode")&&hintingDone(a)}}},n=$("body");window.hintingDone=function(a,b){var d=a.getOption("mode");"javascript"===d&&(d="js"),"htmlmixed"===d&&(d="html");var e=$.extend({},j);if(e.consoleParent=a.getWrapperElement().parentNode.parentNode,c(a,"lintOpt",e),c(a,"lintRules",$.extend({},b,jsbin.settings[d+"hintOptions"])),e.gutter){var f=a.getOption("gutters");-1===f.indexOf("CodeMirror-lint-markers")&&(f.push("CodeMirror-lint-markers"),c(a,"gutters",f)),c(a,"lint",!0);var g=a.getOption("lineNumbers");c(a,"lineNumbers",!g),c(a,"lineNumbers",g)}else c(a,"lint",!0);e.console&&($document.trigger("sizeeditors"),$(a.consolelint.head).on("click",function(){h||$(this).nextAll().toggle(),setTimeout(function(){$document.trigger("sizeeditors")},10)}))};var o=Object.keys(l);o.forEach(f),window.reloadAddons=function(a){a?a.forEach(f):o.forEach(f)}}(),function(){var a,b=$("body"),c=!1;$document.on("history:open",function(){a&&0===jsbin.panels.getVisible().length&&a.appendTo("body")}).on("history:close",function(){null===a&&(a=$("#history").detach())});var d=function(){c||($("html").hasClass("public-listing")?h():$.ajax({dataType:"html",url:jsbin.root+"/list",error:function(){$("#history").remove(),setTimeout(d,500)},success:function(a){$("#history").remove(),b.append(a),h(),c=!0}}))},e=function(a,b){b.attr("src",a+"/quiet"),b.removeAttr("hidden")},f=function(a,b){b.text(a)},g=function(a,b){var c=a.parent();a.detach().each(function(){var a=$(this),c=b?".archived":":not(.archived)",d=$("tr"+c,a).filter(":not(.spacer)");d.length>0?(d.filter(".first").removeClass("first"),a.removeClass("hidden"),d.first().addClass("first")):a.addClass("hidden")}).appendTo(c)},h=function(){if(a=$("#history").detach(),!a.length)return a;var b=$("iframe",a),c=$("#viewing",a),d=a,h=$("tbody",a),i=$("tr",a),j=$("td.created a",a),k=$(".toggle_archive",a),l=null,m=null;return d.delegate("tr:not(.spacer)","click",function(){event.shiftKey||event.metaKey||(window.location=this.getAttribute("data-edit-url"))}),d.delegate(".archive, .unarchive","click",function(){var b=$(this),c=b.parents("tr");return c.toggleClass("archived"),analytics[-1===this.pathname.indexOf("unarchive")?"archive":"unarchive"](jsbin.root+c.data("url")),g(h,a.hasClass("archive_mode")),$.ajax({type:"POST",url:b.attr("href"),error:function(){alert("Something went wrong, please try again"),c.toggleClass("archived"),g(h,a.hasClass("archive_mode"))},success:function(){}}),!1}),k.change(function(){a.toggleClass("archive_mode");var b=a.hasClass("archive_mode");analytics.archiveView(b),g(h,b)}),d.delegate("tr","mouseover",function(){var a=$(this),d=a.attr("data-url");return clearTimeout(m),a.hasClass("spacer")||l===d||(m=setTimeout(function(){i.removeClass("selected"),a.addClass("selected"),l=d,e(d,b),f(d,c)},400)),!1}),$("a[pubdate]",a).attr("pubdate",function(a,b){return b.replace("Z","+0000")}).prettyDate(),setInterval(function(){j.prettyDate()},3e4),setTimeout(function(){g(h,!1)},0),$document.trigger("history:open"),a};$(document).on("jsbinReady",function(){if(!jsbin.embed){var a=$("#panels a"),c=$(".homebtn"),e=b.hasClass("panelsVisible"),f=function(){var b=a.filter(".active").length;1===b&&$(this).hasClass("active")&&d()};c.on("click",d),a.on("mousedown",f),e||d()}})}();var loginVisible=!1,dropdownOpen=!1,keyboardHelpVisible=!1,urlHelpVisible=!1;$document.keydown(function(a){27==a.which&&hideOpen()}),$document.delegate(".modal","click",function(a){$(a.target).is(".modal")&&hideOpen()});var githubIssue=function(){"use strict";function a(){var a="http://github.com/jsbin/jsbin/issues/new",b=["Please provide any additional information, record a screencast ","with http://quickcast.io or http://screenr.com and attach a screenshot ","if possible.\n\n**JS Bin info**\n\n* [%url%](%url%)\n* ",window.navigator.userAgent+"\n",jsbin.user&&jsbin.user.name?"* "+jsbin.user.name:"","\n"].join("");
+return a+"?body="+encodeURIComponent(b.replace(/%url%/g,jsbin.getURL()))}var b=$("#newissue");return $("#help").parent().on("open",function(){b.attr("href",a())}),a}();$("#download").click(function(a){a.preventDefault(),window.location=jsbin.getURL()+"/download",analytics.download()}),$("form.login").submit(function(a){"use strict";a.preventDefault();var b=$(this),c=b.find("input[name=username]").val(),d=b.find("input[name=password]").val(),e=b.find("input[name=email]").val(),f=b.find(".loginFeedback");f.show().text("Checking..."),$.ajax({url:b.attr("action"),data:{username:c,key:d,email:e},type:"POST",dataType:"json",complete:function(a){var b=$.parseJSON(a.responseText)||{};200===a.status?(b.avatar&&$("a.avatar").find("img").remove().end().prepend(' '),b.message?f.text(b.message):window.location=window.location.pathname+window.location.search):(analytics.login(!1),f.text(b.message||'"'+c+'" has already been taken. Please either double check the password, or choose another username.'))}})}),function(){var a,b=$(document.documentElement),c=$("#tip"),d=$("p",c),e=function(a){b.removeClass("showtip"),c.removeClass(),d.html(""),$(window).resize(),a&&setTimeout(a,0)},f=function(f){clearTimeout(a),d.html(f.content),c.removeClass().addClass(f.type||"info"),b.addClass("showtip"),f.autohide&&(a=setTimeout(function(){e()},parseInt(f.autohide,10)||5e3))};$document.on("tip",function(a,b){var g=b;return"string"==typeof b&&(g={},g.content=b,g.type="info"),d.html()===g.content&&c.hasClass(g.type)?f(b):(e(function(){f(g)}),void 0)}),$("#tip").on("click","a.dismiss",function(){return e(),!1}),$document.keydown(function(a){27==a.which&&e()})}();var saving={todo:{html:!1,css:!1,javascript:!1},_inprogress:!1,inprogress:function(a){if("undefined"==typeof a)return saving._inprogress;if(saving._inprogress=a,a===!1){var b=["html","css","javascript"],c=function(){var a=b.pop();a&&saving.todo[a]?(saving._inprogress=!0,updateCode(a,c),saving.todo[a]=!1):a&&c()};c()}}};$("a.save").click(function(a){a.preventDefault(),analytics.milestone();var b=!0;return jsbin.saveDisabled===!0&&(b=!1),saveCode("save",b),!1});var $shareLinks=$("#share .link");$panelCheckboxes=$("#sharemenu #sharepanels input"),$("#sharemenu").bind("open",function(){updateSavedState()}),$document.on("saved",function(){updateSavedState(),$shareLinks.closest(".menu").removeClass("hidden"),$("#jsbinurl").attr("href",jsbin.getURL()).removeClass("hidden"),$("#clone").removeClass("hidden")});var saveChecksum=jsbin.state.checksum||sessionStorage.getItem("checksum")||!1;if(jsbin.state.checksum=saveChecksum,saveChecksum?$("#share div.disabled").removeClass("disabled").unbind("click mousedown mouseup"):$("#share div.disabled").one("click",function(a){a.preventDefault(),$("a.save").click()}),$document.one("saved",function(){$("#share div.disabled").removeClass("disabled").unbind("click mousedown mouseup")}),jsbin.saveDisabled)$document.one("jsbinReady",function(){var a=!1;jsbin.embed||jsbin.sandbox||$document.on("codeChange",function(b,c){if(!c.onload&&!a&&"setValue"!==c.origin){a=!0;var d=-1!==navigator.userAgent.indexOf(" Mac "),e=d?"⌘":"ctrl",f=d?"⇧":"shift",g=d?"":"+";$document.trigger("tip",{type:"notification",content:"You're currently viewing someone else's live stream, but you can clone your own copy ('+e+g+f+g+"S) at any time to save your edits"})}})});else{$(".code.panel .label .name").append("Saved ");var savingLabels={html:$(".panel.html .name span"),javascript:$(".panel.javascript .name span"),css:$(".panel.css .name span")};$document.bind("jsbinReady",function(){jsbin.panels.allEditors(function(a){a.on("processor",function(){jsbin.root!==jsbin.getURL()&&$document.trigger("codeChange",[{panelId:a.id}])})}),$document.bind("codeChange",function(a,b){savingLabels[b.panelId]&&savingLabels[b.panelId].css({opacity:0}).stop(!0,!0)}),$document.bind("saveComplete",throttle(function(a,b){savingLabels[b.panelId].text("Saved").stop(!0,!0).animate({opacity:1},100).delay(1200).animate({opacity:0},500)},500)),$document.bind("codeChange",throttle(function(a,b){if(b.panelId&&!jsbin.state.deleted){var c=b.panelId;if(jsbin.panels.savecontent(),saving.inprogress())return saving.todo[c]=!0,void 0;saving.inprogress(!0),saveChecksum&&jsbin.state.code?updateCode(c):saveCode("save",!0)}},250))})}$("a.clone").click(function(a){a.preventDefault(),jsbin.panels.save(),analytics.clone();var b=setupform("save,new");return b.submit(),!1});var $startingpoint=$("a.startingpoint").click(function(a){return a.preventDefault(),localStorage?(analytics.saveTemplate(),localStorage.setItem("saved-javascript",editors.javascript.getCode()),localStorage.setItem("saved-html",editors.html.getCode()),localStorage.setItem("saved-css",editors.css.getCode()),$document.trigger("tip",{type:"notification",content:"Starting template updated and saved",autohide:3e3})):$document.trigger("tip",{type:"error",content:"Saving templates isn't supported in this browser I'm afraid. Sorry"}),!1});$("a.disabled").on("click mousedown mouseup",function(a){return a.stopImmediatePropagation(),!1}),$("#loginbtn").click(function(){analytics.login(),$(this).toggleClass("open")}),$("a.logout").click(function(a){for(a.preventDefault(),$(this.hash).submit(),i=0;iThis bin is now locked from further changes"),$lockrevision.data("locked",!0),saveChecksum=!1,$document.trigger("locked")),!1}).on("mouseup",function(){return!1});$document.on("saved",function(){$lockrevision.removeClass("icon-lock").addClass("icon-unlocked").data("locked",!1),$lockrevision.html("Click to lock and prevent further changes ")}),$("#share input[type=text], #share textarea").on("beforecopy",function(){analytics.share("copy",this.getAttribute("data-path").substring(1)||"output")});var $panelCheckboxes=$("#sharepanels input").on("change click",updateSavedState);$("#sharemenu").bind("open",function(){$panelCheckboxes.attr("checked",!1),jsbin.panels.getVisible().forEach(function(a){$panelCheckboxes.filter('[data-panel="'+a.id+'"]').attr("checked",!0).change()})});var dropdownOpen=!1,onhover=!1,menuDown=!1,dropdownButtons=$(".button-dropdown, .button-open").mousedown(function(a){return $dropdownLinks.removeClass("hover"),dropdownOpen&&dropdownOpen!==this&&closedropdown(),dropdownOpen||(menuDown=!0,opendropdown(this)),a.preventDefault(),!1}).mouseup(function(){return menuDown?!1:void 0}).click(function(){return menuDown||(analytics.closeMenu(this.hash.substring(1)),closedropdown()),menuDown=!1,!1});$("#actionmenu").click(function(){dropdownOpen=!0});var ignoreUp=!1;$body.bind("mousedown",function(a){dropdownOpen&&$(a.target).closest(".menu").length&&(ignoreUp=!0)}).bind("click mouseup",function(a){return!dropdownOpen||ignoreUp||$(a.target).closest(".menu").length?(ignoreUp=!1,void 0):(closedropdown(),!1)});var fromClick=!1,$dropdownLinks=$(".dropdownmenu a, .dropdownmenu .button").mouseup(function(){setTimeout(closedropdown,0),analytics.selectMenu(this.getAttribute("data-label")||this.hash.substring(1)||this.href),fromClick||(this.hostname===window.location.hostname?$(this).triggerHandler("click")!==!1&&(window.location=this.href):this.getAttribute("target")?window.open(this.href):window.location=this.href),fromClick=!1}).mouseover(function(){$dropdownLinks.removeClass("hover"),$(this).addClass("hover")}).mousedown(function(){fromClick=!0});$("#jsbinurl").click(function(){setTimeout(function(){jsbin.panels.panels.live.hide()},0)}),$("#runwithalerts").click(function(a,b){return analytics.run(b),editors.console.visible?editors.console.render(!0):renderLivePreview(!0),!1}),$("#runconsole").click(function(){return analytics.runconsole(),editors.console.render(!0),!1}),$("#clearconsole").click(function(){return jsconsole.clear(),!1}),$("#showhelp").click(function(){return $body.toggleClass("keyboardHelp"),keyboardHelpVisible=$body.is(".keyboardHelp"),!1}),$("#showurls").click(function(){return $body.toggleClass("urlHelp"),urlHelpVisible=$body.is(".urlHelp"),!1}),$(".code.panel > .label > span.name").dblclick(function(){jsbin.panels.allEditors(function(a){var b=!a.editor.getOption("lineNumbers");a.editor.setOption("lineNumbers",b),jsbin.settings.editor.lineNumbers=b})}),$("#createnew").click(function(a){a.preventDefault();var b,c;for(analytics.createNew(),jsbin.panels.savecontent=function(){},b=0;b'+c+"")}),function(){var a={head://i,metaContent:/content=".*?"/i},b=' \n';$("#addmeta").click(function(){var c=jsbin.panels.panels.html,d=c.editor,e=c.getCode();a.meta.test(e)||(e=a.head.test(e)?e.replace(a.head,"'+jsbin.shareRoot+""})},error:function(){$document.trigger("tip",{type:"error",content:'There was a problem publishing to your vanity URL. Can you try again or file a new issue ?'})}})}),$("a.deletebin").on("click",function(a){a.preventDefault(),confirm("Delete this bin?")&&(analytics["delete"](),$.ajax({type:"post",url:jsbin.getURL()+"/delete",data:{checksum:jsbin.state.checksum},success:function(){jsbin.state.deleted=!0,$document.trigger("tip",{type:"error",content:"This bin is now deleted. You can continue to edit, but once you leave the bin can't be retrieved"})},error:function(a){403===a.status&&$document.trigger("tip",{content:"You don't own this bin, so you can't delete it.",autohide:5e3})}}))}),$("a.archivebin").on("click",function(a){a.preventDefault(),archive()}),$("a.unarchivebin").on("click",function(a){a.preventDefault(),archive(!1)})}(),window.File&&window.FileList&&window.FileReader&&allowDrop(document.body);var Gist=function(){"use strict";var a=!!("withCredentials"in new XMLHttpRequest||"undefined"!=typeof XDomainRequest);if(!a)return $(function(){$("#export-as-gist").remove()});var b=function(a){var b=this,c="";return b.code={},jsbin.user&&jsbin.user.github_token&&(c="?access_token="+jsbin.user.github_token),$.get("https://api.github.com/gists/"+a+c,function(a){a&&($.each(a.files,function(a,c){var d=a.split(".").slice(-1).join("");b.code[d]=c.content}),b.setCode())}),this};return b.prototype.setCode=function(){var a=this;$.each(a.code,function(a,b){var c=jsbin.processors.findByExtension(a),d=c.target||c.id,e=jsbin.panels.panels[d];e&&(processors.set(d,c.id),jsbin.saveDisabled=!0,e.setCode(b),jsbin.saveDisabled=!1)})},$("a.export-as-gist").click(function(){var a={"public":!0,files:{}},b=[{panel:"html"},{panel:"css"},{panel:"javascript",extension:"js"}];b.forEach(function(b){var c;try{c=jsbin.panels.panels[b.panel].getCode()}catch(d){}if(c&&c.length){var e=b.extension||b.panel,f=jsbin.panels.panels[b.panel].processor;f&&f.extensions&&(e=f.extensions[0]||f.name);var g=["jsbin",jsbin.state.code||"untitled",e].join(".");a.files[g]={content:c}}});var c="";return jsbin.user&&jsbin.user.github_token&&(c="?access_token="+jsbin.user.github_token),$.ajax({type:"POST",url:"https://api.github.com/gists"+c,data:JSON.stringify(a),dataType:"json",crossDomain:!0,success:function(a){$document.trigger("tip",{type:"notification",content:'Gist created! Open in new tab. '})},error:function(a,b){$document.trigger("tip",{type:"error",content:"Error: "+b})}}),!1}),b}();!function(){"use strict";function a(a){function d(a,d){var e=d?JSON.parse(d):JSON.parse(a.data);if(e.connections>0&&0===k&&b.addClass("viewers"),k!==e.connections){var f=c.find(".viewers b").removeClass("up down").html(""+e.connections+" "+k+" "+e.connections+" "),g=k>e.connections?"down":"up";setTimeout(function(){f.addClass(g)},0)}k=e.connections,0===k&&setTimeout(function(){b.removeClass("viewers")},250)}function f(){i=new EventSource(jsbin.getURL()+"/stats?checksum="+jsbin.state.checksum),i.addEventListener("stats",throttle(d,1e3))}var g=jsbin.state.metadata||{},h=[],i=null,j=!1;if(g.name&&(c.find(".name b").html(g.name),c.find("img").attr("src",g.avatar),h.push(g.name)),(jsbin.state.checksum||jsbin.user&&g.name===jsbin.user.name)&&(j=!0,h.push("author")),e&&e.stop(),jsbin.state.streaming&&j!==!0?j===!1&&(c.find("time").html("Streaming"),h.push("streaming"),e&&e.start()):c.find("time").html(a?"just now":prettyDate(g.last_updated)),jsbin.checksum||h.push("meta"),g.pro&&h.push("pro"),c.find(".visibility").text(g.visibility),"private"===g.visibility?h.push("private"):"public"===g.visibility&&h.push("public"),jsbin.state.code){b.addClass(h.join(" ")).parent().removeAttr("hidden"),c.click(function(a){a.preventDefault(),b.toggleClass("open")});var k=0;if(jsbin.state.streaming)if(window.EventSource&&j){f();var l=jsbin.getURL();$document.on("saved",function(){var a=window.location.toString();l!==a&&(i.close(),f())})}else jsbin.saveDisabled===!0&&"/edit"===window.location.pathname.slice(-5)&&($.getScript(jsbin.static+"/js/spike.js?"+jsbin.version),$document.on("stats",throttle(d,1e3)))}}if(!jsbin.embed){var b=$("#infocard"),c=b.find("header"),d=c.find("canvas")[0],e=spinner(d);0!==b.length&&(a(),$document.bind("saved",a))}}(),function(){"use strict";function a(){var a=new Date;return a.setTime(+a+36e5),a.toUTCString()}function b(){var b=jsbin.getURL(!0)+"/edit";document.cookie=b?"last="+encodeURIComponent(b)+"; expires="+a()+"; path=/":'last=""; expires=-1; path=/'}function c(a){for(var b=a+"=",c=document.cookie.split(";"),d=0;d= 31 )
+ return;
+
+ return day_diff == 0 && (
+ diff < 60 && "just now" ||
+ diff < 120 && "1 minute ago" ||
+ diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
+ diff < 7200 && "1 hour ago" ||
+ diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
+ day_diff == 1 && "Yesterday" ||
+ day_diff < 7 && day_diff + " days ago" ||
+ day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
+}
+
+// If jQuery is included in the page, adds a jQuery plugin to handle it as well
+if ( typeof window.$ != "undefined" )
+ window.$.fn.prettyDate = function(){
+ return this.each(function(){
+ var date = prettyDate(this.getAttribute('pubdate'));
+ if ( date )
+ $(this).text( date );
+ });
+ };;if (!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
+ "use strict";
+ if (this == null) {
+ throw new TypeError();
+ }
+ var t = Object(this);
+ var len = t.length >>> 0;
+ if (len === 0) {
+ return -1;
+ }
+ var n = 0;
+ if (arguments.length > 0) {
+ n = Number(arguments[1]);
+ if (n != n) { // shortcut for verifying if it's NaN
+ n = 0;
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ }
+ if (n >= len) {
+ return -1;
+ }
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+ for (; k < len; k++) {
+ if (k in t && t[k] === searchElement) {
+ return k;
+ }
+ }
+ return -1;
+ }
+}
+
+// ES5 15.4.4.21
+// http://es5.github.com/#x15.4.4.21
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
+if ('function' !== typeof Array.prototype.reduce) {
+ Array.prototype.reduce = function(callback/*, opt_initialValue*/){
+ 'use strict';
+ if (null === this || 'undefined' === typeof this) {
+ throw new TypeError(
+ 'Array.prototype.reduce called on null or undefined');
+ }
+ if ('function' !== typeof callback) {
+ throw new TypeError(callback + ' is not a function');
+ }
+ var index, value, t = Object( this ),
+ length = t.length >>> 0,
+ isValueSet = false;
+ if (1 < arguments.length) {
+ value = arguments[1];
+ isValueSet = true;
+ }
+ for (index = 0; length > index; ++index) {
+ if (index in t) {
+ if (isValueSet) {
+ value = callback(value, t[index], index, t);
+ }
+ else {
+ value = t[index];
+ isValueSet = true;
+ }
+ }
+ }
+ if (!isValueSet) {
+ throw new TypeError('Reduce of empty array with no initial value');
+ }
+ return value;
+ };
+}
+
+
+// Production steps of ECMA-262, Edition 5, 15.4.4.18
+// Reference: http://es5.github.com/#x15.4.4.18
+if ( !Array.prototype.forEach ) {
+
+ Array.prototype.forEach = function( callback, thisArg ) {
+
+ var T, k;
+
+ if ( this == null ) {
+ throw new TypeError( " this is null or not defined" );
+ }
+
+ // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
+ var O = Object(this);
+
+ // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
+ // 3. Let len be ToUint32(lenValue).
+ var len = O.length >>> 0; // Hack to convert O.length to a UInt32
+
+ // 4. If IsCallable(callback) is false, throw a TypeError exception.
+ // See: http://es5.github.com/#x9.11
+ if ( {}.toString.call(callback) != "[object Function]" ) {
+ throw new TypeError( callback + " is not a function" );
+ }
+
+ // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
+ if ( thisArg ) {
+ T = thisArg;
+ }
+
+ // 6. Let k be 0
+ k = 0;
+
+ // 7. Repeat, while k < len
+ while( k < len ) {
+
+ var kValue;
+
+ // a. Let Pk be ToString(k).
+ // This is implicit for LHS operands of the in operator
+ // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
+ // This step can be combined with c
+ // c. If kPresent is true, then
+ if ( k in O ) {
+
+ // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
+ kValue = O[ k ];
+
+ // ii. Call the Call internal method of callback with T as the this value and
+ // argument list containing kValue, k, and O.
+ callback.call( T, kValue, k, O );
+ }
+ // d. Increase k by 1.
+ k++;
+ }
+ // 8. return undefined
+ };
+}
+
+// https://gist.github.com/1035982
+''.trim||(String.prototype.trim=function(){return this.replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g,'')});
+
+if ( !Object.prototype.hasOwnProperty ) {
+ Object.prototype.hasOwnProperty = function(prop) {
+ var proto = obj.__proto__ || obj.constructor.prototype;
+ return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
+ };
+}
+
+Date.now||(Date.now=function(){return+new Date})
+
+// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
+
+// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
+
+// MIT license
+
+(function() {
+ var lastTime = 0;
+ var vendors = ['ms', 'moz', 'webkit', 'o'];
+ for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
+ window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
+ window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
+ || window[vendors[x]+'CancelRequestAnimationFrame'];
+ }
+
+ if (!window.requestAnimationFrame)
+ window.requestAnimationFrame = function(callback, element) {
+ var currTime = Date.now();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = window.setTimeout(function() { callback(currTime + timeToCall); },
+ timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+
+ if (!window.cancelAnimationFrame)
+ window.cancelAnimationFrame = function(id) {
+ clearTimeout(id);
+ };
+}());
+
+(function () {
+ function Empty() {}
+ var slice = [].slice;
+
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function bind(that) { // .length is 1
+ // 1. Let Target be the this value.
+ var target = this;
+ // 2. If IsCallable(Target) is false, throw a TypeError exception.
+ if (typeof target != "function") {
+ throw new TypeError("Function.prototype.bind called on incompatible " + target);
+ }
+ // 3. Let A be a new (possibly empty) internal list of all of the
+ // argument values provided after thisArg (arg1, arg2 etc), in order.
+ // XXX slicedArgs will stand in for "A" if used
+ var args = slice.call(arguments, 1); // for normal call
+ // 4. Let F be a new native ECMAScript object.
+ // 11. Set the [[Prototype]] internal property of F to the standard
+ // built-in Function prototype object as specified in 15.3.3.1.
+ // 12. Set the [[Call]] internal property of F as described in
+ // 15.3.4.5.1.
+ // 13. Set the [[Construct]] internal property of F as described in
+ // 15.3.4.5.2.
+ // 14. Set the [[HasInstance]] internal property of F as described in
+ // 15.3.4.5.3.
+ var bound = function () {
+
+ if (this instanceof bound) {
+ // 15.3.4.5.2 [[Construct]]
+ // When the [[Construct]] internal method of a function object,
+ // F that was created using the bind function is called with a
+ // list of arguments ExtraArgs, the following steps are taken:
+ // 1. Let target be the value of F's [[TargetFunction]]
+ // internal property.
+ // 2. If target has no [[Construct]] internal method, a
+ // TypeError exception is thrown.
+ // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
+ // property.
+ // 4. Let args be a new list containing the same values as the
+ // list boundArgs in the same order followed by the same
+ // values as the list ExtraArgs in the same order.
+ // 5. Return the result of calling the [[Construct]] internal
+ // method of target providing args as the arguments.
+
+ var result = target.apply(
+ this,
+ args.concat(slice.call(arguments))
+ );
+ if (Object(result) === result) {
+ return result;
+ }
+ return this;
+
+ } else {
+ // 15.3.4.5.1 [[Call]]
+ // When the [[Call]] internal method of a function object, F,
+ // which was created using the bind function is called with a
+ // this value and a list of arguments ExtraArgs, the following
+ // steps are taken:
+ // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
+ // property.
+ // 2. Let boundThis be the value of F's [[BoundThis]] internal
+ // property.
+ // 3. Let target be the value of F's [[TargetFunction]] internal
+ // property.
+ // 4. Let args be a new list containing the same values as the
+ // list boundArgs in the same order followed by the same
+ // values as the list ExtraArgs in the same order.
+ // 5. Return the result of calling the [[Call]] internal method
+ // of target providing boundThis as the this value and
+ // providing args as the arguments.
+
+ // equiv: target.call(this, ...boundArgs, ...args)
+ return target.apply(
+ that,
+ args.concat(slice.call(arguments))
+ );
+
+ }
+
+ };
+ if(target.prototype) {
+ Empty.prototype = target.prototype;
+ bound.prototype = new Empty();
+ // Clean up dangling references.
+ Empty.prototype = null;
+ }
+ // XXX bound.length is never writable, so don't even try
+ //
+ // 15. If the [[Class]] internal property of Target is "Function", then
+ // a. Let L be the length property of Target minus the length of A.
+ // b. Set the length own property of F to either 0 or L, whichever is
+ // larger.
+ // 16. Else set the length own property of F to 0.
+ // 17. Set the attributes of the length own property of F to the values
+ // specified in 15.3.5.1.
+
+ // TODO
+ // 18. Set the [[Extensible]] internal property of F to true.
+
+ // TODO
+ // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
+ // 20. Call the [[DefineOwnProperty]] internal method of F with
+ // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
+ // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
+ // false.
+ // 21. Call the [[DefineOwnProperty]] internal method of F with
+ // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
+ // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
+ // and false.
+
+ // TODO
+ // NOTE Function objects created using Function.prototype.bind do not
+ // have a prototype property or the [[Code]], [[FormalParameters]], and
+ // [[Scope]] internal properties.
+ // XXX can't delete prototype in pure-js.
+
+ // 22. Return F.
+ return bound;
+ };
+ }
+}());
+
+// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
+if (!Object.keys) {
+ Object.keys = (function () {
+ 'use strict';
+ var hasOwnProperty = Object.prototype.hasOwnProperty,
+ hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
+ dontEnums = [
+ 'toString',
+ 'toLocaleString',
+ 'valueOf',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'constructor'
+ ],
+ dontEnumsLength = dontEnums.length;
+
+ return function (obj) {
+ if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
+ throw new TypeError('Object.keys called on non-object');
+ }
+
+ var result = [], prop, i;
+
+ for (prop in obj) {
+ if (hasOwnProperty.call(obj, prop)) {
+ result.push(prop);
+ }
+ }
+
+ if (hasDontEnumBug) {
+ for (i = 0; i < dontEnumsLength; i++) {
+ if (hasOwnProperty.call(obj, dontEnums[i])) {
+ result.push(dontEnums[i]);
+ }
+ }
+ }
+ return result;
+ };
+ }());
+}
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
+if (!Array.prototype.map)
+{
+ Array.prototype.map = function(fun /*, thisArg */)
+ {
+ "use strict";
+
+ if (this === void 0 || this === null)
+ throw new TypeError();
+
+ var t = Object(this);
+ var len = t.length >>> 0;
+ if (typeof fun !== "function")
+ throw new TypeError();
+
+ var res = new Array(len);
+ var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
+ for (var i = 0; i < len; i++)
+ {
+ // NOTE: Absolute correctness would demand Object.defineProperty
+ // be used. But this method is fairly new, and failure is
+ // possible only if Object.prototype or Array.prototype
+ // has a property |i| (very unlikely), so use a less-correct
+ // but more portable alternative.
+ if (i in t)
+ res[i] = fun.call(thisArg, t[i], i, t);
+ }
+
+ return res;
+ };
+};/*! 2.5.1 */
+var JSHINT;
+if (typeof window === 'undefined') window = {};
+(function () {
+var require;
+require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 65 && i <= 90 || // A-Z
+ i === 95 || // _
+ i >= 97 && i <= 122; // a-z
+}
+
+var identifierPartTable = [];
+
+for (var i = 0; i < 128; i++) {
+ identifierPartTable[i] =
+ identifierStartTable[i] || // $, _, A-Z, a-z
+ i >= 48 && i <= 57; // 0-9
+}
+
+module.exports = {
+ asciiIdentifierStartTable: identifierStartTable,
+ asciiIdentifierPartTable: identifierPartTable
+};
+
+},{}],2:[function(require,module,exports){
+module.exports = [
+ 768,
+ 769,
+ 770,
+ 771,
+ 772,
+ 773,
+ 774,
+ 775,
+ 776,
+ 777,
+ 778,
+ 779,
+ 780,
+ 781,
+ 782,
+ 783,
+ 784,
+ 785,
+ 786,
+ 787,
+ 788,
+ 789,
+ 790,
+ 791,
+ 792,
+ 793,
+ 794,
+ 795,
+ 796,
+ 797,
+ 798,
+ 799,
+ 800,
+ 801,
+ 802,
+ 803,
+ 804,
+ 805,
+ 806,
+ 807,
+ 808,
+ 809,
+ 810,
+ 811,
+ 812,
+ 813,
+ 814,
+ 815,
+ 816,
+ 817,
+ 818,
+ 819,
+ 820,
+ 821,
+ 822,
+ 823,
+ 824,
+ 825,
+ 826,
+ 827,
+ 828,
+ 829,
+ 830,
+ 831,
+ 832,
+ 833,
+ 834,
+ 835,
+ 836,
+ 837,
+ 838,
+ 839,
+ 840,
+ 841,
+ 842,
+ 843,
+ 844,
+ 845,
+ 846,
+ 847,
+ 848,
+ 849,
+ 850,
+ 851,
+ 852,
+ 853,
+ 854,
+ 855,
+ 856,
+ 857,
+ 858,
+ 859,
+ 860,
+ 861,
+ 862,
+ 863,
+ 864,
+ 865,
+ 866,
+ 867,
+ 868,
+ 869,
+ 870,
+ 871,
+ 872,
+ 873,
+ 874,
+ 875,
+ 876,
+ 877,
+ 878,
+ 879,
+ 1155,
+ 1156,
+ 1157,
+ 1158,
+ 1159,
+ 1425,
+ 1426,
+ 1427,
+ 1428,
+ 1429,
+ 1430,
+ 1431,
+ 1432,
+ 1433,
+ 1434,
+ 1435,
+ 1436,
+ 1437,
+ 1438,
+ 1439,
+ 1440,
+ 1441,
+ 1442,
+ 1443,
+ 1444,
+ 1445,
+ 1446,
+ 1447,
+ 1448,
+ 1449,
+ 1450,
+ 1451,
+ 1452,
+ 1453,
+ 1454,
+ 1455,
+ 1456,
+ 1457,
+ 1458,
+ 1459,
+ 1460,
+ 1461,
+ 1462,
+ 1463,
+ 1464,
+ 1465,
+ 1466,
+ 1467,
+ 1468,
+ 1469,
+ 1471,
+ 1473,
+ 1474,
+ 1476,
+ 1477,
+ 1479,
+ 1552,
+ 1553,
+ 1554,
+ 1555,
+ 1556,
+ 1557,
+ 1558,
+ 1559,
+ 1560,
+ 1561,
+ 1562,
+ 1611,
+ 1612,
+ 1613,
+ 1614,
+ 1615,
+ 1616,
+ 1617,
+ 1618,
+ 1619,
+ 1620,
+ 1621,
+ 1622,
+ 1623,
+ 1624,
+ 1625,
+ 1626,
+ 1627,
+ 1628,
+ 1629,
+ 1630,
+ 1631,
+ 1632,
+ 1633,
+ 1634,
+ 1635,
+ 1636,
+ 1637,
+ 1638,
+ 1639,
+ 1640,
+ 1641,
+ 1648,
+ 1750,
+ 1751,
+ 1752,
+ 1753,
+ 1754,
+ 1755,
+ 1756,
+ 1759,
+ 1760,
+ 1761,
+ 1762,
+ 1763,
+ 1764,
+ 1767,
+ 1768,
+ 1770,
+ 1771,
+ 1772,
+ 1773,
+ 1776,
+ 1777,
+ 1778,
+ 1779,
+ 1780,
+ 1781,
+ 1782,
+ 1783,
+ 1784,
+ 1785,
+ 1809,
+ 1840,
+ 1841,
+ 1842,
+ 1843,
+ 1844,
+ 1845,
+ 1846,
+ 1847,
+ 1848,
+ 1849,
+ 1850,
+ 1851,
+ 1852,
+ 1853,
+ 1854,
+ 1855,
+ 1856,
+ 1857,
+ 1858,
+ 1859,
+ 1860,
+ 1861,
+ 1862,
+ 1863,
+ 1864,
+ 1865,
+ 1866,
+ 1958,
+ 1959,
+ 1960,
+ 1961,
+ 1962,
+ 1963,
+ 1964,
+ 1965,
+ 1966,
+ 1967,
+ 1968,
+ 1984,
+ 1985,
+ 1986,
+ 1987,
+ 1988,
+ 1989,
+ 1990,
+ 1991,
+ 1992,
+ 1993,
+ 2027,
+ 2028,
+ 2029,
+ 2030,
+ 2031,
+ 2032,
+ 2033,
+ 2034,
+ 2035,
+ 2070,
+ 2071,
+ 2072,
+ 2073,
+ 2075,
+ 2076,
+ 2077,
+ 2078,
+ 2079,
+ 2080,
+ 2081,
+ 2082,
+ 2083,
+ 2085,
+ 2086,
+ 2087,
+ 2089,
+ 2090,
+ 2091,
+ 2092,
+ 2093,
+ 2137,
+ 2138,
+ 2139,
+ 2276,
+ 2277,
+ 2278,
+ 2279,
+ 2280,
+ 2281,
+ 2282,
+ 2283,
+ 2284,
+ 2285,
+ 2286,
+ 2287,
+ 2288,
+ 2289,
+ 2290,
+ 2291,
+ 2292,
+ 2293,
+ 2294,
+ 2295,
+ 2296,
+ 2297,
+ 2298,
+ 2299,
+ 2300,
+ 2301,
+ 2302,
+ 2304,
+ 2305,
+ 2306,
+ 2307,
+ 2362,
+ 2363,
+ 2364,
+ 2366,
+ 2367,
+ 2368,
+ 2369,
+ 2370,
+ 2371,
+ 2372,
+ 2373,
+ 2374,
+ 2375,
+ 2376,
+ 2377,
+ 2378,
+ 2379,
+ 2380,
+ 2381,
+ 2382,
+ 2383,
+ 2385,
+ 2386,
+ 2387,
+ 2388,
+ 2389,
+ 2390,
+ 2391,
+ 2402,
+ 2403,
+ 2406,
+ 2407,
+ 2408,
+ 2409,
+ 2410,
+ 2411,
+ 2412,
+ 2413,
+ 2414,
+ 2415,
+ 2433,
+ 2434,
+ 2435,
+ 2492,
+ 2494,
+ 2495,
+ 2496,
+ 2497,
+ 2498,
+ 2499,
+ 2500,
+ 2503,
+ 2504,
+ 2507,
+ 2508,
+ 2509,
+ 2519,
+ 2530,
+ 2531,
+ 2534,
+ 2535,
+ 2536,
+ 2537,
+ 2538,
+ 2539,
+ 2540,
+ 2541,
+ 2542,
+ 2543,
+ 2561,
+ 2562,
+ 2563,
+ 2620,
+ 2622,
+ 2623,
+ 2624,
+ 2625,
+ 2626,
+ 2631,
+ 2632,
+ 2635,
+ 2636,
+ 2637,
+ 2641,
+ 2662,
+ 2663,
+ 2664,
+ 2665,
+ 2666,
+ 2667,
+ 2668,
+ 2669,
+ 2670,
+ 2671,
+ 2672,
+ 2673,
+ 2677,
+ 2689,
+ 2690,
+ 2691,
+ 2748,
+ 2750,
+ 2751,
+ 2752,
+ 2753,
+ 2754,
+ 2755,
+ 2756,
+ 2757,
+ 2759,
+ 2760,
+ 2761,
+ 2763,
+ 2764,
+ 2765,
+ 2786,
+ 2787,
+ 2790,
+ 2791,
+ 2792,
+ 2793,
+ 2794,
+ 2795,
+ 2796,
+ 2797,
+ 2798,
+ 2799,
+ 2817,
+ 2818,
+ 2819,
+ 2876,
+ 2878,
+ 2879,
+ 2880,
+ 2881,
+ 2882,
+ 2883,
+ 2884,
+ 2887,
+ 2888,
+ 2891,
+ 2892,
+ 2893,
+ 2902,
+ 2903,
+ 2914,
+ 2915,
+ 2918,
+ 2919,
+ 2920,
+ 2921,
+ 2922,
+ 2923,
+ 2924,
+ 2925,
+ 2926,
+ 2927,
+ 2946,
+ 3006,
+ 3007,
+ 3008,
+ 3009,
+ 3010,
+ 3014,
+ 3015,
+ 3016,
+ 3018,
+ 3019,
+ 3020,
+ 3021,
+ 3031,
+ 3046,
+ 3047,
+ 3048,
+ 3049,
+ 3050,
+ 3051,
+ 3052,
+ 3053,
+ 3054,
+ 3055,
+ 3073,
+ 3074,
+ 3075,
+ 3134,
+ 3135,
+ 3136,
+ 3137,
+ 3138,
+ 3139,
+ 3140,
+ 3142,
+ 3143,
+ 3144,
+ 3146,
+ 3147,
+ 3148,
+ 3149,
+ 3157,
+ 3158,
+ 3170,
+ 3171,
+ 3174,
+ 3175,
+ 3176,
+ 3177,
+ 3178,
+ 3179,
+ 3180,
+ 3181,
+ 3182,
+ 3183,
+ 3202,
+ 3203,
+ 3260,
+ 3262,
+ 3263,
+ 3264,
+ 3265,
+ 3266,
+ 3267,
+ 3268,
+ 3270,
+ 3271,
+ 3272,
+ 3274,
+ 3275,
+ 3276,
+ 3277,
+ 3285,
+ 3286,
+ 3298,
+ 3299,
+ 3302,
+ 3303,
+ 3304,
+ 3305,
+ 3306,
+ 3307,
+ 3308,
+ 3309,
+ 3310,
+ 3311,
+ 3330,
+ 3331,
+ 3390,
+ 3391,
+ 3392,
+ 3393,
+ 3394,
+ 3395,
+ 3396,
+ 3398,
+ 3399,
+ 3400,
+ 3402,
+ 3403,
+ 3404,
+ 3405,
+ 3415,
+ 3426,
+ 3427,
+ 3430,
+ 3431,
+ 3432,
+ 3433,
+ 3434,
+ 3435,
+ 3436,
+ 3437,
+ 3438,
+ 3439,
+ 3458,
+ 3459,
+ 3530,
+ 3535,
+ 3536,
+ 3537,
+ 3538,
+ 3539,
+ 3540,
+ 3542,
+ 3544,
+ 3545,
+ 3546,
+ 3547,
+ 3548,
+ 3549,
+ 3550,
+ 3551,
+ 3570,
+ 3571,
+ 3633,
+ 3636,
+ 3637,
+ 3638,
+ 3639,
+ 3640,
+ 3641,
+ 3642,
+ 3655,
+ 3656,
+ 3657,
+ 3658,
+ 3659,
+ 3660,
+ 3661,
+ 3662,
+ 3664,
+ 3665,
+ 3666,
+ 3667,
+ 3668,
+ 3669,
+ 3670,
+ 3671,
+ 3672,
+ 3673,
+ 3761,
+ 3764,
+ 3765,
+ 3766,
+ 3767,
+ 3768,
+ 3769,
+ 3771,
+ 3772,
+ 3784,
+ 3785,
+ 3786,
+ 3787,
+ 3788,
+ 3789,
+ 3792,
+ 3793,
+ 3794,
+ 3795,
+ 3796,
+ 3797,
+ 3798,
+ 3799,
+ 3800,
+ 3801,
+ 3864,
+ 3865,
+ 3872,
+ 3873,
+ 3874,
+ 3875,
+ 3876,
+ 3877,
+ 3878,
+ 3879,
+ 3880,
+ 3881,
+ 3893,
+ 3895,
+ 3897,
+ 3902,
+ 3903,
+ 3953,
+ 3954,
+ 3955,
+ 3956,
+ 3957,
+ 3958,
+ 3959,
+ 3960,
+ 3961,
+ 3962,
+ 3963,
+ 3964,
+ 3965,
+ 3966,
+ 3967,
+ 3968,
+ 3969,
+ 3970,
+ 3971,
+ 3972,
+ 3974,
+ 3975,
+ 3981,
+ 3982,
+ 3983,
+ 3984,
+ 3985,
+ 3986,
+ 3987,
+ 3988,
+ 3989,
+ 3990,
+ 3991,
+ 3993,
+ 3994,
+ 3995,
+ 3996,
+ 3997,
+ 3998,
+ 3999,
+ 4000,
+ 4001,
+ 4002,
+ 4003,
+ 4004,
+ 4005,
+ 4006,
+ 4007,
+ 4008,
+ 4009,
+ 4010,
+ 4011,
+ 4012,
+ 4013,
+ 4014,
+ 4015,
+ 4016,
+ 4017,
+ 4018,
+ 4019,
+ 4020,
+ 4021,
+ 4022,
+ 4023,
+ 4024,
+ 4025,
+ 4026,
+ 4027,
+ 4028,
+ 4038,
+ 4139,
+ 4140,
+ 4141,
+ 4142,
+ 4143,
+ 4144,
+ 4145,
+ 4146,
+ 4147,
+ 4148,
+ 4149,
+ 4150,
+ 4151,
+ 4152,
+ 4153,
+ 4154,
+ 4155,
+ 4156,
+ 4157,
+ 4158,
+ 4160,
+ 4161,
+ 4162,
+ 4163,
+ 4164,
+ 4165,
+ 4166,
+ 4167,
+ 4168,
+ 4169,
+ 4182,
+ 4183,
+ 4184,
+ 4185,
+ 4190,
+ 4191,
+ 4192,
+ 4194,
+ 4195,
+ 4196,
+ 4199,
+ 4200,
+ 4201,
+ 4202,
+ 4203,
+ 4204,
+ 4205,
+ 4209,
+ 4210,
+ 4211,
+ 4212,
+ 4226,
+ 4227,
+ 4228,
+ 4229,
+ 4230,
+ 4231,
+ 4232,
+ 4233,
+ 4234,
+ 4235,
+ 4236,
+ 4237,
+ 4239,
+ 4240,
+ 4241,
+ 4242,
+ 4243,
+ 4244,
+ 4245,
+ 4246,
+ 4247,
+ 4248,
+ 4249,
+ 4250,
+ 4251,
+ 4252,
+ 4253,
+ 4957,
+ 4958,
+ 4959,
+ 5906,
+ 5907,
+ 5908,
+ 5938,
+ 5939,
+ 5940,
+ 5970,
+ 5971,
+ 6002,
+ 6003,
+ 6068,
+ 6069,
+ 6070,
+ 6071,
+ 6072,
+ 6073,
+ 6074,
+ 6075,
+ 6076,
+ 6077,
+ 6078,
+ 6079,
+ 6080,
+ 6081,
+ 6082,
+ 6083,
+ 6084,
+ 6085,
+ 6086,
+ 6087,
+ 6088,
+ 6089,
+ 6090,
+ 6091,
+ 6092,
+ 6093,
+ 6094,
+ 6095,
+ 6096,
+ 6097,
+ 6098,
+ 6099,
+ 6109,
+ 6112,
+ 6113,
+ 6114,
+ 6115,
+ 6116,
+ 6117,
+ 6118,
+ 6119,
+ 6120,
+ 6121,
+ 6155,
+ 6156,
+ 6157,
+ 6160,
+ 6161,
+ 6162,
+ 6163,
+ 6164,
+ 6165,
+ 6166,
+ 6167,
+ 6168,
+ 6169,
+ 6313,
+ 6432,
+ 6433,
+ 6434,
+ 6435,
+ 6436,
+ 6437,
+ 6438,
+ 6439,
+ 6440,
+ 6441,
+ 6442,
+ 6443,
+ 6448,
+ 6449,
+ 6450,
+ 6451,
+ 6452,
+ 6453,
+ 6454,
+ 6455,
+ 6456,
+ 6457,
+ 6458,
+ 6459,
+ 6470,
+ 6471,
+ 6472,
+ 6473,
+ 6474,
+ 6475,
+ 6476,
+ 6477,
+ 6478,
+ 6479,
+ 6576,
+ 6577,
+ 6578,
+ 6579,
+ 6580,
+ 6581,
+ 6582,
+ 6583,
+ 6584,
+ 6585,
+ 6586,
+ 6587,
+ 6588,
+ 6589,
+ 6590,
+ 6591,
+ 6592,
+ 6600,
+ 6601,
+ 6608,
+ 6609,
+ 6610,
+ 6611,
+ 6612,
+ 6613,
+ 6614,
+ 6615,
+ 6616,
+ 6617,
+ 6679,
+ 6680,
+ 6681,
+ 6682,
+ 6683,
+ 6741,
+ 6742,
+ 6743,
+ 6744,
+ 6745,
+ 6746,
+ 6747,
+ 6748,
+ 6749,
+ 6750,
+ 6752,
+ 6753,
+ 6754,
+ 6755,
+ 6756,
+ 6757,
+ 6758,
+ 6759,
+ 6760,
+ 6761,
+ 6762,
+ 6763,
+ 6764,
+ 6765,
+ 6766,
+ 6767,
+ 6768,
+ 6769,
+ 6770,
+ 6771,
+ 6772,
+ 6773,
+ 6774,
+ 6775,
+ 6776,
+ 6777,
+ 6778,
+ 6779,
+ 6780,
+ 6783,
+ 6784,
+ 6785,
+ 6786,
+ 6787,
+ 6788,
+ 6789,
+ 6790,
+ 6791,
+ 6792,
+ 6793,
+ 6800,
+ 6801,
+ 6802,
+ 6803,
+ 6804,
+ 6805,
+ 6806,
+ 6807,
+ 6808,
+ 6809,
+ 6912,
+ 6913,
+ 6914,
+ 6915,
+ 6916,
+ 6964,
+ 6965,
+ 6966,
+ 6967,
+ 6968,
+ 6969,
+ 6970,
+ 6971,
+ 6972,
+ 6973,
+ 6974,
+ 6975,
+ 6976,
+ 6977,
+ 6978,
+ 6979,
+ 6980,
+ 6992,
+ 6993,
+ 6994,
+ 6995,
+ 6996,
+ 6997,
+ 6998,
+ 6999,
+ 7000,
+ 7001,
+ 7019,
+ 7020,
+ 7021,
+ 7022,
+ 7023,
+ 7024,
+ 7025,
+ 7026,
+ 7027,
+ 7040,
+ 7041,
+ 7042,
+ 7073,
+ 7074,
+ 7075,
+ 7076,
+ 7077,
+ 7078,
+ 7079,
+ 7080,
+ 7081,
+ 7082,
+ 7083,
+ 7084,
+ 7085,
+ 7088,
+ 7089,
+ 7090,
+ 7091,
+ 7092,
+ 7093,
+ 7094,
+ 7095,
+ 7096,
+ 7097,
+ 7142,
+ 7143,
+ 7144,
+ 7145,
+ 7146,
+ 7147,
+ 7148,
+ 7149,
+ 7150,
+ 7151,
+ 7152,
+ 7153,
+ 7154,
+ 7155,
+ 7204,
+ 7205,
+ 7206,
+ 7207,
+ 7208,
+ 7209,
+ 7210,
+ 7211,
+ 7212,
+ 7213,
+ 7214,
+ 7215,
+ 7216,
+ 7217,
+ 7218,
+ 7219,
+ 7220,
+ 7221,
+ 7222,
+ 7223,
+ 7232,
+ 7233,
+ 7234,
+ 7235,
+ 7236,
+ 7237,
+ 7238,
+ 7239,
+ 7240,
+ 7241,
+ 7248,
+ 7249,
+ 7250,
+ 7251,
+ 7252,
+ 7253,
+ 7254,
+ 7255,
+ 7256,
+ 7257,
+ 7376,
+ 7377,
+ 7378,
+ 7380,
+ 7381,
+ 7382,
+ 7383,
+ 7384,
+ 7385,
+ 7386,
+ 7387,
+ 7388,
+ 7389,
+ 7390,
+ 7391,
+ 7392,
+ 7393,
+ 7394,
+ 7395,
+ 7396,
+ 7397,
+ 7398,
+ 7399,
+ 7400,
+ 7405,
+ 7410,
+ 7411,
+ 7412,
+ 7616,
+ 7617,
+ 7618,
+ 7619,
+ 7620,
+ 7621,
+ 7622,
+ 7623,
+ 7624,
+ 7625,
+ 7626,
+ 7627,
+ 7628,
+ 7629,
+ 7630,
+ 7631,
+ 7632,
+ 7633,
+ 7634,
+ 7635,
+ 7636,
+ 7637,
+ 7638,
+ 7639,
+ 7640,
+ 7641,
+ 7642,
+ 7643,
+ 7644,
+ 7645,
+ 7646,
+ 7647,
+ 7648,
+ 7649,
+ 7650,
+ 7651,
+ 7652,
+ 7653,
+ 7654,
+ 7676,
+ 7677,
+ 7678,
+ 7679,
+ 8204,
+ 8205,
+ 8255,
+ 8256,
+ 8276,
+ 8400,
+ 8401,
+ 8402,
+ 8403,
+ 8404,
+ 8405,
+ 8406,
+ 8407,
+ 8408,
+ 8409,
+ 8410,
+ 8411,
+ 8412,
+ 8417,
+ 8421,
+ 8422,
+ 8423,
+ 8424,
+ 8425,
+ 8426,
+ 8427,
+ 8428,
+ 8429,
+ 8430,
+ 8431,
+ 8432,
+ 11503,
+ 11504,
+ 11505,
+ 11647,
+ 11744,
+ 11745,
+ 11746,
+ 11747,
+ 11748,
+ 11749,
+ 11750,
+ 11751,
+ 11752,
+ 11753,
+ 11754,
+ 11755,
+ 11756,
+ 11757,
+ 11758,
+ 11759,
+ 11760,
+ 11761,
+ 11762,
+ 11763,
+ 11764,
+ 11765,
+ 11766,
+ 11767,
+ 11768,
+ 11769,
+ 11770,
+ 11771,
+ 11772,
+ 11773,
+ 11774,
+ 11775,
+ 12330,
+ 12331,
+ 12332,
+ 12333,
+ 12334,
+ 12335,
+ 12441,
+ 12442,
+ 42528,
+ 42529,
+ 42530,
+ 42531,
+ 42532,
+ 42533,
+ 42534,
+ 42535,
+ 42536,
+ 42537,
+ 42607,
+ 42612,
+ 42613,
+ 42614,
+ 42615,
+ 42616,
+ 42617,
+ 42618,
+ 42619,
+ 42620,
+ 42621,
+ 42655,
+ 42736,
+ 42737,
+ 43010,
+ 43014,
+ 43019,
+ 43043,
+ 43044,
+ 43045,
+ 43046,
+ 43047,
+ 43136,
+ 43137,
+ 43188,
+ 43189,
+ 43190,
+ 43191,
+ 43192,
+ 43193,
+ 43194,
+ 43195,
+ 43196,
+ 43197,
+ 43198,
+ 43199,
+ 43200,
+ 43201,
+ 43202,
+ 43203,
+ 43204,
+ 43216,
+ 43217,
+ 43218,
+ 43219,
+ 43220,
+ 43221,
+ 43222,
+ 43223,
+ 43224,
+ 43225,
+ 43232,
+ 43233,
+ 43234,
+ 43235,
+ 43236,
+ 43237,
+ 43238,
+ 43239,
+ 43240,
+ 43241,
+ 43242,
+ 43243,
+ 43244,
+ 43245,
+ 43246,
+ 43247,
+ 43248,
+ 43249,
+ 43264,
+ 43265,
+ 43266,
+ 43267,
+ 43268,
+ 43269,
+ 43270,
+ 43271,
+ 43272,
+ 43273,
+ 43302,
+ 43303,
+ 43304,
+ 43305,
+ 43306,
+ 43307,
+ 43308,
+ 43309,
+ 43335,
+ 43336,
+ 43337,
+ 43338,
+ 43339,
+ 43340,
+ 43341,
+ 43342,
+ 43343,
+ 43344,
+ 43345,
+ 43346,
+ 43347,
+ 43392,
+ 43393,
+ 43394,
+ 43395,
+ 43443,
+ 43444,
+ 43445,
+ 43446,
+ 43447,
+ 43448,
+ 43449,
+ 43450,
+ 43451,
+ 43452,
+ 43453,
+ 43454,
+ 43455,
+ 43456,
+ 43472,
+ 43473,
+ 43474,
+ 43475,
+ 43476,
+ 43477,
+ 43478,
+ 43479,
+ 43480,
+ 43481,
+ 43561,
+ 43562,
+ 43563,
+ 43564,
+ 43565,
+ 43566,
+ 43567,
+ 43568,
+ 43569,
+ 43570,
+ 43571,
+ 43572,
+ 43573,
+ 43574,
+ 43587,
+ 43596,
+ 43597,
+ 43600,
+ 43601,
+ 43602,
+ 43603,
+ 43604,
+ 43605,
+ 43606,
+ 43607,
+ 43608,
+ 43609,
+ 43643,
+ 43696,
+ 43698,
+ 43699,
+ 43700,
+ 43703,
+ 43704,
+ 43710,
+ 43711,
+ 43713,
+ 43755,
+ 43756,
+ 43757,
+ 43758,
+ 43759,
+ 43765,
+ 43766,
+ 44003,
+ 44004,
+ 44005,
+ 44006,
+ 44007,
+ 44008,
+ 44009,
+ 44010,
+ 44012,
+ 44013,
+ 44016,
+ 44017,
+ 44018,
+ 44019,
+ 44020,
+ 44021,
+ 44022,
+ 44023,
+ 44024,
+ 44025,
+ 64286,
+ 65024,
+ 65025,
+ 65026,
+ 65027,
+ 65028,
+ 65029,
+ 65030,
+ 65031,
+ 65032,
+ 65033,
+ 65034,
+ 65035,
+ 65036,
+ 65037,
+ 65038,
+ 65039,
+ 65056,
+ 65057,
+ 65058,
+ 65059,
+ 65060,
+ 65061,
+ 65062,
+ 65075,
+ 65076,
+ 65101,
+ 65102,
+ 65103,
+ 65296,
+ 65297,
+ 65298,
+ 65299,
+ 65300,
+ 65301,
+ 65302,
+ 65303,
+ 65304,
+ 65305,
+ 65343
+];
+
+},{}],3:[function(require,module,exports){
+module.exports = [
+ 170,
+ 181,
+ 186,
+ 192,
+ 193,
+ 194,
+ 195,
+ 196,
+ 197,
+ 198,
+ 199,
+ 200,
+ 201,
+ 202,
+ 203,
+ 204,
+ 205,
+ 206,
+ 207,
+ 208,
+ 209,
+ 210,
+ 211,
+ 212,
+ 213,
+ 214,
+ 216,
+ 217,
+ 218,
+ 219,
+ 220,
+ 221,
+ 222,
+ 223,
+ 224,
+ 225,
+ 226,
+ 227,
+ 228,
+ 229,
+ 230,
+ 231,
+ 232,
+ 233,
+ 234,
+ 235,
+ 236,
+ 237,
+ 238,
+ 239,
+ 240,
+ 241,
+ 242,
+ 243,
+ 244,
+ 245,
+ 246,
+ 248,
+ 249,
+ 250,
+ 251,
+ 252,
+ 253,
+ 254,
+ 255,
+ 256,
+ 257,
+ 258,
+ 259,
+ 260,
+ 261,
+ 262,
+ 263,
+ 264,
+ 265,
+ 266,
+ 267,
+ 268,
+ 269,
+ 270,
+ 271,
+ 272,
+ 273,
+ 274,
+ 275,
+ 276,
+ 277,
+ 278,
+ 279,
+ 280,
+ 281,
+ 282,
+ 283,
+ 284,
+ 285,
+ 286,
+ 287,
+ 288,
+ 289,
+ 290,
+ 291,
+ 292,
+ 293,
+ 294,
+ 295,
+ 296,
+ 297,
+ 298,
+ 299,
+ 300,
+ 301,
+ 302,
+ 303,
+ 304,
+ 305,
+ 306,
+ 307,
+ 308,
+ 309,
+ 310,
+ 311,
+ 312,
+ 313,
+ 314,
+ 315,
+ 316,
+ 317,
+ 318,
+ 319,
+ 320,
+ 321,
+ 322,
+ 323,
+ 324,
+ 325,
+ 326,
+ 327,
+ 328,
+ 329,
+ 330,
+ 331,
+ 332,
+ 333,
+ 334,
+ 335,
+ 336,
+ 337,
+ 338,
+ 339,
+ 340,
+ 341,
+ 342,
+ 343,
+ 344,
+ 345,
+ 346,
+ 347,
+ 348,
+ 349,
+ 350,
+ 351,
+ 352,
+ 353,
+ 354,
+ 355,
+ 356,
+ 357,
+ 358,
+ 359,
+ 360,
+ 361,
+ 362,
+ 363,
+ 364,
+ 365,
+ 366,
+ 367,
+ 368,
+ 369,
+ 370,
+ 371,
+ 372,
+ 373,
+ 374,
+ 375,
+ 376,
+ 377,
+ 378,
+ 379,
+ 380,
+ 381,
+ 382,
+ 383,
+ 384,
+ 385,
+ 386,
+ 387,
+ 388,
+ 389,
+ 390,
+ 391,
+ 392,
+ 393,
+ 394,
+ 395,
+ 396,
+ 397,
+ 398,
+ 399,
+ 400,
+ 401,
+ 402,
+ 403,
+ 404,
+ 405,
+ 406,
+ 407,
+ 408,
+ 409,
+ 410,
+ 411,
+ 412,
+ 413,
+ 414,
+ 415,
+ 416,
+ 417,
+ 418,
+ 419,
+ 420,
+ 421,
+ 422,
+ 423,
+ 424,
+ 425,
+ 426,
+ 427,
+ 428,
+ 429,
+ 430,
+ 431,
+ 432,
+ 433,
+ 434,
+ 435,
+ 436,
+ 437,
+ 438,
+ 439,
+ 440,
+ 441,
+ 442,
+ 443,
+ 444,
+ 445,
+ 446,
+ 447,
+ 448,
+ 449,
+ 450,
+ 451,
+ 452,
+ 453,
+ 454,
+ 455,
+ 456,
+ 457,
+ 458,
+ 459,
+ 460,
+ 461,
+ 462,
+ 463,
+ 464,
+ 465,
+ 466,
+ 467,
+ 468,
+ 469,
+ 470,
+ 471,
+ 472,
+ 473,
+ 474,
+ 475,
+ 476,
+ 477,
+ 478,
+ 479,
+ 480,
+ 481,
+ 482,
+ 483,
+ 484,
+ 485,
+ 486,
+ 487,
+ 488,
+ 489,
+ 490,
+ 491,
+ 492,
+ 493,
+ 494,
+ 495,
+ 496,
+ 497,
+ 498,
+ 499,
+ 500,
+ 501,
+ 502,
+ 503,
+ 504,
+ 505,
+ 506,
+ 507,
+ 508,
+ 509,
+ 510,
+ 511,
+ 512,
+ 513,
+ 514,
+ 515,
+ 516,
+ 517,
+ 518,
+ 519,
+ 520,
+ 521,
+ 522,
+ 523,
+ 524,
+ 525,
+ 526,
+ 527,
+ 528,
+ 529,
+ 530,
+ 531,
+ 532,
+ 533,
+ 534,
+ 535,
+ 536,
+ 537,
+ 538,
+ 539,
+ 540,
+ 541,
+ 542,
+ 543,
+ 544,
+ 545,
+ 546,
+ 547,
+ 548,
+ 549,
+ 550,
+ 551,
+ 552,
+ 553,
+ 554,
+ 555,
+ 556,
+ 557,
+ 558,
+ 559,
+ 560,
+ 561,
+ 562,
+ 563,
+ 564,
+ 565,
+ 566,
+ 567,
+ 568,
+ 569,
+ 570,
+ 571,
+ 572,
+ 573,
+ 574,
+ 575,
+ 576,
+ 577,
+ 578,
+ 579,
+ 580,
+ 581,
+ 582,
+ 583,
+ 584,
+ 585,
+ 586,
+ 587,
+ 588,
+ 589,
+ 590,
+ 591,
+ 592,
+ 593,
+ 594,
+ 595,
+ 596,
+ 597,
+ 598,
+ 599,
+ 600,
+ 601,
+ 602,
+ 603,
+ 604,
+ 605,
+ 606,
+ 607,
+ 608,
+ 609,
+ 610,
+ 611,
+ 612,
+ 613,
+ 614,
+ 615,
+ 616,
+ 617,
+ 618,
+ 619,
+ 620,
+ 621,
+ 622,
+ 623,
+ 624,
+ 625,
+ 626,
+ 627,
+ 628,
+ 629,
+ 630,
+ 631,
+ 632,
+ 633,
+ 634,
+ 635,
+ 636,
+ 637,
+ 638,
+ 639,
+ 640,
+ 641,
+ 642,
+ 643,
+ 644,
+ 645,
+ 646,
+ 647,
+ 648,
+ 649,
+ 650,
+ 651,
+ 652,
+ 653,
+ 654,
+ 655,
+ 656,
+ 657,
+ 658,
+ 659,
+ 660,
+ 661,
+ 662,
+ 663,
+ 664,
+ 665,
+ 666,
+ 667,
+ 668,
+ 669,
+ 670,
+ 671,
+ 672,
+ 673,
+ 674,
+ 675,
+ 676,
+ 677,
+ 678,
+ 679,
+ 680,
+ 681,
+ 682,
+ 683,
+ 684,
+ 685,
+ 686,
+ 687,
+ 688,
+ 689,
+ 690,
+ 691,
+ 692,
+ 693,
+ 694,
+ 695,
+ 696,
+ 697,
+ 698,
+ 699,
+ 700,
+ 701,
+ 702,
+ 703,
+ 704,
+ 705,
+ 710,
+ 711,
+ 712,
+ 713,
+ 714,
+ 715,
+ 716,
+ 717,
+ 718,
+ 719,
+ 720,
+ 721,
+ 736,
+ 737,
+ 738,
+ 739,
+ 740,
+ 748,
+ 750,
+ 880,
+ 881,
+ 882,
+ 883,
+ 884,
+ 886,
+ 887,
+ 890,
+ 891,
+ 892,
+ 893,
+ 902,
+ 904,
+ 905,
+ 906,
+ 908,
+ 910,
+ 911,
+ 912,
+ 913,
+ 914,
+ 915,
+ 916,
+ 917,
+ 918,
+ 919,
+ 920,
+ 921,
+ 922,
+ 923,
+ 924,
+ 925,
+ 926,
+ 927,
+ 928,
+ 929,
+ 931,
+ 932,
+ 933,
+ 934,
+ 935,
+ 936,
+ 937,
+ 938,
+ 939,
+ 940,
+ 941,
+ 942,
+ 943,
+ 944,
+ 945,
+ 946,
+ 947,
+ 948,
+ 949,
+ 950,
+ 951,
+ 952,
+ 953,
+ 954,
+ 955,
+ 956,
+ 957,
+ 958,
+ 959,
+ 960,
+ 961,
+ 962,
+ 963,
+ 964,
+ 965,
+ 966,
+ 967,
+ 968,
+ 969,
+ 970,
+ 971,
+ 972,
+ 973,
+ 974,
+ 975,
+ 976,
+ 977,
+ 978,
+ 979,
+ 980,
+ 981,
+ 982,
+ 983,
+ 984,
+ 985,
+ 986,
+ 987,
+ 988,
+ 989,
+ 990,
+ 991,
+ 992,
+ 993,
+ 994,
+ 995,
+ 996,
+ 997,
+ 998,
+ 999,
+ 1000,
+ 1001,
+ 1002,
+ 1003,
+ 1004,
+ 1005,
+ 1006,
+ 1007,
+ 1008,
+ 1009,
+ 1010,
+ 1011,
+ 1012,
+ 1013,
+ 1015,
+ 1016,
+ 1017,
+ 1018,
+ 1019,
+ 1020,
+ 1021,
+ 1022,
+ 1023,
+ 1024,
+ 1025,
+ 1026,
+ 1027,
+ 1028,
+ 1029,
+ 1030,
+ 1031,
+ 1032,
+ 1033,
+ 1034,
+ 1035,
+ 1036,
+ 1037,
+ 1038,
+ 1039,
+ 1040,
+ 1041,
+ 1042,
+ 1043,
+ 1044,
+ 1045,
+ 1046,
+ 1047,
+ 1048,
+ 1049,
+ 1050,
+ 1051,
+ 1052,
+ 1053,
+ 1054,
+ 1055,
+ 1056,
+ 1057,
+ 1058,
+ 1059,
+ 1060,
+ 1061,
+ 1062,
+ 1063,
+ 1064,
+ 1065,
+ 1066,
+ 1067,
+ 1068,
+ 1069,
+ 1070,
+ 1071,
+ 1072,
+ 1073,
+ 1074,
+ 1075,
+ 1076,
+ 1077,
+ 1078,
+ 1079,
+ 1080,
+ 1081,
+ 1082,
+ 1083,
+ 1084,
+ 1085,
+ 1086,
+ 1087,
+ 1088,
+ 1089,
+ 1090,
+ 1091,
+ 1092,
+ 1093,
+ 1094,
+ 1095,
+ 1096,
+ 1097,
+ 1098,
+ 1099,
+ 1100,
+ 1101,
+ 1102,
+ 1103,
+ 1104,
+ 1105,
+ 1106,
+ 1107,
+ 1108,
+ 1109,
+ 1110,
+ 1111,
+ 1112,
+ 1113,
+ 1114,
+ 1115,
+ 1116,
+ 1117,
+ 1118,
+ 1119,
+ 1120,
+ 1121,
+ 1122,
+ 1123,
+ 1124,
+ 1125,
+ 1126,
+ 1127,
+ 1128,
+ 1129,
+ 1130,
+ 1131,
+ 1132,
+ 1133,
+ 1134,
+ 1135,
+ 1136,
+ 1137,
+ 1138,
+ 1139,
+ 1140,
+ 1141,
+ 1142,
+ 1143,
+ 1144,
+ 1145,
+ 1146,
+ 1147,
+ 1148,
+ 1149,
+ 1150,
+ 1151,
+ 1152,
+ 1153,
+ 1162,
+ 1163,
+ 1164,
+ 1165,
+ 1166,
+ 1167,
+ 1168,
+ 1169,
+ 1170,
+ 1171,
+ 1172,
+ 1173,
+ 1174,
+ 1175,
+ 1176,
+ 1177,
+ 1178,
+ 1179,
+ 1180,
+ 1181,
+ 1182,
+ 1183,
+ 1184,
+ 1185,
+ 1186,
+ 1187,
+ 1188,
+ 1189,
+ 1190,
+ 1191,
+ 1192,
+ 1193,
+ 1194,
+ 1195,
+ 1196,
+ 1197,
+ 1198,
+ 1199,
+ 1200,
+ 1201,
+ 1202,
+ 1203,
+ 1204,
+ 1205,
+ 1206,
+ 1207,
+ 1208,
+ 1209,
+ 1210,
+ 1211,
+ 1212,
+ 1213,
+ 1214,
+ 1215,
+ 1216,
+ 1217,
+ 1218,
+ 1219,
+ 1220,
+ 1221,
+ 1222,
+ 1223,
+ 1224,
+ 1225,
+ 1226,
+ 1227,
+ 1228,
+ 1229,
+ 1230,
+ 1231,
+ 1232,
+ 1233,
+ 1234,
+ 1235,
+ 1236,
+ 1237,
+ 1238,
+ 1239,
+ 1240,
+ 1241,
+ 1242,
+ 1243,
+ 1244,
+ 1245,
+ 1246,
+ 1247,
+ 1248,
+ 1249,
+ 1250,
+ 1251,
+ 1252,
+ 1253,
+ 1254,
+ 1255,
+ 1256,
+ 1257,
+ 1258,
+ 1259,
+ 1260,
+ 1261,
+ 1262,
+ 1263,
+ 1264,
+ 1265,
+ 1266,
+ 1267,
+ 1268,
+ 1269,
+ 1270,
+ 1271,
+ 1272,
+ 1273,
+ 1274,
+ 1275,
+ 1276,
+ 1277,
+ 1278,
+ 1279,
+ 1280,
+ 1281,
+ 1282,
+ 1283,
+ 1284,
+ 1285,
+ 1286,
+ 1287,
+ 1288,
+ 1289,
+ 1290,
+ 1291,
+ 1292,
+ 1293,
+ 1294,
+ 1295,
+ 1296,
+ 1297,
+ 1298,
+ 1299,
+ 1300,
+ 1301,
+ 1302,
+ 1303,
+ 1304,
+ 1305,
+ 1306,
+ 1307,
+ 1308,
+ 1309,
+ 1310,
+ 1311,
+ 1312,
+ 1313,
+ 1314,
+ 1315,
+ 1316,
+ 1317,
+ 1318,
+ 1319,
+ 1329,
+ 1330,
+ 1331,
+ 1332,
+ 1333,
+ 1334,
+ 1335,
+ 1336,
+ 1337,
+ 1338,
+ 1339,
+ 1340,
+ 1341,
+ 1342,
+ 1343,
+ 1344,
+ 1345,
+ 1346,
+ 1347,
+ 1348,
+ 1349,
+ 1350,
+ 1351,
+ 1352,
+ 1353,
+ 1354,
+ 1355,
+ 1356,
+ 1357,
+ 1358,
+ 1359,
+ 1360,
+ 1361,
+ 1362,
+ 1363,
+ 1364,
+ 1365,
+ 1366,
+ 1369,
+ 1377,
+ 1378,
+ 1379,
+ 1380,
+ 1381,
+ 1382,
+ 1383,
+ 1384,
+ 1385,
+ 1386,
+ 1387,
+ 1388,
+ 1389,
+ 1390,
+ 1391,
+ 1392,
+ 1393,
+ 1394,
+ 1395,
+ 1396,
+ 1397,
+ 1398,
+ 1399,
+ 1400,
+ 1401,
+ 1402,
+ 1403,
+ 1404,
+ 1405,
+ 1406,
+ 1407,
+ 1408,
+ 1409,
+ 1410,
+ 1411,
+ 1412,
+ 1413,
+ 1414,
+ 1415,
+ 1488,
+ 1489,
+ 1490,
+ 1491,
+ 1492,
+ 1493,
+ 1494,
+ 1495,
+ 1496,
+ 1497,
+ 1498,
+ 1499,
+ 1500,
+ 1501,
+ 1502,
+ 1503,
+ 1504,
+ 1505,
+ 1506,
+ 1507,
+ 1508,
+ 1509,
+ 1510,
+ 1511,
+ 1512,
+ 1513,
+ 1514,
+ 1520,
+ 1521,
+ 1522,
+ 1568,
+ 1569,
+ 1570,
+ 1571,
+ 1572,
+ 1573,
+ 1574,
+ 1575,
+ 1576,
+ 1577,
+ 1578,
+ 1579,
+ 1580,
+ 1581,
+ 1582,
+ 1583,
+ 1584,
+ 1585,
+ 1586,
+ 1587,
+ 1588,
+ 1589,
+ 1590,
+ 1591,
+ 1592,
+ 1593,
+ 1594,
+ 1595,
+ 1596,
+ 1597,
+ 1598,
+ 1599,
+ 1600,
+ 1601,
+ 1602,
+ 1603,
+ 1604,
+ 1605,
+ 1606,
+ 1607,
+ 1608,
+ 1609,
+ 1610,
+ 1646,
+ 1647,
+ 1649,
+ 1650,
+ 1651,
+ 1652,
+ 1653,
+ 1654,
+ 1655,
+ 1656,
+ 1657,
+ 1658,
+ 1659,
+ 1660,
+ 1661,
+ 1662,
+ 1663,
+ 1664,
+ 1665,
+ 1666,
+ 1667,
+ 1668,
+ 1669,
+ 1670,
+ 1671,
+ 1672,
+ 1673,
+ 1674,
+ 1675,
+ 1676,
+ 1677,
+ 1678,
+ 1679,
+ 1680,
+ 1681,
+ 1682,
+ 1683,
+ 1684,
+ 1685,
+ 1686,
+ 1687,
+ 1688,
+ 1689,
+ 1690,
+ 1691,
+ 1692,
+ 1693,
+ 1694,
+ 1695,
+ 1696,
+ 1697,
+ 1698,
+ 1699,
+ 1700,
+ 1701,
+ 1702,
+ 1703,
+ 1704,
+ 1705,
+ 1706,
+ 1707,
+ 1708,
+ 1709,
+ 1710,
+ 1711,
+ 1712,
+ 1713,
+ 1714,
+ 1715,
+ 1716,
+ 1717,
+ 1718,
+ 1719,
+ 1720,
+ 1721,
+ 1722,
+ 1723,
+ 1724,
+ 1725,
+ 1726,
+ 1727,
+ 1728,
+ 1729,
+ 1730,
+ 1731,
+ 1732,
+ 1733,
+ 1734,
+ 1735,
+ 1736,
+ 1737,
+ 1738,
+ 1739,
+ 1740,
+ 1741,
+ 1742,
+ 1743,
+ 1744,
+ 1745,
+ 1746,
+ 1747,
+ 1749,
+ 1765,
+ 1766,
+ 1774,
+ 1775,
+ 1786,
+ 1787,
+ 1788,
+ 1791,
+ 1808,
+ 1810,
+ 1811,
+ 1812,
+ 1813,
+ 1814,
+ 1815,
+ 1816,
+ 1817,
+ 1818,
+ 1819,
+ 1820,
+ 1821,
+ 1822,
+ 1823,
+ 1824,
+ 1825,
+ 1826,
+ 1827,
+ 1828,
+ 1829,
+ 1830,
+ 1831,
+ 1832,
+ 1833,
+ 1834,
+ 1835,
+ 1836,
+ 1837,
+ 1838,
+ 1839,
+ 1869,
+ 1870,
+ 1871,
+ 1872,
+ 1873,
+ 1874,
+ 1875,
+ 1876,
+ 1877,
+ 1878,
+ 1879,
+ 1880,
+ 1881,
+ 1882,
+ 1883,
+ 1884,
+ 1885,
+ 1886,
+ 1887,
+ 1888,
+ 1889,
+ 1890,
+ 1891,
+ 1892,
+ 1893,
+ 1894,
+ 1895,
+ 1896,
+ 1897,
+ 1898,
+ 1899,
+ 1900,
+ 1901,
+ 1902,
+ 1903,
+ 1904,
+ 1905,
+ 1906,
+ 1907,
+ 1908,
+ 1909,
+ 1910,
+ 1911,
+ 1912,
+ 1913,
+ 1914,
+ 1915,
+ 1916,
+ 1917,
+ 1918,
+ 1919,
+ 1920,
+ 1921,
+ 1922,
+ 1923,
+ 1924,
+ 1925,
+ 1926,
+ 1927,
+ 1928,
+ 1929,
+ 1930,
+ 1931,
+ 1932,
+ 1933,
+ 1934,
+ 1935,
+ 1936,
+ 1937,
+ 1938,
+ 1939,
+ 1940,
+ 1941,
+ 1942,
+ 1943,
+ 1944,
+ 1945,
+ 1946,
+ 1947,
+ 1948,
+ 1949,
+ 1950,
+ 1951,
+ 1952,
+ 1953,
+ 1954,
+ 1955,
+ 1956,
+ 1957,
+ 1969,
+ 1994,
+ 1995,
+ 1996,
+ 1997,
+ 1998,
+ 1999,
+ 2000,
+ 2001,
+ 2002,
+ 2003,
+ 2004,
+ 2005,
+ 2006,
+ 2007,
+ 2008,
+ 2009,
+ 2010,
+ 2011,
+ 2012,
+ 2013,
+ 2014,
+ 2015,
+ 2016,
+ 2017,
+ 2018,
+ 2019,
+ 2020,
+ 2021,
+ 2022,
+ 2023,
+ 2024,
+ 2025,
+ 2026,
+ 2036,
+ 2037,
+ 2042,
+ 2048,
+ 2049,
+ 2050,
+ 2051,
+ 2052,
+ 2053,
+ 2054,
+ 2055,
+ 2056,
+ 2057,
+ 2058,
+ 2059,
+ 2060,
+ 2061,
+ 2062,
+ 2063,
+ 2064,
+ 2065,
+ 2066,
+ 2067,
+ 2068,
+ 2069,
+ 2074,
+ 2084,
+ 2088,
+ 2112,
+ 2113,
+ 2114,
+ 2115,
+ 2116,
+ 2117,
+ 2118,
+ 2119,
+ 2120,
+ 2121,
+ 2122,
+ 2123,
+ 2124,
+ 2125,
+ 2126,
+ 2127,
+ 2128,
+ 2129,
+ 2130,
+ 2131,
+ 2132,
+ 2133,
+ 2134,
+ 2135,
+ 2136,
+ 2208,
+ 2210,
+ 2211,
+ 2212,
+ 2213,
+ 2214,
+ 2215,
+ 2216,
+ 2217,
+ 2218,
+ 2219,
+ 2220,
+ 2308,
+ 2309,
+ 2310,
+ 2311,
+ 2312,
+ 2313,
+ 2314,
+ 2315,
+ 2316,
+ 2317,
+ 2318,
+ 2319,
+ 2320,
+ 2321,
+ 2322,
+ 2323,
+ 2324,
+ 2325,
+ 2326,
+ 2327,
+ 2328,
+ 2329,
+ 2330,
+ 2331,
+ 2332,
+ 2333,
+ 2334,
+ 2335,
+ 2336,
+ 2337,
+ 2338,
+ 2339,
+ 2340,
+ 2341,
+ 2342,
+ 2343,
+ 2344,
+ 2345,
+ 2346,
+ 2347,
+ 2348,
+ 2349,
+ 2350,
+ 2351,
+ 2352,
+ 2353,
+ 2354,
+ 2355,
+ 2356,
+ 2357,
+ 2358,
+ 2359,
+ 2360,
+ 2361,
+ 2365,
+ 2384,
+ 2392,
+ 2393,
+ 2394,
+ 2395,
+ 2396,
+ 2397,
+ 2398,
+ 2399,
+ 2400,
+ 2401,
+ 2417,
+ 2418,
+ 2419,
+ 2420,
+ 2421,
+ 2422,
+ 2423,
+ 2425,
+ 2426,
+ 2427,
+ 2428,
+ 2429,
+ 2430,
+ 2431,
+ 2437,
+ 2438,
+ 2439,
+ 2440,
+ 2441,
+ 2442,
+ 2443,
+ 2444,
+ 2447,
+ 2448,
+ 2451,
+ 2452,
+ 2453,
+ 2454,
+ 2455,
+ 2456,
+ 2457,
+ 2458,
+ 2459,
+ 2460,
+ 2461,
+ 2462,
+ 2463,
+ 2464,
+ 2465,
+ 2466,
+ 2467,
+ 2468,
+ 2469,
+ 2470,
+ 2471,
+ 2472,
+ 2474,
+ 2475,
+ 2476,
+ 2477,
+ 2478,
+ 2479,
+ 2480,
+ 2482,
+ 2486,
+ 2487,
+ 2488,
+ 2489,
+ 2493,
+ 2510,
+ 2524,
+ 2525,
+ 2527,
+ 2528,
+ 2529,
+ 2544,
+ 2545,
+ 2565,
+ 2566,
+ 2567,
+ 2568,
+ 2569,
+ 2570,
+ 2575,
+ 2576,
+ 2579,
+ 2580,
+ 2581,
+ 2582,
+ 2583,
+ 2584,
+ 2585,
+ 2586,
+ 2587,
+ 2588,
+ 2589,
+ 2590,
+ 2591,
+ 2592,
+ 2593,
+ 2594,
+ 2595,
+ 2596,
+ 2597,
+ 2598,
+ 2599,
+ 2600,
+ 2602,
+ 2603,
+ 2604,
+ 2605,
+ 2606,
+ 2607,
+ 2608,
+ 2610,
+ 2611,
+ 2613,
+ 2614,
+ 2616,
+ 2617,
+ 2649,
+ 2650,
+ 2651,
+ 2652,
+ 2654,
+ 2674,
+ 2675,
+ 2676,
+ 2693,
+ 2694,
+ 2695,
+ 2696,
+ 2697,
+ 2698,
+ 2699,
+ 2700,
+ 2701,
+ 2703,
+ 2704,
+ 2705,
+ 2707,
+ 2708,
+ 2709,
+ 2710,
+ 2711,
+ 2712,
+ 2713,
+ 2714,
+ 2715,
+ 2716,
+ 2717,
+ 2718,
+ 2719,
+ 2720,
+ 2721,
+ 2722,
+ 2723,
+ 2724,
+ 2725,
+ 2726,
+ 2727,
+ 2728,
+ 2730,
+ 2731,
+ 2732,
+ 2733,
+ 2734,
+ 2735,
+ 2736,
+ 2738,
+ 2739,
+ 2741,
+ 2742,
+ 2743,
+ 2744,
+ 2745,
+ 2749,
+ 2768,
+ 2784,
+ 2785,
+ 2821,
+ 2822,
+ 2823,
+ 2824,
+ 2825,
+ 2826,
+ 2827,
+ 2828,
+ 2831,
+ 2832,
+ 2835,
+ 2836,
+ 2837,
+ 2838,
+ 2839,
+ 2840,
+ 2841,
+ 2842,
+ 2843,
+ 2844,
+ 2845,
+ 2846,
+ 2847,
+ 2848,
+ 2849,
+ 2850,
+ 2851,
+ 2852,
+ 2853,
+ 2854,
+ 2855,
+ 2856,
+ 2858,
+ 2859,
+ 2860,
+ 2861,
+ 2862,
+ 2863,
+ 2864,
+ 2866,
+ 2867,
+ 2869,
+ 2870,
+ 2871,
+ 2872,
+ 2873,
+ 2877,
+ 2908,
+ 2909,
+ 2911,
+ 2912,
+ 2913,
+ 2929,
+ 2947,
+ 2949,
+ 2950,
+ 2951,
+ 2952,
+ 2953,
+ 2954,
+ 2958,
+ 2959,
+ 2960,
+ 2962,
+ 2963,
+ 2964,
+ 2965,
+ 2969,
+ 2970,
+ 2972,
+ 2974,
+ 2975,
+ 2979,
+ 2980,
+ 2984,
+ 2985,
+ 2986,
+ 2990,
+ 2991,
+ 2992,
+ 2993,
+ 2994,
+ 2995,
+ 2996,
+ 2997,
+ 2998,
+ 2999,
+ 3000,
+ 3001,
+ 3024,
+ 3077,
+ 3078,
+ 3079,
+ 3080,
+ 3081,
+ 3082,
+ 3083,
+ 3084,
+ 3086,
+ 3087,
+ 3088,
+ 3090,
+ 3091,
+ 3092,
+ 3093,
+ 3094,
+ 3095,
+ 3096,
+ 3097,
+ 3098,
+ 3099,
+ 3100,
+ 3101,
+ 3102,
+ 3103,
+ 3104,
+ 3105,
+ 3106,
+ 3107,
+ 3108,
+ 3109,
+ 3110,
+ 3111,
+ 3112,
+ 3114,
+ 3115,
+ 3116,
+ 3117,
+ 3118,
+ 3119,
+ 3120,
+ 3121,
+ 3122,
+ 3123,
+ 3125,
+ 3126,
+ 3127,
+ 3128,
+ 3129,
+ 3133,
+ 3160,
+ 3161,
+ 3168,
+ 3169,
+ 3205,
+ 3206,
+ 3207,
+ 3208,
+ 3209,
+ 3210,
+ 3211,
+ 3212,
+ 3214,
+ 3215,
+ 3216,
+ 3218,
+ 3219,
+ 3220,
+ 3221,
+ 3222,
+ 3223,
+ 3224,
+ 3225,
+ 3226,
+ 3227,
+ 3228,
+ 3229,
+ 3230,
+ 3231,
+ 3232,
+ 3233,
+ 3234,
+ 3235,
+ 3236,
+ 3237,
+ 3238,
+ 3239,
+ 3240,
+ 3242,
+ 3243,
+ 3244,
+ 3245,
+ 3246,
+ 3247,
+ 3248,
+ 3249,
+ 3250,
+ 3251,
+ 3253,
+ 3254,
+ 3255,
+ 3256,
+ 3257,
+ 3261,
+ 3294,
+ 3296,
+ 3297,
+ 3313,
+ 3314,
+ 3333,
+ 3334,
+ 3335,
+ 3336,
+ 3337,
+ 3338,
+ 3339,
+ 3340,
+ 3342,
+ 3343,
+ 3344,
+ 3346,
+ 3347,
+ 3348,
+ 3349,
+ 3350,
+ 3351,
+ 3352,
+ 3353,
+ 3354,
+ 3355,
+ 3356,
+ 3357,
+ 3358,
+ 3359,
+ 3360,
+ 3361,
+ 3362,
+ 3363,
+ 3364,
+ 3365,
+ 3366,
+ 3367,
+ 3368,
+ 3369,
+ 3370,
+ 3371,
+ 3372,
+ 3373,
+ 3374,
+ 3375,
+ 3376,
+ 3377,
+ 3378,
+ 3379,
+ 3380,
+ 3381,
+ 3382,
+ 3383,
+ 3384,
+ 3385,
+ 3386,
+ 3389,
+ 3406,
+ 3424,
+ 3425,
+ 3450,
+ 3451,
+ 3452,
+ 3453,
+ 3454,
+ 3455,
+ 3461,
+ 3462,
+ 3463,
+ 3464,
+ 3465,
+ 3466,
+ 3467,
+ 3468,
+ 3469,
+ 3470,
+ 3471,
+ 3472,
+ 3473,
+ 3474,
+ 3475,
+ 3476,
+ 3477,
+ 3478,
+ 3482,
+ 3483,
+ 3484,
+ 3485,
+ 3486,
+ 3487,
+ 3488,
+ 3489,
+ 3490,
+ 3491,
+ 3492,
+ 3493,
+ 3494,
+ 3495,
+ 3496,
+ 3497,
+ 3498,
+ 3499,
+ 3500,
+ 3501,
+ 3502,
+ 3503,
+ 3504,
+ 3505,
+ 3507,
+ 3508,
+ 3509,
+ 3510,
+ 3511,
+ 3512,
+ 3513,
+ 3514,
+ 3515,
+ 3517,
+ 3520,
+ 3521,
+ 3522,
+ 3523,
+ 3524,
+ 3525,
+ 3526,
+ 3585,
+ 3586,
+ 3587,
+ 3588,
+ 3589,
+ 3590,
+ 3591,
+ 3592,
+ 3593,
+ 3594,
+ 3595,
+ 3596,
+ 3597,
+ 3598,
+ 3599,
+ 3600,
+ 3601,
+ 3602,
+ 3603,
+ 3604,
+ 3605,
+ 3606,
+ 3607,
+ 3608,
+ 3609,
+ 3610,
+ 3611,
+ 3612,
+ 3613,
+ 3614,
+ 3615,
+ 3616,
+ 3617,
+ 3618,
+ 3619,
+ 3620,
+ 3621,
+ 3622,
+ 3623,
+ 3624,
+ 3625,
+ 3626,
+ 3627,
+ 3628,
+ 3629,
+ 3630,
+ 3631,
+ 3632,
+ 3634,
+ 3635,
+ 3648,
+ 3649,
+ 3650,
+ 3651,
+ 3652,
+ 3653,
+ 3654,
+ 3713,
+ 3714,
+ 3716,
+ 3719,
+ 3720,
+ 3722,
+ 3725,
+ 3732,
+ 3733,
+ 3734,
+ 3735,
+ 3737,
+ 3738,
+ 3739,
+ 3740,
+ 3741,
+ 3742,
+ 3743,
+ 3745,
+ 3746,
+ 3747,
+ 3749,
+ 3751,
+ 3754,
+ 3755,
+ 3757,
+ 3758,
+ 3759,
+ 3760,
+ 3762,
+ 3763,
+ 3773,
+ 3776,
+ 3777,
+ 3778,
+ 3779,
+ 3780,
+ 3782,
+ 3804,
+ 3805,
+ 3806,
+ 3807,
+ 3840,
+ 3904,
+ 3905,
+ 3906,
+ 3907,
+ 3908,
+ 3909,
+ 3910,
+ 3911,
+ 3913,
+ 3914,
+ 3915,
+ 3916,
+ 3917,
+ 3918,
+ 3919,
+ 3920,
+ 3921,
+ 3922,
+ 3923,
+ 3924,
+ 3925,
+ 3926,
+ 3927,
+ 3928,
+ 3929,
+ 3930,
+ 3931,
+ 3932,
+ 3933,
+ 3934,
+ 3935,
+ 3936,
+ 3937,
+ 3938,
+ 3939,
+ 3940,
+ 3941,
+ 3942,
+ 3943,
+ 3944,
+ 3945,
+ 3946,
+ 3947,
+ 3948,
+ 3976,
+ 3977,
+ 3978,
+ 3979,
+ 3980,
+ 4096,
+ 4097,
+ 4098,
+ 4099,
+ 4100,
+ 4101,
+ 4102,
+ 4103,
+ 4104,
+ 4105,
+ 4106,
+ 4107,
+ 4108,
+ 4109,
+ 4110,
+ 4111,
+ 4112,
+ 4113,
+ 4114,
+ 4115,
+ 4116,
+ 4117,
+ 4118,
+ 4119,
+ 4120,
+ 4121,
+ 4122,
+ 4123,
+ 4124,
+ 4125,
+ 4126,
+ 4127,
+ 4128,
+ 4129,
+ 4130,
+ 4131,
+ 4132,
+ 4133,
+ 4134,
+ 4135,
+ 4136,
+ 4137,
+ 4138,
+ 4159,
+ 4176,
+ 4177,
+ 4178,
+ 4179,
+ 4180,
+ 4181,
+ 4186,
+ 4187,
+ 4188,
+ 4189,
+ 4193,
+ 4197,
+ 4198,
+ 4206,
+ 4207,
+ 4208,
+ 4213,
+ 4214,
+ 4215,
+ 4216,
+ 4217,
+ 4218,
+ 4219,
+ 4220,
+ 4221,
+ 4222,
+ 4223,
+ 4224,
+ 4225,
+ 4238,
+ 4256,
+ 4257,
+ 4258,
+ 4259,
+ 4260,
+ 4261,
+ 4262,
+ 4263,
+ 4264,
+ 4265,
+ 4266,
+ 4267,
+ 4268,
+ 4269,
+ 4270,
+ 4271,
+ 4272,
+ 4273,
+ 4274,
+ 4275,
+ 4276,
+ 4277,
+ 4278,
+ 4279,
+ 4280,
+ 4281,
+ 4282,
+ 4283,
+ 4284,
+ 4285,
+ 4286,
+ 4287,
+ 4288,
+ 4289,
+ 4290,
+ 4291,
+ 4292,
+ 4293,
+ 4295,
+ 4301,
+ 4304,
+ 4305,
+ 4306,
+ 4307,
+ 4308,
+ 4309,
+ 4310,
+ 4311,
+ 4312,
+ 4313,
+ 4314,
+ 4315,
+ 4316,
+ 4317,
+ 4318,
+ 4319,
+ 4320,
+ 4321,
+ 4322,
+ 4323,
+ 4324,
+ 4325,
+ 4326,
+ 4327,
+ 4328,
+ 4329,
+ 4330,
+ 4331,
+ 4332,
+ 4333,
+ 4334,
+ 4335,
+ 4336,
+ 4337,
+ 4338,
+ 4339,
+ 4340,
+ 4341,
+ 4342,
+ 4343,
+ 4344,
+ 4345,
+ 4346,
+ 4348,
+ 4349,
+ 4350,
+ 4351,
+ 4352,
+ 4353,
+ 4354,
+ 4355,
+ 4356,
+ 4357,
+ 4358,
+ 4359,
+ 4360,
+ 4361,
+ 4362,
+ 4363,
+ 4364,
+ 4365,
+ 4366,
+ 4367,
+ 4368,
+ 4369,
+ 4370,
+ 4371,
+ 4372,
+ 4373,
+ 4374,
+ 4375,
+ 4376,
+ 4377,
+ 4378,
+ 4379,
+ 4380,
+ 4381,
+ 4382,
+ 4383,
+ 4384,
+ 4385,
+ 4386,
+ 4387,
+ 4388,
+ 4389,
+ 4390,
+ 4391,
+ 4392,
+ 4393,
+ 4394,
+ 4395,
+ 4396,
+ 4397,
+ 4398,
+ 4399,
+ 4400,
+ 4401,
+ 4402,
+ 4403,
+ 4404,
+ 4405,
+ 4406,
+ 4407,
+ 4408,
+ 4409,
+ 4410,
+ 4411,
+ 4412,
+ 4413,
+ 4414,
+ 4415,
+ 4416,
+ 4417,
+ 4418,
+ 4419,
+ 4420,
+ 4421,
+ 4422,
+ 4423,
+ 4424,
+ 4425,
+ 4426,
+ 4427,
+ 4428,
+ 4429,
+ 4430,
+ 4431,
+ 4432,
+ 4433,
+ 4434,
+ 4435,
+ 4436,
+ 4437,
+ 4438,
+ 4439,
+ 4440,
+ 4441,
+ 4442,
+ 4443,
+ 4444,
+ 4445,
+ 4446,
+ 4447,
+ 4448,
+ 4449,
+ 4450,
+ 4451,
+ 4452,
+ 4453,
+ 4454,
+ 4455,
+ 4456,
+ 4457,
+ 4458,
+ 4459,
+ 4460,
+ 4461,
+ 4462,
+ 4463,
+ 4464,
+ 4465,
+ 4466,
+ 4467,
+ 4468,
+ 4469,
+ 4470,
+ 4471,
+ 4472,
+ 4473,
+ 4474,
+ 4475,
+ 4476,
+ 4477,
+ 4478,
+ 4479,
+ 4480,
+ 4481,
+ 4482,
+ 4483,
+ 4484,
+ 4485,
+ 4486,
+ 4487,
+ 4488,
+ 4489,
+ 4490,
+ 4491,
+ 4492,
+ 4493,
+ 4494,
+ 4495,
+ 4496,
+ 4497,
+ 4498,
+ 4499,
+ 4500,
+ 4501,
+ 4502,
+ 4503,
+ 4504,
+ 4505,
+ 4506,
+ 4507,
+ 4508,
+ 4509,
+ 4510,
+ 4511,
+ 4512,
+ 4513,
+ 4514,
+ 4515,
+ 4516,
+ 4517,
+ 4518,
+ 4519,
+ 4520,
+ 4521,
+ 4522,
+ 4523,
+ 4524,
+ 4525,
+ 4526,
+ 4527,
+ 4528,
+ 4529,
+ 4530,
+ 4531,
+ 4532,
+ 4533,
+ 4534,
+ 4535,
+ 4536,
+ 4537,
+ 4538,
+ 4539,
+ 4540,
+ 4541,
+ 4542,
+ 4543,
+ 4544,
+ 4545,
+ 4546,
+ 4547,
+ 4548,
+ 4549,
+ 4550,
+ 4551,
+ 4552,
+ 4553,
+ 4554,
+ 4555,
+ 4556,
+ 4557,
+ 4558,
+ 4559,
+ 4560,
+ 4561,
+ 4562,
+ 4563,
+ 4564,
+ 4565,
+ 4566,
+ 4567,
+ 4568,
+ 4569,
+ 4570,
+ 4571,
+ 4572,
+ 4573,
+ 4574,
+ 4575,
+ 4576,
+ 4577,
+ 4578,
+ 4579,
+ 4580,
+ 4581,
+ 4582,
+ 4583,
+ 4584,
+ 4585,
+ 4586,
+ 4587,
+ 4588,
+ 4589,
+ 4590,
+ 4591,
+ 4592,
+ 4593,
+ 4594,
+ 4595,
+ 4596,
+ 4597,
+ 4598,
+ 4599,
+ 4600,
+ 4601,
+ 4602,
+ 4603,
+ 4604,
+ 4605,
+ 4606,
+ 4607,
+ 4608,
+ 4609,
+ 4610,
+ 4611,
+ 4612,
+ 4613,
+ 4614,
+ 4615,
+ 4616,
+ 4617,
+ 4618,
+ 4619,
+ 4620,
+ 4621,
+ 4622,
+ 4623,
+ 4624,
+ 4625,
+ 4626,
+ 4627,
+ 4628,
+ 4629,
+ 4630,
+ 4631,
+ 4632,
+ 4633,
+ 4634,
+ 4635,
+ 4636,
+ 4637,
+ 4638,
+ 4639,
+ 4640,
+ 4641,
+ 4642,
+ 4643,
+ 4644,
+ 4645,
+ 4646,
+ 4647,
+ 4648,
+ 4649,
+ 4650,
+ 4651,
+ 4652,
+ 4653,
+ 4654,
+ 4655,
+ 4656,
+ 4657,
+ 4658,
+ 4659,
+ 4660,
+ 4661,
+ 4662,
+ 4663,
+ 4664,
+ 4665,
+ 4666,
+ 4667,
+ 4668,
+ 4669,
+ 4670,
+ 4671,
+ 4672,
+ 4673,
+ 4674,
+ 4675,
+ 4676,
+ 4677,
+ 4678,
+ 4679,
+ 4680,
+ 4682,
+ 4683,
+ 4684,
+ 4685,
+ 4688,
+ 4689,
+ 4690,
+ 4691,
+ 4692,
+ 4693,
+ 4694,
+ 4696,
+ 4698,
+ 4699,
+ 4700,
+ 4701,
+ 4704,
+ 4705,
+ 4706,
+ 4707,
+ 4708,
+ 4709,
+ 4710,
+ 4711,
+ 4712,
+ 4713,
+ 4714,
+ 4715,
+ 4716,
+ 4717,
+ 4718,
+ 4719,
+ 4720,
+ 4721,
+ 4722,
+ 4723,
+ 4724,
+ 4725,
+ 4726,
+ 4727,
+ 4728,
+ 4729,
+ 4730,
+ 4731,
+ 4732,
+ 4733,
+ 4734,
+ 4735,
+ 4736,
+ 4737,
+ 4738,
+ 4739,
+ 4740,
+ 4741,
+ 4742,
+ 4743,
+ 4744,
+ 4746,
+ 4747,
+ 4748,
+ 4749,
+ 4752,
+ 4753,
+ 4754,
+ 4755,
+ 4756,
+ 4757,
+ 4758,
+ 4759,
+ 4760,
+ 4761,
+ 4762,
+ 4763,
+ 4764,
+ 4765,
+ 4766,
+ 4767,
+ 4768,
+ 4769,
+ 4770,
+ 4771,
+ 4772,
+ 4773,
+ 4774,
+ 4775,
+ 4776,
+ 4777,
+ 4778,
+ 4779,
+ 4780,
+ 4781,
+ 4782,
+ 4783,
+ 4784,
+ 4786,
+ 4787,
+ 4788,
+ 4789,
+ 4792,
+ 4793,
+ 4794,
+ 4795,
+ 4796,
+ 4797,
+ 4798,
+ 4800,
+ 4802,
+ 4803,
+ 4804,
+ 4805,
+ 4808,
+ 4809,
+ 4810,
+ 4811,
+ 4812,
+ 4813,
+ 4814,
+ 4815,
+ 4816,
+ 4817,
+ 4818,
+ 4819,
+ 4820,
+ 4821,
+ 4822,
+ 4824,
+ 4825,
+ 4826,
+ 4827,
+ 4828,
+ 4829,
+ 4830,
+ 4831,
+ 4832,
+ 4833,
+ 4834,
+ 4835,
+ 4836,
+ 4837,
+ 4838,
+ 4839,
+ 4840,
+ 4841,
+ 4842,
+ 4843,
+ 4844,
+ 4845,
+ 4846,
+ 4847,
+ 4848,
+ 4849,
+ 4850,
+ 4851,
+ 4852,
+ 4853,
+ 4854,
+ 4855,
+ 4856,
+ 4857,
+ 4858,
+ 4859,
+ 4860,
+ 4861,
+ 4862,
+ 4863,
+ 4864,
+ 4865,
+ 4866,
+ 4867,
+ 4868,
+ 4869,
+ 4870,
+ 4871,
+ 4872,
+ 4873,
+ 4874,
+ 4875,
+ 4876,
+ 4877,
+ 4878,
+ 4879,
+ 4880,
+ 4882,
+ 4883,
+ 4884,
+ 4885,
+ 4888,
+ 4889,
+ 4890,
+ 4891,
+ 4892,
+ 4893,
+ 4894,
+ 4895,
+ 4896,
+ 4897,
+ 4898,
+ 4899,
+ 4900,
+ 4901,
+ 4902,
+ 4903,
+ 4904,
+ 4905,
+ 4906,
+ 4907,
+ 4908,
+ 4909,
+ 4910,
+ 4911,
+ 4912,
+ 4913,
+ 4914,
+ 4915,
+ 4916,
+ 4917,
+ 4918,
+ 4919,
+ 4920,
+ 4921,
+ 4922,
+ 4923,
+ 4924,
+ 4925,
+ 4926,
+ 4927,
+ 4928,
+ 4929,
+ 4930,
+ 4931,
+ 4932,
+ 4933,
+ 4934,
+ 4935,
+ 4936,
+ 4937,
+ 4938,
+ 4939,
+ 4940,
+ 4941,
+ 4942,
+ 4943,
+ 4944,
+ 4945,
+ 4946,
+ 4947,
+ 4948,
+ 4949,
+ 4950,
+ 4951,
+ 4952,
+ 4953,
+ 4954,
+ 4992,
+ 4993,
+ 4994,
+ 4995,
+ 4996,
+ 4997,
+ 4998,
+ 4999,
+ 5000,
+ 5001,
+ 5002,
+ 5003,
+ 5004,
+ 5005,
+ 5006,
+ 5007,
+ 5024,
+ 5025,
+ 5026,
+ 5027,
+ 5028,
+ 5029,
+ 5030,
+ 5031,
+ 5032,
+ 5033,
+ 5034,
+ 5035,
+ 5036,
+ 5037,
+ 5038,
+ 5039,
+ 5040,
+ 5041,
+ 5042,
+ 5043,
+ 5044,
+ 5045,
+ 5046,
+ 5047,
+ 5048,
+ 5049,
+ 5050,
+ 5051,
+ 5052,
+ 5053,
+ 5054,
+ 5055,
+ 5056,
+ 5057,
+ 5058,
+ 5059,
+ 5060,
+ 5061,
+ 5062,
+ 5063,
+ 5064,
+ 5065,
+ 5066,
+ 5067,
+ 5068,
+ 5069,
+ 5070,
+ 5071,
+ 5072,
+ 5073,
+ 5074,
+ 5075,
+ 5076,
+ 5077,
+ 5078,
+ 5079,
+ 5080,
+ 5081,
+ 5082,
+ 5083,
+ 5084,
+ 5085,
+ 5086,
+ 5087,
+ 5088,
+ 5089,
+ 5090,
+ 5091,
+ 5092,
+ 5093,
+ 5094,
+ 5095,
+ 5096,
+ 5097,
+ 5098,
+ 5099,
+ 5100,
+ 5101,
+ 5102,
+ 5103,
+ 5104,
+ 5105,
+ 5106,
+ 5107,
+ 5108,
+ 5121,
+ 5122,
+ 5123,
+ 5124,
+ 5125,
+ 5126,
+ 5127,
+ 5128,
+ 5129,
+ 5130,
+ 5131,
+ 5132,
+ 5133,
+ 5134,
+ 5135,
+ 5136,
+ 5137,
+ 5138,
+ 5139,
+ 5140,
+ 5141,
+ 5142,
+ 5143,
+ 5144,
+ 5145,
+ 5146,
+ 5147,
+ 5148,
+ 5149,
+ 5150,
+ 5151,
+ 5152,
+ 5153,
+ 5154,
+ 5155,
+ 5156,
+ 5157,
+ 5158,
+ 5159,
+ 5160,
+ 5161,
+ 5162,
+ 5163,
+ 5164,
+ 5165,
+ 5166,
+ 5167,
+ 5168,
+ 5169,
+ 5170,
+ 5171,
+ 5172,
+ 5173,
+ 5174,
+ 5175,
+ 5176,
+ 5177,
+ 5178,
+ 5179,
+ 5180,
+ 5181,
+ 5182,
+ 5183,
+ 5184,
+ 5185,
+ 5186,
+ 5187,
+ 5188,
+ 5189,
+ 5190,
+ 5191,
+ 5192,
+ 5193,
+ 5194,
+ 5195,
+ 5196,
+ 5197,
+ 5198,
+ 5199,
+ 5200,
+ 5201,
+ 5202,
+ 5203,
+ 5204,
+ 5205,
+ 5206,
+ 5207,
+ 5208,
+ 5209,
+ 5210,
+ 5211,
+ 5212,
+ 5213,
+ 5214,
+ 5215,
+ 5216,
+ 5217,
+ 5218,
+ 5219,
+ 5220,
+ 5221,
+ 5222,
+ 5223,
+ 5224,
+ 5225,
+ 5226,
+ 5227,
+ 5228,
+ 5229,
+ 5230,
+ 5231,
+ 5232,
+ 5233,
+ 5234,
+ 5235,
+ 5236,
+ 5237,
+ 5238,
+ 5239,
+ 5240,
+ 5241,
+ 5242,
+ 5243,
+ 5244,
+ 5245,
+ 5246,
+ 5247,
+ 5248,
+ 5249,
+ 5250,
+ 5251,
+ 5252,
+ 5253,
+ 5254,
+ 5255,
+ 5256,
+ 5257,
+ 5258,
+ 5259,
+ 5260,
+ 5261,
+ 5262,
+ 5263,
+ 5264,
+ 5265,
+ 5266,
+ 5267,
+ 5268,
+ 5269,
+ 5270,
+ 5271,
+ 5272,
+ 5273,
+ 5274,
+ 5275,
+ 5276,
+ 5277,
+ 5278,
+ 5279,
+ 5280,
+ 5281,
+ 5282,
+ 5283,
+ 5284,
+ 5285,
+ 5286,
+ 5287,
+ 5288,
+ 5289,
+ 5290,
+ 5291,
+ 5292,
+ 5293,
+ 5294,
+ 5295,
+ 5296,
+ 5297,
+ 5298,
+ 5299,
+ 5300,
+ 5301,
+ 5302,
+ 5303,
+ 5304,
+ 5305,
+ 5306,
+ 5307,
+ 5308,
+ 5309,
+ 5310,
+ 5311,
+ 5312,
+ 5313,
+ 5314,
+ 5315,
+ 5316,
+ 5317,
+ 5318,
+ 5319,
+ 5320,
+ 5321,
+ 5322,
+ 5323,
+ 5324,
+ 5325,
+ 5326,
+ 5327,
+ 5328,
+ 5329,
+ 5330,
+ 5331,
+ 5332,
+ 5333,
+ 5334,
+ 5335,
+ 5336,
+ 5337,
+ 5338,
+ 5339,
+ 5340,
+ 5341,
+ 5342,
+ 5343,
+ 5344,
+ 5345,
+ 5346,
+ 5347,
+ 5348,
+ 5349,
+ 5350,
+ 5351,
+ 5352,
+ 5353,
+ 5354,
+ 5355,
+ 5356,
+ 5357,
+ 5358,
+ 5359,
+ 5360,
+ 5361,
+ 5362,
+ 5363,
+ 5364,
+ 5365,
+ 5366,
+ 5367,
+ 5368,
+ 5369,
+ 5370,
+ 5371,
+ 5372,
+ 5373,
+ 5374,
+ 5375,
+ 5376,
+ 5377,
+ 5378,
+ 5379,
+ 5380,
+ 5381,
+ 5382,
+ 5383,
+ 5384,
+ 5385,
+ 5386,
+ 5387,
+ 5388,
+ 5389,
+ 5390,
+ 5391,
+ 5392,
+ 5393,
+ 5394,
+ 5395,
+ 5396,
+ 5397,
+ 5398,
+ 5399,
+ 5400,
+ 5401,
+ 5402,
+ 5403,
+ 5404,
+ 5405,
+ 5406,
+ 5407,
+ 5408,
+ 5409,
+ 5410,
+ 5411,
+ 5412,
+ 5413,
+ 5414,
+ 5415,
+ 5416,
+ 5417,
+ 5418,
+ 5419,
+ 5420,
+ 5421,
+ 5422,
+ 5423,
+ 5424,
+ 5425,
+ 5426,
+ 5427,
+ 5428,
+ 5429,
+ 5430,
+ 5431,
+ 5432,
+ 5433,
+ 5434,
+ 5435,
+ 5436,
+ 5437,
+ 5438,
+ 5439,
+ 5440,
+ 5441,
+ 5442,
+ 5443,
+ 5444,
+ 5445,
+ 5446,
+ 5447,
+ 5448,
+ 5449,
+ 5450,
+ 5451,
+ 5452,
+ 5453,
+ 5454,
+ 5455,
+ 5456,
+ 5457,
+ 5458,
+ 5459,
+ 5460,
+ 5461,
+ 5462,
+ 5463,
+ 5464,
+ 5465,
+ 5466,
+ 5467,
+ 5468,
+ 5469,
+ 5470,
+ 5471,
+ 5472,
+ 5473,
+ 5474,
+ 5475,
+ 5476,
+ 5477,
+ 5478,
+ 5479,
+ 5480,
+ 5481,
+ 5482,
+ 5483,
+ 5484,
+ 5485,
+ 5486,
+ 5487,
+ 5488,
+ 5489,
+ 5490,
+ 5491,
+ 5492,
+ 5493,
+ 5494,
+ 5495,
+ 5496,
+ 5497,
+ 5498,
+ 5499,
+ 5500,
+ 5501,
+ 5502,
+ 5503,
+ 5504,
+ 5505,
+ 5506,
+ 5507,
+ 5508,
+ 5509,
+ 5510,
+ 5511,
+ 5512,
+ 5513,
+ 5514,
+ 5515,
+ 5516,
+ 5517,
+ 5518,
+ 5519,
+ 5520,
+ 5521,
+ 5522,
+ 5523,
+ 5524,
+ 5525,
+ 5526,
+ 5527,
+ 5528,
+ 5529,
+ 5530,
+ 5531,
+ 5532,
+ 5533,
+ 5534,
+ 5535,
+ 5536,
+ 5537,
+ 5538,
+ 5539,
+ 5540,
+ 5541,
+ 5542,
+ 5543,
+ 5544,
+ 5545,
+ 5546,
+ 5547,
+ 5548,
+ 5549,
+ 5550,
+ 5551,
+ 5552,
+ 5553,
+ 5554,
+ 5555,
+ 5556,
+ 5557,
+ 5558,
+ 5559,
+ 5560,
+ 5561,
+ 5562,
+ 5563,
+ 5564,
+ 5565,
+ 5566,
+ 5567,
+ 5568,
+ 5569,
+ 5570,
+ 5571,
+ 5572,
+ 5573,
+ 5574,
+ 5575,
+ 5576,
+ 5577,
+ 5578,
+ 5579,
+ 5580,
+ 5581,
+ 5582,
+ 5583,
+ 5584,
+ 5585,
+ 5586,
+ 5587,
+ 5588,
+ 5589,
+ 5590,
+ 5591,
+ 5592,
+ 5593,
+ 5594,
+ 5595,
+ 5596,
+ 5597,
+ 5598,
+ 5599,
+ 5600,
+ 5601,
+ 5602,
+ 5603,
+ 5604,
+ 5605,
+ 5606,
+ 5607,
+ 5608,
+ 5609,
+ 5610,
+ 5611,
+ 5612,
+ 5613,
+ 5614,
+ 5615,
+ 5616,
+ 5617,
+ 5618,
+ 5619,
+ 5620,
+ 5621,
+ 5622,
+ 5623,
+ 5624,
+ 5625,
+ 5626,
+ 5627,
+ 5628,
+ 5629,
+ 5630,
+ 5631,
+ 5632,
+ 5633,
+ 5634,
+ 5635,
+ 5636,
+ 5637,
+ 5638,
+ 5639,
+ 5640,
+ 5641,
+ 5642,
+ 5643,
+ 5644,
+ 5645,
+ 5646,
+ 5647,
+ 5648,
+ 5649,
+ 5650,
+ 5651,
+ 5652,
+ 5653,
+ 5654,
+ 5655,
+ 5656,
+ 5657,
+ 5658,
+ 5659,
+ 5660,
+ 5661,
+ 5662,
+ 5663,
+ 5664,
+ 5665,
+ 5666,
+ 5667,
+ 5668,
+ 5669,
+ 5670,
+ 5671,
+ 5672,
+ 5673,
+ 5674,
+ 5675,
+ 5676,
+ 5677,
+ 5678,
+ 5679,
+ 5680,
+ 5681,
+ 5682,
+ 5683,
+ 5684,
+ 5685,
+ 5686,
+ 5687,
+ 5688,
+ 5689,
+ 5690,
+ 5691,
+ 5692,
+ 5693,
+ 5694,
+ 5695,
+ 5696,
+ 5697,
+ 5698,
+ 5699,
+ 5700,
+ 5701,
+ 5702,
+ 5703,
+ 5704,
+ 5705,
+ 5706,
+ 5707,
+ 5708,
+ 5709,
+ 5710,
+ 5711,
+ 5712,
+ 5713,
+ 5714,
+ 5715,
+ 5716,
+ 5717,
+ 5718,
+ 5719,
+ 5720,
+ 5721,
+ 5722,
+ 5723,
+ 5724,
+ 5725,
+ 5726,
+ 5727,
+ 5728,
+ 5729,
+ 5730,
+ 5731,
+ 5732,
+ 5733,
+ 5734,
+ 5735,
+ 5736,
+ 5737,
+ 5738,
+ 5739,
+ 5740,
+ 5743,
+ 5744,
+ 5745,
+ 5746,
+ 5747,
+ 5748,
+ 5749,
+ 5750,
+ 5751,
+ 5752,
+ 5753,
+ 5754,
+ 5755,
+ 5756,
+ 5757,
+ 5758,
+ 5759,
+ 5761,
+ 5762,
+ 5763,
+ 5764,
+ 5765,
+ 5766,
+ 5767,
+ 5768,
+ 5769,
+ 5770,
+ 5771,
+ 5772,
+ 5773,
+ 5774,
+ 5775,
+ 5776,
+ 5777,
+ 5778,
+ 5779,
+ 5780,
+ 5781,
+ 5782,
+ 5783,
+ 5784,
+ 5785,
+ 5786,
+ 5792,
+ 5793,
+ 5794,
+ 5795,
+ 5796,
+ 5797,
+ 5798,
+ 5799,
+ 5800,
+ 5801,
+ 5802,
+ 5803,
+ 5804,
+ 5805,
+ 5806,
+ 5807,
+ 5808,
+ 5809,
+ 5810,
+ 5811,
+ 5812,
+ 5813,
+ 5814,
+ 5815,
+ 5816,
+ 5817,
+ 5818,
+ 5819,
+ 5820,
+ 5821,
+ 5822,
+ 5823,
+ 5824,
+ 5825,
+ 5826,
+ 5827,
+ 5828,
+ 5829,
+ 5830,
+ 5831,
+ 5832,
+ 5833,
+ 5834,
+ 5835,
+ 5836,
+ 5837,
+ 5838,
+ 5839,
+ 5840,
+ 5841,
+ 5842,
+ 5843,
+ 5844,
+ 5845,
+ 5846,
+ 5847,
+ 5848,
+ 5849,
+ 5850,
+ 5851,
+ 5852,
+ 5853,
+ 5854,
+ 5855,
+ 5856,
+ 5857,
+ 5858,
+ 5859,
+ 5860,
+ 5861,
+ 5862,
+ 5863,
+ 5864,
+ 5865,
+ 5866,
+ 5870,
+ 5871,
+ 5872,
+ 5888,
+ 5889,
+ 5890,
+ 5891,
+ 5892,
+ 5893,
+ 5894,
+ 5895,
+ 5896,
+ 5897,
+ 5898,
+ 5899,
+ 5900,
+ 5902,
+ 5903,
+ 5904,
+ 5905,
+ 5920,
+ 5921,
+ 5922,
+ 5923,
+ 5924,
+ 5925,
+ 5926,
+ 5927,
+ 5928,
+ 5929,
+ 5930,
+ 5931,
+ 5932,
+ 5933,
+ 5934,
+ 5935,
+ 5936,
+ 5937,
+ 5952,
+ 5953,
+ 5954,
+ 5955,
+ 5956,
+ 5957,
+ 5958,
+ 5959,
+ 5960,
+ 5961,
+ 5962,
+ 5963,
+ 5964,
+ 5965,
+ 5966,
+ 5967,
+ 5968,
+ 5969,
+ 5984,
+ 5985,
+ 5986,
+ 5987,
+ 5988,
+ 5989,
+ 5990,
+ 5991,
+ 5992,
+ 5993,
+ 5994,
+ 5995,
+ 5996,
+ 5998,
+ 5999,
+ 6000,
+ 6016,
+ 6017,
+ 6018,
+ 6019,
+ 6020,
+ 6021,
+ 6022,
+ 6023,
+ 6024,
+ 6025,
+ 6026,
+ 6027,
+ 6028,
+ 6029,
+ 6030,
+ 6031,
+ 6032,
+ 6033,
+ 6034,
+ 6035,
+ 6036,
+ 6037,
+ 6038,
+ 6039,
+ 6040,
+ 6041,
+ 6042,
+ 6043,
+ 6044,
+ 6045,
+ 6046,
+ 6047,
+ 6048,
+ 6049,
+ 6050,
+ 6051,
+ 6052,
+ 6053,
+ 6054,
+ 6055,
+ 6056,
+ 6057,
+ 6058,
+ 6059,
+ 6060,
+ 6061,
+ 6062,
+ 6063,
+ 6064,
+ 6065,
+ 6066,
+ 6067,
+ 6103,
+ 6108,
+ 6176,
+ 6177,
+ 6178,
+ 6179,
+ 6180,
+ 6181,
+ 6182,
+ 6183,
+ 6184,
+ 6185,
+ 6186,
+ 6187,
+ 6188,
+ 6189,
+ 6190,
+ 6191,
+ 6192,
+ 6193,
+ 6194,
+ 6195,
+ 6196,
+ 6197,
+ 6198,
+ 6199,
+ 6200,
+ 6201,
+ 6202,
+ 6203,
+ 6204,
+ 6205,
+ 6206,
+ 6207,
+ 6208,
+ 6209,
+ 6210,
+ 6211,
+ 6212,
+ 6213,
+ 6214,
+ 6215,
+ 6216,
+ 6217,
+ 6218,
+ 6219,
+ 6220,
+ 6221,
+ 6222,
+ 6223,
+ 6224,
+ 6225,
+ 6226,
+ 6227,
+ 6228,
+ 6229,
+ 6230,
+ 6231,
+ 6232,
+ 6233,
+ 6234,
+ 6235,
+ 6236,
+ 6237,
+ 6238,
+ 6239,
+ 6240,
+ 6241,
+ 6242,
+ 6243,
+ 6244,
+ 6245,
+ 6246,
+ 6247,
+ 6248,
+ 6249,
+ 6250,
+ 6251,
+ 6252,
+ 6253,
+ 6254,
+ 6255,
+ 6256,
+ 6257,
+ 6258,
+ 6259,
+ 6260,
+ 6261,
+ 6262,
+ 6263,
+ 6272,
+ 6273,
+ 6274,
+ 6275,
+ 6276,
+ 6277,
+ 6278,
+ 6279,
+ 6280,
+ 6281,
+ 6282,
+ 6283,
+ 6284,
+ 6285,
+ 6286,
+ 6287,
+ 6288,
+ 6289,
+ 6290,
+ 6291,
+ 6292,
+ 6293,
+ 6294,
+ 6295,
+ 6296,
+ 6297,
+ 6298,
+ 6299,
+ 6300,
+ 6301,
+ 6302,
+ 6303,
+ 6304,
+ 6305,
+ 6306,
+ 6307,
+ 6308,
+ 6309,
+ 6310,
+ 6311,
+ 6312,
+ 6314,
+ 6320,
+ 6321,
+ 6322,
+ 6323,
+ 6324,
+ 6325,
+ 6326,
+ 6327,
+ 6328,
+ 6329,
+ 6330,
+ 6331,
+ 6332,
+ 6333,
+ 6334,
+ 6335,
+ 6336,
+ 6337,
+ 6338,
+ 6339,
+ 6340,
+ 6341,
+ 6342,
+ 6343,
+ 6344,
+ 6345,
+ 6346,
+ 6347,
+ 6348,
+ 6349,
+ 6350,
+ 6351,
+ 6352,
+ 6353,
+ 6354,
+ 6355,
+ 6356,
+ 6357,
+ 6358,
+ 6359,
+ 6360,
+ 6361,
+ 6362,
+ 6363,
+ 6364,
+ 6365,
+ 6366,
+ 6367,
+ 6368,
+ 6369,
+ 6370,
+ 6371,
+ 6372,
+ 6373,
+ 6374,
+ 6375,
+ 6376,
+ 6377,
+ 6378,
+ 6379,
+ 6380,
+ 6381,
+ 6382,
+ 6383,
+ 6384,
+ 6385,
+ 6386,
+ 6387,
+ 6388,
+ 6389,
+ 6400,
+ 6401,
+ 6402,
+ 6403,
+ 6404,
+ 6405,
+ 6406,
+ 6407,
+ 6408,
+ 6409,
+ 6410,
+ 6411,
+ 6412,
+ 6413,
+ 6414,
+ 6415,
+ 6416,
+ 6417,
+ 6418,
+ 6419,
+ 6420,
+ 6421,
+ 6422,
+ 6423,
+ 6424,
+ 6425,
+ 6426,
+ 6427,
+ 6428,
+ 6480,
+ 6481,
+ 6482,
+ 6483,
+ 6484,
+ 6485,
+ 6486,
+ 6487,
+ 6488,
+ 6489,
+ 6490,
+ 6491,
+ 6492,
+ 6493,
+ 6494,
+ 6495,
+ 6496,
+ 6497,
+ 6498,
+ 6499,
+ 6500,
+ 6501,
+ 6502,
+ 6503,
+ 6504,
+ 6505,
+ 6506,
+ 6507,
+ 6508,
+ 6509,
+ 6512,
+ 6513,
+ 6514,
+ 6515,
+ 6516,
+ 6528,
+ 6529,
+ 6530,
+ 6531,
+ 6532,
+ 6533,
+ 6534,
+ 6535,
+ 6536,
+ 6537,
+ 6538,
+ 6539,
+ 6540,
+ 6541,
+ 6542,
+ 6543,
+ 6544,
+ 6545,
+ 6546,
+ 6547,
+ 6548,
+ 6549,
+ 6550,
+ 6551,
+ 6552,
+ 6553,
+ 6554,
+ 6555,
+ 6556,
+ 6557,
+ 6558,
+ 6559,
+ 6560,
+ 6561,
+ 6562,
+ 6563,
+ 6564,
+ 6565,
+ 6566,
+ 6567,
+ 6568,
+ 6569,
+ 6570,
+ 6571,
+ 6593,
+ 6594,
+ 6595,
+ 6596,
+ 6597,
+ 6598,
+ 6599,
+ 6656,
+ 6657,
+ 6658,
+ 6659,
+ 6660,
+ 6661,
+ 6662,
+ 6663,
+ 6664,
+ 6665,
+ 6666,
+ 6667,
+ 6668,
+ 6669,
+ 6670,
+ 6671,
+ 6672,
+ 6673,
+ 6674,
+ 6675,
+ 6676,
+ 6677,
+ 6678,
+ 6688,
+ 6689,
+ 6690,
+ 6691,
+ 6692,
+ 6693,
+ 6694,
+ 6695,
+ 6696,
+ 6697,
+ 6698,
+ 6699,
+ 6700,
+ 6701,
+ 6702,
+ 6703,
+ 6704,
+ 6705,
+ 6706,
+ 6707,
+ 6708,
+ 6709,
+ 6710,
+ 6711,
+ 6712,
+ 6713,
+ 6714,
+ 6715,
+ 6716,
+ 6717,
+ 6718,
+ 6719,
+ 6720,
+ 6721,
+ 6722,
+ 6723,
+ 6724,
+ 6725,
+ 6726,
+ 6727,
+ 6728,
+ 6729,
+ 6730,
+ 6731,
+ 6732,
+ 6733,
+ 6734,
+ 6735,
+ 6736,
+ 6737,
+ 6738,
+ 6739,
+ 6740,
+ 6823,
+ 6917,
+ 6918,
+ 6919,
+ 6920,
+ 6921,
+ 6922,
+ 6923,
+ 6924,
+ 6925,
+ 6926,
+ 6927,
+ 6928,
+ 6929,
+ 6930,
+ 6931,
+ 6932,
+ 6933,
+ 6934,
+ 6935,
+ 6936,
+ 6937,
+ 6938,
+ 6939,
+ 6940,
+ 6941,
+ 6942,
+ 6943,
+ 6944,
+ 6945,
+ 6946,
+ 6947,
+ 6948,
+ 6949,
+ 6950,
+ 6951,
+ 6952,
+ 6953,
+ 6954,
+ 6955,
+ 6956,
+ 6957,
+ 6958,
+ 6959,
+ 6960,
+ 6961,
+ 6962,
+ 6963,
+ 6981,
+ 6982,
+ 6983,
+ 6984,
+ 6985,
+ 6986,
+ 6987,
+ 7043,
+ 7044,
+ 7045,
+ 7046,
+ 7047,
+ 7048,
+ 7049,
+ 7050,
+ 7051,
+ 7052,
+ 7053,
+ 7054,
+ 7055,
+ 7056,
+ 7057,
+ 7058,
+ 7059,
+ 7060,
+ 7061,
+ 7062,
+ 7063,
+ 7064,
+ 7065,
+ 7066,
+ 7067,
+ 7068,
+ 7069,
+ 7070,
+ 7071,
+ 7072,
+ 7086,
+ 7087,
+ 7098,
+ 7099,
+ 7100,
+ 7101,
+ 7102,
+ 7103,
+ 7104,
+ 7105,
+ 7106,
+ 7107,
+ 7108,
+ 7109,
+ 7110,
+ 7111,
+ 7112,
+ 7113,
+ 7114,
+ 7115,
+ 7116,
+ 7117,
+ 7118,
+ 7119,
+ 7120,
+ 7121,
+ 7122,
+ 7123,
+ 7124,
+ 7125,
+ 7126,
+ 7127,
+ 7128,
+ 7129,
+ 7130,
+ 7131,
+ 7132,
+ 7133,
+ 7134,
+ 7135,
+ 7136,
+ 7137,
+ 7138,
+ 7139,
+ 7140,
+ 7141,
+ 7168,
+ 7169,
+ 7170,
+ 7171,
+ 7172,
+ 7173,
+ 7174,
+ 7175,
+ 7176,
+ 7177,
+ 7178,
+ 7179,
+ 7180,
+ 7181,
+ 7182,
+ 7183,
+ 7184,
+ 7185,
+ 7186,
+ 7187,
+ 7188,
+ 7189,
+ 7190,
+ 7191,
+ 7192,
+ 7193,
+ 7194,
+ 7195,
+ 7196,
+ 7197,
+ 7198,
+ 7199,
+ 7200,
+ 7201,
+ 7202,
+ 7203,
+ 7245,
+ 7246,
+ 7247,
+ 7258,
+ 7259,
+ 7260,
+ 7261,
+ 7262,
+ 7263,
+ 7264,
+ 7265,
+ 7266,
+ 7267,
+ 7268,
+ 7269,
+ 7270,
+ 7271,
+ 7272,
+ 7273,
+ 7274,
+ 7275,
+ 7276,
+ 7277,
+ 7278,
+ 7279,
+ 7280,
+ 7281,
+ 7282,
+ 7283,
+ 7284,
+ 7285,
+ 7286,
+ 7287,
+ 7288,
+ 7289,
+ 7290,
+ 7291,
+ 7292,
+ 7293,
+ 7401,
+ 7402,
+ 7403,
+ 7404,
+ 7406,
+ 7407,
+ 7408,
+ 7409,
+ 7413,
+ 7414,
+ 7424,
+ 7425,
+ 7426,
+ 7427,
+ 7428,
+ 7429,
+ 7430,
+ 7431,
+ 7432,
+ 7433,
+ 7434,
+ 7435,
+ 7436,
+ 7437,
+ 7438,
+ 7439,
+ 7440,
+ 7441,
+ 7442,
+ 7443,
+ 7444,
+ 7445,
+ 7446,
+ 7447,
+ 7448,
+ 7449,
+ 7450,
+ 7451,
+ 7452,
+ 7453,
+ 7454,
+ 7455,
+ 7456,
+ 7457,
+ 7458,
+ 7459,
+ 7460,
+ 7461,
+ 7462,
+ 7463,
+ 7464,
+ 7465,
+ 7466,
+ 7467,
+ 7468,
+ 7469,
+ 7470,
+ 7471,
+ 7472,
+ 7473,
+ 7474,
+ 7475,
+ 7476,
+ 7477,
+ 7478,
+ 7479,
+ 7480,
+ 7481,
+ 7482,
+ 7483,
+ 7484,
+ 7485,
+ 7486,
+ 7487,
+ 7488,
+ 7489,
+ 7490,
+ 7491,
+ 7492,
+ 7493,
+ 7494,
+ 7495,
+ 7496,
+ 7497,
+ 7498,
+ 7499,
+ 7500,
+ 7501,
+ 7502,
+ 7503,
+ 7504,
+ 7505,
+ 7506,
+ 7507,
+ 7508,
+ 7509,
+ 7510,
+ 7511,
+ 7512,
+ 7513,
+ 7514,
+ 7515,
+ 7516,
+ 7517,
+ 7518,
+ 7519,
+ 7520,
+ 7521,
+ 7522,
+ 7523,
+ 7524,
+ 7525,
+ 7526,
+ 7527,
+ 7528,
+ 7529,
+ 7530,
+ 7531,
+ 7532,
+ 7533,
+ 7534,
+ 7535,
+ 7536,
+ 7537,
+ 7538,
+ 7539,
+ 7540,
+ 7541,
+ 7542,
+ 7543,
+ 7544,
+ 7545,
+ 7546,
+ 7547,
+ 7548,
+ 7549,
+ 7550,
+ 7551,
+ 7552,
+ 7553,
+ 7554,
+ 7555,
+ 7556,
+ 7557,
+ 7558,
+ 7559,
+ 7560,
+ 7561,
+ 7562,
+ 7563,
+ 7564,
+ 7565,
+ 7566,
+ 7567,
+ 7568,
+ 7569,
+ 7570,
+ 7571,
+ 7572,
+ 7573,
+ 7574,
+ 7575,
+ 7576,
+ 7577,
+ 7578,
+ 7579,
+ 7580,
+ 7581,
+ 7582,
+ 7583,
+ 7584,
+ 7585,
+ 7586,
+ 7587,
+ 7588,
+ 7589,
+ 7590,
+ 7591,
+ 7592,
+ 7593,
+ 7594,
+ 7595,
+ 7596,
+ 7597,
+ 7598,
+ 7599,
+ 7600,
+ 7601,
+ 7602,
+ 7603,
+ 7604,
+ 7605,
+ 7606,
+ 7607,
+ 7608,
+ 7609,
+ 7610,
+ 7611,
+ 7612,
+ 7613,
+ 7614,
+ 7615,
+ 7680,
+ 7681,
+ 7682,
+ 7683,
+ 7684,
+ 7685,
+ 7686,
+ 7687,
+ 7688,
+ 7689,
+ 7690,
+ 7691,
+ 7692,
+ 7693,
+ 7694,
+ 7695,
+ 7696,
+ 7697,
+ 7698,
+ 7699,
+ 7700,
+ 7701,
+ 7702,
+ 7703,
+ 7704,
+ 7705,
+ 7706,
+ 7707,
+ 7708,
+ 7709,
+ 7710,
+ 7711,
+ 7712,
+ 7713,
+ 7714,
+ 7715,
+ 7716,
+ 7717,
+ 7718,
+ 7719,
+ 7720,
+ 7721,
+ 7722,
+ 7723,
+ 7724,
+ 7725,
+ 7726,
+ 7727,
+ 7728,
+ 7729,
+ 7730,
+ 7731,
+ 7732,
+ 7733,
+ 7734,
+ 7735,
+ 7736,
+ 7737,
+ 7738,
+ 7739,
+ 7740,
+ 7741,
+ 7742,
+ 7743,
+ 7744,
+ 7745,
+ 7746,
+ 7747,
+ 7748,
+ 7749,
+ 7750,
+ 7751,
+ 7752,
+ 7753,
+ 7754,
+ 7755,
+ 7756,
+ 7757,
+ 7758,
+ 7759,
+ 7760,
+ 7761,
+ 7762,
+ 7763,
+ 7764,
+ 7765,
+ 7766,
+ 7767,
+ 7768,
+ 7769,
+ 7770,
+ 7771,
+ 7772,
+ 7773,
+ 7774,
+ 7775,
+ 7776,
+ 7777,
+ 7778,
+ 7779,
+ 7780,
+ 7781,
+ 7782,
+ 7783,
+ 7784,
+ 7785,
+ 7786,
+ 7787,
+ 7788,
+ 7789,
+ 7790,
+ 7791,
+ 7792,
+ 7793,
+ 7794,
+ 7795,
+ 7796,
+ 7797,
+ 7798,
+ 7799,
+ 7800,
+ 7801,
+ 7802,
+ 7803,
+ 7804,
+ 7805,
+ 7806,
+ 7807,
+ 7808,
+ 7809,
+ 7810,
+ 7811,
+ 7812,
+ 7813,
+ 7814,
+ 7815,
+ 7816,
+ 7817,
+ 7818,
+ 7819,
+ 7820,
+ 7821,
+ 7822,
+ 7823,
+ 7824,
+ 7825,
+ 7826,
+ 7827,
+ 7828,
+ 7829,
+ 7830,
+ 7831,
+ 7832,
+ 7833,
+ 7834,
+ 7835,
+ 7836,
+ 7837,
+ 7838,
+ 7839,
+ 7840,
+ 7841,
+ 7842,
+ 7843,
+ 7844,
+ 7845,
+ 7846,
+ 7847,
+ 7848,
+ 7849,
+ 7850,
+ 7851,
+ 7852,
+ 7853,
+ 7854,
+ 7855,
+ 7856,
+ 7857,
+ 7858,
+ 7859,
+ 7860,
+ 7861,
+ 7862,
+ 7863,
+ 7864,
+ 7865,
+ 7866,
+ 7867,
+ 7868,
+ 7869,
+ 7870,
+ 7871,
+ 7872,
+ 7873,
+ 7874,
+ 7875,
+ 7876,
+ 7877,
+ 7878,
+ 7879,
+ 7880,
+ 7881,
+ 7882,
+ 7883,
+ 7884,
+ 7885,
+ 7886,
+ 7887,
+ 7888,
+ 7889,
+ 7890,
+ 7891,
+ 7892,
+ 7893,
+ 7894,
+ 7895,
+ 7896,
+ 7897,
+ 7898,
+ 7899,
+ 7900,
+ 7901,
+ 7902,
+ 7903,
+ 7904,
+ 7905,
+ 7906,
+ 7907,
+ 7908,
+ 7909,
+ 7910,
+ 7911,
+ 7912,
+ 7913,
+ 7914,
+ 7915,
+ 7916,
+ 7917,
+ 7918,
+ 7919,
+ 7920,
+ 7921,
+ 7922,
+ 7923,
+ 7924,
+ 7925,
+ 7926,
+ 7927,
+ 7928,
+ 7929,
+ 7930,
+ 7931,
+ 7932,
+ 7933,
+ 7934,
+ 7935,
+ 7936,
+ 7937,
+ 7938,
+ 7939,
+ 7940,
+ 7941,
+ 7942,
+ 7943,
+ 7944,
+ 7945,
+ 7946,
+ 7947,
+ 7948,
+ 7949,
+ 7950,
+ 7951,
+ 7952,
+ 7953,
+ 7954,
+ 7955,
+ 7956,
+ 7957,
+ 7960,
+ 7961,
+ 7962,
+ 7963,
+ 7964,
+ 7965,
+ 7968,
+ 7969,
+ 7970,
+ 7971,
+ 7972,
+ 7973,
+ 7974,
+ 7975,
+ 7976,
+ 7977,
+ 7978,
+ 7979,
+ 7980,
+ 7981,
+ 7982,
+ 7983,
+ 7984,
+ 7985,
+ 7986,
+ 7987,
+ 7988,
+ 7989,
+ 7990,
+ 7991,
+ 7992,
+ 7993,
+ 7994,
+ 7995,
+ 7996,
+ 7997,
+ 7998,
+ 7999,
+ 8000,
+ 8001,
+ 8002,
+ 8003,
+ 8004,
+ 8005,
+ 8008,
+ 8009,
+ 8010,
+ 8011,
+ 8012,
+ 8013,
+ 8016,
+ 8017,
+ 8018,
+ 8019,
+ 8020,
+ 8021,
+ 8022,
+ 8023,
+ 8025,
+ 8027,
+ 8029,
+ 8031,
+ 8032,
+ 8033,
+ 8034,
+ 8035,
+ 8036,
+ 8037,
+ 8038,
+ 8039,
+ 8040,
+ 8041,
+ 8042,
+ 8043,
+ 8044,
+ 8045,
+ 8046,
+ 8047,
+ 8048,
+ 8049,
+ 8050,
+ 8051,
+ 8052,
+ 8053,
+ 8054,
+ 8055,
+ 8056,
+ 8057,
+ 8058,
+ 8059,
+ 8060,
+ 8061,
+ 8064,
+ 8065,
+ 8066,
+ 8067,
+ 8068,
+ 8069,
+ 8070,
+ 8071,
+ 8072,
+ 8073,
+ 8074,
+ 8075,
+ 8076,
+ 8077,
+ 8078,
+ 8079,
+ 8080,
+ 8081,
+ 8082,
+ 8083,
+ 8084,
+ 8085,
+ 8086,
+ 8087,
+ 8088,
+ 8089,
+ 8090,
+ 8091,
+ 8092,
+ 8093,
+ 8094,
+ 8095,
+ 8096,
+ 8097,
+ 8098,
+ 8099,
+ 8100,
+ 8101,
+ 8102,
+ 8103,
+ 8104,
+ 8105,
+ 8106,
+ 8107,
+ 8108,
+ 8109,
+ 8110,
+ 8111,
+ 8112,
+ 8113,
+ 8114,
+ 8115,
+ 8116,
+ 8118,
+ 8119,
+ 8120,
+ 8121,
+ 8122,
+ 8123,
+ 8124,
+ 8126,
+ 8130,
+ 8131,
+ 8132,
+ 8134,
+ 8135,
+ 8136,
+ 8137,
+ 8138,
+ 8139,
+ 8140,
+ 8144,
+ 8145,
+ 8146,
+ 8147,
+ 8150,
+ 8151,
+ 8152,
+ 8153,
+ 8154,
+ 8155,
+ 8160,
+ 8161,
+ 8162,
+ 8163,
+ 8164,
+ 8165,
+ 8166,
+ 8167,
+ 8168,
+ 8169,
+ 8170,
+ 8171,
+ 8172,
+ 8178,
+ 8179,
+ 8180,
+ 8182,
+ 8183,
+ 8184,
+ 8185,
+ 8186,
+ 8187,
+ 8188,
+ 8305,
+ 8319,
+ 8336,
+ 8337,
+ 8338,
+ 8339,
+ 8340,
+ 8341,
+ 8342,
+ 8343,
+ 8344,
+ 8345,
+ 8346,
+ 8347,
+ 8348,
+ 8450,
+ 8455,
+ 8458,
+ 8459,
+ 8460,
+ 8461,
+ 8462,
+ 8463,
+ 8464,
+ 8465,
+ 8466,
+ 8467,
+ 8469,
+ 8473,
+ 8474,
+ 8475,
+ 8476,
+ 8477,
+ 8484,
+ 8486,
+ 8488,
+ 8490,
+ 8491,
+ 8492,
+ 8493,
+ 8495,
+ 8496,
+ 8497,
+ 8498,
+ 8499,
+ 8500,
+ 8501,
+ 8502,
+ 8503,
+ 8504,
+ 8505,
+ 8508,
+ 8509,
+ 8510,
+ 8511,
+ 8517,
+ 8518,
+ 8519,
+ 8520,
+ 8521,
+ 8526,
+ 8544,
+ 8545,
+ 8546,
+ 8547,
+ 8548,
+ 8549,
+ 8550,
+ 8551,
+ 8552,
+ 8553,
+ 8554,
+ 8555,
+ 8556,
+ 8557,
+ 8558,
+ 8559,
+ 8560,
+ 8561,
+ 8562,
+ 8563,
+ 8564,
+ 8565,
+ 8566,
+ 8567,
+ 8568,
+ 8569,
+ 8570,
+ 8571,
+ 8572,
+ 8573,
+ 8574,
+ 8575,
+ 8576,
+ 8577,
+ 8578,
+ 8579,
+ 8580,
+ 8581,
+ 8582,
+ 8583,
+ 8584,
+ 11264,
+ 11265,
+ 11266,
+ 11267,
+ 11268,
+ 11269,
+ 11270,
+ 11271,
+ 11272,
+ 11273,
+ 11274,
+ 11275,
+ 11276,
+ 11277,
+ 11278,
+ 11279,
+ 11280,
+ 11281,
+ 11282,
+ 11283,
+ 11284,
+ 11285,
+ 11286,
+ 11287,
+ 11288,
+ 11289,
+ 11290,
+ 11291,
+ 11292,
+ 11293,
+ 11294,
+ 11295,
+ 11296,
+ 11297,
+ 11298,
+ 11299,
+ 11300,
+ 11301,
+ 11302,
+ 11303,
+ 11304,
+ 11305,
+ 11306,
+ 11307,
+ 11308,
+ 11309,
+ 11310,
+ 11312,
+ 11313,
+ 11314,
+ 11315,
+ 11316,
+ 11317,
+ 11318,
+ 11319,
+ 11320,
+ 11321,
+ 11322,
+ 11323,
+ 11324,
+ 11325,
+ 11326,
+ 11327,
+ 11328,
+ 11329,
+ 11330,
+ 11331,
+ 11332,
+ 11333,
+ 11334,
+ 11335,
+ 11336,
+ 11337,
+ 11338,
+ 11339,
+ 11340,
+ 11341,
+ 11342,
+ 11343,
+ 11344,
+ 11345,
+ 11346,
+ 11347,
+ 11348,
+ 11349,
+ 11350,
+ 11351,
+ 11352,
+ 11353,
+ 11354,
+ 11355,
+ 11356,
+ 11357,
+ 11358,
+ 11360,
+ 11361,
+ 11362,
+ 11363,
+ 11364,
+ 11365,
+ 11366,
+ 11367,
+ 11368,
+ 11369,
+ 11370,
+ 11371,
+ 11372,
+ 11373,
+ 11374,
+ 11375,
+ 11376,
+ 11377,
+ 11378,
+ 11379,
+ 11380,
+ 11381,
+ 11382,
+ 11383,
+ 11384,
+ 11385,
+ 11386,
+ 11387,
+ 11388,
+ 11389,
+ 11390,
+ 11391,
+ 11392,
+ 11393,
+ 11394,
+ 11395,
+ 11396,
+ 11397,
+ 11398,
+ 11399,
+ 11400,
+ 11401,
+ 11402,
+ 11403,
+ 11404,
+ 11405,
+ 11406,
+ 11407,
+ 11408,
+ 11409,
+ 11410,
+ 11411,
+ 11412,
+ 11413,
+ 11414,
+ 11415,
+ 11416,
+ 11417,
+ 11418,
+ 11419,
+ 11420,
+ 11421,
+ 11422,
+ 11423,
+ 11424,
+ 11425,
+ 11426,
+ 11427,
+ 11428,
+ 11429,
+ 11430,
+ 11431,
+ 11432,
+ 11433,
+ 11434,
+ 11435,
+ 11436,
+ 11437,
+ 11438,
+ 11439,
+ 11440,
+ 11441,
+ 11442,
+ 11443,
+ 11444,
+ 11445,
+ 11446,
+ 11447,
+ 11448,
+ 11449,
+ 11450,
+ 11451,
+ 11452,
+ 11453,
+ 11454,
+ 11455,
+ 11456,
+ 11457,
+ 11458,
+ 11459,
+ 11460,
+ 11461,
+ 11462,
+ 11463,
+ 11464,
+ 11465,
+ 11466,
+ 11467,
+ 11468,
+ 11469,
+ 11470,
+ 11471,
+ 11472,
+ 11473,
+ 11474,
+ 11475,
+ 11476,
+ 11477,
+ 11478,
+ 11479,
+ 11480,
+ 11481,
+ 11482,
+ 11483,
+ 11484,
+ 11485,
+ 11486,
+ 11487,
+ 11488,
+ 11489,
+ 11490,
+ 11491,
+ 11492,
+ 11499,
+ 11500,
+ 11501,
+ 11502,
+ 11506,
+ 11507,
+ 11520,
+ 11521,
+ 11522,
+ 11523,
+ 11524,
+ 11525,
+ 11526,
+ 11527,
+ 11528,
+ 11529,
+ 11530,
+ 11531,
+ 11532,
+ 11533,
+ 11534,
+ 11535,
+ 11536,
+ 11537,
+ 11538,
+ 11539,
+ 11540,
+ 11541,
+ 11542,
+ 11543,
+ 11544,
+ 11545,
+ 11546,
+ 11547,
+ 11548,
+ 11549,
+ 11550,
+ 11551,
+ 11552,
+ 11553,
+ 11554,
+ 11555,
+ 11556,
+ 11557,
+ 11559,
+ 11565,
+ 11568,
+ 11569,
+ 11570,
+ 11571,
+ 11572,
+ 11573,
+ 11574,
+ 11575,
+ 11576,
+ 11577,
+ 11578,
+ 11579,
+ 11580,
+ 11581,
+ 11582,
+ 11583,
+ 11584,
+ 11585,
+ 11586,
+ 11587,
+ 11588,
+ 11589,
+ 11590,
+ 11591,
+ 11592,
+ 11593,
+ 11594,
+ 11595,
+ 11596,
+ 11597,
+ 11598,
+ 11599,
+ 11600,
+ 11601,
+ 11602,
+ 11603,
+ 11604,
+ 11605,
+ 11606,
+ 11607,
+ 11608,
+ 11609,
+ 11610,
+ 11611,
+ 11612,
+ 11613,
+ 11614,
+ 11615,
+ 11616,
+ 11617,
+ 11618,
+ 11619,
+ 11620,
+ 11621,
+ 11622,
+ 11623,
+ 11631,
+ 11648,
+ 11649,
+ 11650,
+ 11651,
+ 11652,
+ 11653,
+ 11654,
+ 11655,
+ 11656,
+ 11657,
+ 11658,
+ 11659,
+ 11660,
+ 11661,
+ 11662,
+ 11663,
+ 11664,
+ 11665,
+ 11666,
+ 11667,
+ 11668,
+ 11669,
+ 11670,
+ 11680,
+ 11681,
+ 11682,
+ 11683,
+ 11684,
+ 11685,
+ 11686,
+ 11688,
+ 11689,
+ 11690,
+ 11691,
+ 11692,
+ 11693,
+ 11694,
+ 11696,
+ 11697,
+ 11698,
+ 11699,
+ 11700,
+ 11701,
+ 11702,
+ 11704,
+ 11705,
+ 11706,
+ 11707,
+ 11708,
+ 11709,
+ 11710,
+ 11712,
+ 11713,
+ 11714,
+ 11715,
+ 11716,
+ 11717,
+ 11718,
+ 11720,
+ 11721,
+ 11722,
+ 11723,
+ 11724,
+ 11725,
+ 11726,
+ 11728,
+ 11729,
+ 11730,
+ 11731,
+ 11732,
+ 11733,
+ 11734,
+ 11736,
+ 11737,
+ 11738,
+ 11739,
+ 11740,
+ 11741,
+ 11742,
+ 11823,
+ 12293,
+ 12294,
+ 12295,
+ 12321,
+ 12322,
+ 12323,
+ 12324,
+ 12325,
+ 12326,
+ 12327,
+ 12328,
+ 12329,
+ 12337,
+ 12338,
+ 12339,
+ 12340,
+ 12341,
+ 12344,
+ 12345,
+ 12346,
+ 12347,
+ 12348,
+ 12353,
+ 12354,
+ 12355,
+ 12356,
+ 12357,
+ 12358,
+ 12359,
+ 12360,
+ 12361,
+ 12362,
+ 12363,
+ 12364,
+ 12365,
+ 12366,
+ 12367,
+ 12368,
+ 12369,
+ 12370,
+ 12371,
+ 12372,
+ 12373,
+ 12374,
+ 12375,
+ 12376,
+ 12377,
+ 12378,
+ 12379,
+ 12380,
+ 12381,
+ 12382,
+ 12383,
+ 12384,
+ 12385,
+ 12386,
+ 12387,
+ 12388,
+ 12389,
+ 12390,
+ 12391,
+ 12392,
+ 12393,
+ 12394,
+ 12395,
+ 12396,
+ 12397,
+ 12398,
+ 12399,
+ 12400,
+ 12401,
+ 12402,
+ 12403,
+ 12404,
+ 12405,
+ 12406,
+ 12407,
+ 12408,
+ 12409,
+ 12410,
+ 12411,
+ 12412,
+ 12413,
+ 12414,
+ 12415,
+ 12416,
+ 12417,
+ 12418,
+ 12419,
+ 12420,
+ 12421,
+ 12422,
+ 12423,
+ 12424,
+ 12425,
+ 12426,
+ 12427,
+ 12428,
+ 12429,
+ 12430,
+ 12431,
+ 12432,
+ 12433,
+ 12434,
+ 12435,
+ 12436,
+ 12437,
+ 12438,
+ 12445,
+ 12446,
+ 12447,
+ 12449,
+ 12450,
+ 12451,
+ 12452,
+ 12453,
+ 12454,
+ 12455,
+ 12456,
+ 12457,
+ 12458,
+ 12459,
+ 12460,
+ 12461,
+ 12462,
+ 12463,
+ 12464,
+ 12465,
+ 12466,
+ 12467,
+ 12468,
+ 12469,
+ 12470,
+ 12471,
+ 12472,
+ 12473,
+ 12474,
+ 12475,
+ 12476,
+ 12477,
+ 12478,
+ 12479,
+ 12480,
+ 12481,
+ 12482,
+ 12483,
+ 12484,
+ 12485,
+ 12486,
+ 12487,
+ 12488,
+ 12489,
+ 12490,
+ 12491,
+ 12492,
+ 12493,
+ 12494,
+ 12495,
+ 12496,
+ 12497,
+ 12498,
+ 12499,
+ 12500,
+ 12501,
+ 12502,
+ 12503,
+ 12504,
+ 12505,
+ 12506,
+ 12507,
+ 12508,
+ 12509,
+ 12510,
+ 12511,
+ 12512,
+ 12513,
+ 12514,
+ 12515,
+ 12516,
+ 12517,
+ 12518,
+ 12519,
+ 12520,
+ 12521,
+ 12522,
+ 12523,
+ 12524,
+ 12525,
+ 12526,
+ 12527,
+ 12528,
+ 12529,
+ 12530,
+ 12531,
+ 12532,
+ 12533,
+ 12534,
+ 12535,
+ 12536,
+ 12537,
+ 12538,
+ 12540,
+ 12541,
+ 12542,
+ 12543,
+ 12549,
+ 12550,
+ 12551,
+ 12552,
+ 12553,
+ 12554,
+ 12555,
+ 12556,
+ 12557,
+ 12558,
+ 12559,
+ 12560,
+ 12561,
+ 12562,
+ 12563,
+ 12564,
+ 12565,
+ 12566,
+ 12567,
+ 12568,
+ 12569,
+ 12570,
+ 12571,
+ 12572,
+ 12573,
+ 12574,
+ 12575,
+ 12576,
+ 12577,
+ 12578,
+ 12579,
+ 12580,
+ 12581,
+ 12582,
+ 12583,
+ 12584,
+ 12585,
+ 12586,
+ 12587,
+ 12588,
+ 12589,
+ 12593,
+ 12594,
+ 12595,
+ 12596,
+ 12597,
+ 12598,
+ 12599,
+ 12600,
+ 12601,
+ 12602,
+ 12603,
+ 12604,
+ 12605,
+ 12606,
+ 12607,
+ 12608,
+ 12609,
+ 12610,
+ 12611,
+ 12612,
+ 12613,
+ 12614,
+ 12615,
+ 12616,
+ 12617,
+ 12618,
+ 12619,
+ 12620,
+ 12621,
+ 12622,
+ 12623,
+ 12624,
+ 12625,
+ 12626,
+ 12627,
+ 12628,
+ 12629,
+ 12630,
+ 12631,
+ 12632,
+ 12633,
+ 12634,
+ 12635,
+ 12636,
+ 12637,
+ 12638,
+ 12639,
+ 12640,
+ 12641,
+ 12642,
+ 12643,
+ 12644,
+ 12645,
+ 12646,
+ 12647,
+ 12648,
+ 12649,
+ 12650,
+ 12651,
+ 12652,
+ 12653,
+ 12654,
+ 12655,
+ 12656,
+ 12657,
+ 12658,
+ 12659,
+ 12660,
+ 12661,
+ 12662,
+ 12663,
+ 12664,
+ 12665,
+ 12666,
+ 12667,
+ 12668,
+ 12669,
+ 12670,
+ 12671,
+ 12672,
+ 12673,
+ 12674,
+ 12675,
+ 12676,
+ 12677,
+ 12678,
+ 12679,
+ 12680,
+ 12681,
+ 12682,
+ 12683,
+ 12684,
+ 12685,
+ 12686,
+ 12704,
+ 12705,
+ 12706,
+ 12707,
+ 12708,
+ 12709,
+ 12710,
+ 12711,
+ 12712,
+ 12713,
+ 12714,
+ 12715,
+ 12716,
+ 12717,
+ 12718,
+ 12719,
+ 12720,
+ 12721,
+ 12722,
+ 12723,
+ 12724,
+ 12725,
+ 12726,
+ 12727,
+ 12728,
+ 12729,
+ 12730,
+ 12784,
+ 12785,
+ 12786,
+ 12787,
+ 12788,
+ 12789,
+ 12790,
+ 12791,
+ 12792,
+ 12793,
+ 12794,
+ 12795,
+ 12796,
+ 12797,
+ 12798,
+ 12799,
+ 13312,
+ 13313,
+ 13314,
+ 13315,
+ 13316,
+ 13317,
+ 13318,
+ 13319,
+ 13320,
+ 13321,
+ 13322,
+ 13323,
+ 13324,
+ 13325,
+ 13326,
+ 13327,
+ 13328,
+ 13329,
+ 13330,
+ 13331,
+ 13332,
+ 13333,
+ 13334,
+ 13335,
+ 13336,
+ 13337,
+ 13338,
+ 13339,
+ 13340,
+ 13341,
+ 13342,
+ 13343,
+ 13344,
+ 13345,
+ 13346,
+ 13347,
+ 13348,
+ 13349,
+ 13350,
+ 13351,
+ 13352,
+ 13353,
+ 13354,
+ 13355,
+ 13356,
+ 13357,
+ 13358,
+ 13359,
+ 13360,
+ 13361,
+ 13362,
+ 13363,
+ 13364,
+ 13365,
+ 13366,
+ 13367,
+ 13368,
+ 13369,
+ 13370,
+ 13371,
+ 13372,
+ 13373,
+ 13374,
+ 13375,
+ 13376,
+ 13377,
+ 13378,
+ 13379,
+ 13380,
+ 13381,
+ 13382,
+ 13383,
+ 13384,
+ 13385,
+ 13386,
+ 13387,
+ 13388,
+ 13389,
+ 13390,
+ 13391,
+ 13392,
+ 13393,
+ 13394,
+ 13395,
+ 13396,
+ 13397,
+ 13398,
+ 13399,
+ 13400,
+ 13401,
+ 13402,
+ 13403,
+ 13404,
+ 13405,
+ 13406,
+ 13407,
+ 13408,
+ 13409,
+ 13410,
+ 13411,
+ 13412,
+ 13413,
+ 13414,
+ 13415,
+ 13416,
+ 13417,
+ 13418,
+ 13419,
+ 13420,
+ 13421,
+ 13422,
+ 13423,
+ 13424,
+ 13425,
+ 13426,
+ 13427,
+ 13428,
+ 13429,
+ 13430,
+ 13431,
+ 13432,
+ 13433,
+ 13434,
+ 13435,
+ 13436,
+ 13437,
+ 13438,
+ 13439,
+ 13440,
+ 13441,
+ 13442,
+ 13443,
+ 13444,
+ 13445,
+ 13446,
+ 13447,
+ 13448,
+ 13449,
+ 13450,
+ 13451,
+ 13452,
+ 13453,
+ 13454,
+ 13455,
+ 13456,
+ 13457,
+ 13458,
+ 13459,
+ 13460,
+ 13461,
+ 13462,
+ 13463,
+ 13464,
+ 13465,
+ 13466,
+ 13467,
+ 13468,
+ 13469,
+ 13470,
+ 13471,
+ 13472,
+ 13473,
+ 13474,
+ 13475,
+ 13476,
+ 13477,
+ 13478,
+ 13479,
+ 13480,
+ 13481,
+ 13482,
+ 13483,
+ 13484,
+ 13485,
+ 13486,
+ 13487,
+ 13488,
+ 13489,
+ 13490,
+ 13491,
+ 13492,
+ 13493,
+ 13494,
+ 13495,
+ 13496,
+ 13497,
+ 13498,
+ 13499,
+ 13500,
+ 13501,
+ 13502,
+ 13503,
+ 13504,
+ 13505,
+ 13506,
+ 13507,
+ 13508,
+ 13509,
+ 13510,
+ 13511,
+ 13512,
+ 13513,
+ 13514,
+ 13515,
+ 13516,
+ 13517,
+ 13518,
+ 13519,
+ 13520,
+ 13521,
+ 13522,
+ 13523,
+ 13524,
+ 13525,
+ 13526,
+ 13527,
+ 13528,
+ 13529,
+ 13530,
+ 13531,
+ 13532,
+ 13533,
+ 13534,
+ 13535,
+ 13536,
+ 13537,
+ 13538,
+ 13539,
+ 13540,
+ 13541,
+ 13542,
+ 13543,
+ 13544,
+ 13545,
+ 13546,
+ 13547,
+ 13548,
+ 13549,
+ 13550,
+ 13551,
+ 13552,
+ 13553,
+ 13554,
+ 13555,
+ 13556,
+ 13557,
+ 13558,
+ 13559,
+ 13560,
+ 13561,
+ 13562,
+ 13563,
+ 13564,
+ 13565,
+ 13566,
+ 13567,
+ 13568,
+ 13569,
+ 13570,
+ 13571,
+ 13572,
+ 13573,
+ 13574,
+ 13575,
+ 13576,
+ 13577,
+ 13578,
+ 13579,
+ 13580,
+ 13581,
+ 13582,
+ 13583,
+ 13584,
+ 13585,
+ 13586,
+ 13587,
+ 13588,
+ 13589,
+ 13590,
+ 13591,
+ 13592,
+ 13593,
+ 13594,
+ 13595,
+ 13596,
+ 13597,
+ 13598,
+ 13599,
+ 13600,
+ 13601,
+ 13602,
+ 13603,
+ 13604,
+ 13605,
+ 13606,
+ 13607,
+ 13608,
+ 13609,
+ 13610,
+ 13611,
+ 13612,
+ 13613,
+ 13614,
+ 13615,
+ 13616,
+ 13617,
+ 13618,
+ 13619,
+ 13620,
+ 13621,
+ 13622,
+ 13623,
+ 13624,
+ 13625,
+ 13626,
+ 13627,
+ 13628,
+ 13629,
+ 13630,
+ 13631,
+ 13632,
+ 13633,
+ 13634,
+ 13635,
+ 13636,
+ 13637,
+ 13638,
+ 13639,
+ 13640,
+ 13641,
+ 13642,
+ 13643,
+ 13644,
+ 13645,
+ 13646,
+ 13647,
+ 13648,
+ 13649,
+ 13650,
+ 13651,
+ 13652,
+ 13653,
+ 13654,
+ 13655,
+ 13656,
+ 13657,
+ 13658,
+ 13659,
+ 13660,
+ 13661,
+ 13662,
+ 13663,
+ 13664,
+ 13665,
+ 13666,
+ 13667,
+ 13668,
+ 13669,
+ 13670,
+ 13671,
+ 13672,
+ 13673,
+ 13674,
+ 13675,
+ 13676,
+ 13677,
+ 13678,
+ 13679,
+ 13680,
+ 13681,
+ 13682,
+ 13683,
+ 13684,
+ 13685,
+ 13686,
+ 13687,
+ 13688,
+ 13689,
+ 13690,
+ 13691,
+ 13692,
+ 13693,
+ 13694,
+ 13695,
+ 13696,
+ 13697,
+ 13698,
+ 13699,
+ 13700,
+ 13701,
+ 13702,
+ 13703,
+ 13704,
+ 13705,
+ 13706,
+ 13707,
+ 13708,
+ 13709,
+ 13710,
+ 13711,
+ 13712,
+ 13713,
+ 13714,
+ 13715,
+ 13716,
+ 13717,
+ 13718,
+ 13719,
+ 13720,
+ 13721,
+ 13722,
+ 13723,
+ 13724,
+ 13725,
+ 13726,
+ 13727,
+ 13728,
+ 13729,
+ 13730,
+ 13731,
+ 13732,
+ 13733,
+ 13734,
+ 13735,
+ 13736,
+ 13737,
+ 13738,
+ 13739,
+ 13740,
+ 13741,
+ 13742,
+ 13743,
+ 13744,
+ 13745,
+ 13746,
+ 13747,
+ 13748,
+ 13749,
+ 13750,
+ 13751,
+ 13752,
+ 13753,
+ 13754,
+ 13755,
+ 13756,
+ 13757,
+ 13758,
+ 13759,
+ 13760,
+ 13761,
+ 13762,
+ 13763,
+ 13764,
+ 13765,
+ 13766,
+ 13767,
+ 13768,
+ 13769,
+ 13770,
+ 13771,
+ 13772,
+ 13773,
+ 13774,
+ 13775,
+ 13776,
+ 13777,
+ 13778,
+ 13779,
+ 13780,
+ 13781,
+ 13782,
+ 13783,
+ 13784,
+ 13785,
+ 13786,
+ 13787,
+ 13788,
+ 13789,
+ 13790,
+ 13791,
+ 13792,
+ 13793,
+ 13794,
+ 13795,
+ 13796,
+ 13797,
+ 13798,
+ 13799,
+ 13800,
+ 13801,
+ 13802,
+ 13803,
+ 13804,
+ 13805,
+ 13806,
+ 13807,
+ 13808,
+ 13809,
+ 13810,
+ 13811,
+ 13812,
+ 13813,
+ 13814,
+ 13815,
+ 13816,
+ 13817,
+ 13818,
+ 13819,
+ 13820,
+ 13821,
+ 13822,
+ 13823,
+ 13824,
+ 13825,
+ 13826,
+ 13827,
+ 13828,
+ 13829,
+ 13830,
+ 13831,
+ 13832,
+ 13833,
+ 13834,
+ 13835,
+ 13836,
+ 13837,
+ 13838,
+ 13839,
+ 13840,
+ 13841,
+ 13842,
+ 13843,
+ 13844,
+ 13845,
+ 13846,
+ 13847,
+ 13848,
+ 13849,
+ 13850,
+ 13851,
+ 13852,
+ 13853,
+ 13854,
+ 13855,
+ 13856,
+ 13857,
+ 13858,
+ 13859,
+ 13860,
+ 13861,
+ 13862,
+ 13863,
+ 13864,
+ 13865,
+ 13866,
+ 13867,
+ 13868,
+ 13869,
+ 13870,
+ 13871,
+ 13872,
+ 13873,
+ 13874,
+ 13875,
+ 13876,
+ 13877,
+ 13878,
+ 13879,
+ 13880,
+ 13881,
+ 13882,
+ 13883,
+ 13884,
+ 13885,
+ 13886,
+ 13887,
+ 13888,
+ 13889,
+ 13890,
+ 13891,
+ 13892,
+ 13893,
+ 13894,
+ 13895,
+ 13896,
+ 13897,
+ 13898,
+ 13899,
+ 13900,
+ 13901,
+ 13902,
+ 13903,
+ 13904,
+ 13905,
+ 13906,
+ 13907,
+ 13908,
+ 13909,
+ 13910,
+ 13911,
+ 13912,
+ 13913,
+ 13914,
+ 13915,
+ 13916,
+ 13917,
+ 13918,
+ 13919,
+ 13920,
+ 13921,
+ 13922,
+ 13923,
+ 13924,
+ 13925,
+ 13926,
+ 13927,
+ 13928,
+ 13929,
+ 13930,
+ 13931,
+ 13932,
+ 13933,
+ 13934,
+ 13935,
+ 13936,
+ 13937,
+ 13938,
+ 13939,
+ 13940,
+ 13941,
+ 13942,
+ 13943,
+ 13944,
+ 13945,
+ 13946,
+ 13947,
+ 13948,
+ 13949,
+ 13950,
+ 13951,
+ 13952,
+ 13953,
+ 13954,
+ 13955,
+ 13956,
+ 13957,
+ 13958,
+ 13959,
+ 13960,
+ 13961,
+ 13962,
+ 13963,
+ 13964,
+ 13965,
+ 13966,
+ 13967,
+ 13968,
+ 13969,
+ 13970,
+ 13971,
+ 13972,
+ 13973,
+ 13974,
+ 13975,
+ 13976,
+ 13977,
+ 13978,
+ 13979,
+ 13980,
+ 13981,
+ 13982,
+ 13983,
+ 13984,
+ 13985,
+ 13986,
+ 13987,
+ 13988,
+ 13989,
+ 13990,
+ 13991,
+ 13992,
+ 13993,
+ 13994,
+ 13995,
+ 13996,
+ 13997,
+ 13998,
+ 13999,
+ 14000,
+ 14001,
+ 14002,
+ 14003,
+ 14004,
+ 14005,
+ 14006,
+ 14007,
+ 14008,
+ 14009,
+ 14010,
+ 14011,
+ 14012,
+ 14013,
+ 14014,
+ 14015,
+ 14016,
+ 14017,
+ 14018,
+ 14019,
+ 14020,
+ 14021,
+ 14022,
+ 14023,
+ 14024,
+ 14025,
+ 14026,
+ 14027,
+ 14028,
+ 14029,
+ 14030,
+ 14031,
+ 14032,
+ 14033,
+ 14034,
+ 14035,
+ 14036,
+ 14037,
+ 14038,
+ 14039,
+ 14040,
+ 14041,
+ 14042,
+ 14043,
+ 14044,
+ 14045,
+ 14046,
+ 14047,
+ 14048,
+ 14049,
+ 14050,
+ 14051,
+ 14052,
+ 14053,
+ 14054,
+ 14055,
+ 14056,
+ 14057,
+ 14058,
+ 14059,
+ 14060,
+ 14061,
+ 14062,
+ 14063,
+ 14064,
+ 14065,
+ 14066,
+ 14067,
+ 14068,
+ 14069,
+ 14070,
+ 14071,
+ 14072,
+ 14073,
+ 14074,
+ 14075,
+ 14076,
+ 14077,
+ 14078,
+ 14079,
+ 14080,
+ 14081,
+ 14082,
+ 14083,
+ 14084,
+ 14085,
+ 14086,
+ 14087,
+ 14088,
+ 14089,
+ 14090,
+ 14091,
+ 14092,
+ 14093,
+ 14094,
+ 14095,
+ 14096,
+ 14097,
+ 14098,
+ 14099,
+ 14100,
+ 14101,
+ 14102,
+ 14103,
+ 14104,
+ 14105,
+ 14106,
+ 14107,
+ 14108,
+ 14109,
+ 14110,
+ 14111,
+ 14112,
+ 14113,
+ 14114,
+ 14115,
+ 14116,
+ 14117,
+ 14118,
+ 14119,
+ 14120,
+ 14121,
+ 14122,
+ 14123,
+ 14124,
+ 14125,
+ 14126,
+ 14127,
+ 14128,
+ 14129,
+ 14130,
+ 14131,
+ 14132,
+ 14133,
+ 14134,
+ 14135,
+ 14136,
+ 14137,
+ 14138,
+ 14139,
+ 14140,
+ 14141,
+ 14142,
+ 14143,
+ 14144,
+ 14145,
+ 14146,
+ 14147,
+ 14148,
+ 14149,
+ 14150,
+ 14151,
+ 14152,
+ 14153,
+ 14154,
+ 14155,
+ 14156,
+ 14157,
+ 14158,
+ 14159,
+ 14160,
+ 14161,
+ 14162,
+ 14163,
+ 14164,
+ 14165,
+ 14166,
+ 14167,
+ 14168,
+ 14169,
+ 14170,
+ 14171,
+ 14172,
+ 14173,
+ 14174,
+ 14175,
+ 14176,
+ 14177,
+ 14178,
+ 14179,
+ 14180,
+ 14181,
+ 14182,
+ 14183,
+ 14184,
+ 14185,
+ 14186,
+ 14187,
+ 14188,
+ 14189,
+ 14190,
+ 14191,
+ 14192,
+ 14193,
+ 14194,
+ 14195,
+ 14196,
+ 14197,
+ 14198,
+ 14199,
+ 14200,
+ 14201,
+ 14202,
+ 14203,
+ 14204,
+ 14205,
+ 14206,
+ 14207,
+ 14208,
+ 14209,
+ 14210,
+ 14211,
+ 14212,
+ 14213,
+ 14214,
+ 14215,
+ 14216,
+ 14217,
+ 14218,
+ 14219,
+ 14220,
+ 14221,
+ 14222,
+ 14223,
+ 14224,
+ 14225,
+ 14226,
+ 14227,
+ 14228,
+ 14229,
+ 14230,
+ 14231,
+ 14232,
+ 14233,
+ 14234,
+ 14235,
+ 14236,
+ 14237,
+ 14238,
+ 14239,
+ 14240,
+ 14241,
+ 14242,
+ 14243,
+ 14244,
+ 14245,
+ 14246,
+ 14247,
+ 14248,
+ 14249,
+ 14250,
+ 14251,
+ 14252,
+ 14253,
+ 14254,
+ 14255,
+ 14256,
+ 14257,
+ 14258,
+ 14259,
+ 14260,
+ 14261,
+ 14262,
+ 14263,
+ 14264,
+ 14265,
+ 14266,
+ 14267,
+ 14268,
+ 14269,
+ 14270,
+ 14271,
+ 14272,
+ 14273,
+ 14274,
+ 14275,
+ 14276,
+ 14277,
+ 14278,
+ 14279,
+ 14280,
+ 14281,
+ 14282,
+ 14283,
+ 14284,
+ 14285,
+ 14286,
+ 14287,
+ 14288,
+ 14289,
+ 14290,
+ 14291,
+ 14292,
+ 14293,
+ 14294,
+ 14295,
+ 14296,
+ 14297,
+ 14298,
+ 14299,
+ 14300,
+ 14301,
+ 14302,
+ 14303,
+ 14304,
+ 14305,
+ 14306,
+ 14307,
+ 14308,
+ 14309,
+ 14310,
+ 14311,
+ 14312,
+ 14313,
+ 14314,
+ 14315,
+ 14316,
+ 14317,
+ 14318,
+ 14319,
+ 14320,
+ 14321,
+ 14322,
+ 14323,
+ 14324,
+ 14325,
+ 14326,
+ 14327,
+ 14328,
+ 14329,
+ 14330,
+ 14331,
+ 14332,
+ 14333,
+ 14334,
+ 14335,
+ 14336,
+ 14337,
+ 14338,
+ 14339,
+ 14340,
+ 14341,
+ 14342,
+ 14343,
+ 14344,
+ 14345,
+ 14346,
+ 14347,
+ 14348,
+ 14349,
+ 14350,
+ 14351,
+ 14352,
+ 14353,
+ 14354,
+ 14355,
+ 14356,
+ 14357,
+ 14358,
+ 14359,
+ 14360,
+ 14361,
+ 14362,
+ 14363,
+ 14364,
+ 14365,
+ 14366,
+ 14367,
+ 14368,
+ 14369,
+ 14370,
+ 14371,
+ 14372,
+ 14373,
+ 14374,
+ 14375,
+ 14376,
+ 14377,
+ 14378,
+ 14379,
+ 14380,
+ 14381,
+ 14382,
+ 14383,
+ 14384,
+ 14385,
+ 14386,
+ 14387,
+ 14388,
+ 14389,
+ 14390,
+ 14391,
+ 14392,
+ 14393,
+ 14394,
+ 14395,
+ 14396,
+ 14397,
+ 14398,
+ 14399,
+ 14400,
+ 14401,
+ 14402,
+ 14403,
+ 14404,
+ 14405,
+ 14406,
+ 14407,
+ 14408,
+ 14409,
+ 14410,
+ 14411,
+ 14412,
+ 14413,
+ 14414,
+ 14415,
+ 14416,
+ 14417,
+ 14418,
+ 14419,
+ 14420,
+ 14421,
+ 14422,
+ 14423,
+ 14424,
+ 14425,
+ 14426,
+ 14427,
+ 14428,
+ 14429,
+ 14430,
+ 14431,
+ 14432,
+ 14433,
+ 14434,
+ 14435,
+ 14436,
+ 14437,
+ 14438,
+ 14439,
+ 14440,
+ 14441,
+ 14442,
+ 14443,
+ 14444,
+ 14445,
+ 14446,
+ 14447,
+ 14448,
+ 14449,
+ 14450,
+ 14451,
+ 14452,
+ 14453,
+ 14454,
+ 14455,
+ 14456,
+ 14457,
+ 14458,
+ 14459,
+ 14460,
+ 14461,
+ 14462,
+ 14463,
+ 14464,
+ 14465,
+ 14466,
+ 14467,
+ 14468,
+ 14469,
+ 14470,
+ 14471,
+ 14472,
+ 14473,
+ 14474,
+ 14475,
+ 14476,
+ 14477,
+ 14478,
+ 14479,
+ 14480,
+ 14481,
+ 14482,
+ 14483,
+ 14484,
+ 14485,
+ 14486,
+ 14487,
+ 14488,
+ 14489,
+ 14490,
+ 14491,
+ 14492,
+ 14493,
+ 14494,
+ 14495,
+ 14496,
+ 14497,
+ 14498,
+ 14499,
+ 14500,
+ 14501,
+ 14502,
+ 14503,
+ 14504,
+ 14505,
+ 14506,
+ 14507,
+ 14508,
+ 14509,
+ 14510,
+ 14511,
+ 14512,
+ 14513,
+ 14514,
+ 14515,
+ 14516,
+ 14517,
+ 14518,
+ 14519,
+ 14520,
+ 14521,
+ 14522,
+ 14523,
+ 14524,
+ 14525,
+ 14526,
+ 14527,
+ 14528,
+ 14529,
+ 14530,
+ 14531,
+ 14532,
+ 14533,
+ 14534,
+ 14535,
+ 14536,
+ 14537,
+ 14538,
+ 14539,
+ 14540,
+ 14541,
+ 14542,
+ 14543,
+ 14544,
+ 14545,
+ 14546,
+ 14547,
+ 14548,
+ 14549,
+ 14550,
+ 14551,
+ 14552,
+ 14553,
+ 14554,
+ 14555,
+ 14556,
+ 14557,
+ 14558,
+ 14559,
+ 14560,
+ 14561,
+ 14562,
+ 14563,
+ 14564,
+ 14565,
+ 14566,
+ 14567,
+ 14568,
+ 14569,
+ 14570,
+ 14571,
+ 14572,
+ 14573,
+ 14574,
+ 14575,
+ 14576,
+ 14577,
+ 14578,
+ 14579,
+ 14580,
+ 14581,
+ 14582,
+ 14583,
+ 14584,
+ 14585,
+ 14586,
+ 14587,
+ 14588,
+ 14589,
+ 14590,
+ 14591,
+ 14592,
+ 14593,
+ 14594,
+ 14595,
+ 14596,
+ 14597,
+ 14598,
+ 14599,
+ 14600,
+ 14601,
+ 14602,
+ 14603,
+ 14604,
+ 14605,
+ 14606,
+ 14607,
+ 14608,
+ 14609,
+ 14610,
+ 14611,
+ 14612,
+ 14613,
+ 14614,
+ 14615,
+ 14616,
+ 14617,
+ 14618,
+ 14619,
+ 14620,
+ 14621,
+ 14622,
+ 14623,
+ 14624,
+ 14625,
+ 14626,
+ 14627,
+ 14628,
+ 14629,
+ 14630,
+ 14631,
+ 14632,
+ 14633,
+ 14634,
+ 14635,
+ 14636,
+ 14637,
+ 14638,
+ 14639,
+ 14640,
+ 14641,
+ 14642,
+ 14643,
+ 14644,
+ 14645,
+ 14646,
+ 14647,
+ 14648,
+ 14649,
+ 14650,
+ 14651,
+ 14652,
+ 14653,
+ 14654,
+ 14655,
+ 14656,
+ 14657,
+ 14658,
+ 14659,
+ 14660,
+ 14661,
+ 14662,
+ 14663,
+ 14664,
+ 14665,
+ 14666,
+ 14667,
+ 14668,
+ 14669,
+ 14670,
+ 14671,
+ 14672,
+ 14673,
+ 14674,
+ 14675,
+ 14676,
+ 14677,
+ 14678,
+ 14679,
+ 14680,
+ 14681,
+ 14682,
+ 14683,
+ 14684,
+ 14685,
+ 14686,
+ 14687,
+ 14688,
+ 14689,
+ 14690,
+ 14691,
+ 14692,
+ 14693,
+ 14694,
+ 14695,
+ 14696,
+ 14697,
+ 14698,
+ 14699,
+ 14700,
+ 14701,
+ 14702,
+ 14703,
+ 14704,
+ 14705,
+ 14706,
+ 14707,
+ 14708,
+ 14709,
+ 14710,
+ 14711,
+ 14712,
+ 14713,
+ 14714,
+ 14715,
+ 14716,
+ 14717,
+ 14718,
+ 14719,
+ 14720,
+ 14721,
+ 14722,
+ 14723,
+ 14724,
+ 14725,
+ 14726,
+ 14727,
+ 14728,
+ 14729,
+ 14730,
+ 14731,
+ 14732,
+ 14733,
+ 14734,
+ 14735,
+ 14736,
+ 14737,
+ 14738,
+ 14739,
+ 14740,
+ 14741,
+ 14742,
+ 14743,
+ 14744,
+ 14745,
+ 14746,
+ 14747,
+ 14748,
+ 14749,
+ 14750,
+ 14751,
+ 14752,
+ 14753,
+ 14754,
+ 14755,
+ 14756,
+ 14757,
+ 14758,
+ 14759,
+ 14760,
+ 14761,
+ 14762,
+ 14763,
+ 14764,
+ 14765,
+ 14766,
+ 14767,
+ 14768,
+ 14769,
+ 14770,
+ 14771,
+ 14772,
+ 14773,
+ 14774,
+ 14775,
+ 14776,
+ 14777,
+ 14778,
+ 14779,
+ 14780,
+ 14781,
+ 14782,
+ 14783,
+ 14784,
+ 14785,
+ 14786,
+ 14787,
+ 14788,
+ 14789,
+ 14790,
+ 14791,
+ 14792,
+ 14793,
+ 14794,
+ 14795,
+ 14796,
+ 14797,
+ 14798,
+ 14799,
+ 14800,
+ 14801,
+ 14802,
+ 14803,
+ 14804,
+ 14805,
+ 14806,
+ 14807,
+ 14808,
+ 14809,
+ 14810,
+ 14811,
+ 14812,
+ 14813,
+ 14814,
+ 14815,
+ 14816,
+ 14817,
+ 14818,
+ 14819,
+ 14820,
+ 14821,
+ 14822,
+ 14823,
+ 14824,
+ 14825,
+ 14826,
+ 14827,
+ 14828,
+ 14829,
+ 14830,
+ 14831,
+ 14832,
+ 14833,
+ 14834,
+ 14835,
+ 14836,
+ 14837,
+ 14838,
+ 14839,
+ 14840,
+ 14841,
+ 14842,
+ 14843,
+ 14844,
+ 14845,
+ 14846,
+ 14847,
+ 14848,
+ 14849,
+ 14850,
+ 14851,
+ 14852,
+ 14853,
+ 14854,
+ 14855,
+ 14856,
+ 14857,
+ 14858,
+ 14859,
+ 14860,
+ 14861,
+ 14862,
+ 14863,
+ 14864,
+ 14865,
+ 14866,
+ 14867,
+ 14868,
+ 14869,
+ 14870,
+ 14871,
+ 14872,
+ 14873,
+ 14874,
+ 14875,
+ 14876,
+ 14877,
+ 14878,
+ 14879,
+ 14880,
+ 14881,
+ 14882,
+ 14883,
+ 14884,
+ 14885,
+ 14886,
+ 14887,
+ 14888,
+ 14889,
+ 14890,
+ 14891,
+ 14892,
+ 14893,
+ 14894,
+ 14895,
+ 14896,
+ 14897,
+ 14898,
+ 14899,
+ 14900,
+ 14901,
+ 14902,
+ 14903,
+ 14904,
+ 14905,
+ 14906,
+ 14907,
+ 14908,
+ 14909,
+ 14910,
+ 14911,
+ 14912,
+ 14913,
+ 14914,
+ 14915,
+ 14916,
+ 14917,
+ 14918,
+ 14919,
+ 14920,
+ 14921,
+ 14922,
+ 14923,
+ 14924,
+ 14925,
+ 14926,
+ 14927,
+ 14928,
+ 14929,
+ 14930,
+ 14931,
+ 14932,
+ 14933,
+ 14934,
+ 14935,
+ 14936,
+ 14937,
+ 14938,
+ 14939,
+ 14940,
+ 14941,
+ 14942,
+ 14943,
+ 14944,
+ 14945,
+ 14946,
+ 14947,
+ 14948,
+ 14949,
+ 14950,
+ 14951,
+ 14952,
+ 14953,
+ 14954,
+ 14955,
+ 14956,
+ 14957,
+ 14958,
+ 14959,
+ 14960,
+ 14961,
+ 14962,
+ 14963,
+ 14964,
+ 14965,
+ 14966,
+ 14967,
+ 14968,
+ 14969,
+ 14970,
+ 14971,
+ 14972,
+ 14973,
+ 14974,
+ 14975,
+ 14976,
+ 14977,
+ 14978,
+ 14979,
+ 14980,
+ 14981,
+ 14982,
+ 14983,
+ 14984,
+ 14985,
+ 14986,
+ 14987,
+ 14988,
+ 14989,
+ 14990,
+ 14991,
+ 14992,
+ 14993,
+ 14994,
+ 14995,
+ 14996,
+ 14997,
+ 14998,
+ 14999,
+ 15000,
+ 15001,
+ 15002,
+ 15003,
+ 15004,
+ 15005,
+ 15006,
+ 15007,
+ 15008,
+ 15009,
+ 15010,
+ 15011,
+ 15012,
+ 15013,
+ 15014,
+ 15015,
+ 15016,
+ 15017,
+ 15018,
+ 15019,
+ 15020,
+ 15021,
+ 15022,
+ 15023,
+ 15024,
+ 15025,
+ 15026,
+ 15027,
+ 15028,
+ 15029,
+ 15030,
+ 15031,
+ 15032,
+ 15033,
+ 15034,
+ 15035,
+ 15036,
+ 15037,
+ 15038,
+ 15039,
+ 15040,
+ 15041,
+ 15042,
+ 15043,
+ 15044,
+ 15045,
+ 15046,
+ 15047,
+ 15048,
+ 15049,
+ 15050,
+ 15051,
+ 15052,
+ 15053,
+ 15054,
+ 15055,
+ 15056,
+ 15057,
+ 15058,
+ 15059,
+ 15060,
+ 15061,
+ 15062,
+ 15063,
+ 15064,
+ 15065,
+ 15066,
+ 15067,
+ 15068,
+ 15069,
+ 15070,
+ 15071,
+ 15072,
+ 15073,
+ 15074,
+ 15075,
+ 15076,
+ 15077,
+ 15078,
+ 15079,
+ 15080,
+ 15081,
+ 15082,
+ 15083,
+ 15084,
+ 15085,
+ 15086,
+ 15087,
+ 15088,
+ 15089,
+ 15090,
+ 15091,
+ 15092,
+ 15093,
+ 15094,
+ 15095,
+ 15096,
+ 15097,
+ 15098,
+ 15099,
+ 15100,
+ 15101,
+ 15102,
+ 15103,
+ 15104,
+ 15105,
+ 15106,
+ 15107,
+ 15108,
+ 15109,
+ 15110,
+ 15111,
+ 15112,
+ 15113,
+ 15114,
+ 15115,
+ 15116,
+ 15117,
+ 15118,
+ 15119,
+ 15120,
+ 15121,
+ 15122,
+ 15123,
+ 15124,
+ 15125,
+ 15126,
+ 15127,
+ 15128,
+ 15129,
+ 15130,
+ 15131,
+ 15132,
+ 15133,
+ 15134,
+ 15135,
+ 15136,
+ 15137,
+ 15138,
+ 15139,
+ 15140,
+ 15141,
+ 15142,
+ 15143,
+ 15144,
+ 15145,
+ 15146,
+ 15147,
+ 15148,
+ 15149,
+ 15150,
+ 15151,
+ 15152,
+ 15153,
+ 15154,
+ 15155,
+ 15156,
+ 15157,
+ 15158,
+ 15159,
+ 15160,
+ 15161,
+ 15162,
+ 15163,
+ 15164,
+ 15165,
+ 15166,
+ 15167,
+ 15168,
+ 15169,
+ 15170,
+ 15171,
+ 15172,
+ 15173,
+ 15174,
+ 15175,
+ 15176,
+ 15177,
+ 15178,
+ 15179,
+ 15180,
+ 15181,
+ 15182,
+ 15183,
+ 15184,
+ 15185,
+ 15186,
+ 15187,
+ 15188,
+ 15189,
+ 15190,
+ 15191,
+ 15192,
+ 15193,
+ 15194,
+ 15195,
+ 15196,
+ 15197,
+ 15198,
+ 15199,
+ 15200,
+ 15201,
+ 15202,
+ 15203,
+ 15204,
+ 15205,
+ 15206,
+ 15207,
+ 15208,
+ 15209,
+ 15210,
+ 15211,
+ 15212,
+ 15213,
+ 15214,
+ 15215,
+ 15216,
+ 15217,
+ 15218,
+ 15219,
+ 15220,
+ 15221,
+ 15222,
+ 15223,
+ 15224,
+ 15225,
+ 15226,
+ 15227,
+ 15228,
+ 15229,
+ 15230,
+ 15231,
+ 15232,
+ 15233,
+ 15234,
+ 15235,
+ 15236,
+ 15237,
+ 15238,
+ 15239,
+ 15240,
+ 15241,
+ 15242,
+ 15243,
+ 15244,
+ 15245,
+ 15246,
+ 15247,
+ 15248,
+ 15249,
+ 15250,
+ 15251,
+ 15252,
+ 15253,
+ 15254,
+ 15255,
+ 15256,
+ 15257,
+ 15258,
+ 15259,
+ 15260,
+ 15261,
+ 15262,
+ 15263,
+ 15264,
+ 15265,
+ 15266,
+ 15267,
+ 15268,
+ 15269,
+ 15270,
+ 15271,
+ 15272,
+ 15273,
+ 15274,
+ 15275,
+ 15276,
+ 15277,
+ 15278,
+ 15279,
+ 15280,
+ 15281,
+ 15282,
+ 15283,
+ 15284,
+ 15285,
+ 15286,
+ 15287,
+ 15288,
+ 15289,
+ 15290,
+ 15291,
+ 15292,
+ 15293,
+ 15294,
+ 15295,
+ 15296,
+ 15297,
+ 15298,
+ 15299,
+ 15300,
+ 15301,
+ 15302,
+ 15303,
+ 15304,
+ 15305,
+ 15306,
+ 15307,
+ 15308,
+ 15309,
+ 15310,
+ 15311,
+ 15312,
+ 15313,
+ 15314,
+ 15315,
+ 15316,
+ 15317,
+ 15318,
+ 15319,
+ 15320,
+ 15321,
+ 15322,
+ 15323,
+ 15324,
+ 15325,
+ 15326,
+ 15327,
+ 15328,
+ 15329,
+ 15330,
+ 15331,
+ 15332,
+ 15333,
+ 15334,
+ 15335,
+ 15336,
+ 15337,
+ 15338,
+ 15339,
+ 15340,
+ 15341,
+ 15342,
+ 15343,
+ 15344,
+ 15345,
+ 15346,
+ 15347,
+ 15348,
+ 15349,
+ 15350,
+ 15351,
+ 15352,
+ 15353,
+ 15354,
+ 15355,
+ 15356,
+ 15357,
+ 15358,
+ 15359,
+ 15360,
+ 15361,
+ 15362,
+ 15363,
+ 15364,
+ 15365,
+ 15366,
+ 15367,
+ 15368,
+ 15369,
+ 15370,
+ 15371,
+ 15372,
+ 15373,
+ 15374,
+ 15375,
+ 15376,
+ 15377,
+ 15378,
+ 15379,
+ 15380,
+ 15381,
+ 15382,
+ 15383,
+ 15384,
+ 15385,
+ 15386,
+ 15387,
+ 15388,
+ 15389,
+ 15390,
+ 15391,
+ 15392,
+ 15393,
+ 15394,
+ 15395,
+ 15396,
+ 15397,
+ 15398,
+ 15399,
+ 15400,
+ 15401,
+ 15402,
+ 15403,
+ 15404,
+ 15405,
+ 15406,
+ 15407,
+ 15408,
+ 15409,
+ 15410,
+ 15411,
+ 15412,
+ 15413,
+ 15414,
+ 15415,
+ 15416,
+ 15417,
+ 15418,
+ 15419,
+ 15420,
+ 15421,
+ 15422,
+ 15423,
+ 15424,
+ 15425,
+ 15426,
+ 15427,
+ 15428,
+ 15429,
+ 15430,
+ 15431,
+ 15432,
+ 15433,
+ 15434,
+ 15435,
+ 15436,
+ 15437,
+ 15438,
+ 15439,
+ 15440,
+ 15441,
+ 15442,
+ 15443,
+ 15444,
+ 15445,
+ 15446,
+ 15447,
+ 15448,
+ 15449,
+ 15450,
+ 15451,
+ 15452,
+ 15453,
+ 15454,
+ 15455,
+ 15456,
+ 15457,
+ 15458,
+ 15459,
+ 15460,
+ 15461,
+ 15462,
+ 15463,
+ 15464,
+ 15465,
+ 15466,
+ 15467,
+ 15468,
+ 15469,
+ 15470,
+ 15471,
+ 15472,
+ 15473,
+ 15474,
+ 15475,
+ 15476,
+ 15477,
+ 15478,
+ 15479,
+ 15480,
+ 15481,
+ 15482,
+ 15483,
+ 15484,
+ 15485,
+ 15486,
+ 15487,
+ 15488,
+ 15489,
+ 15490,
+ 15491,
+ 15492,
+ 15493,
+ 15494,
+ 15495,
+ 15496,
+ 15497,
+ 15498,
+ 15499,
+ 15500,
+ 15501,
+ 15502,
+ 15503,
+ 15504,
+ 15505,
+ 15506,
+ 15507,
+ 15508,
+ 15509,
+ 15510,
+ 15511,
+ 15512,
+ 15513,
+ 15514,
+ 15515,
+ 15516,
+ 15517,
+ 15518,
+ 15519,
+ 15520,
+ 15521,
+ 15522,
+ 15523,
+ 15524,
+ 15525,
+ 15526,
+ 15527,
+ 15528,
+ 15529,
+ 15530,
+ 15531,
+ 15532,
+ 15533,
+ 15534,
+ 15535,
+ 15536,
+ 15537,
+ 15538,
+ 15539,
+ 15540,
+ 15541,
+ 15542,
+ 15543,
+ 15544,
+ 15545,
+ 15546,
+ 15547,
+ 15548,
+ 15549,
+ 15550,
+ 15551,
+ 15552,
+ 15553,
+ 15554,
+ 15555,
+ 15556,
+ 15557,
+ 15558,
+ 15559,
+ 15560,
+ 15561,
+ 15562,
+ 15563,
+ 15564,
+ 15565,
+ 15566,
+ 15567,
+ 15568,
+ 15569,
+ 15570,
+ 15571,
+ 15572,
+ 15573,
+ 15574,
+ 15575,
+ 15576,
+ 15577,
+ 15578,
+ 15579,
+ 15580,
+ 15581,
+ 15582,
+ 15583,
+ 15584,
+ 15585,
+ 15586,
+ 15587,
+ 15588,
+ 15589,
+ 15590,
+ 15591,
+ 15592,
+ 15593,
+ 15594,
+ 15595,
+ 15596,
+ 15597,
+ 15598,
+ 15599,
+ 15600,
+ 15601,
+ 15602,
+ 15603,
+ 15604,
+ 15605,
+ 15606,
+ 15607,
+ 15608,
+ 15609,
+ 15610,
+ 15611,
+ 15612,
+ 15613,
+ 15614,
+ 15615,
+ 15616,
+ 15617,
+ 15618,
+ 15619,
+ 15620,
+ 15621,
+ 15622,
+ 15623,
+ 15624,
+ 15625,
+ 15626,
+ 15627,
+ 15628,
+ 15629,
+ 15630,
+ 15631,
+ 15632,
+ 15633,
+ 15634,
+ 15635,
+ 15636,
+ 15637,
+ 15638,
+ 15639,
+ 15640,
+ 15641,
+ 15642,
+ 15643,
+ 15644,
+ 15645,
+ 15646,
+ 15647,
+ 15648,
+ 15649,
+ 15650,
+ 15651,
+ 15652,
+ 15653,
+ 15654,
+ 15655,
+ 15656,
+ 15657,
+ 15658,
+ 15659,
+ 15660,
+ 15661,
+ 15662,
+ 15663,
+ 15664,
+ 15665,
+ 15666,
+ 15667,
+ 15668,
+ 15669,
+ 15670,
+ 15671,
+ 15672,
+ 15673,
+ 15674,
+ 15675,
+ 15676,
+ 15677,
+ 15678,
+ 15679,
+ 15680,
+ 15681,
+ 15682,
+ 15683,
+ 15684,
+ 15685,
+ 15686,
+ 15687,
+ 15688,
+ 15689,
+ 15690,
+ 15691,
+ 15692,
+ 15693,
+ 15694,
+ 15695,
+ 15696,
+ 15697,
+ 15698,
+ 15699,
+ 15700,
+ 15701,
+ 15702,
+ 15703,
+ 15704,
+ 15705,
+ 15706,
+ 15707,
+ 15708,
+ 15709,
+ 15710,
+ 15711,
+ 15712,
+ 15713,
+ 15714,
+ 15715,
+ 15716,
+ 15717,
+ 15718,
+ 15719,
+ 15720,
+ 15721,
+ 15722,
+ 15723,
+ 15724,
+ 15725,
+ 15726,
+ 15727,
+ 15728,
+ 15729,
+ 15730,
+ 15731,
+ 15732,
+ 15733,
+ 15734,
+ 15735,
+ 15736,
+ 15737,
+ 15738,
+ 15739,
+ 15740,
+ 15741,
+ 15742,
+ 15743,
+ 15744,
+ 15745,
+ 15746,
+ 15747,
+ 15748,
+ 15749,
+ 15750,
+ 15751,
+ 15752,
+ 15753,
+ 15754,
+ 15755,
+ 15756,
+ 15757,
+ 15758,
+ 15759,
+ 15760,
+ 15761,
+ 15762,
+ 15763,
+ 15764,
+ 15765,
+ 15766,
+ 15767,
+ 15768,
+ 15769,
+ 15770,
+ 15771,
+ 15772,
+ 15773,
+ 15774,
+ 15775,
+ 15776,
+ 15777,
+ 15778,
+ 15779,
+ 15780,
+ 15781,
+ 15782,
+ 15783,
+ 15784,
+ 15785,
+ 15786,
+ 15787,
+ 15788,
+ 15789,
+ 15790,
+ 15791,
+ 15792,
+ 15793,
+ 15794,
+ 15795,
+ 15796,
+ 15797,
+ 15798,
+ 15799,
+ 15800,
+ 15801,
+ 15802,
+ 15803,
+ 15804,
+ 15805,
+ 15806,
+ 15807,
+ 15808,
+ 15809,
+ 15810,
+ 15811,
+ 15812,
+ 15813,
+ 15814,
+ 15815,
+ 15816,
+ 15817,
+ 15818,
+ 15819,
+ 15820,
+ 15821,
+ 15822,
+ 15823,
+ 15824,
+ 15825,
+ 15826,
+ 15827,
+ 15828,
+ 15829,
+ 15830,
+ 15831,
+ 15832,
+ 15833,
+ 15834,
+ 15835,
+ 15836,
+ 15837,
+ 15838,
+ 15839,
+ 15840,
+ 15841,
+ 15842,
+ 15843,
+ 15844,
+ 15845,
+ 15846,
+ 15847,
+ 15848,
+ 15849,
+ 15850,
+ 15851,
+ 15852,
+ 15853,
+ 15854,
+ 15855,
+ 15856,
+ 15857,
+ 15858,
+ 15859,
+ 15860,
+ 15861,
+ 15862,
+ 15863,
+ 15864,
+ 15865,
+ 15866,
+ 15867,
+ 15868,
+ 15869,
+ 15870,
+ 15871,
+ 15872,
+ 15873,
+ 15874,
+ 15875,
+ 15876,
+ 15877,
+ 15878,
+ 15879,
+ 15880,
+ 15881,
+ 15882,
+ 15883,
+ 15884,
+ 15885,
+ 15886,
+ 15887,
+ 15888,
+ 15889,
+ 15890,
+ 15891,
+ 15892,
+ 15893,
+ 15894,
+ 15895,
+ 15896,
+ 15897,
+ 15898,
+ 15899,
+ 15900,
+ 15901,
+ 15902,
+ 15903,
+ 15904,
+ 15905,
+ 15906,
+ 15907,
+ 15908,
+ 15909,
+ 15910,
+ 15911,
+ 15912,
+ 15913,
+ 15914,
+ 15915,
+ 15916,
+ 15917,
+ 15918,
+ 15919,
+ 15920,
+ 15921,
+ 15922,
+ 15923,
+ 15924,
+ 15925,
+ 15926,
+ 15927,
+ 15928,
+ 15929,
+ 15930,
+ 15931,
+ 15932,
+ 15933,
+ 15934,
+ 15935,
+ 15936,
+ 15937,
+ 15938,
+ 15939,
+ 15940,
+ 15941,
+ 15942,
+ 15943,
+ 15944,
+ 15945,
+ 15946,
+ 15947,
+ 15948,
+ 15949,
+ 15950,
+ 15951,
+ 15952,
+ 15953,
+ 15954,
+ 15955,
+ 15956,
+ 15957,
+ 15958,
+ 15959,
+ 15960,
+ 15961,
+ 15962,
+ 15963,
+ 15964,
+ 15965,
+ 15966,
+ 15967,
+ 15968,
+ 15969,
+ 15970,
+ 15971,
+ 15972,
+ 15973,
+ 15974,
+ 15975,
+ 15976,
+ 15977,
+ 15978,
+ 15979,
+ 15980,
+ 15981,
+ 15982,
+ 15983,
+ 15984,
+ 15985,
+ 15986,
+ 15987,
+ 15988,
+ 15989,
+ 15990,
+ 15991,
+ 15992,
+ 15993,
+ 15994,
+ 15995,
+ 15996,
+ 15997,
+ 15998,
+ 15999,
+ 16000,
+ 16001,
+ 16002,
+ 16003,
+ 16004,
+ 16005,
+ 16006,
+ 16007,
+ 16008,
+ 16009,
+ 16010,
+ 16011,
+ 16012,
+ 16013,
+ 16014,
+ 16015,
+ 16016,
+ 16017,
+ 16018,
+ 16019,
+ 16020,
+ 16021,
+ 16022,
+ 16023,
+ 16024,
+ 16025,
+ 16026,
+ 16027,
+ 16028,
+ 16029,
+ 16030,
+ 16031,
+ 16032,
+ 16033,
+ 16034,
+ 16035,
+ 16036,
+ 16037,
+ 16038,
+ 16039,
+ 16040,
+ 16041,
+ 16042,
+ 16043,
+ 16044,
+ 16045,
+ 16046,
+ 16047,
+ 16048,
+ 16049,
+ 16050,
+ 16051,
+ 16052,
+ 16053,
+ 16054,
+ 16055,
+ 16056,
+ 16057,
+ 16058,
+ 16059,
+ 16060,
+ 16061,
+ 16062,
+ 16063,
+ 16064,
+ 16065,
+ 16066,
+ 16067,
+ 16068,
+ 16069,
+ 16070,
+ 16071,
+ 16072,
+ 16073,
+ 16074,
+ 16075,
+ 16076,
+ 16077,
+ 16078,
+ 16079,
+ 16080,
+ 16081,
+ 16082,
+ 16083,
+ 16084,
+ 16085,
+ 16086,
+ 16087,
+ 16088,
+ 16089,
+ 16090,
+ 16091,
+ 16092,
+ 16093,
+ 16094,
+ 16095,
+ 16096,
+ 16097,
+ 16098,
+ 16099,
+ 16100,
+ 16101,
+ 16102,
+ 16103,
+ 16104,
+ 16105,
+ 16106,
+ 16107,
+ 16108,
+ 16109,
+ 16110,
+ 16111,
+ 16112,
+ 16113,
+ 16114,
+ 16115,
+ 16116,
+ 16117,
+ 16118,
+ 16119,
+ 16120,
+ 16121,
+ 16122,
+ 16123,
+ 16124,
+ 16125,
+ 16126,
+ 16127,
+ 16128,
+ 16129,
+ 16130,
+ 16131,
+ 16132,
+ 16133,
+ 16134,
+ 16135,
+ 16136,
+ 16137,
+ 16138,
+ 16139,
+ 16140,
+ 16141,
+ 16142,
+ 16143,
+ 16144,
+ 16145,
+ 16146,
+ 16147,
+ 16148,
+ 16149,
+ 16150,
+ 16151,
+ 16152,
+ 16153,
+ 16154,
+ 16155,
+ 16156,
+ 16157,
+ 16158,
+ 16159,
+ 16160,
+ 16161,
+ 16162,
+ 16163,
+ 16164,
+ 16165,
+ 16166,
+ 16167,
+ 16168,
+ 16169,
+ 16170,
+ 16171,
+ 16172,
+ 16173,
+ 16174,
+ 16175,
+ 16176,
+ 16177,
+ 16178,
+ 16179,
+ 16180,
+ 16181,
+ 16182,
+ 16183,
+ 16184,
+ 16185,
+ 16186,
+ 16187,
+ 16188,
+ 16189,
+ 16190,
+ 16191,
+ 16192,
+ 16193,
+ 16194,
+ 16195,
+ 16196,
+ 16197,
+ 16198,
+ 16199,
+ 16200,
+ 16201,
+ 16202,
+ 16203,
+ 16204,
+ 16205,
+ 16206,
+ 16207,
+ 16208,
+ 16209,
+ 16210,
+ 16211,
+ 16212,
+ 16213,
+ 16214,
+ 16215,
+ 16216,
+ 16217,
+ 16218,
+ 16219,
+ 16220,
+ 16221,
+ 16222,
+ 16223,
+ 16224,
+ 16225,
+ 16226,
+ 16227,
+ 16228,
+ 16229,
+ 16230,
+ 16231,
+ 16232,
+ 16233,
+ 16234,
+ 16235,
+ 16236,
+ 16237,
+ 16238,
+ 16239,
+ 16240,
+ 16241,
+ 16242,
+ 16243,
+ 16244,
+ 16245,
+ 16246,
+ 16247,
+ 16248,
+ 16249,
+ 16250,
+ 16251,
+ 16252,
+ 16253,
+ 16254,
+ 16255,
+ 16256,
+ 16257,
+ 16258,
+ 16259,
+ 16260,
+ 16261,
+ 16262,
+ 16263,
+ 16264,
+ 16265,
+ 16266,
+ 16267,
+ 16268,
+ 16269,
+ 16270,
+ 16271,
+ 16272,
+ 16273,
+ 16274,
+ 16275,
+ 16276,
+ 16277,
+ 16278,
+ 16279,
+ 16280,
+ 16281,
+ 16282,
+ 16283,
+ 16284,
+ 16285,
+ 16286,
+ 16287,
+ 16288,
+ 16289,
+ 16290,
+ 16291,
+ 16292,
+ 16293,
+ 16294,
+ 16295,
+ 16296,
+ 16297,
+ 16298,
+ 16299,
+ 16300,
+ 16301,
+ 16302,
+ 16303,
+ 16304,
+ 16305,
+ 16306,
+ 16307,
+ 16308,
+ 16309,
+ 16310,
+ 16311,
+ 16312,
+ 16313,
+ 16314,
+ 16315,
+ 16316,
+ 16317,
+ 16318,
+ 16319,
+ 16320,
+ 16321,
+ 16322,
+ 16323,
+ 16324,
+ 16325,
+ 16326,
+ 16327,
+ 16328,
+ 16329,
+ 16330,
+ 16331,
+ 16332,
+ 16333,
+ 16334,
+ 16335,
+ 16336,
+ 16337,
+ 16338,
+ 16339,
+ 16340,
+ 16341,
+ 16342,
+ 16343,
+ 16344,
+ 16345,
+ 16346,
+ 16347,
+ 16348,
+ 16349,
+ 16350,
+ 16351,
+ 16352,
+ 16353,
+ 16354,
+ 16355,
+ 16356,
+ 16357,
+ 16358,
+ 16359,
+ 16360,
+ 16361,
+ 16362,
+ 16363,
+ 16364,
+ 16365,
+ 16366,
+ 16367,
+ 16368,
+ 16369,
+ 16370,
+ 16371,
+ 16372,
+ 16373,
+ 16374,
+ 16375,
+ 16376,
+ 16377,
+ 16378,
+ 16379,
+ 16380,
+ 16381,
+ 16382,
+ 16383,
+ 16384,
+ 16385,
+ 16386,
+ 16387,
+ 16388,
+ 16389,
+ 16390,
+ 16391,
+ 16392,
+ 16393,
+ 16394,
+ 16395,
+ 16396,
+ 16397,
+ 16398,
+ 16399,
+ 16400,
+ 16401,
+ 16402,
+ 16403,
+ 16404,
+ 16405,
+ 16406,
+ 16407,
+ 16408,
+ 16409,
+ 16410,
+ 16411,
+ 16412,
+ 16413,
+ 16414,
+ 16415,
+ 16416,
+ 16417,
+ 16418,
+ 16419,
+ 16420,
+ 16421,
+ 16422,
+ 16423,
+ 16424,
+ 16425,
+ 16426,
+ 16427,
+ 16428,
+ 16429,
+ 16430,
+ 16431,
+ 16432,
+ 16433,
+ 16434,
+ 16435,
+ 16436,
+ 16437,
+ 16438,
+ 16439,
+ 16440,
+ 16441,
+ 16442,
+ 16443,
+ 16444,
+ 16445,
+ 16446,
+ 16447,
+ 16448,
+ 16449,
+ 16450,
+ 16451,
+ 16452,
+ 16453,
+ 16454,
+ 16455,
+ 16456,
+ 16457,
+ 16458,
+ 16459,
+ 16460,
+ 16461,
+ 16462,
+ 16463,
+ 16464,
+ 16465,
+ 16466,
+ 16467,
+ 16468,
+ 16469,
+ 16470,
+ 16471,
+ 16472,
+ 16473,
+ 16474,
+ 16475,
+ 16476,
+ 16477,
+ 16478,
+ 16479,
+ 16480,
+ 16481,
+ 16482,
+ 16483,
+ 16484,
+ 16485,
+ 16486,
+ 16487,
+ 16488,
+ 16489,
+ 16490,
+ 16491,
+ 16492,
+ 16493,
+ 16494,
+ 16495,
+ 16496,
+ 16497,
+ 16498,
+ 16499,
+ 16500,
+ 16501,
+ 16502,
+ 16503,
+ 16504,
+ 16505,
+ 16506,
+ 16507,
+ 16508,
+ 16509,
+ 16510,
+ 16511,
+ 16512,
+ 16513,
+ 16514,
+ 16515,
+ 16516,
+ 16517,
+ 16518,
+ 16519,
+ 16520,
+ 16521,
+ 16522,
+ 16523,
+ 16524,
+ 16525,
+ 16526,
+ 16527,
+ 16528,
+ 16529,
+ 16530,
+ 16531,
+ 16532,
+ 16533,
+ 16534,
+ 16535,
+ 16536,
+ 16537,
+ 16538,
+ 16539,
+ 16540,
+ 16541,
+ 16542,
+ 16543,
+ 16544,
+ 16545,
+ 16546,
+ 16547,
+ 16548,
+ 16549,
+ 16550,
+ 16551,
+ 16552,
+ 16553,
+ 16554,
+ 16555,
+ 16556,
+ 16557,
+ 16558,
+ 16559,
+ 16560,
+ 16561,
+ 16562,
+ 16563,
+ 16564,
+ 16565,
+ 16566,
+ 16567,
+ 16568,
+ 16569,
+ 16570,
+ 16571,
+ 16572,
+ 16573,
+ 16574,
+ 16575,
+ 16576,
+ 16577,
+ 16578,
+ 16579,
+ 16580,
+ 16581,
+ 16582,
+ 16583,
+ 16584,
+ 16585,
+ 16586,
+ 16587,
+ 16588,
+ 16589,
+ 16590,
+ 16591,
+ 16592,
+ 16593,
+ 16594,
+ 16595,
+ 16596,
+ 16597,
+ 16598,
+ 16599,
+ 16600,
+ 16601,
+ 16602,
+ 16603,
+ 16604,
+ 16605,
+ 16606,
+ 16607,
+ 16608,
+ 16609,
+ 16610,
+ 16611,
+ 16612,
+ 16613,
+ 16614,
+ 16615,
+ 16616,
+ 16617,
+ 16618,
+ 16619,
+ 16620,
+ 16621,
+ 16622,
+ 16623,
+ 16624,
+ 16625,
+ 16626,
+ 16627,
+ 16628,
+ 16629,
+ 16630,
+ 16631,
+ 16632,
+ 16633,
+ 16634,
+ 16635,
+ 16636,
+ 16637,
+ 16638,
+ 16639,
+ 16640,
+ 16641,
+ 16642,
+ 16643,
+ 16644,
+ 16645,
+ 16646,
+ 16647,
+ 16648,
+ 16649,
+ 16650,
+ 16651,
+ 16652,
+ 16653,
+ 16654,
+ 16655,
+ 16656,
+ 16657,
+ 16658,
+ 16659,
+ 16660,
+ 16661,
+ 16662,
+ 16663,
+ 16664,
+ 16665,
+ 16666,
+ 16667,
+ 16668,
+ 16669,
+ 16670,
+ 16671,
+ 16672,
+ 16673,
+ 16674,
+ 16675,
+ 16676,
+ 16677,
+ 16678,
+ 16679,
+ 16680,
+ 16681,
+ 16682,
+ 16683,
+ 16684,
+ 16685,
+ 16686,
+ 16687,
+ 16688,
+ 16689,
+ 16690,
+ 16691,
+ 16692,
+ 16693,
+ 16694,
+ 16695,
+ 16696,
+ 16697,
+ 16698,
+ 16699,
+ 16700,
+ 16701,
+ 16702,
+ 16703,
+ 16704,
+ 16705,
+ 16706,
+ 16707,
+ 16708,
+ 16709,
+ 16710,
+ 16711,
+ 16712,
+ 16713,
+ 16714,
+ 16715,
+ 16716,
+ 16717,
+ 16718,
+ 16719,
+ 16720,
+ 16721,
+ 16722,
+ 16723,
+ 16724,
+ 16725,
+ 16726,
+ 16727,
+ 16728,
+ 16729,
+ 16730,
+ 16731,
+ 16732,
+ 16733,
+ 16734,
+ 16735,
+ 16736,
+ 16737,
+ 16738,
+ 16739,
+ 16740,
+ 16741,
+ 16742,
+ 16743,
+ 16744,
+ 16745,
+ 16746,
+ 16747,
+ 16748,
+ 16749,
+ 16750,
+ 16751,
+ 16752,
+ 16753,
+ 16754,
+ 16755,
+ 16756,
+ 16757,
+ 16758,
+ 16759,
+ 16760,
+ 16761,
+ 16762,
+ 16763,
+ 16764,
+ 16765,
+ 16766,
+ 16767,
+ 16768,
+ 16769,
+ 16770,
+ 16771,
+ 16772,
+ 16773,
+ 16774,
+ 16775,
+ 16776,
+ 16777,
+ 16778,
+ 16779,
+ 16780,
+ 16781,
+ 16782,
+ 16783,
+ 16784,
+ 16785,
+ 16786,
+ 16787,
+ 16788,
+ 16789,
+ 16790,
+ 16791,
+ 16792,
+ 16793,
+ 16794,
+ 16795,
+ 16796,
+ 16797,
+ 16798,
+ 16799,
+ 16800,
+ 16801,
+ 16802,
+ 16803,
+ 16804,
+ 16805,
+ 16806,
+ 16807,
+ 16808,
+ 16809,
+ 16810,
+ 16811,
+ 16812,
+ 16813,
+ 16814,
+ 16815,
+ 16816,
+ 16817,
+ 16818,
+ 16819,
+ 16820,
+ 16821,
+ 16822,
+ 16823,
+ 16824,
+ 16825,
+ 16826,
+ 16827,
+ 16828,
+ 16829,
+ 16830,
+ 16831,
+ 16832,
+ 16833,
+ 16834,
+ 16835,
+ 16836,
+ 16837,
+ 16838,
+ 16839,
+ 16840,
+ 16841,
+ 16842,
+ 16843,
+ 16844,
+ 16845,
+ 16846,
+ 16847,
+ 16848,
+ 16849,
+ 16850,
+ 16851,
+ 16852,
+ 16853,
+ 16854,
+ 16855,
+ 16856,
+ 16857,
+ 16858,
+ 16859,
+ 16860,
+ 16861,
+ 16862,
+ 16863,
+ 16864,
+ 16865,
+ 16866,
+ 16867,
+ 16868,
+ 16869,
+ 16870,
+ 16871,
+ 16872,
+ 16873,
+ 16874,
+ 16875,
+ 16876,
+ 16877,
+ 16878,
+ 16879,
+ 16880,
+ 16881,
+ 16882,
+ 16883,
+ 16884,
+ 16885,
+ 16886,
+ 16887,
+ 16888,
+ 16889,
+ 16890,
+ 16891,
+ 16892,
+ 16893,
+ 16894,
+ 16895,
+ 16896,
+ 16897,
+ 16898,
+ 16899,
+ 16900,
+ 16901,
+ 16902,
+ 16903,
+ 16904,
+ 16905,
+ 16906,
+ 16907,
+ 16908,
+ 16909,
+ 16910,
+ 16911,
+ 16912,
+ 16913,
+ 16914,
+ 16915,
+ 16916,
+ 16917,
+ 16918,
+ 16919,
+ 16920,
+ 16921,
+ 16922,
+ 16923,
+ 16924,
+ 16925,
+ 16926,
+ 16927,
+ 16928,
+ 16929,
+ 16930,
+ 16931,
+ 16932,
+ 16933,
+ 16934,
+ 16935,
+ 16936,
+ 16937,
+ 16938,
+ 16939,
+ 16940,
+ 16941,
+ 16942,
+ 16943,
+ 16944,
+ 16945,
+ 16946,
+ 16947,
+ 16948,
+ 16949,
+ 16950,
+ 16951,
+ 16952,
+ 16953,
+ 16954,
+ 16955,
+ 16956,
+ 16957,
+ 16958,
+ 16959,
+ 16960,
+ 16961,
+ 16962,
+ 16963,
+ 16964,
+ 16965,
+ 16966,
+ 16967,
+ 16968,
+ 16969,
+ 16970,
+ 16971,
+ 16972,
+ 16973,
+ 16974,
+ 16975,
+ 16976,
+ 16977,
+ 16978,
+ 16979,
+ 16980,
+ 16981,
+ 16982,
+ 16983,
+ 16984,
+ 16985,
+ 16986,
+ 16987,
+ 16988,
+ 16989,
+ 16990,
+ 16991,
+ 16992,
+ 16993,
+ 16994,
+ 16995,
+ 16996,
+ 16997,
+ 16998,
+ 16999,
+ 17000,
+ 17001,
+ 17002,
+ 17003,
+ 17004,
+ 17005,
+ 17006,
+ 17007,
+ 17008,
+ 17009,
+ 17010,
+ 17011,
+ 17012,
+ 17013,
+ 17014,
+ 17015,
+ 17016,
+ 17017,
+ 17018,
+ 17019,
+ 17020,
+ 17021,
+ 17022,
+ 17023,
+ 17024,
+ 17025,
+ 17026,
+ 17027,
+ 17028,
+ 17029,
+ 17030,
+ 17031,
+ 17032,
+ 17033,
+ 17034,
+ 17035,
+ 17036,
+ 17037,
+ 17038,
+ 17039,
+ 17040,
+ 17041,
+ 17042,
+ 17043,
+ 17044,
+ 17045,
+ 17046,
+ 17047,
+ 17048,
+ 17049,
+ 17050,
+ 17051,
+ 17052,
+ 17053,
+ 17054,
+ 17055,
+ 17056,
+ 17057,
+ 17058,
+ 17059,
+ 17060,
+ 17061,
+ 17062,
+ 17063,
+ 17064,
+ 17065,
+ 17066,
+ 17067,
+ 17068,
+ 17069,
+ 17070,
+ 17071,
+ 17072,
+ 17073,
+ 17074,
+ 17075,
+ 17076,
+ 17077,
+ 17078,
+ 17079,
+ 17080,
+ 17081,
+ 17082,
+ 17083,
+ 17084,
+ 17085,
+ 17086,
+ 17087,
+ 17088,
+ 17089,
+ 17090,
+ 17091,
+ 17092,
+ 17093,
+ 17094,
+ 17095,
+ 17096,
+ 17097,
+ 17098,
+ 17099,
+ 17100,
+ 17101,
+ 17102,
+ 17103,
+ 17104,
+ 17105,
+ 17106,
+ 17107,
+ 17108,
+ 17109,
+ 17110,
+ 17111,
+ 17112,
+ 17113,
+ 17114,
+ 17115,
+ 17116,
+ 17117,
+ 17118,
+ 17119,
+ 17120,
+ 17121,
+ 17122,
+ 17123,
+ 17124,
+ 17125,
+ 17126,
+ 17127,
+ 17128,
+ 17129,
+ 17130,
+ 17131,
+ 17132,
+ 17133,
+ 17134,
+ 17135,
+ 17136,
+ 17137,
+ 17138,
+ 17139,
+ 17140,
+ 17141,
+ 17142,
+ 17143,
+ 17144,
+ 17145,
+ 17146,
+ 17147,
+ 17148,
+ 17149,
+ 17150,
+ 17151,
+ 17152,
+ 17153,
+ 17154,
+ 17155,
+ 17156,
+ 17157,
+ 17158,
+ 17159,
+ 17160,
+ 17161,
+ 17162,
+ 17163,
+ 17164,
+ 17165,
+ 17166,
+ 17167,
+ 17168,
+ 17169,
+ 17170,
+ 17171,
+ 17172,
+ 17173,
+ 17174,
+ 17175,
+ 17176,
+ 17177,
+ 17178,
+ 17179,
+ 17180,
+ 17181,
+ 17182,
+ 17183,
+ 17184,
+ 17185,
+ 17186,
+ 17187,
+ 17188,
+ 17189,
+ 17190,
+ 17191,
+ 17192,
+ 17193,
+ 17194,
+ 17195,
+ 17196,
+ 17197,
+ 17198,
+ 17199,
+ 17200,
+ 17201,
+ 17202,
+ 17203,
+ 17204,
+ 17205,
+ 17206,
+ 17207,
+ 17208,
+ 17209,
+ 17210,
+ 17211,
+ 17212,
+ 17213,
+ 17214,
+ 17215,
+ 17216,
+ 17217,
+ 17218,
+ 17219,
+ 17220,
+ 17221,
+ 17222,
+ 17223,
+ 17224,
+ 17225,
+ 17226,
+ 17227,
+ 17228,
+ 17229,
+ 17230,
+ 17231,
+ 17232,
+ 17233,
+ 17234,
+ 17235,
+ 17236,
+ 17237,
+ 17238,
+ 17239,
+ 17240,
+ 17241,
+ 17242,
+ 17243,
+ 17244,
+ 17245,
+ 17246,
+ 17247,
+ 17248,
+ 17249,
+ 17250,
+ 17251,
+ 17252,
+ 17253,
+ 17254,
+ 17255,
+ 17256,
+ 17257,
+ 17258,
+ 17259,
+ 17260,
+ 17261,
+ 17262,
+ 17263,
+ 17264,
+ 17265,
+ 17266,
+ 17267,
+ 17268,
+ 17269,
+ 17270,
+ 17271,
+ 17272,
+ 17273,
+ 17274,
+ 17275,
+ 17276,
+ 17277,
+ 17278,
+ 17279,
+ 17280,
+ 17281,
+ 17282,
+ 17283,
+ 17284,
+ 17285,
+ 17286,
+ 17287,
+ 17288,
+ 17289,
+ 17290,
+ 17291,
+ 17292,
+ 17293,
+ 17294,
+ 17295,
+ 17296,
+ 17297,
+ 17298,
+ 17299,
+ 17300,
+ 17301,
+ 17302,
+ 17303,
+ 17304,
+ 17305,
+ 17306,
+ 17307,
+ 17308,
+ 17309,
+ 17310,
+ 17311,
+ 17312,
+ 17313,
+ 17314,
+ 17315,
+ 17316,
+ 17317,
+ 17318,
+ 17319,
+ 17320,
+ 17321,
+ 17322,
+ 17323,
+ 17324,
+ 17325,
+ 17326,
+ 17327,
+ 17328,
+ 17329,
+ 17330,
+ 17331,
+ 17332,
+ 17333,
+ 17334,
+ 17335,
+ 17336,
+ 17337,
+ 17338,
+ 17339,
+ 17340,
+ 17341,
+ 17342,
+ 17343,
+ 17344,
+ 17345,
+ 17346,
+ 17347,
+ 17348,
+ 17349,
+ 17350,
+ 17351,
+ 17352,
+ 17353,
+ 17354,
+ 17355,
+ 17356,
+ 17357,
+ 17358,
+ 17359,
+ 17360,
+ 17361,
+ 17362,
+ 17363,
+ 17364,
+ 17365,
+ 17366,
+ 17367,
+ 17368,
+ 17369,
+ 17370,
+ 17371,
+ 17372,
+ 17373,
+ 17374,
+ 17375,
+ 17376,
+ 17377,
+ 17378,
+ 17379,
+ 17380,
+ 17381,
+ 17382,
+ 17383,
+ 17384,
+ 17385,
+ 17386,
+ 17387,
+ 17388,
+ 17389,
+ 17390,
+ 17391,
+ 17392,
+ 17393,
+ 17394,
+ 17395,
+ 17396,
+ 17397,
+ 17398,
+ 17399,
+ 17400,
+ 17401,
+ 17402,
+ 17403,
+ 17404,
+ 17405,
+ 17406,
+ 17407,
+ 17408,
+ 17409,
+ 17410,
+ 17411,
+ 17412,
+ 17413,
+ 17414,
+ 17415,
+ 17416,
+ 17417,
+ 17418,
+ 17419,
+ 17420,
+ 17421,
+ 17422,
+ 17423,
+ 17424,
+ 17425,
+ 17426,
+ 17427,
+ 17428,
+ 17429,
+ 17430,
+ 17431,
+ 17432,
+ 17433,
+ 17434,
+ 17435,
+ 17436,
+ 17437,
+ 17438,
+ 17439,
+ 17440,
+ 17441,
+ 17442,
+ 17443,
+ 17444,
+ 17445,
+ 17446,
+ 17447,
+ 17448,
+ 17449,
+ 17450,
+ 17451,
+ 17452,
+ 17453,
+ 17454,
+ 17455,
+ 17456,
+ 17457,
+ 17458,
+ 17459,
+ 17460,
+ 17461,
+ 17462,
+ 17463,
+ 17464,
+ 17465,
+ 17466,
+ 17467,
+ 17468,
+ 17469,
+ 17470,
+ 17471,
+ 17472,
+ 17473,
+ 17474,
+ 17475,
+ 17476,
+ 17477,
+ 17478,
+ 17479,
+ 17480,
+ 17481,
+ 17482,
+ 17483,
+ 17484,
+ 17485,
+ 17486,
+ 17487,
+ 17488,
+ 17489,
+ 17490,
+ 17491,
+ 17492,
+ 17493,
+ 17494,
+ 17495,
+ 17496,
+ 17497,
+ 17498,
+ 17499,
+ 17500,
+ 17501,
+ 17502,
+ 17503,
+ 17504,
+ 17505,
+ 17506,
+ 17507,
+ 17508,
+ 17509,
+ 17510,
+ 17511,
+ 17512,
+ 17513,
+ 17514,
+ 17515,
+ 17516,
+ 17517,
+ 17518,
+ 17519,
+ 17520,
+ 17521,
+ 17522,
+ 17523,
+ 17524,
+ 17525,
+ 17526,
+ 17527,
+ 17528,
+ 17529,
+ 17530,
+ 17531,
+ 17532,
+ 17533,
+ 17534,
+ 17535,
+ 17536,
+ 17537,
+ 17538,
+ 17539,
+ 17540,
+ 17541,
+ 17542,
+ 17543,
+ 17544,
+ 17545,
+ 17546,
+ 17547,
+ 17548,
+ 17549,
+ 17550,
+ 17551,
+ 17552,
+ 17553,
+ 17554,
+ 17555,
+ 17556,
+ 17557,
+ 17558,
+ 17559,
+ 17560,
+ 17561,
+ 17562,
+ 17563,
+ 17564,
+ 17565,
+ 17566,
+ 17567,
+ 17568,
+ 17569,
+ 17570,
+ 17571,
+ 17572,
+ 17573,
+ 17574,
+ 17575,
+ 17576,
+ 17577,
+ 17578,
+ 17579,
+ 17580,
+ 17581,
+ 17582,
+ 17583,
+ 17584,
+ 17585,
+ 17586,
+ 17587,
+ 17588,
+ 17589,
+ 17590,
+ 17591,
+ 17592,
+ 17593,
+ 17594,
+ 17595,
+ 17596,
+ 17597,
+ 17598,
+ 17599,
+ 17600,
+ 17601,
+ 17602,
+ 17603,
+ 17604,
+ 17605,
+ 17606,
+ 17607,
+ 17608,
+ 17609,
+ 17610,
+ 17611,
+ 17612,
+ 17613,
+ 17614,
+ 17615,
+ 17616,
+ 17617,
+ 17618,
+ 17619,
+ 17620,
+ 17621,
+ 17622,
+ 17623,
+ 17624,
+ 17625,
+ 17626,
+ 17627,
+ 17628,
+ 17629,
+ 17630,
+ 17631,
+ 17632,
+ 17633,
+ 17634,
+ 17635,
+ 17636,
+ 17637,
+ 17638,
+ 17639,
+ 17640,
+ 17641,
+ 17642,
+ 17643,
+ 17644,
+ 17645,
+ 17646,
+ 17647,
+ 17648,
+ 17649,
+ 17650,
+ 17651,
+ 17652,
+ 17653,
+ 17654,
+ 17655,
+ 17656,
+ 17657,
+ 17658,
+ 17659,
+ 17660,
+ 17661,
+ 17662,
+ 17663,
+ 17664,
+ 17665,
+ 17666,
+ 17667,
+ 17668,
+ 17669,
+ 17670,
+ 17671,
+ 17672,
+ 17673,
+ 17674,
+ 17675,
+ 17676,
+ 17677,
+ 17678,
+ 17679,
+ 17680,
+ 17681,
+ 17682,
+ 17683,
+ 17684,
+ 17685,
+ 17686,
+ 17687,
+ 17688,
+ 17689,
+ 17690,
+ 17691,
+ 17692,
+ 17693,
+ 17694,
+ 17695,
+ 17696,
+ 17697,
+ 17698,
+ 17699,
+ 17700,
+ 17701,
+ 17702,
+ 17703,
+ 17704,
+ 17705,
+ 17706,
+ 17707,
+ 17708,
+ 17709,
+ 17710,
+ 17711,
+ 17712,
+ 17713,
+ 17714,
+ 17715,
+ 17716,
+ 17717,
+ 17718,
+ 17719,
+ 17720,
+ 17721,
+ 17722,
+ 17723,
+ 17724,
+ 17725,
+ 17726,
+ 17727,
+ 17728,
+ 17729,
+ 17730,
+ 17731,
+ 17732,
+ 17733,
+ 17734,
+ 17735,
+ 17736,
+ 17737,
+ 17738,
+ 17739,
+ 17740,
+ 17741,
+ 17742,
+ 17743,
+ 17744,
+ 17745,
+ 17746,
+ 17747,
+ 17748,
+ 17749,
+ 17750,
+ 17751,
+ 17752,
+ 17753,
+ 17754,
+ 17755,
+ 17756,
+ 17757,
+ 17758,
+ 17759,
+ 17760,
+ 17761,
+ 17762,
+ 17763,
+ 17764,
+ 17765,
+ 17766,
+ 17767,
+ 17768,
+ 17769,
+ 17770,
+ 17771,
+ 17772,
+ 17773,
+ 17774,
+ 17775,
+ 17776,
+ 17777,
+ 17778,
+ 17779,
+ 17780,
+ 17781,
+ 17782,
+ 17783,
+ 17784,
+ 17785,
+ 17786,
+ 17787,
+ 17788,
+ 17789,
+ 17790,
+ 17791,
+ 17792,
+ 17793,
+ 17794,
+ 17795,
+ 17796,
+ 17797,
+ 17798,
+ 17799,
+ 17800,
+ 17801,
+ 17802,
+ 17803,
+ 17804,
+ 17805,
+ 17806,
+ 17807,
+ 17808,
+ 17809,
+ 17810,
+ 17811,
+ 17812,
+ 17813,
+ 17814,
+ 17815,
+ 17816,
+ 17817,
+ 17818,
+ 17819,
+ 17820,
+ 17821,
+ 17822,
+ 17823,
+ 17824,
+ 17825,
+ 17826,
+ 17827,
+ 17828,
+ 17829,
+ 17830,
+ 17831,
+ 17832,
+ 17833,
+ 17834,
+ 17835,
+ 17836,
+ 17837,
+ 17838,
+ 17839,
+ 17840,
+ 17841,
+ 17842,
+ 17843,
+ 17844,
+ 17845,
+ 17846,
+ 17847,
+ 17848,
+ 17849,
+ 17850,
+ 17851,
+ 17852,
+ 17853,
+ 17854,
+ 17855,
+ 17856,
+ 17857,
+ 17858,
+ 17859,
+ 17860,
+ 17861,
+ 17862,
+ 17863,
+ 17864,
+ 17865,
+ 17866,
+ 17867,
+ 17868,
+ 17869,
+ 17870,
+ 17871,
+ 17872,
+ 17873,
+ 17874,
+ 17875,
+ 17876,
+ 17877,
+ 17878,
+ 17879,
+ 17880,
+ 17881,
+ 17882,
+ 17883,
+ 17884,
+ 17885,
+ 17886,
+ 17887,
+ 17888,
+ 17889,
+ 17890,
+ 17891,
+ 17892,
+ 17893,
+ 17894,
+ 17895,
+ 17896,
+ 17897,
+ 17898,
+ 17899,
+ 17900,
+ 17901,
+ 17902,
+ 17903,
+ 17904,
+ 17905,
+ 17906,
+ 17907,
+ 17908,
+ 17909,
+ 17910,
+ 17911,
+ 17912,
+ 17913,
+ 17914,
+ 17915,
+ 17916,
+ 17917,
+ 17918,
+ 17919,
+ 17920,
+ 17921,
+ 17922,
+ 17923,
+ 17924,
+ 17925,
+ 17926,
+ 17927,
+ 17928,
+ 17929,
+ 17930,
+ 17931,
+ 17932,
+ 17933,
+ 17934,
+ 17935,
+ 17936,
+ 17937,
+ 17938,
+ 17939,
+ 17940,
+ 17941,
+ 17942,
+ 17943,
+ 17944,
+ 17945,
+ 17946,
+ 17947,
+ 17948,
+ 17949,
+ 17950,
+ 17951,
+ 17952,
+ 17953,
+ 17954,
+ 17955,
+ 17956,
+ 17957,
+ 17958,
+ 17959,
+ 17960,
+ 17961,
+ 17962,
+ 17963,
+ 17964,
+ 17965,
+ 17966,
+ 17967,
+ 17968,
+ 17969,
+ 17970,
+ 17971,
+ 17972,
+ 17973,
+ 17974,
+ 17975,
+ 17976,
+ 17977,
+ 17978,
+ 17979,
+ 17980,
+ 17981,
+ 17982,
+ 17983,
+ 17984,
+ 17985,
+ 17986,
+ 17987,
+ 17988,
+ 17989,
+ 17990,
+ 17991,
+ 17992,
+ 17993,
+ 17994,
+ 17995,
+ 17996,
+ 17997,
+ 17998,
+ 17999,
+ 18000,
+ 18001,
+ 18002,
+ 18003,
+ 18004,
+ 18005,
+ 18006,
+ 18007,
+ 18008,
+ 18009,
+ 18010,
+ 18011,
+ 18012,
+ 18013,
+ 18014,
+ 18015,
+ 18016,
+ 18017,
+ 18018,
+ 18019,
+ 18020,
+ 18021,
+ 18022,
+ 18023,
+ 18024,
+ 18025,
+ 18026,
+ 18027,
+ 18028,
+ 18029,
+ 18030,
+ 18031,
+ 18032,
+ 18033,
+ 18034,
+ 18035,
+ 18036,
+ 18037,
+ 18038,
+ 18039,
+ 18040,
+ 18041,
+ 18042,
+ 18043,
+ 18044,
+ 18045,
+ 18046,
+ 18047,
+ 18048,
+ 18049,
+ 18050,
+ 18051,
+ 18052,
+ 18053,
+ 18054,
+ 18055,
+ 18056,
+ 18057,
+ 18058,
+ 18059,
+ 18060,
+ 18061,
+ 18062,
+ 18063,
+ 18064,
+ 18065,
+ 18066,
+ 18067,
+ 18068,
+ 18069,
+ 18070,
+ 18071,
+ 18072,
+ 18073,
+ 18074,
+ 18075,
+ 18076,
+ 18077,
+ 18078,
+ 18079,
+ 18080,
+ 18081,
+ 18082,
+ 18083,
+ 18084,
+ 18085,
+ 18086,
+ 18087,
+ 18088,
+ 18089,
+ 18090,
+ 18091,
+ 18092,
+ 18093,
+ 18094,
+ 18095,
+ 18096,
+ 18097,
+ 18098,
+ 18099,
+ 18100,
+ 18101,
+ 18102,
+ 18103,
+ 18104,
+ 18105,
+ 18106,
+ 18107,
+ 18108,
+ 18109,
+ 18110,
+ 18111,
+ 18112,
+ 18113,
+ 18114,
+ 18115,
+ 18116,
+ 18117,
+ 18118,
+ 18119,
+ 18120,
+ 18121,
+ 18122,
+ 18123,
+ 18124,
+ 18125,
+ 18126,
+ 18127,
+ 18128,
+ 18129,
+ 18130,
+ 18131,
+ 18132,
+ 18133,
+ 18134,
+ 18135,
+ 18136,
+ 18137,
+ 18138,
+ 18139,
+ 18140,
+ 18141,
+ 18142,
+ 18143,
+ 18144,
+ 18145,
+ 18146,
+ 18147,
+ 18148,
+ 18149,
+ 18150,
+ 18151,
+ 18152,
+ 18153,
+ 18154,
+ 18155,
+ 18156,
+ 18157,
+ 18158,
+ 18159,
+ 18160,
+ 18161,
+ 18162,
+ 18163,
+ 18164,
+ 18165,
+ 18166,
+ 18167,
+ 18168,
+ 18169,
+ 18170,
+ 18171,
+ 18172,
+ 18173,
+ 18174,
+ 18175,
+ 18176,
+ 18177,
+ 18178,
+ 18179,
+ 18180,
+ 18181,
+ 18182,
+ 18183,
+ 18184,
+ 18185,
+ 18186,
+ 18187,
+ 18188,
+ 18189,
+ 18190,
+ 18191,
+ 18192,
+ 18193,
+ 18194,
+ 18195,
+ 18196,
+ 18197,
+ 18198,
+ 18199,
+ 18200,
+ 18201,
+ 18202,
+ 18203,
+ 18204,
+ 18205,
+ 18206,
+ 18207,
+ 18208,
+ 18209,
+ 18210,
+ 18211,
+ 18212,
+ 18213,
+ 18214,
+ 18215,
+ 18216,
+ 18217,
+ 18218,
+ 18219,
+ 18220,
+ 18221,
+ 18222,
+ 18223,
+ 18224,
+ 18225,
+ 18226,
+ 18227,
+ 18228,
+ 18229,
+ 18230,
+ 18231,
+ 18232,
+ 18233,
+ 18234,
+ 18235,
+ 18236,
+ 18237,
+ 18238,
+ 18239,
+ 18240,
+ 18241,
+ 18242,
+ 18243,
+ 18244,
+ 18245,
+ 18246,
+ 18247,
+ 18248,
+ 18249,
+ 18250,
+ 18251,
+ 18252,
+ 18253,
+ 18254,
+ 18255,
+ 18256,
+ 18257,
+ 18258,
+ 18259,
+ 18260,
+ 18261,
+ 18262,
+ 18263,
+ 18264,
+ 18265,
+ 18266,
+ 18267,
+ 18268,
+ 18269,
+ 18270,
+ 18271,
+ 18272,
+ 18273,
+ 18274,
+ 18275,
+ 18276,
+ 18277,
+ 18278,
+ 18279,
+ 18280,
+ 18281,
+ 18282,
+ 18283,
+ 18284,
+ 18285,
+ 18286,
+ 18287,
+ 18288,
+ 18289,
+ 18290,
+ 18291,
+ 18292,
+ 18293,
+ 18294,
+ 18295,
+ 18296,
+ 18297,
+ 18298,
+ 18299,
+ 18300,
+ 18301,
+ 18302,
+ 18303,
+ 18304,
+ 18305,
+ 18306,
+ 18307,
+ 18308,
+ 18309,
+ 18310,
+ 18311,
+ 18312,
+ 18313,
+ 18314,
+ 18315,
+ 18316,
+ 18317,
+ 18318,
+ 18319,
+ 18320,
+ 18321,
+ 18322,
+ 18323,
+ 18324,
+ 18325,
+ 18326,
+ 18327,
+ 18328,
+ 18329,
+ 18330,
+ 18331,
+ 18332,
+ 18333,
+ 18334,
+ 18335,
+ 18336,
+ 18337,
+ 18338,
+ 18339,
+ 18340,
+ 18341,
+ 18342,
+ 18343,
+ 18344,
+ 18345,
+ 18346,
+ 18347,
+ 18348,
+ 18349,
+ 18350,
+ 18351,
+ 18352,
+ 18353,
+ 18354,
+ 18355,
+ 18356,
+ 18357,
+ 18358,
+ 18359,
+ 18360,
+ 18361,
+ 18362,
+ 18363,
+ 18364,
+ 18365,
+ 18366,
+ 18367,
+ 18368,
+ 18369,
+ 18370,
+ 18371,
+ 18372,
+ 18373,
+ 18374,
+ 18375,
+ 18376,
+ 18377,
+ 18378,
+ 18379,
+ 18380,
+ 18381,
+ 18382,
+ 18383,
+ 18384,
+ 18385,
+ 18386,
+ 18387,
+ 18388,
+ 18389,
+ 18390,
+ 18391,
+ 18392,
+ 18393,
+ 18394,
+ 18395,
+ 18396,
+ 18397,
+ 18398,
+ 18399,
+ 18400,
+ 18401,
+ 18402,
+ 18403,
+ 18404,
+ 18405,
+ 18406,
+ 18407,
+ 18408,
+ 18409,
+ 18410,
+ 18411,
+ 18412,
+ 18413,
+ 18414,
+ 18415,
+ 18416,
+ 18417,
+ 18418,
+ 18419,
+ 18420,
+ 18421,
+ 18422,
+ 18423,
+ 18424,
+ 18425,
+ 18426,
+ 18427,
+ 18428,
+ 18429,
+ 18430,
+ 18431,
+ 18432,
+ 18433,
+ 18434,
+ 18435,
+ 18436,
+ 18437,
+ 18438,
+ 18439,
+ 18440,
+ 18441,
+ 18442,
+ 18443,
+ 18444,
+ 18445,
+ 18446,
+ 18447,
+ 18448,
+ 18449,
+ 18450,
+ 18451,
+ 18452,
+ 18453,
+ 18454,
+ 18455,
+ 18456,
+ 18457,
+ 18458,
+ 18459,
+ 18460,
+ 18461,
+ 18462,
+ 18463,
+ 18464,
+ 18465,
+ 18466,
+ 18467,
+ 18468,
+ 18469,
+ 18470,
+ 18471,
+ 18472,
+ 18473,
+ 18474,
+ 18475,
+ 18476,
+ 18477,
+ 18478,
+ 18479,
+ 18480,
+ 18481,
+ 18482,
+ 18483,
+ 18484,
+ 18485,
+ 18486,
+ 18487,
+ 18488,
+ 18489,
+ 18490,
+ 18491,
+ 18492,
+ 18493,
+ 18494,
+ 18495,
+ 18496,
+ 18497,
+ 18498,
+ 18499,
+ 18500,
+ 18501,
+ 18502,
+ 18503,
+ 18504,
+ 18505,
+ 18506,
+ 18507,
+ 18508,
+ 18509,
+ 18510,
+ 18511,
+ 18512,
+ 18513,
+ 18514,
+ 18515,
+ 18516,
+ 18517,
+ 18518,
+ 18519,
+ 18520,
+ 18521,
+ 18522,
+ 18523,
+ 18524,
+ 18525,
+ 18526,
+ 18527,
+ 18528,
+ 18529,
+ 18530,
+ 18531,
+ 18532,
+ 18533,
+ 18534,
+ 18535,
+ 18536,
+ 18537,
+ 18538,
+ 18539,
+ 18540,
+ 18541,
+ 18542,
+ 18543,
+ 18544,
+ 18545,
+ 18546,
+ 18547,
+ 18548,
+ 18549,
+ 18550,
+ 18551,
+ 18552,
+ 18553,
+ 18554,
+ 18555,
+ 18556,
+ 18557,
+ 18558,
+ 18559,
+ 18560,
+ 18561,
+ 18562,
+ 18563,
+ 18564,
+ 18565,
+ 18566,
+ 18567,
+ 18568,
+ 18569,
+ 18570,
+ 18571,
+ 18572,
+ 18573,
+ 18574,
+ 18575,
+ 18576,
+ 18577,
+ 18578,
+ 18579,
+ 18580,
+ 18581,
+ 18582,
+ 18583,
+ 18584,
+ 18585,
+ 18586,
+ 18587,
+ 18588,
+ 18589,
+ 18590,
+ 18591,
+ 18592,
+ 18593,
+ 18594,
+ 18595,
+ 18596,
+ 18597,
+ 18598,
+ 18599,
+ 18600,
+ 18601,
+ 18602,
+ 18603,
+ 18604,
+ 18605,
+ 18606,
+ 18607,
+ 18608,
+ 18609,
+ 18610,
+ 18611,
+ 18612,
+ 18613,
+ 18614,
+ 18615,
+ 18616,
+ 18617,
+ 18618,
+ 18619,
+ 18620,
+ 18621,
+ 18622,
+ 18623,
+ 18624,
+ 18625,
+ 18626,
+ 18627,
+ 18628,
+ 18629,
+ 18630,
+ 18631,
+ 18632,
+ 18633,
+ 18634,
+ 18635,
+ 18636,
+ 18637,
+ 18638,
+ 18639,
+ 18640,
+ 18641,
+ 18642,
+ 18643,
+ 18644,
+ 18645,
+ 18646,
+ 18647,
+ 18648,
+ 18649,
+ 18650,
+ 18651,
+ 18652,
+ 18653,
+ 18654,
+ 18655,
+ 18656,
+ 18657,
+ 18658,
+ 18659,
+ 18660,
+ 18661,
+ 18662,
+ 18663,
+ 18664,
+ 18665,
+ 18666,
+ 18667,
+ 18668,
+ 18669,
+ 18670,
+ 18671,
+ 18672,
+ 18673,
+ 18674,
+ 18675,
+ 18676,
+ 18677,
+ 18678,
+ 18679,
+ 18680,
+ 18681,
+ 18682,
+ 18683,
+ 18684,
+ 18685,
+ 18686,
+ 18687,
+ 18688,
+ 18689,
+ 18690,
+ 18691,
+ 18692,
+ 18693,
+ 18694,
+ 18695,
+ 18696,
+ 18697,
+ 18698,
+ 18699,
+ 18700,
+ 18701,
+ 18702,
+ 18703,
+ 18704,
+ 18705,
+ 18706,
+ 18707,
+ 18708,
+ 18709,
+ 18710,
+ 18711,
+ 18712,
+ 18713,
+ 18714,
+ 18715,
+ 18716,
+ 18717,
+ 18718,
+ 18719,
+ 18720,
+ 18721,
+ 18722,
+ 18723,
+ 18724,
+ 18725,
+ 18726,
+ 18727,
+ 18728,
+ 18729,
+ 18730,
+ 18731,
+ 18732,
+ 18733,
+ 18734,
+ 18735,
+ 18736,
+ 18737,
+ 18738,
+ 18739,
+ 18740,
+ 18741,
+ 18742,
+ 18743,
+ 18744,
+ 18745,
+ 18746,
+ 18747,
+ 18748,
+ 18749,
+ 18750,
+ 18751,
+ 18752,
+ 18753,
+ 18754,
+ 18755,
+ 18756,
+ 18757,
+ 18758,
+ 18759,
+ 18760,
+ 18761,
+ 18762,
+ 18763,
+ 18764,
+ 18765,
+ 18766,
+ 18767,
+ 18768,
+ 18769,
+ 18770,
+ 18771,
+ 18772,
+ 18773,
+ 18774,
+ 18775,
+ 18776,
+ 18777,
+ 18778,
+ 18779,
+ 18780,
+ 18781,
+ 18782,
+ 18783,
+ 18784,
+ 18785,
+ 18786,
+ 18787,
+ 18788,
+ 18789,
+ 18790,
+ 18791,
+ 18792,
+ 18793,
+ 18794,
+ 18795,
+ 18796,
+ 18797,
+ 18798,
+ 18799,
+ 18800,
+ 18801,
+ 18802,
+ 18803,
+ 18804,
+ 18805,
+ 18806,
+ 18807,
+ 18808,
+ 18809,
+ 18810,
+ 18811,
+ 18812,
+ 18813,
+ 18814,
+ 18815,
+ 18816,
+ 18817,
+ 18818,
+ 18819,
+ 18820,
+ 18821,
+ 18822,
+ 18823,
+ 18824,
+ 18825,
+ 18826,
+ 18827,
+ 18828,
+ 18829,
+ 18830,
+ 18831,
+ 18832,
+ 18833,
+ 18834,
+ 18835,
+ 18836,
+ 18837,
+ 18838,
+ 18839,
+ 18840,
+ 18841,
+ 18842,
+ 18843,
+ 18844,
+ 18845,
+ 18846,
+ 18847,
+ 18848,
+ 18849,
+ 18850,
+ 18851,
+ 18852,
+ 18853,
+ 18854,
+ 18855,
+ 18856,
+ 18857,
+ 18858,
+ 18859,
+ 18860,
+ 18861,
+ 18862,
+ 18863,
+ 18864,
+ 18865,
+ 18866,
+ 18867,
+ 18868,
+ 18869,
+ 18870,
+ 18871,
+ 18872,
+ 18873,
+ 18874,
+ 18875,
+ 18876,
+ 18877,
+ 18878,
+ 18879,
+ 18880,
+ 18881,
+ 18882,
+ 18883,
+ 18884,
+ 18885,
+ 18886,
+ 18887,
+ 18888,
+ 18889,
+ 18890,
+ 18891,
+ 18892,
+ 18893,
+ 18894,
+ 18895,
+ 18896,
+ 18897,
+ 18898,
+ 18899,
+ 18900,
+ 18901,
+ 18902,
+ 18903,
+ 18904,
+ 18905,
+ 18906,
+ 18907,
+ 18908,
+ 18909,
+ 18910,
+ 18911,
+ 18912,
+ 18913,
+ 18914,
+ 18915,
+ 18916,
+ 18917,
+ 18918,
+ 18919,
+ 18920,
+ 18921,
+ 18922,
+ 18923,
+ 18924,
+ 18925,
+ 18926,
+ 18927,
+ 18928,
+ 18929,
+ 18930,
+ 18931,
+ 18932,
+ 18933,
+ 18934,
+ 18935,
+ 18936,
+ 18937,
+ 18938,
+ 18939,
+ 18940,
+ 18941,
+ 18942,
+ 18943,
+ 18944,
+ 18945,
+ 18946,
+ 18947,
+ 18948,
+ 18949,
+ 18950,
+ 18951,
+ 18952,
+ 18953,
+ 18954,
+ 18955,
+ 18956,
+ 18957,
+ 18958,
+ 18959,
+ 18960,
+ 18961,
+ 18962,
+ 18963,
+ 18964,
+ 18965,
+ 18966,
+ 18967,
+ 18968,
+ 18969,
+ 18970,
+ 18971,
+ 18972,
+ 18973,
+ 18974,
+ 18975,
+ 18976,
+ 18977,
+ 18978,
+ 18979,
+ 18980,
+ 18981,
+ 18982,
+ 18983,
+ 18984,
+ 18985,
+ 18986,
+ 18987,
+ 18988,
+ 18989,
+ 18990,
+ 18991,
+ 18992,
+ 18993,
+ 18994,
+ 18995,
+ 18996,
+ 18997,
+ 18998,
+ 18999,
+ 19000,
+ 19001,
+ 19002,
+ 19003,
+ 19004,
+ 19005,
+ 19006,
+ 19007,
+ 19008,
+ 19009,
+ 19010,
+ 19011,
+ 19012,
+ 19013,
+ 19014,
+ 19015,
+ 19016,
+ 19017,
+ 19018,
+ 19019,
+ 19020,
+ 19021,
+ 19022,
+ 19023,
+ 19024,
+ 19025,
+ 19026,
+ 19027,
+ 19028,
+ 19029,
+ 19030,
+ 19031,
+ 19032,
+ 19033,
+ 19034,
+ 19035,
+ 19036,
+ 19037,
+ 19038,
+ 19039,
+ 19040,
+ 19041,
+ 19042,
+ 19043,
+ 19044,
+ 19045,
+ 19046,
+ 19047,
+ 19048,
+ 19049,
+ 19050,
+ 19051,
+ 19052,
+ 19053,
+ 19054,
+ 19055,
+ 19056,
+ 19057,
+ 19058,
+ 19059,
+ 19060,
+ 19061,
+ 19062,
+ 19063,
+ 19064,
+ 19065,
+ 19066,
+ 19067,
+ 19068,
+ 19069,
+ 19070,
+ 19071,
+ 19072,
+ 19073,
+ 19074,
+ 19075,
+ 19076,
+ 19077,
+ 19078,
+ 19079,
+ 19080,
+ 19081,
+ 19082,
+ 19083,
+ 19084,
+ 19085,
+ 19086,
+ 19087,
+ 19088,
+ 19089,
+ 19090,
+ 19091,
+ 19092,
+ 19093,
+ 19094,
+ 19095,
+ 19096,
+ 19097,
+ 19098,
+ 19099,
+ 19100,
+ 19101,
+ 19102,
+ 19103,
+ 19104,
+ 19105,
+ 19106,
+ 19107,
+ 19108,
+ 19109,
+ 19110,
+ 19111,
+ 19112,
+ 19113,
+ 19114,
+ 19115,
+ 19116,
+ 19117,
+ 19118,
+ 19119,
+ 19120,
+ 19121,
+ 19122,
+ 19123,
+ 19124,
+ 19125,
+ 19126,
+ 19127,
+ 19128,
+ 19129,
+ 19130,
+ 19131,
+ 19132,
+ 19133,
+ 19134,
+ 19135,
+ 19136,
+ 19137,
+ 19138,
+ 19139,
+ 19140,
+ 19141,
+ 19142,
+ 19143,
+ 19144,
+ 19145,
+ 19146,
+ 19147,
+ 19148,
+ 19149,
+ 19150,
+ 19151,
+ 19152,
+ 19153,
+ 19154,
+ 19155,
+ 19156,
+ 19157,
+ 19158,
+ 19159,
+ 19160,
+ 19161,
+ 19162,
+ 19163,
+ 19164,
+ 19165,
+ 19166,
+ 19167,
+ 19168,
+ 19169,
+ 19170,
+ 19171,
+ 19172,
+ 19173,
+ 19174,
+ 19175,
+ 19176,
+ 19177,
+ 19178,
+ 19179,
+ 19180,
+ 19181,
+ 19182,
+ 19183,
+ 19184,
+ 19185,
+ 19186,
+ 19187,
+ 19188,
+ 19189,
+ 19190,
+ 19191,
+ 19192,
+ 19193,
+ 19194,
+ 19195,
+ 19196,
+ 19197,
+ 19198,
+ 19199,
+ 19200,
+ 19201,
+ 19202,
+ 19203,
+ 19204,
+ 19205,
+ 19206,
+ 19207,
+ 19208,
+ 19209,
+ 19210,
+ 19211,
+ 19212,
+ 19213,
+ 19214,
+ 19215,
+ 19216,
+ 19217,
+ 19218,
+ 19219,
+ 19220,
+ 19221,
+ 19222,
+ 19223,
+ 19224,
+ 19225,
+ 19226,
+ 19227,
+ 19228,
+ 19229,
+ 19230,
+ 19231,
+ 19232,
+ 19233,
+ 19234,
+ 19235,
+ 19236,
+ 19237,
+ 19238,
+ 19239,
+ 19240,
+ 19241,
+ 19242,
+ 19243,
+ 19244,
+ 19245,
+ 19246,
+ 19247,
+ 19248,
+ 19249,
+ 19250,
+ 19251,
+ 19252,
+ 19253,
+ 19254,
+ 19255,
+ 19256,
+ 19257,
+ 19258,
+ 19259,
+ 19260,
+ 19261,
+ 19262,
+ 19263,
+ 19264,
+ 19265,
+ 19266,
+ 19267,
+ 19268,
+ 19269,
+ 19270,
+ 19271,
+ 19272,
+ 19273,
+ 19274,
+ 19275,
+ 19276,
+ 19277,
+ 19278,
+ 19279,
+ 19280,
+ 19281,
+ 19282,
+ 19283,
+ 19284,
+ 19285,
+ 19286,
+ 19287,
+ 19288,
+ 19289,
+ 19290,
+ 19291,
+ 19292,
+ 19293,
+ 19294,
+ 19295,
+ 19296,
+ 19297,
+ 19298,
+ 19299,
+ 19300,
+ 19301,
+ 19302,
+ 19303,
+ 19304,
+ 19305,
+ 19306,
+ 19307,
+ 19308,
+ 19309,
+ 19310,
+ 19311,
+ 19312,
+ 19313,
+ 19314,
+ 19315,
+ 19316,
+ 19317,
+ 19318,
+ 19319,
+ 19320,
+ 19321,
+ 19322,
+ 19323,
+ 19324,
+ 19325,
+ 19326,
+ 19327,
+ 19328,
+ 19329,
+ 19330,
+ 19331,
+ 19332,
+ 19333,
+ 19334,
+ 19335,
+ 19336,
+ 19337,
+ 19338,
+ 19339,
+ 19340,
+ 19341,
+ 19342,
+ 19343,
+ 19344,
+ 19345,
+ 19346,
+ 19347,
+ 19348,
+ 19349,
+ 19350,
+ 19351,
+ 19352,
+ 19353,
+ 19354,
+ 19355,
+ 19356,
+ 19357,
+ 19358,
+ 19359,
+ 19360,
+ 19361,
+ 19362,
+ 19363,
+ 19364,
+ 19365,
+ 19366,
+ 19367,
+ 19368,
+ 19369,
+ 19370,
+ 19371,
+ 19372,
+ 19373,
+ 19374,
+ 19375,
+ 19376,
+ 19377,
+ 19378,
+ 19379,
+ 19380,
+ 19381,
+ 19382,
+ 19383,
+ 19384,
+ 19385,
+ 19386,
+ 19387,
+ 19388,
+ 19389,
+ 19390,
+ 19391,
+ 19392,
+ 19393,
+ 19394,
+ 19395,
+ 19396,
+ 19397,
+ 19398,
+ 19399,
+ 19400,
+ 19401,
+ 19402,
+ 19403,
+ 19404,
+ 19405,
+ 19406,
+ 19407,
+ 19408,
+ 19409,
+ 19410,
+ 19411,
+ 19412,
+ 19413,
+ 19414,
+ 19415,
+ 19416,
+ 19417,
+ 19418,
+ 19419,
+ 19420,
+ 19421,
+ 19422,
+ 19423,
+ 19424,
+ 19425,
+ 19426,
+ 19427,
+ 19428,
+ 19429,
+ 19430,
+ 19431,
+ 19432,
+ 19433,
+ 19434,
+ 19435,
+ 19436,
+ 19437,
+ 19438,
+ 19439,
+ 19440,
+ 19441,
+ 19442,
+ 19443,
+ 19444,
+ 19445,
+ 19446,
+ 19447,
+ 19448,
+ 19449,
+ 19450,
+ 19451,
+ 19452,
+ 19453,
+ 19454,
+ 19455,
+ 19456,
+ 19457,
+ 19458,
+ 19459,
+ 19460,
+ 19461,
+ 19462,
+ 19463,
+ 19464,
+ 19465,
+ 19466,
+ 19467,
+ 19468,
+ 19469,
+ 19470,
+ 19471,
+ 19472,
+ 19473,
+ 19474,
+ 19475,
+ 19476,
+ 19477,
+ 19478,
+ 19479,
+ 19480,
+ 19481,
+ 19482,
+ 19483,
+ 19484,
+ 19485,
+ 19486,
+ 19487,
+ 19488,
+ 19489,
+ 19490,
+ 19491,
+ 19492,
+ 19493,
+ 19494,
+ 19495,
+ 19496,
+ 19497,
+ 19498,
+ 19499,
+ 19500,
+ 19501,
+ 19502,
+ 19503,
+ 19504,
+ 19505,
+ 19506,
+ 19507,
+ 19508,
+ 19509,
+ 19510,
+ 19511,
+ 19512,
+ 19513,
+ 19514,
+ 19515,
+ 19516,
+ 19517,
+ 19518,
+ 19519,
+ 19520,
+ 19521,
+ 19522,
+ 19523,
+ 19524,
+ 19525,
+ 19526,
+ 19527,
+ 19528,
+ 19529,
+ 19530,
+ 19531,
+ 19532,
+ 19533,
+ 19534,
+ 19535,
+ 19536,
+ 19537,
+ 19538,
+ 19539,
+ 19540,
+ 19541,
+ 19542,
+ 19543,
+ 19544,
+ 19545,
+ 19546,
+ 19547,
+ 19548,
+ 19549,
+ 19550,
+ 19551,
+ 19552,
+ 19553,
+ 19554,
+ 19555,
+ 19556,
+ 19557,
+ 19558,
+ 19559,
+ 19560,
+ 19561,
+ 19562,
+ 19563,
+ 19564,
+ 19565,
+ 19566,
+ 19567,
+ 19568,
+ 19569,
+ 19570,
+ 19571,
+ 19572,
+ 19573,
+ 19574,
+ 19575,
+ 19576,
+ 19577,
+ 19578,
+ 19579,
+ 19580,
+ 19581,
+ 19582,
+ 19583,
+ 19584,
+ 19585,
+ 19586,
+ 19587,
+ 19588,
+ 19589,
+ 19590,
+ 19591,
+ 19592,
+ 19593,
+ 19594,
+ 19595,
+ 19596,
+ 19597,
+ 19598,
+ 19599,
+ 19600,
+ 19601,
+ 19602,
+ 19603,
+ 19604,
+ 19605,
+ 19606,
+ 19607,
+ 19608,
+ 19609,
+ 19610,
+ 19611,
+ 19612,
+ 19613,
+ 19614,
+ 19615,
+ 19616,
+ 19617,
+ 19618,
+ 19619,
+ 19620,
+ 19621,
+ 19622,
+ 19623,
+ 19624,
+ 19625,
+ 19626,
+ 19627,
+ 19628,
+ 19629,
+ 19630,
+ 19631,
+ 19632,
+ 19633,
+ 19634,
+ 19635,
+ 19636,
+ 19637,
+ 19638,
+ 19639,
+ 19640,
+ 19641,
+ 19642,
+ 19643,
+ 19644,
+ 19645,
+ 19646,
+ 19647,
+ 19648,
+ 19649,
+ 19650,
+ 19651,
+ 19652,
+ 19653,
+ 19654,
+ 19655,
+ 19656,
+ 19657,
+ 19658,
+ 19659,
+ 19660,
+ 19661,
+ 19662,
+ 19663,
+ 19664,
+ 19665,
+ 19666,
+ 19667,
+ 19668,
+ 19669,
+ 19670,
+ 19671,
+ 19672,
+ 19673,
+ 19674,
+ 19675,
+ 19676,
+ 19677,
+ 19678,
+ 19679,
+ 19680,
+ 19681,
+ 19682,
+ 19683,
+ 19684,
+ 19685,
+ 19686,
+ 19687,
+ 19688,
+ 19689,
+ 19690,
+ 19691,
+ 19692,
+ 19693,
+ 19694,
+ 19695,
+ 19696,
+ 19697,
+ 19698,
+ 19699,
+ 19700,
+ 19701,
+ 19702,
+ 19703,
+ 19704,
+ 19705,
+ 19706,
+ 19707,
+ 19708,
+ 19709,
+ 19710,
+ 19711,
+ 19712,
+ 19713,
+ 19714,
+ 19715,
+ 19716,
+ 19717,
+ 19718,
+ 19719,
+ 19720,
+ 19721,
+ 19722,
+ 19723,
+ 19724,
+ 19725,
+ 19726,
+ 19727,
+ 19728,
+ 19729,
+ 19730,
+ 19731,
+ 19732,
+ 19733,
+ 19734,
+ 19735,
+ 19736,
+ 19737,
+ 19738,
+ 19739,
+ 19740,
+ 19741,
+ 19742,
+ 19743,
+ 19744,
+ 19745,
+ 19746,
+ 19747,
+ 19748,
+ 19749,
+ 19750,
+ 19751,
+ 19752,
+ 19753,
+ 19754,
+ 19755,
+ 19756,
+ 19757,
+ 19758,
+ 19759,
+ 19760,
+ 19761,
+ 19762,
+ 19763,
+ 19764,
+ 19765,
+ 19766,
+ 19767,
+ 19768,
+ 19769,
+ 19770,
+ 19771,
+ 19772,
+ 19773,
+ 19774,
+ 19775,
+ 19776,
+ 19777,
+ 19778,
+ 19779,
+ 19780,
+ 19781,
+ 19782,
+ 19783,
+ 19784,
+ 19785,
+ 19786,
+ 19787,
+ 19788,
+ 19789,
+ 19790,
+ 19791,
+ 19792,
+ 19793,
+ 19794,
+ 19795,
+ 19796,
+ 19797,
+ 19798,
+ 19799,
+ 19800,
+ 19801,
+ 19802,
+ 19803,
+ 19804,
+ 19805,
+ 19806,
+ 19807,
+ 19808,
+ 19809,
+ 19810,
+ 19811,
+ 19812,
+ 19813,
+ 19814,
+ 19815,
+ 19816,
+ 19817,
+ 19818,
+ 19819,
+ 19820,
+ 19821,
+ 19822,
+ 19823,
+ 19824,
+ 19825,
+ 19826,
+ 19827,
+ 19828,
+ 19829,
+ 19830,
+ 19831,
+ 19832,
+ 19833,
+ 19834,
+ 19835,
+ 19836,
+ 19837,
+ 19838,
+ 19839,
+ 19840,
+ 19841,
+ 19842,
+ 19843,
+ 19844,
+ 19845,
+ 19846,
+ 19847,
+ 19848,
+ 19849,
+ 19850,
+ 19851,
+ 19852,
+ 19853,
+ 19854,
+ 19855,
+ 19856,
+ 19857,
+ 19858,
+ 19859,
+ 19860,
+ 19861,
+ 19862,
+ 19863,
+ 19864,
+ 19865,
+ 19866,
+ 19867,
+ 19868,
+ 19869,
+ 19870,
+ 19871,
+ 19872,
+ 19873,
+ 19874,
+ 19875,
+ 19876,
+ 19877,
+ 19878,
+ 19879,
+ 19880,
+ 19881,
+ 19882,
+ 19883,
+ 19884,
+ 19885,
+ 19886,
+ 19887,
+ 19888,
+ 19889,
+ 19890,
+ 19891,
+ 19892,
+ 19893,
+ 19968,
+ 19969,
+ 19970,
+ 19971,
+ 19972,
+ 19973,
+ 19974,
+ 19975,
+ 19976,
+ 19977,
+ 19978,
+ 19979,
+ 19980,
+ 19981,
+ 19982,
+ 19983,
+ 19984,
+ 19985,
+ 19986,
+ 19987,
+ 19988,
+ 19989,
+ 19990,
+ 19991,
+ 19992,
+ 19993,
+ 19994,
+ 19995,
+ 19996,
+ 19997,
+ 19998,
+ 19999,
+ 20000,
+ 20001,
+ 20002,
+ 20003,
+ 20004,
+ 20005,
+ 20006,
+ 20007,
+ 20008,
+ 20009,
+ 20010,
+ 20011,
+ 20012,
+ 20013,
+ 20014,
+ 20015,
+ 20016,
+ 20017,
+ 20018,
+ 20019,
+ 20020,
+ 20021,
+ 20022,
+ 20023,
+ 20024,
+ 20025,
+ 20026,
+ 20027,
+ 20028,
+ 20029,
+ 20030,
+ 20031,
+ 20032,
+ 20033,
+ 20034,
+ 20035,
+ 20036,
+ 20037,
+ 20038,
+ 20039,
+ 20040,
+ 20041,
+ 20042,
+ 20043,
+ 20044,
+ 20045,
+ 20046,
+ 20047,
+ 20048,
+ 20049,
+ 20050,
+ 20051,
+ 20052,
+ 20053,
+ 20054,
+ 20055,
+ 20056,
+ 20057,
+ 20058,
+ 20059,
+ 20060,
+ 20061,
+ 20062,
+ 20063,
+ 20064,
+ 20065,
+ 20066,
+ 20067,
+ 20068,
+ 20069,
+ 20070,
+ 20071,
+ 20072,
+ 20073,
+ 20074,
+ 20075,
+ 20076,
+ 20077,
+ 20078,
+ 20079,
+ 20080,
+ 20081,
+ 20082,
+ 20083,
+ 20084,
+ 20085,
+ 20086,
+ 20087,
+ 20088,
+ 20089,
+ 20090,
+ 20091,
+ 20092,
+ 20093,
+ 20094,
+ 20095,
+ 20096,
+ 20097,
+ 20098,
+ 20099,
+ 20100,
+ 20101,
+ 20102,
+ 20103,
+ 20104,
+ 20105,
+ 20106,
+ 20107,
+ 20108,
+ 20109,
+ 20110,
+ 20111,
+ 20112,
+ 20113,
+ 20114,
+ 20115,
+ 20116,
+ 20117,
+ 20118,
+ 20119,
+ 20120,
+ 20121,
+ 20122,
+ 20123,
+ 20124,
+ 20125,
+ 20126,
+ 20127,
+ 20128,
+ 20129,
+ 20130,
+ 20131,
+ 20132,
+ 20133,
+ 20134,
+ 20135,
+ 20136,
+ 20137,
+ 20138,
+ 20139,
+ 20140,
+ 20141,
+ 20142,
+ 20143,
+ 20144,
+ 20145,
+ 20146,
+ 20147,
+ 20148,
+ 20149,
+ 20150,
+ 20151,
+ 20152,
+ 20153,
+ 20154,
+ 20155,
+ 20156,
+ 20157,
+ 20158,
+ 20159,
+ 20160,
+ 20161,
+ 20162,
+ 20163,
+ 20164,
+ 20165,
+ 20166,
+ 20167,
+ 20168,
+ 20169,
+ 20170,
+ 20171,
+ 20172,
+ 20173,
+ 20174,
+ 20175,
+ 20176,
+ 20177,
+ 20178,
+ 20179,
+ 20180,
+ 20181,
+ 20182,
+ 20183,
+ 20184,
+ 20185,
+ 20186,
+ 20187,
+ 20188,
+ 20189,
+ 20190,
+ 20191,
+ 20192,
+ 20193,
+ 20194,
+ 20195,
+ 20196,
+ 20197,
+ 20198,
+ 20199,
+ 20200,
+ 20201,
+ 20202,
+ 20203,
+ 20204,
+ 20205,
+ 20206,
+ 20207,
+ 20208,
+ 20209,
+ 20210,
+ 20211,
+ 20212,
+ 20213,
+ 20214,
+ 20215,
+ 20216,
+ 20217,
+ 20218,
+ 20219,
+ 20220,
+ 20221,
+ 20222,
+ 20223,
+ 20224,
+ 20225,
+ 20226,
+ 20227,
+ 20228,
+ 20229,
+ 20230,
+ 20231,
+ 20232,
+ 20233,
+ 20234,
+ 20235,
+ 20236,
+ 20237,
+ 20238,
+ 20239,
+ 20240,
+ 20241,
+ 20242,
+ 20243,
+ 20244,
+ 20245,
+ 20246,
+ 20247,
+ 20248,
+ 20249,
+ 20250,
+ 20251,
+ 20252,
+ 20253,
+ 20254,
+ 20255,
+ 20256,
+ 20257,
+ 20258,
+ 20259,
+ 20260,
+ 20261,
+ 20262,
+ 20263,
+ 20264,
+ 20265,
+ 20266,
+ 20267,
+ 20268,
+ 20269,
+ 20270,
+ 20271,
+ 20272,
+ 20273,
+ 20274,
+ 20275,
+ 20276,
+ 20277,
+ 20278,
+ 20279,
+ 20280,
+ 20281,
+ 20282,
+ 20283,
+ 20284,
+ 20285,
+ 20286,
+ 20287,
+ 20288,
+ 20289,
+ 20290,
+ 20291,
+ 20292,
+ 20293,
+ 20294,
+ 20295,
+ 20296,
+ 20297,
+ 20298,
+ 20299,
+ 20300,
+ 20301,
+ 20302,
+ 20303,
+ 20304,
+ 20305,
+ 20306,
+ 20307,
+ 20308,
+ 20309,
+ 20310,
+ 20311,
+ 20312,
+ 20313,
+ 20314,
+ 20315,
+ 20316,
+ 20317,
+ 20318,
+ 20319,
+ 20320,
+ 20321,
+ 20322,
+ 20323,
+ 20324,
+ 20325,
+ 20326,
+ 20327,
+ 20328,
+ 20329,
+ 20330,
+ 20331,
+ 20332,
+ 20333,
+ 20334,
+ 20335,
+ 20336,
+ 20337,
+ 20338,
+ 20339,
+ 20340,
+ 20341,
+ 20342,
+ 20343,
+ 20344,
+ 20345,
+ 20346,
+ 20347,
+ 20348,
+ 20349,
+ 20350,
+ 20351,
+ 20352,
+ 20353,
+ 20354,
+ 20355,
+ 20356,
+ 20357,
+ 20358,
+ 20359,
+ 20360,
+ 20361,
+ 20362,
+ 20363,
+ 20364,
+ 20365,
+ 20366,
+ 20367,
+ 20368,
+ 20369,
+ 20370,
+ 20371,
+ 20372,
+ 20373,
+ 20374,
+ 20375,
+ 20376,
+ 20377,
+ 20378,
+ 20379,
+ 20380,
+ 20381,
+ 20382,
+ 20383,
+ 20384,
+ 20385,
+ 20386,
+ 20387,
+ 20388,
+ 20389,
+ 20390,
+ 20391,
+ 20392,
+ 20393,
+ 20394,
+ 20395,
+ 20396,
+ 20397,
+ 20398,
+ 20399,
+ 20400,
+ 20401,
+ 20402,
+ 20403,
+ 20404,
+ 20405,
+ 20406,
+ 20407,
+ 20408,
+ 20409,
+ 20410,
+ 20411,
+ 20412,
+ 20413,
+ 20414,
+ 20415,
+ 20416,
+ 20417,
+ 20418,
+ 20419,
+ 20420,
+ 20421,
+ 20422,
+ 20423,
+ 20424,
+ 20425,
+ 20426,
+ 20427,
+ 20428,
+ 20429,
+ 20430,
+ 20431,
+ 20432,
+ 20433,
+ 20434,
+ 20435,
+ 20436,
+ 20437,
+ 20438,
+ 20439,
+ 20440,
+ 20441,
+ 20442,
+ 20443,
+ 20444,
+ 20445,
+ 20446,
+ 20447,
+ 20448,
+ 20449,
+ 20450,
+ 20451,
+ 20452,
+ 20453,
+ 20454,
+ 20455,
+ 20456,
+ 20457,
+ 20458,
+ 20459,
+ 20460,
+ 20461,
+ 20462,
+ 20463,
+ 20464,
+ 20465,
+ 20466,
+ 20467,
+ 20468,
+ 20469,
+ 20470,
+ 20471,
+ 20472,
+ 20473,
+ 20474,
+ 20475,
+ 20476,
+ 20477,
+ 20478,
+ 20479,
+ 20480,
+ 20481,
+ 20482,
+ 20483,
+ 20484,
+ 20485,
+ 20486,
+ 20487,
+ 20488,
+ 20489,
+ 20490,
+ 20491,
+ 20492,
+ 20493,
+ 20494,
+ 20495,
+ 20496,
+ 20497,
+ 20498,
+ 20499,
+ 20500,
+ 20501,
+ 20502,
+ 20503,
+ 20504,
+ 20505,
+ 20506,
+ 20507,
+ 20508,
+ 20509,
+ 20510,
+ 20511,
+ 20512,
+ 20513,
+ 20514,
+ 20515,
+ 20516,
+ 20517,
+ 20518,
+ 20519,
+ 20520,
+ 20521,
+ 20522,
+ 20523,
+ 20524,
+ 20525,
+ 20526,
+ 20527,
+ 20528,
+ 20529,
+ 20530,
+ 20531,
+ 20532,
+ 20533,
+ 20534,
+ 20535,
+ 20536,
+ 20537,
+ 20538,
+ 20539,
+ 20540,
+ 20541,
+ 20542,
+ 20543,
+ 20544,
+ 20545,
+ 20546,
+ 20547,
+ 20548,
+ 20549,
+ 20550,
+ 20551,
+ 20552,
+ 20553,
+ 20554,
+ 20555,
+ 20556,
+ 20557,
+ 20558,
+ 20559,
+ 20560,
+ 20561,
+ 20562,
+ 20563,
+ 20564,
+ 20565,
+ 20566,
+ 20567,
+ 20568,
+ 20569,
+ 20570,
+ 20571,
+ 20572,
+ 20573,
+ 20574,
+ 20575,
+ 20576,
+ 20577,
+ 20578,
+ 20579,
+ 20580,
+ 20581,
+ 20582,
+ 20583,
+ 20584,
+ 20585,
+ 20586,
+ 20587,
+ 20588,
+ 20589,
+ 20590,
+ 20591,
+ 20592,
+ 20593,
+ 20594,
+ 20595,
+ 20596,
+ 20597,
+ 20598,
+ 20599,
+ 20600,
+ 20601,
+ 20602,
+ 20603,
+ 20604,
+ 20605,
+ 20606,
+ 20607,
+ 20608,
+ 20609,
+ 20610,
+ 20611,
+ 20612,
+ 20613,
+ 20614,
+ 20615,
+ 20616,
+ 20617,
+ 20618,
+ 20619,
+ 20620,
+ 20621,
+ 20622,
+ 20623,
+ 20624,
+ 20625,
+ 20626,
+ 20627,
+ 20628,
+ 20629,
+ 20630,
+ 20631,
+ 20632,
+ 20633,
+ 20634,
+ 20635,
+ 20636,
+ 20637,
+ 20638,
+ 20639,
+ 20640,
+ 20641,
+ 20642,
+ 20643,
+ 20644,
+ 20645,
+ 20646,
+ 20647,
+ 20648,
+ 20649,
+ 20650,
+ 20651,
+ 20652,
+ 20653,
+ 20654,
+ 20655,
+ 20656,
+ 20657,
+ 20658,
+ 20659,
+ 20660,
+ 20661,
+ 20662,
+ 20663,
+ 20664,
+ 20665,
+ 20666,
+ 20667,
+ 20668,
+ 20669,
+ 20670,
+ 20671,
+ 20672,
+ 20673,
+ 20674,
+ 20675,
+ 20676,
+ 20677,
+ 20678,
+ 20679,
+ 20680,
+ 20681,
+ 20682,
+ 20683,
+ 20684,
+ 20685,
+ 20686,
+ 20687,
+ 20688,
+ 20689,
+ 20690,
+ 20691,
+ 20692,
+ 20693,
+ 20694,
+ 20695,
+ 20696,
+ 20697,
+ 20698,
+ 20699,
+ 20700,
+ 20701,
+ 20702,
+ 20703,
+ 20704,
+ 20705,
+ 20706,
+ 20707,
+ 20708,
+ 20709,
+ 20710,
+ 20711,
+ 20712,
+ 20713,
+ 20714,
+ 20715,
+ 20716,
+ 20717,
+ 20718,
+ 20719,
+ 20720,
+ 20721,
+ 20722,
+ 20723,
+ 20724,
+ 20725,
+ 20726,
+ 20727,
+ 20728,
+ 20729,
+ 20730,
+ 20731,
+ 20732,
+ 20733,
+ 20734,
+ 20735,
+ 20736,
+ 20737,
+ 20738,
+ 20739,
+ 20740,
+ 20741,
+ 20742,
+ 20743,
+ 20744,
+ 20745,
+ 20746,
+ 20747,
+ 20748,
+ 20749,
+ 20750,
+ 20751,
+ 20752,
+ 20753,
+ 20754,
+ 20755,
+ 20756,
+ 20757,
+ 20758,
+ 20759,
+ 20760,
+ 20761,
+ 20762,
+ 20763,
+ 20764,
+ 20765,
+ 20766,
+ 20767,
+ 20768,
+ 20769,
+ 20770,
+ 20771,
+ 20772,
+ 20773,
+ 20774,
+ 20775,
+ 20776,
+ 20777,
+ 20778,
+ 20779,
+ 20780,
+ 20781,
+ 20782,
+ 20783,
+ 20784,
+ 20785,
+ 20786,
+ 20787,
+ 20788,
+ 20789,
+ 20790,
+ 20791,
+ 20792,
+ 20793,
+ 20794,
+ 20795,
+ 20796,
+ 20797,
+ 20798,
+ 20799,
+ 20800,
+ 20801,
+ 20802,
+ 20803,
+ 20804,
+ 20805,
+ 20806,
+ 20807,
+ 20808,
+ 20809,
+ 20810,
+ 20811,
+ 20812,
+ 20813,
+ 20814,
+ 20815,
+ 20816,
+ 20817,
+ 20818,
+ 20819,
+ 20820,
+ 20821,
+ 20822,
+ 20823,
+ 20824,
+ 20825,
+ 20826,
+ 20827,
+ 20828,
+ 20829,
+ 20830,
+ 20831,
+ 20832,
+ 20833,
+ 20834,
+ 20835,
+ 20836,
+ 20837,
+ 20838,
+ 20839,
+ 20840,
+ 20841,
+ 20842,
+ 20843,
+ 20844,
+ 20845,
+ 20846,
+ 20847,
+ 20848,
+ 20849,
+ 20850,
+ 20851,
+ 20852,
+ 20853,
+ 20854,
+ 20855,
+ 20856,
+ 20857,
+ 20858,
+ 20859,
+ 20860,
+ 20861,
+ 20862,
+ 20863,
+ 20864,
+ 20865,
+ 20866,
+ 20867,
+ 20868,
+ 20869,
+ 20870,
+ 20871,
+ 20872,
+ 20873,
+ 20874,
+ 20875,
+ 20876,
+ 20877,
+ 20878,
+ 20879,
+ 20880,
+ 20881,
+ 20882,
+ 20883,
+ 20884,
+ 20885,
+ 20886,
+ 20887,
+ 20888,
+ 20889,
+ 20890,
+ 20891,
+ 20892,
+ 20893,
+ 20894,
+ 20895,
+ 20896,
+ 20897,
+ 20898,
+ 20899,
+ 20900,
+ 20901,
+ 20902,
+ 20903,
+ 20904,
+ 20905,
+ 20906,
+ 20907,
+ 20908,
+ 20909,
+ 20910,
+ 20911,
+ 20912,
+ 20913,
+ 20914,
+ 20915,
+ 20916,
+ 20917,
+ 20918,
+ 20919,
+ 20920,
+ 20921,
+ 20922,
+ 20923,
+ 20924,
+ 20925,
+ 20926,
+ 20927,
+ 20928,
+ 20929,
+ 20930,
+ 20931,
+ 20932,
+ 20933,
+ 20934,
+ 20935,
+ 20936,
+ 20937,
+ 20938,
+ 20939,
+ 20940,
+ 20941,
+ 20942,
+ 20943,
+ 20944,
+ 20945,
+ 20946,
+ 20947,
+ 20948,
+ 20949,
+ 20950,
+ 20951,
+ 20952,
+ 20953,
+ 20954,
+ 20955,
+ 20956,
+ 20957,
+ 20958,
+ 20959,
+ 20960,
+ 20961,
+ 20962,
+ 20963,
+ 20964,
+ 20965,
+ 20966,
+ 20967,
+ 20968,
+ 20969,
+ 20970,
+ 20971,
+ 20972,
+ 20973,
+ 20974,
+ 20975,
+ 20976,
+ 20977,
+ 20978,
+ 20979,
+ 20980,
+ 20981,
+ 20982,
+ 20983,
+ 20984,
+ 20985,
+ 20986,
+ 20987,
+ 20988,
+ 20989,
+ 20990,
+ 20991,
+ 20992,
+ 20993,
+ 20994,
+ 20995,
+ 20996,
+ 20997,
+ 20998,
+ 20999,
+ 21000,
+ 21001,
+ 21002,
+ 21003,
+ 21004,
+ 21005,
+ 21006,
+ 21007,
+ 21008,
+ 21009,
+ 21010,
+ 21011,
+ 21012,
+ 21013,
+ 21014,
+ 21015,
+ 21016,
+ 21017,
+ 21018,
+ 21019,
+ 21020,
+ 21021,
+ 21022,
+ 21023,
+ 21024,
+ 21025,
+ 21026,
+ 21027,
+ 21028,
+ 21029,
+ 21030,
+ 21031,
+ 21032,
+ 21033,
+ 21034,
+ 21035,
+ 21036,
+ 21037,
+ 21038,
+ 21039,
+ 21040,
+ 21041,
+ 21042,
+ 21043,
+ 21044,
+ 21045,
+ 21046,
+ 21047,
+ 21048,
+ 21049,
+ 21050,
+ 21051,
+ 21052,
+ 21053,
+ 21054,
+ 21055,
+ 21056,
+ 21057,
+ 21058,
+ 21059,
+ 21060,
+ 21061,
+ 21062,
+ 21063,
+ 21064,
+ 21065,
+ 21066,
+ 21067,
+ 21068,
+ 21069,
+ 21070,
+ 21071,
+ 21072,
+ 21073,
+ 21074,
+ 21075,
+ 21076,
+ 21077,
+ 21078,
+ 21079,
+ 21080,
+ 21081,
+ 21082,
+ 21083,
+ 21084,
+ 21085,
+ 21086,
+ 21087,
+ 21088,
+ 21089,
+ 21090,
+ 21091,
+ 21092,
+ 21093,
+ 21094,
+ 21095,
+ 21096,
+ 21097,
+ 21098,
+ 21099,
+ 21100,
+ 21101,
+ 21102,
+ 21103,
+ 21104,
+ 21105,
+ 21106,
+ 21107,
+ 21108,
+ 21109,
+ 21110,
+ 21111,
+ 21112,
+ 21113,
+ 21114,
+ 21115,
+ 21116,
+ 21117,
+ 21118,
+ 21119,
+ 21120,
+ 21121,
+ 21122,
+ 21123,
+ 21124,
+ 21125,
+ 21126,
+ 21127,
+ 21128,
+ 21129,
+ 21130,
+ 21131,
+ 21132,
+ 21133,
+ 21134,
+ 21135,
+ 21136,
+ 21137,
+ 21138,
+ 21139,
+ 21140,
+ 21141,
+ 21142,
+ 21143,
+ 21144,
+ 21145,
+ 21146,
+ 21147,
+ 21148,
+ 21149,
+ 21150,
+ 21151,
+ 21152,
+ 21153,
+ 21154,
+ 21155,
+ 21156,
+ 21157,
+ 21158,
+ 21159,
+ 21160,
+ 21161,
+ 21162,
+ 21163,
+ 21164,
+ 21165,
+ 21166,
+ 21167,
+ 21168,
+ 21169,
+ 21170,
+ 21171,
+ 21172,
+ 21173,
+ 21174,
+ 21175,
+ 21176,
+ 21177,
+ 21178,
+ 21179,
+ 21180,
+ 21181,
+ 21182,
+ 21183,
+ 21184,
+ 21185,
+ 21186,
+ 21187,
+ 21188,
+ 21189,
+ 21190,
+ 21191,
+ 21192,
+ 21193,
+ 21194,
+ 21195,
+ 21196,
+ 21197,
+ 21198,
+ 21199,
+ 21200,
+ 21201,
+ 21202,
+ 21203,
+ 21204,
+ 21205,
+ 21206,
+ 21207,
+ 21208,
+ 21209,
+ 21210,
+ 21211,
+ 21212,
+ 21213,
+ 21214,
+ 21215,
+ 21216,
+ 21217,
+ 21218,
+ 21219,
+ 21220,
+ 21221,
+ 21222,
+ 21223,
+ 21224,
+ 21225,
+ 21226,
+ 21227,
+ 21228,
+ 21229,
+ 21230,
+ 21231,
+ 21232,
+ 21233,
+ 21234,
+ 21235,
+ 21236,
+ 21237,
+ 21238,
+ 21239,
+ 21240,
+ 21241,
+ 21242,
+ 21243,
+ 21244,
+ 21245,
+ 21246,
+ 21247,
+ 21248,
+ 21249,
+ 21250,
+ 21251,
+ 21252,
+ 21253,
+ 21254,
+ 21255,
+ 21256,
+ 21257,
+ 21258,
+ 21259,
+ 21260,
+ 21261,
+ 21262,
+ 21263,
+ 21264,
+ 21265,
+ 21266,
+ 21267,
+ 21268,
+ 21269,
+ 21270,
+ 21271,
+ 21272,
+ 21273,
+ 21274,
+ 21275,
+ 21276,
+ 21277,
+ 21278,
+ 21279,
+ 21280,
+ 21281,
+ 21282,
+ 21283,
+ 21284,
+ 21285,
+ 21286,
+ 21287,
+ 21288,
+ 21289,
+ 21290,
+ 21291,
+ 21292,
+ 21293,
+ 21294,
+ 21295,
+ 21296,
+ 21297,
+ 21298,
+ 21299,
+ 21300,
+ 21301,
+ 21302,
+ 21303,
+ 21304,
+ 21305,
+ 21306,
+ 21307,
+ 21308,
+ 21309,
+ 21310,
+ 21311,
+ 21312,
+ 21313,
+ 21314,
+ 21315,
+ 21316,
+ 21317,
+ 21318,
+ 21319,
+ 21320,
+ 21321,
+ 21322,
+ 21323,
+ 21324,
+ 21325,
+ 21326,
+ 21327,
+ 21328,
+ 21329,
+ 21330,
+ 21331,
+ 21332,
+ 21333,
+ 21334,
+ 21335,
+ 21336,
+ 21337,
+ 21338,
+ 21339,
+ 21340,
+ 21341,
+ 21342,
+ 21343,
+ 21344,
+ 21345,
+ 21346,
+ 21347,
+ 21348,
+ 21349,
+ 21350,
+ 21351,
+ 21352,
+ 21353,
+ 21354,
+ 21355,
+ 21356,
+ 21357,
+ 21358,
+ 21359,
+ 21360,
+ 21361,
+ 21362,
+ 21363,
+ 21364,
+ 21365,
+ 21366,
+ 21367,
+ 21368,
+ 21369,
+ 21370,
+ 21371,
+ 21372,
+ 21373,
+ 21374,
+ 21375,
+ 21376,
+ 21377,
+ 21378,
+ 21379,
+ 21380,
+ 21381,
+ 21382,
+ 21383,
+ 21384,
+ 21385,
+ 21386,
+ 21387,
+ 21388,
+ 21389,
+ 21390,
+ 21391,
+ 21392,
+ 21393,
+ 21394,
+ 21395,
+ 21396,
+ 21397,
+ 21398,
+ 21399,
+ 21400,
+ 21401,
+ 21402,
+ 21403,
+ 21404,
+ 21405,
+ 21406,
+ 21407,
+ 21408,
+ 21409,
+ 21410,
+ 21411,
+ 21412,
+ 21413,
+ 21414,
+ 21415,
+ 21416,
+ 21417,
+ 21418,
+ 21419,
+ 21420,
+ 21421,
+ 21422,
+ 21423,
+ 21424,
+ 21425,
+ 21426,
+ 21427,
+ 21428,
+ 21429,
+ 21430,
+ 21431,
+ 21432,
+ 21433,
+ 21434,
+ 21435,
+ 21436,
+ 21437,
+ 21438,
+ 21439,
+ 21440,
+ 21441,
+ 21442,
+ 21443,
+ 21444,
+ 21445,
+ 21446,
+ 21447,
+ 21448,
+ 21449,
+ 21450,
+ 21451,
+ 21452,
+ 21453,
+ 21454,
+ 21455,
+ 21456,
+ 21457,
+ 21458,
+ 21459,
+ 21460,
+ 21461,
+ 21462,
+ 21463,
+ 21464,
+ 21465,
+ 21466,
+ 21467,
+ 21468,
+ 21469,
+ 21470,
+ 21471,
+ 21472,
+ 21473,
+ 21474,
+ 21475,
+ 21476,
+ 21477,
+ 21478,
+ 21479,
+ 21480,
+ 21481,
+ 21482,
+ 21483,
+ 21484,
+ 21485,
+ 21486,
+ 21487,
+ 21488,
+ 21489,
+ 21490,
+ 21491,
+ 21492,
+ 21493,
+ 21494,
+ 21495,
+ 21496,
+ 21497,
+ 21498,
+ 21499,
+ 21500,
+ 21501,
+ 21502,
+ 21503,
+ 21504,
+ 21505,
+ 21506,
+ 21507,
+ 21508,
+ 21509,
+ 21510,
+ 21511,
+ 21512,
+ 21513,
+ 21514,
+ 21515,
+ 21516,
+ 21517,
+ 21518,
+ 21519,
+ 21520,
+ 21521,
+ 21522,
+ 21523,
+ 21524,
+ 21525,
+ 21526,
+ 21527,
+ 21528,
+ 21529,
+ 21530,
+ 21531,
+ 21532,
+ 21533,
+ 21534,
+ 21535,
+ 21536,
+ 21537,
+ 21538,
+ 21539,
+ 21540,
+ 21541,
+ 21542,
+ 21543,
+ 21544,
+ 21545,
+ 21546,
+ 21547,
+ 21548,
+ 21549,
+ 21550,
+ 21551,
+ 21552,
+ 21553,
+ 21554,
+ 21555,
+ 21556,
+ 21557,
+ 21558,
+ 21559,
+ 21560,
+ 21561,
+ 21562,
+ 21563,
+ 21564,
+ 21565,
+ 21566,
+ 21567,
+ 21568,
+ 21569,
+ 21570,
+ 21571,
+ 21572,
+ 21573,
+ 21574,
+ 21575,
+ 21576,
+ 21577,
+ 21578,
+ 21579,
+ 21580,
+ 21581,
+ 21582,
+ 21583,
+ 21584,
+ 21585,
+ 21586,
+ 21587,
+ 21588,
+ 21589,
+ 21590,
+ 21591,
+ 21592,
+ 21593,
+ 21594,
+ 21595,
+ 21596,
+ 21597,
+ 21598,
+ 21599,
+ 21600,
+ 21601,
+ 21602,
+ 21603,
+ 21604,
+ 21605,
+ 21606,
+ 21607,
+ 21608,
+ 21609,
+ 21610,
+ 21611,
+ 21612,
+ 21613,
+ 21614,
+ 21615,
+ 21616,
+ 21617,
+ 21618,
+ 21619,
+ 21620,
+ 21621,
+ 21622,
+ 21623,
+ 21624,
+ 21625,
+ 21626,
+ 21627,
+ 21628,
+ 21629,
+ 21630,
+ 21631,
+ 21632,
+ 21633,
+ 21634,
+ 21635,
+ 21636,
+ 21637,
+ 21638,
+ 21639,
+ 21640,
+ 21641,
+ 21642,
+ 21643,
+ 21644,
+ 21645,
+ 21646,
+ 21647,
+ 21648,
+ 21649,
+ 21650,
+ 21651,
+ 21652,
+ 21653,
+ 21654,
+ 21655,
+ 21656,
+ 21657,
+ 21658,
+ 21659,
+ 21660,
+ 21661,
+ 21662,
+ 21663,
+ 21664,
+ 21665,
+ 21666,
+ 21667,
+ 21668,
+ 21669,
+ 21670,
+ 21671,
+ 21672,
+ 21673,
+ 21674,
+ 21675,
+ 21676,
+ 21677,
+ 21678,
+ 21679,
+ 21680,
+ 21681,
+ 21682,
+ 21683,
+ 21684,
+ 21685,
+ 21686,
+ 21687,
+ 21688,
+ 21689,
+ 21690,
+ 21691,
+ 21692,
+ 21693,
+ 21694,
+ 21695,
+ 21696,
+ 21697,
+ 21698,
+ 21699,
+ 21700,
+ 21701,
+ 21702,
+ 21703,
+ 21704,
+ 21705,
+ 21706,
+ 21707,
+ 21708,
+ 21709,
+ 21710,
+ 21711,
+ 21712,
+ 21713,
+ 21714,
+ 21715,
+ 21716,
+ 21717,
+ 21718,
+ 21719,
+ 21720,
+ 21721,
+ 21722,
+ 21723,
+ 21724,
+ 21725,
+ 21726,
+ 21727,
+ 21728,
+ 21729,
+ 21730,
+ 21731,
+ 21732,
+ 21733,
+ 21734,
+ 21735,
+ 21736,
+ 21737,
+ 21738,
+ 21739,
+ 21740,
+ 21741,
+ 21742,
+ 21743,
+ 21744,
+ 21745,
+ 21746,
+ 21747,
+ 21748,
+ 21749,
+ 21750,
+ 21751,
+ 21752,
+ 21753,
+ 21754,
+ 21755,
+ 21756,
+ 21757,
+ 21758,
+ 21759,
+ 21760,
+ 21761,
+ 21762,
+ 21763,
+ 21764,
+ 21765,
+ 21766,
+ 21767,
+ 21768,
+ 21769,
+ 21770,
+ 21771,
+ 21772,
+ 21773,
+ 21774,
+ 21775,
+ 21776,
+ 21777,
+ 21778,
+ 21779,
+ 21780,
+ 21781,
+ 21782,
+ 21783,
+ 21784,
+ 21785,
+ 21786,
+ 21787,
+ 21788,
+ 21789,
+ 21790,
+ 21791,
+ 21792,
+ 21793,
+ 21794,
+ 21795,
+ 21796,
+ 21797,
+ 21798,
+ 21799,
+ 21800,
+ 21801,
+ 21802,
+ 21803,
+ 21804,
+ 21805,
+ 21806,
+ 21807,
+ 21808,
+ 21809,
+ 21810,
+ 21811,
+ 21812,
+ 21813,
+ 21814,
+ 21815,
+ 21816,
+ 21817,
+ 21818,
+ 21819,
+ 21820,
+ 21821,
+ 21822,
+ 21823,
+ 21824,
+ 21825,
+ 21826,
+ 21827,
+ 21828,
+ 21829,
+ 21830,
+ 21831,
+ 21832,
+ 21833,
+ 21834,
+ 21835,
+ 21836,
+ 21837,
+ 21838,
+ 21839,
+ 21840,
+ 21841,
+ 21842,
+ 21843,
+ 21844,
+ 21845,
+ 21846,
+ 21847,
+ 21848,
+ 21849,
+ 21850,
+ 21851,
+ 21852,
+ 21853,
+ 21854,
+ 21855,
+ 21856,
+ 21857,
+ 21858,
+ 21859,
+ 21860,
+ 21861,
+ 21862,
+ 21863,
+ 21864,
+ 21865,
+ 21866,
+ 21867,
+ 21868,
+ 21869,
+ 21870,
+ 21871,
+ 21872,
+ 21873,
+ 21874,
+ 21875,
+ 21876,
+ 21877,
+ 21878,
+ 21879,
+ 21880,
+ 21881,
+ 21882,
+ 21883,
+ 21884,
+ 21885,
+ 21886,
+ 21887,
+ 21888,
+ 21889,
+ 21890,
+ 21891,
+ 21892,
+ 21893,
+ 21894,
+ 21895,
+ 21896,
+ 21897,
+ 21898,
+ 21899,
+ 21900,
+ 21901,
+ 21902,
+ 21903,
+ 21904,
+ 21905,
+ 21906,
+ 21907,
+ 21908,
+ 21909,
+ 21910,
+ 21911,
+ 21912,
+ 21913,
+ 21914,
+ 21915,
+ 21916,
+ 21917,
+ 21918,
+ 21919,
+ 21920,
+ 21921,
+ 21922,
+ 21923,
+ 21924,
+ 21925,
+ 21926,
+ 21927,
+ 21928,
+ 21929,
+ 21930,
+ 21931,
+ 21932,
+ 21933,
+ 21934,
+ 21935,
+ 21936,
+ 21937,
+ 21938,
+ 21939,
+ 21940,
+ 21941,
+ 21942,
+ 21943,
+ 21944,
+ 21945,
+ 21946,
+ 21947,
+ 21948,
+ 21949,
+ 21950,
+ 21951,
+ 21952,
+ 21953,
+ 21954,
+ 21955,
+ 21956,
+ 21957,
+ 21958,
+ 21959,
+ 21960,
+ 21961,
+ 21962,
+ 21963,
+ 21964,
+ 21965,
+ 21966,
+ 21967,
+ 21968,
+ 21969,
+ 21970,
+ 21971,
+ 21972,
+ 21973,
+ 21974,
+ 21975,
+ 21976,
+ 21977,
+ 21978,
+ 21979,
+ 21980,
+ 21981,
+ 21982,
+ 21983,
+ 21984,
+ 21985,
+ 21986,
+ 21987,
+ 21988,
+ 21989,
+ 21990,
+ 21991,
+ 21992,
+ 21993,
+ 21994,
+ 21995,
+ 21996,
+ 21997,
+ 21998,
+ 21999,
+ 22000,
+ 22001,
+ 22002,
+ 22003,
+ 22004,
+ 22005,
+ 22006,
+ 22007,
+ 22008,
+ 22009,
+ 22010,
+ 22011,
+ 22012,
+ 22013,
+ 22014,
+ 22015,
+ 22016,
+ 22017,
+ 22018,
+ 22019,
+ 22020,
+ 22021,
+ 22022,
+ 22023,
+ 22024,
+ 22025,
+ 22026,
+ 22027,
+ 22028,
+ 22029,
+ 22030,
+ 22031,
+ 22032,
+ 22033,
+ 22034,
+ 22035,
+ 22036,
+ 22037,
+ 22038,
+ 22039,
+ 22040,
+ 22041,
+ 22042,
+ 22043,
+ 22044,
+ 22045,
+ 22046,
+ 22047,
+ 22048,
+ 22049,
+ 22050,
+ 22051,
+ 22052,
+ 22053,
+ 22054,
+ 22055,
+ 22056,
+ 22057,
+ 22058,
+ 22059,
+ 22060,
+ 22061,
+ 22062,
+ 22063,
+ 22064,
+ 22065,
+ 22066,
+ 22067,
+ 22068,
+ 22069,
+ 22070,
+ 22071,
+ 22072,
+ 22073,
+ 22074,
+ 22075,
+ 22076,
+ 22077,
+ 22078,
+ 22079,
+ 22080,
+ 22081,
+ 22082,
+ 22083,
+ 22084,
+ 22085,
+ 22086,
+ 22087,
+ 22088,
+ 22089,
+ 22090,
+ 22091,
+ 22092,
+ 22093,
+ 22094,
+ 22095,
+ 22096,
+ 22097,
+ 22098,
+ 22099,
+ 22100,
+ 22101,
+ 22102,
+ 22103,
+ 22104,
+ 22105,
+ 22106,
+ 22107,
+ 22108,
+ 22109,
+ 22110,
+ 22111,
+ 22112,
+ 22113,
+ 22114,
+ 22115,
+ 22116,
+ 22117,
+ 22118,
+ 22119,
+ 22120,
+ 22121,
+ 22122,
+ 22123,
+ 22124,
+ 22125,
+ 22126,
+ 22127,
+ 22128,
+ 22129,
+ 22130,
+ 22131,
+ 22132,
+ 22133,
+ 22134,
+ 22135,
+ 22136,
+ 22137,
+ 22138,
+ 22139,
+ 22140,
+ 22141,
+ 22142,
+ 22143,
+ 22144,
+ 22145,
+ 22146,
+ 22147,
+ 22148,
+ 22149,
+ 22150,
+ 22151,
+ 22152,
+ 22153,
+ 22154,
+ 22155,
+ 22156,
+ 22157,
+ 22158,
+ 22159,
+ 22160,
+ 22161,
+ 22162,
+ 22163,
+ 22164,
+ 22165,
+ 22166,
+ 22167,
+ 22168,
+ 22169,
+ 22170,
+ 22171,
+ 22172,
+ 22173,
+ 22174,
+ 22175,
+ 22176,
+ 22177,
+ 22178,
+ 22179,
+ 22180,
+ 22181,
+ 22182,
+ 22183,
+ 22184,
+ 22185,
+ 22186,
+ 22187,
+ 22188,
+ 22189,
+ 22190,
+ 22191,
+ 22192,
+ 22193,
+ 22194,
+ 22195,
+ 22196,
+ 22197,
+ 22198,
+ 22199,
+ 22200,
+ 22201,
+ 22202,
+ 22203,
+ 22204,
+ 22205,
+ 22206,
+ 22207,
+ 22208,
+ 22209,
+ 22210,
+ 22211,
+ 22212,
+ 22213,
+ 22214,
+ 22215,
+ 22216,
+ 22217,
+ 22218,
+ 22219,
+ 22220,
+ 22221,
+ 22222,
+ 22223,
+ 22224,
+ 22225,
+ 22226,
+ 22227,
+ 22228,
+ 22229,
+ 22230,
+ 22231,
+ 22232,
+ 22233,
+ 22234,
+ 22235,
+ 22236,
+ 22237,
+ 22238,
+ 22239,
+ 22240,
+ 22241,
+ 22242,
+ 22243,
+ 22244,
+ 22245,
+ 22246,
+ 22247,
+ 22248,
+ 22249,
+ 22250,
+ 22251,
+ 22252,
+ 22253,
+ 22254,
+ 22255,
+ 22256,
+ 22257,
+ 22258,
+ 22259,
+ 22260,
+ 22261,
+ 22262,
+ 22263,
+ 22264,
+ 22265,
+ 22266,
+ 22267,
+ 22268,
+ 22269,
+ 22270,
+ 22271,
+ 22272,
+ 22273,
+ 22274,
+ 22275,
+ 22276,
+ 22277,
+ 22278,
+ 22279,
+ 22280,
+ 22281,
+ 22282,
+ 22283,
+ 22284,
+ 22285,
+ 22286,
+ 22287,
+ 22288,
+ 22289,
+ 22290,
+ 22291,
+ 22292,
+ 22293,
+ 22294,
+ 22295,
+ 22296,
+ 22297,
+ 22298,
+ 22299,
+ 22300,
+ 22301,
+ 22302,
+ 22303,
+ 22304,
+ 22305,
+ 22306,
+ 22307,
+ 22308,
+ 22309,
+ 22310,
+ 22311,
+ 22312,
+ 22313,
+ 22314,
+ 22315,
+ 22316,
+ 22317,
+ 22318,
+ 22319,
+ 22320,
+ 22321,
+ 22322,
+ 22323,
+ 22324,
+ 22325,
+ 22326,
+ 22327,
+ 22328,
+ 22329,
+ 22330,
+ 22331,
+ 22332,
+ 22333,
+ 22334,
+ 22335,
+ 22336,
+ 22337,
+ 22338,
+ 22339,
+ 22340,
+ 22341,
+ 22342,
+ 22343,
+ 22344,
+ 22345,
+ 22346,
+ 22347,
+ 22348,
+ 22349,
+ 22350,
+ 22351,
+ 22352,
+ 22353,
+ 22354,
+ 22355,
+ 22356,
+ 22357,
+ 22358,
+ 22359,
+ 22360,
+ 22361,
+ 22362,
+ 22363,
+ 22364,
+ 22365,
+ 22366,
+ 22367,
+ 22368,
+ 22369,
+ 22370,
+ 22371,
+ 22372,
+ 22373,
+ 22374,
+ 22375,
+ 22376,
+ 22377,
+ 22378,
+ 22379,
+ 22380,
+ 22381,
+ 22382,
+ 22383,
+ 22384,
+ 22385,
+ 22386,
+ 22387,
+ 22388,
+ 22389,
+ 22390,
+ 22391,
+ 22392,
+ 22393,
+ 22394,
+ 22395,
+ 22396,
+ 22397,
+ 22398,
+ 22399,
+ 22400,
+ 22401,
+ 22402,
+ 22403,
+ 22404,
+ 22405,
+ 22406,
+ 22407,
+ 22408,
+ 22409,
+ 22410,
+ 22411,
+ 22412,
+ 22413,
+ 22414,
+ 22415,
+ 22416,
+ 22417,
+ 22418,
+ 22419,
+ 22420,
+ 22421,
+ 22422,
+ 22423,
+ 22424,
+ 22425,
+ 22426,
+ 22427,
+ 22428,
+ 22429,
+ 22430,
+ 22431,
+ 22432,
+ 22433,
+ 22434,
+ 22435,
+ 22436,
+ 22437,
+ 22438,
+ 22439,
+ 22440,
+ 22441,
+ 22442,
+ 22443,
+ 22444,
+ 22445,
+ 22446,
+ 22447,
+ 22448,
+ 22449,
+ 22450,
+ 22451,
+ 22452,
+ 22453,
+ 22454,
+ 22455,
+ 22456,
+ 22457,
+ 22458,
+ 22459,
+ 22460,
+ 22461,
+ 22462,
+ 22463,
+ 22464,
+ 22465,
+ 22466,
+ 22467,
+ 22468,
+ 22469,
+ 22470,
+ 22471,
+ 22472,
+ 22473,
+ 22474,
+ 22475,
+ 22476,
+ 22477,
+ 22478,
+ 22479,
+ 22480,
+ 22481,
+ 22482,
+ 22483,
+ 22484,
+ 22485,
+ 22486,
+ 22487,
+ 22488,
+ 22489,
+ 22490,
+ 22491,
+ 22492,
+ 22493,
+ 22494,
+ 22495,
+ 22496,
+ 22497,
+ 22498,
+ 22499,
+ 22500,
+ 22501,
+ 22502,
+ 22503,
+ 22504,
+ 22505,
+ 22506,
+ 22507,
+ 22508,
+ 22509,
+ 22510,
+ 22511,
+ 22512,
+ 22513,
+ 22514,
+ 22515,
+ 22516,
+ 22517,
+ 22518,
+ 22519,
+ 22520,
+ 22521,
+ 22522,
+ 22523,
+ 22524,
+ 22525,
+ 22526,
+ 22527,
+ 22528,
+ 22529,
+ 22530,
+ 22531,
+ 22532,
+ 22533,
+ 22534,
+ 22535,
+ 22536,
+ 22537,
+ 22538,
+ 22539,
+ 22540,
+ 22541,
+ 22542,
+ 22543,
+ 22544,
+ 22545,
+ 22546,
+ 22547,
+ 22548,
+ 22549,
+ 22550,
+ 22551,
+ 22552,
+ 22553,
+ 22554,
+ 22555,
+ 22556,
+ 22557,
+ 22558,
+ 22559,
+ 22560,
+ 22561,
+ 22562,
+ 22563,
+ 22564,
+ 22565,
+ 22566,
+ 22567,
+ 22568,
+ 22569,
+ 22570,
+ 22571,
+ 22572,
+ 22573,
+ 22574,
+ 22575,
+ 22576,
+ 22577,
+ 22578,
+ 22579,
+ 22580,
+ 22581,
+ 22582,
+ 22583,
+ 22584,
+ 22585,
+ 22586,
+ 22587,
+ 22588,
+ 22589,
+ 22590,
+ 22591,
+ 22592,
+ 22593,
+ 22594,
+ 22595,
+ 22596,
+ 22597,
+ 22598,
+ 22599,
+ 22600,
+ 22601,
+ 22602,
+ 22603,
+ 22604,
+ 22605,
+ 22606,
+ 22607,
+ 22608,
+ 22609,
+ 22610,
+ 22611,
+ 22612,
+ 22613,
+ 22614,
+ 22615,
+ 22616,
+ 22617,
+ 22618,
+ 22619,
+ 22620,
+ 22621,
+ 22622,
+ 22623,
+ 22624,
+ 22625,
+ 22626,
+ 22627,
+ 22628,
+ 22629,
+ 22630,
+ 22631,
+ 22632,
+ 22633,
+ 22634,
+ 22635,
+ 22636,
+ 22637,
+ 22638,
+ 22639,
+ 22640,
+ 22641,
+ 22642,
+ 22643,
+ 22644,
+ 22645,
+ 22646,
+ 22647,
+ 22648,
+ 22649,
+ 22650,
+ 22651,
+ 22652,
+ 22653,
+ 22654,
+ 22655,
+ 22656,
+ 22657,
+ 22658,
+ 22659,
+ 22660,
+ 22661,
+ 22662,
+ 22663,
+ 22664,
+ 22665,
+ 22666,
+ 22667,
+ 22668,
+ 22669,
+ 22670,
+ 22671,
+ 22672,
+ 22673,
+ 22674,
+ 22675,
+ 22676,
+ 22677,
+ 22678,
+ 22679,
+ 22680,
+ 22681,
+ 22682,
+ 22683,
+ 22684,
+ 22685,
+ 22686,
+ 22687,
+ 22688,
+ 22689,
+ 22690,
+ 22691,
+ 22692,
+ 22693,
+ 22694,
+ 22695,
+ 22696,
+ 22697,
+ 22698,
+ 22699,
+ 22700,
+ 22701,
+ 22702,
+ 22703,
+ 22704,
+ 22705,
+ 22706,
+ 22707,
+ 22708,
+ 22709,
+ 22710,
+ 22711,
+ 22712,
+ 22713,
+ 22714,
+ 22715,
+ 22716,
+ 22717,
+ 22718,
+ 22719,
+ 22720,
+ 22721,
+ 22722,
+ 22723,
+ 22724,
+ 22725,
+ 22726,
+ 22727,
+ 22728,
+ 22729,
+ 22730,
+ 22731,
+ 22732,
+ 22733,
+ 22734,
+ 22735,
+ 22736,
+ 22737,
+ 22738,
+ 22739,
+ 22740,
+ 22741,
+ 22742,
+ 22743,
+ 22744,
+ 22745,
+ 22746,
+ 22747,
+ 22748,
+ 22749,
+ 22750,
+ 22751,
+ 22752,
+ 22753,
+ 22754,
+ 22755,
+ 22756,
+ 22757,
+ 22758,
+ 22759,
+ 22760,
+ 22761,
+ 22762,
+ 22763,
+ 22764,
+ 22765,
+ 22766,
+ 22767,
+ 22768,
+ 22769,
+ 22770,
+ 22771,
+ 22772,
+ 22773,
+ 22774,
+ 22775,
+ 22776,
+ 22777,
+ 22778,
+ 22779,
+ 22780,
+ 22781,
+ 22782,
+ 22783,
+ 22784,
+ 22785,
+ 22786,
+ 22787,
+ 22788,
+ 22789,
+ 22790,
+ 22791,
+ 22792,
+ 22793,
+ 22794,
+ 22795,
+ 22796,
+ 22797,
+ 22798,
+ 22799,
+ 22800,
+ 22801,
+ 22802,
+ 22803,
+ 22804,
+ 22805,
+ 22806,
+ 22807,
+ 22808,
+ 22809,
+ 22810,
+ 22811,
+ 22812,
+ 22813,
+ 22814,
+ 22815,
+ 22816,
+ 22817,
+ 22818,
+ 22819,
+ 22820,
+ 22821,
+ 22822,
+ 22823,
+ 22824,
+ 22825,
+ 22826,
+ 22827,
+ 22828,
+ 22829,
+ 22830,
+ 22831,
+ 22832,
+ 22833,
+ 22834,
+ 22835,
+ 22836,
+ 22837,
+ 22838,
+ 22839,
+ 22840,
+ 22841,
+ 22842,
+ 22843,
+ 22844,
+ 22845,
+ 22846,
+ 22847,
+ 22848,
+ 22849,
+ 22850,
+ 22851,
+ 22852,
+ 22853,
+ 22854,
+ 22855,
+ 22856,
+ 22857,
+ 22858,
+ 22859,
+ 22860,
+ 22861,
+ 22862,
+ 22863,
+ 22864,
+ 22865,
+ 22866,
+ 22867,
+ 22868,
+ 22869,
+ 22870,
+ 22871,
+ 22872,
+ 22873,
+ 22874,
+ 22875,
+ 22876,
+ 22877,
+ 22878,
+ 22879,
+ 22880,
+ 22881,
+ 22882,
+ 22883,
+ 22884,
+ 22885,
+ 22886,
+ 22887,
+ 22888,
+ 22889,
+ 22890,
+ 22891,
+ 22892,
+ 22893,
+ 22894,
+ 22895,
+ 22896,
+ 22897,
+ 22898,
+ 22899,
+ 22900,
+ 22901,
+ 22902,
+ 22903,
+ 22904,
+ 22905,
+ 22906,
+ 22907,
+ 22908,
+ 22909,
+ 22910,
+ 22911,
+ 22912,
+ 22913,
+ 22914,
+ 22915,
+ 22916,
+ 22917,
+ 22918,
+ 22919,
+ 22920,
+ 22921,
+ 22922,
+ 22923,
+ 22924,
+ 22925,
+ 22926,
+ 22927,
+ 22928,
+ 22929,
+ 22930,
+ 22931,
+ 22932,
+ 22933,
+ 22934,
+ 22935,
+ 22936,
+ 22937,
+ 22938,
+ 22939,
+ 22940,
+ 22941,
+ 22942,
+ 22943,
+ 22944,
+ 22945,
+ 22946,
+ 22947,
+ 22948,
+ 22949,
+ 22950,
+ 22951,
+ 22952,
+ 22953,
+ 22954,
+ 22955,
+ 22956,
+ 22957,
+ 22958,
+ 22959,
+ 22960,
+ 22961,
+ 22962,
+ 22963,
+ 22964,
+ 22965,
+ 22966,
+ 22967,
+ 22968,
+ 22969,
+ 22970,
+ 22971,
+ 22972,
+ 22973,
+ 22974,
+ 22975,
+ 22976,
+ 22977,
+ 22978,
+ 22979,
+ 22980,
+ 22981,
+ 22982,
+ 22983,
+ 22984,
+ 22985,
+ 22986,
+ 22987,
+ 22988,
+ 22989,
+ 22990,
+ 22991,
+ 22992,
+ 22993,
+ 22994,
+ 22995,
+ 22996,
+ 22997,
+ 22998,
+ 22999,
+ 23000,
+ 23001,
+ 23002,
+ 23003,
+ 23004,
+ 23005,
+ 23006,
+ 23007,
+ 23008,
+ 23009,
+ 23010,
+ 23011,
+ 23012,
+ 23013,
+ 23014,
+ 23015,
+ 23016,
+ 23017,
+ 23018,
+ 23019,
+ 23020,
+ 23021,
+ 23022,
+ 23023,
+ 23024,
+ 23025,
+ 23026,
+ 23027,
+ 23028,
+ 23029,
+ 23030,
+ 23031,
+ 23032,
+ 23033,
+ 23034,
+ 23035,
+ 23036,
+ 23037,
+ 23038,
+ 23039,
+ 23040,
+ 23041,
+ 23042,
+ 23043,
+ 23044,
+ 23045,
+ 23046,
+ 23047,
+ 23048,
+ 23049,
+ 23050,
+ 23051,
+ 23052,
+ 23053,
+ 23054,
+ 23055,
+ 23056,
+ 23057,
+ 23058,
+ 23059,
+ 23060,
+ 23061,
+ 23062,
+ 23063,
+ 23064,
+ 23065,
+ 23066,
+ 23067,
+ 23068,
+ 23069,
+ 23070,
+ 23071,
+ 23072,
+ 23073,
+ 23074,
+ 23075,
+ 23076,
+ 23077,
+ 23078,
+ 23079,
+ 23080,
+ 23081,
+ 23082,
+ 23083,
+ 23084,
+ 23085,
+ 23086,
+ 23087,
+ 23088,
+ 23089,
+ 23090,
+ 23091,
+ 23092,
+ 23093,
+ 23094,
+ 23095,
+ 23096,
+ 23097,
+ 23098,
+ 23099,
+ 23100,
+ 23101,
+ 23102,
+ 23103,
+ 23104,
+ 23105,
+ 23106,
+ 23107,
+ 23108,
+ 23109,
+ 23110,
+ 23111,
+ 23112,
+ 23113,
+ 23114,
+ 23115,
+ 23116,
+ 23117,
+ 23118,
+ 23119,
+ 23120,
+ 23121,
+ 23122,
+ 23123,
+ 23124,
+ 23125,
+ 23126,
+ 23127,
+ 23128,
+ 23129,
+ 23130,
+ 23131,
+ 23132,
+ 23133,
+ 23134,
+ 23135,
+ 23136,
+ 23137,
+ 23138,
+ 23139,
+ 23140,
+ 23141,
+ 23142,
+ 23143,
+ 23144,
+ 23145,
+ 23146,
+ 23147,
+ 23148,
+ 23149,
+ 23150,
+ 23151,
+ 23152,
+ 23153,
+ 23154,
+ 23155,
+ 23156,
+ 23157,
+ 23158,
+ 23159,
+ 23160,
+ 23161,
+ 23162,
+ 23163,
+ 23164,
+ 23165,
+ 23166,
+ 23167,
+ 23168,
+ 23169,
+ 23170,
+ 23171,
+ 23172,
+ 23173,
+ 23174,
+ 23175,
+ 23176,
+ 23177,
+ 23178,
+ 23179,
+ 23180,
+ 23181,
+ 23182,
+ 23183,
+ 23184,
+ 23185,
+ 23186,
+ 23187,
+ 23188,
+ 23189,
+ 23190,
+ 23191,
+ 23192,
+ 23193,
+ 23194,
+ 23195,
+ 23196,
+ 23197,
+ 23198,
+ 23199,
+ 23200,
+ 23201,
+ 23202,
+ 23203,
+ 23204,
+ 23205,
+ 23206,
+ 23207,
+ 23208,
+ 23209,
+ 23210,
+ 23211,
+ 23212,
+ 23213,
+ 23214,
+ 23215,
+ 23216,
+ 23217,
+ 23218,
+ 23219,
+ 23220,
+ 23221,
+ 23222,
+ 23223,
+ 23224,
+ 23225,
+ 23226,
+ 23227,
+ 23228,
+ 23229,
+ 23230,
+ 23231,
+ 23232,
+ 23233,
+ 23234,
+ 23235,
+ 23236,
+ 23237,
+ 23238,
+ 23239,
+ 23240,
+ 23241,
+ 23242,
+ 23243,
+ 23244,
+ 23245,
+ 23246,
+ 23247,
+ 23248,
+ 23249,
+ 23250,
+ 23251,
+ 23252,
+ 23253,
+ 23254,
+ 23255,
+ 23256,
+ 23257,
+ 23258,
+ 23259,
+ 23260,
+ 23261,
+ 23262,
+ 23263,
+ 23264,
+ 23265,
+ 23266,
+ 23267,
+ 23268,
+ 23269,
+ 23270,
+ 23271,
+ 23272,
+ 23273,
+ 23274,
+ 23275,
+ 23276,
+ 23277,
+ 23278,
+ 23279,
+ 23280,
+ 23281,
+ 23282,
+ 23283,
+ 23284,
+ 23285,
+ 23286,
+ 23287,
+ 23288,
+ 23289,
+ 23290,
+ 23291,
+ 23292,
+ 23293,
+ 23294,
+ 23295,
+ 23296,
+ 23297,
+ 23298,
+ 23299,
+ 23300,
+ 23301,
+ 23302,
+ 23303,
+ 23304,
+ 23305,
+ 23306,
+ 23307,
+ 23308,
+ 23309,
+ 23310,
+ 23311,
+ 23312,
+ 23313,
+ 23314,
+ 23315,
+ 23316,
+ 23317,
+ 23318,
+ 23319,
+ 23320,
+ 23321,
+ 23322,
+ 23323,
+ 23324,
+ 23325,
+ 23326,
+ 23327,
+ 23328,
+ 23329,
+ 23330,
+ 23331,
+ 23332,
+ 23333,
+ 23334,
+ 23335,
+ 23336,
+ 23337,
+ 23338,
+ 23339,
+ 23340,
+ 23341,
+ 23342,
+ 23343,
+ 23344,
+ 23345,
+ 23346,
+ 23347,
+ 23348,
+ 23349,
+ 23350,
+ 23351,
+ 23352,
+ 23353,
+ 23354,
+ 23355,
+ 23356,
+ 23357,
+ 23358,
+ 23359,
+ 23360,
+ 23361,
+ 23362,
+ 23363,
+ 23364,
+ 23365,
+ 23366,
+ 23367,
+ 23368,
+ 23369,
+ 23370,
+ 23371,
+ 23372,
+ 23373,
+ 23374,
+ 23375,
+ 23376,
+ 23377,
+ 23378,
+ 23379,
+ 23380,
+ 23381,
+ 23382,
+ 23383,
+ 23384,
+ 23385,
+ 23386,
+ 23387,
+ 23388,
+ 23389,
+ 23390,
+ 23391,
+ 23392,
+ 23393,
+ 23394,
+ 23395,
+ 23396,
+ 23397,
+ 23398,
+ 23399,
+ 23400,
+ 23401,
+ 23402,
+ 23403,
+ 23404,
+ 23405,
+ 23406,
+ 23407,
+ 23408,
+ 23409,
+ 23410,
+ 23411,
+ 23412,
+ 23413,
+ 23414,
+ 23415,
+ 23416,
+ 23417,
+ 23418,
+ 23419,
+ 23420,
+ 23421,
+ 23422,
+ 23423,
+ 23424,
+ 23425,
+ 23426,
+ 23427,
+ 23428,
+ 23429,
+ 23430,
+ 23431,
+ 23432,
+ 23433,
+ 23434,
+ 23435,
+ 23436,
+ 23437,
+ 23438,
+ 23439,
+ 23440,
+ 23441,
+ 23442,
+ 23443,
+ 23444,
+ 23445,
+ 23446,
+ 23447,
+ 23448,
+ 23449,
+ 23450,
+ 23451,
+ 23452,
+ 23453,
+ 23454,
+ 23455,
+ 23456,
+ 23457,
+ 23458,
+ 23459,
+ 23460,
+ 23461,
+ 23462,
+ 23463,
+ 23464,
+ 23465,
+ 23466,
+ 23467,
+ 23468,
+ 23469,
+ 23470,
+ 23471,
+ 23472,
+ 23473,
+ 23474,
+ 23475,
+ 23476,
+ 23477,
+ 23478,
+ 23479,
+ 23480,
+ 23481,
+ 23482,
+ 23483,
+ 23484,
+ 23485,
+ 23486,
+ 23487,
+ 23488,
+ 23489,
+ 23490,
+ 23491,
+ 23492,
+ 23493,
+ 23494,
+ 23495,
+ 23496,
+ 23497,
+ 23498,
+ 23499,
+ 23500,
+ 23501,
+ 23502,
+ 23503,
+ 23504,
+ 23505,
+ 23506,
+ 23507,
+ 23508,
+ 23509,
+ 23510,
+ 23511,
+ 23512,
+ 23513,
+ 23514,
+ 23515,
+ 23516,
+ 23517,
+ 23518,
+ 23519,
+ 23520,
+ 23521,
+ 23522,
+ 23523,
+ 23524,
+ 23525,
+ 23526,
+ 23527,
+ 23528,
+ 23529,
+ 23530,
+ 23531,
+ 23532,
+ 23533,
+ 23534,
+ 23535,
+ 23536,
+ 23537,
+ 23538,
+ 23539,
+ 23540,
+ 23541,
+ 23542,
+ 23543,
+ 23544,
+ 23545,
+ 23546,
+ 23547,
+ 23548,
+ 23549,
+ 23550,
+ 23551,
+ 23552,
+ 23553,
+ 23554,
+ 23555,
+ 23556,
+ 23557,
+ 23558,
+ 23559,
+ 23560,
+ 23561,
+ 23562,
+ 23563,
+ 23564,
+ 23565,
+ 23566,
+ 23567,
+ 23568,
+ 23569,
+ 23570,
+ 23571,
+ 23572,
+ 23573,
+ 23574,
+ 23575,
+ 23576,
+ 23577,
+ 23578,
+ 23579,
+ 23580,
+ 23581,
+ 23582,
+ 23583,
+ 23584,
+ 23585,
+ 23586,
+ 23587,
+ 23588,
+ 23589,
+ 23590,
+ 23591,
+ 23592,
+ 23593,
+ 23594,
+ 23595,
+ 23596,
+ 23597,
+ 23598,
+ 23599,
+ 23600,
+ 23601,
+ 23602,
+ 23603,
+ 23604,
+ 23605,
+ 23606,
+ 23607,
+ 23608,
+ 23609,
+ 23610,
+ 23611,
+ 23612,
+ 23613,
+ 23614,
+ 23615,
+ 23616,
+ 23617,
+ 23618,
+ 23619,
+ 23620,
+ 23621,
+ 23622,
+ 23623,
+ 23624,
+ 23625,
+ 23626,
+ 23627,
+ 23628,
+ 23629,
+ 23630,
+ 23631,
+ 23632,
+ 23633,
+ 23634,
+ 23635,
+ 23636,
+ 23637,
+ 23638,
+ 23639,
+ 23640,
+ 23641,
+ 23642,
+ 23643,
+ 23644,
+ 23645,
+ 23646,
+ 23647,
+ 23648,
+ 23649,
+ 23650,
+ 23651,
+ 23652,
+ 23653,
+ 23654,
+ 23655,
+ 23656,
+ 23657,
+ 23658,
+ 23659,
+ 23660,
+ 23661,
+ 23662,
+ 23663,
+ 23664,
+ 23665,
+ 23666,
+ 23667,
+ 23668,
+ 23669,
+ 23670,
+ 23671,
+ 23672,
+ 23673,
+ 23674,
+ 23675,
+ 23676,
+ 23677,
+ 23678,
+ 23679,
+ 23680,
+ 23681,
+ 23682,
+ 23683,
+ 23684,
+ 23685,
+ 23686,
+ 23687,
+ 23688,
+ 23689,
+ 23690,
+ 23691,
+ 23692,
+ 23693,
+ 23694,
+ 23695,
+ 23696,
+ 23697,
+ 23698,
+ 23699,
+ 23700,
+ 23701,
+ 23702,
+ 23703,
+ 23704,
+ 23705,
+ 23706,
+ 23707,
+ 23708,
+ 23709,
+ 23710,
+ 23711,
+ 23712,
+ 23713,
+ 23714,
+ 23715,
+ 23716,
+ 23717,
+ 23718,
+ 23719,
+ 23720,
+ 23721,
+ 23722,
+ 23723,
+ 23724,
+ 23725,
+ 23726,
+ 23727,
+ 23728,
+ 23729,
+ 23730,
+ 23731,
+ 23732,
+ 23733,
+ 23734,
+ 23735,
+ 23736,
+ 23737,
+ 23738,
+ 23739,
+ 23740,
+ 23741,
+ 23742,
+ 23743,
+ 23744,
+ 23745,
+ 23746,
+ 23747,
+ 23748,
+ 23749,
+ 23750,
+ 23751,
+ 23752,
+ 23753,
+ 23754,
+ 23755,
+ 23756,
+ 23757,
+ 23758,
+ 23759,
+ 23760,
+ 23761,
+ 23762,
+ 23763,
+ 23764,
+ 23765,
+ 23766,
+ 23767,
+ 23768,
+ 23769,
+ 23770,
+ 23771,
+ 23772,
+ 23773,
+ 23774,
+ 23775,
+ 23776,
+ 23777,
+ 23778,
+ 23779,
+ 23780,
+ 23781,
+ 23782,
+ 23783,
+ 23784,
+ 23785,
+ 23786,
+ 23787,
+ 23788,
+ 23789,
+ 23790,
+ 23791,
+ 23792,
+ 23793,
+ 23794,
+ 23795,
+ 23796,
+ 23797,
+ 23798,
+ 23799,
+ 23800,
+ 23801,
+ 23802,
+ 23803,
+ 23804,
+ 23805,
+ 23806,
+ 23807,
+ 23808,
+ 23809,
+ 23810,
+ 23811,
+ 23812,
+ 23813,
+ 23814,
+ 23815,
+ 23816,
+ 23817,
+ 23818,
+ 23819,
+ 23820,
+ 23821,
+ 23822,
+ 23823,
+ 23824,
+ 23825,
+ 23826,
+ 23827,
+ 23828,
+ 23829,
+ 23830,
+ 23831,
+ 23832,
+ 23833,
+ 23834,
+ 23835,
+ 23836,
+ 23837,
+ 23838,
+ 23839,
+ 23840,
+ 23841,
+ 23842,
+ 23843,
+ 23844,
+ 23845,
+ 23846,
+ 23847,
+ 23848,
+ 23849,
+ 23850,
+ 23851,
+ 23852,
+ 23853,
+ 23854,
+ 23855,
+ 23856,
+ 23857,
+ 23858,
+ 23859,
+ 23860,
+ 23861,
+ 23862,
+ 23863,
+ 23864,
+ 23865,
+ 23866,
+ 23867,
+ 23868,
+ 23869,
+ 23870,
+ 23871,
+ 23872,
+ 23873,
+ 23874,
+ 23875,
+ 23876,
+ 23877,
+ 23878,
+ 23879,
+ 23880,
+ 23881,
+ 23882,
+ 23883,
+ 23884,
+ 23885,
+ 23886,
+ 23887,
+ 23888,
+ 23889,
+ 23890,
+ 23891,
+ 23892,
+ 23893,
+ 23894,
+ 23895,
+ 23896,
+ 23897,
+ 23898,
+ 23899,
+ 23900,
+ 23901,
+ 23902,
+ 23903,
+ 23904,
+ 23905,
+ 23906,
+ 23907,
+ 23908,
+ 23909,
+ 23910,
+ 23911,
+ 23912,
+ 23913,
+ 23914,
+ 23915,
+ 23916,
+ 23917,
+ 23918,
+ 23919,
+ 23920,
+ 23921,
+ 23922,
+ 23923,
+ 23924,
+ 23925,
+ 23926,
+ 23927,
+ 23928,
+ 23929,
+ 23930,
+ 23931,
+ 23932,
+ 23933,
+ 23934,
+ 23935,
+ 23936,
+ 23937,
+ 23938,
+ 23939,
+ 23940,
+ 23941,
+ 23942,
+ 23943,
+ 23944,
+ 23945,
+ 23946,
+ 23947,
+ 23948,
+ 23949,
+ 23950,
+ 23951,
+ 23952,
+ 23953,
+ 23954,
+ 23955,
+ 23956,
+ 23957,
+ 23958,
+ 23959,
+ 23960,
+ 23961,
+ 23962,
+ 23963,
+ 23964,
+ 23965,
+ 23966,
+ 23967,
+ 23968,
+ 23969,
+ 23970,
+ 23971,
+ 23972,
+ 23973,
+ 23974,
+ 23975,
+ 23976,
+ 23977,
+ 23978,
+ 23979,
+ 23980,
+ 23981,
+ 23982,
+ 23983,
+ 23984,
+ 23985,
+ 23986,
+ 23987,
+ 23988,
+ 23989,
+ 23990,
+ 23991,
+ 23992,
+ 23993,
+ 23994,
+ 23995,
+ 23996,
+ 23997,
+ 23998,
+ 23999,
+ 24000,
+ 24001,
+ 24002,
+ 24003,
+ 24004,
+ 24005,
+ 24006,
+ 24007,
+ 24008,
+ 24009,
+ 24010,
+ 24011,
+ 24012,
+ 24013,
+ 24014,
+ 24015,
+ 24016,
+ 24017,
+ 24018,
+ 24019,
+ 24020,
+ 24021,
+ 24022,
+ 24023,
+ 24024,
+ 24025,
+ 24026,
+ 24027,
+ 24028,
+ 24029,
+ 24030,
+ 24031,
+ 24032,
+ 24033,
+ 24034,
+ 24035,
+ 24036,
+ 24037,
+ 24038,
+ 24039,
+ 24040,
+ 24041,
+ 24042,
+ 24043,
+ 24044,
+ 24045,
+ 24046,
+ 24047,
+ 24048,
+ 24049,
+ 24050,
+ 24051,
+ 24052,
+ 24053,
+ 24054,
+ 24055,
+ 24056,
+ 24057,
+ 24058,
+ 24059,
+ 24060,
+ 24061,
+ 24062,
+ 24063,
+ 24064,
+ 24065,
+ 24066,
+ 24067,
+ 24068,
+ 24069,
+ 24070,
+ 24071,
+ 24072,
+ 24073,
+ 24074,
+ 24075,
+ 24076,
+ 24077,
+ 24078,
+ 24079,
+ 24080,
+ 24081,
+ 24082,
+ 24083,
+ 24084,
+ 24085,
+ 24086,
+ 24087,
+ 24088,
+ 24089,
+ 24090,
+ 24091,
+ 24092,
+ 24093,
+ 24094,
+ 24095,
+ 24096,
+ 24097,
+ 24098,
+ 24099,
+ 24100,
+ 24101,
+ 24102,
+ 24103,
+ 24104,
+ 24105,
+ 24106,
+ 24107,
+ 24108,
+ 24109,
+ 24110,
+ 24111,
+ 24112,
+ 24113,
+ 24114,
+ 24115,
+ 24116,
+ 24117,
+ 24118,
+ 24119,
+ 24120,
+ 24121,
+ 24122,
+ 24123,
+ 24124,
+ 24125,
+ 24126,
+ 24127,
+ 24128,
+ 24129,
+ 24130,
+ 24131,
+ 24132,
+ 24133,
+ 24134,
+ 24135,
+ 24136,
+ 24137,
+ 24138,
+ 24139,
+ 24140,
+ 24141,
+ 24142,
+ 24143,
+ 24144,
+ 24145,
+ 24146,
+ 24147,
+ 24148,
+ 24149,
+ 24150,
+ 24151,
+ 24152,
+ 24153,
+ 24154,
+ 24155,
+ 24156,
+ 24157,
+ 24158,
+ 24159,
+ 24160,
+ 24161,
+ 24162,
+ 24163,
+ 24164,
+ 24165,
+ 24166,
+ 24167,
+ 24168,
+ 24169,
+ 24170,
+ 24171,
+ 24172,
+ 24173,
+ 24174,
+ 24175,
+ 24176,
+ 24177,
+ 24178,
+ 24179,
+ 24180,
+ 24181,
+ 24182,
+ 24183,
+ 24184,
+ 24185,
+ 24186,
+ 24187,
+ 24188,
+ 24189,
+ 24190,
+ 24191,
+ 24192,
+ 24193,
+ 24194,
+ 24195,
+ 24196,
+ 24197,
+ 24198,
+ 24199,
+ 24200,
+ 24201,
+ 24202,
+ 24203,
+ 24204,
+ 24205,
+ 24206,
+ 24207,
+ 24208,
+ 24209,
+ 24210,
+ 24211,
+ 24212,
+ 24213,
+ 24214,
+ 24215,
+ 24216,
+ 24217,
+ 24218,
+ 24219,
+ 24220,
+ 24221,
+ 24222,
+ 24223,
+ 24224,
+ 24225,
+ 24226,
+ 24227,
+ 24228,
+ 24229,
+ 24230,
+ 24231,
+ 24232,
+ 24233,
+ 24234,
+ 24235,
+ 24236,
+ 24237,
+ 24238,
+ 24239,
+ 24240,
+ 24241,
+ 24242,
+ 24243,
+ 24244,
+ 24245,
+ 24246,
+ 24247,
+ 24248,
+ 24249,
+ 24250,
+ 24251,
+ 24252,
+ 24253,
+ 24254,
+ 24255,
+ 24256,
+ 24257,
+ 24258,
+ 24259,
+ 24260,
+ 24261,
+ 24262,
+ 24263,
+ 24264,
+ 24265,
+ 24266,
+ 24267,
+ 24268,
+ 24269,
+ 24270,
+ 24271,
+ 24272,
+ 24273,
+ 24274,
+ 24275,
+ 24276,
+ 24277,
+ 24278,
+ 24279,
+ 24280,
+ 24281,
+ 24282,
+ 24283,
+ 24284,
+ 24285,
+ 24286,
+ 24287,
+ 24288,
+ 24289,
+ 24290,
+ 24291,
+ 24292,
+ 24293,
+ 24294,
+ 24295,
+ 24296,
+ 24297,
+ 24298,
+ 24299,
+ 24300,
+ 24301,
+ 24302,
+ 24303,
+ 24304,
+ 24305,
+ 24306,
+ 24307,
+ 24308,
+ 24309,
+ 24310,
+ 24311,
+ 24312,
+ 24313,
+ 24314,
+ 24315,
+ 24316,
+ 24317,
+ 24318,
+ 24319,
+ 24320,
+ 24321,
+ 24322,
+ 24323,
+ 24324,
+ 24325,
+ 24326,
+ 24327,
+ 24328,
+ 24329,
+ 24330,
+ 24331,
+ 24332,
+ 24333,
+ 24334,
+ 24335,
+ 24336,
+ 24337,
+ 24338,
+ 24339,
+ 24340,
+ 24341,
+ 24342,
+ 24343,
+ 24344,
+ 24345,
+ 24346,
+ 24347,
+ 24348,
+ 24349,
+ 24350,
+ 24351,
+ 24352,
+ 24353,
+ 24354,
+ 24355,
+ 24356,
+ 24357,
+ 24358,
+ 24359,
+ 24360,
+ 24361,
+ 24362,
+ 24363,
+ 24364,
+ 24365,
+ 24366,
+ 24367,
+ 24368,
+ 24369,
+ 24370,
+ 24371,
+ 24372,
+ 24373,
+ 24374,
+ 24375,
+ 24376,
+ 24377,
+ 24378,
+ 24379,
+ 24380,
+ 24381,
+ 24382,
+ 24383,
+ 24384,
+ 24385,
+ 24386,
+ 24387,
+ 24388,
+ 24389,
+ 24390,
+ 24391,
+ 24392,
+ 24393,
+ 24394,
+ 24395,
+ 24396,
+ 24397,
+ 24398,
+ 24399,
+ 24400,
+ 24401,
+ 24402,
+ 24403,
+ 24404,
+ 24405,
+ 24406,
+ 24407,
+ 24408,
+ 24409,
+ 24410,
+ 24411,
+ 24412,
+ 24413,
+ 24414,
+ 24415,
+ 24416,
+ 24417,
+ 24418,
+ 24419,
+ 24420,
+ 24421,
+ 24422,
+ 24423,
+ 24424,
+ 24425,
+ 24426,
+ 24427,
+ 24428,
+ 24429,
+ 24430,
+ 24431,
+ 24432,
+ 24433,
+ 24434,
+ 24435,
+ 24436,
+ 24437,
+ 24438,
+ 24439,
+ 24440,
+ 24441,
+ 24442,
+ 24443,
+ 24444,
+ 24445,
+ 24446,
+ 24447,
+ 24448,
+ 24449,
+ 24450,
+ 24451,
+ 24452,
+ 24453,
+ 24454,
+ 24455,
+ 24456,
+ 24457,
+ 24458,
+ 24459,
+ 24460,
+ 24461,
+ 24462,
+ 24463,
+ 24464,
+ 24465,
+ 24466,
+ 24467,
+ 24468,
+ 24469,
+ 24470,
+ 24471,
+ 24472,
+ 24473,
+ 24474,
+ 24475,
+ 24476,
+ 24477,
+ 24478,
+ 24479,
+ 24480,
+ 24481,
+ 24482,
+ 24483,
+ 24484,
+ 24485,
+ 24486,
+ 24487,
+ 24488,
+ 24489,
+ 24490,
+ 24491,
+ 24492,
+ 24493,
+ 24494,
+ 24495,
+ 24496,
+ 24497,
+ 24498,
+ 24499,
+ 24500,
+ 24501,
+ 24502,
+ 24503,
+ 24504,
+ 24505,
+ 24506,
+ 24507,
+ 24508,
+ 24509,
+ 24510,
+ 24511,
+ 24512,
+ 24513,
+ 24514,
+ 24515,
+ 24516,
+ 24517,
+ 24518,
+ 24519,
+ 24520,
+ 24521,
+ 24522,
+ 24523,
+ 24524,
+ 24525,
+ 24526,
+ 24527,
+ 24528,
+ 24529,
+ 24530,
+ 24531,
+ 24532,
+ 24533,
+ 24534,
+ 24535,
+ 24536,
+ 24537,
+ 24538,
+ 24539,
+ 24540,
+ 24541,
+ 24542,
+ 24543,
+ 24544,
+ 24545,
+ 24546,
+ 24547,
+ 24548,
+ 24549,
+ 24550,
+ 24551,
+ 24552,
+ 24553,
+ 24554,
+ 24555,
+ 24556,
+ 24557,
+ 24558,
+ 24559,
+ 24560,
+ 24561,
+ 24562,
+ 24563,
+ 24564,
+ 24565,
+ 24566,
+ 24567,
+ 24568,
+ 24569,
+ 24570,
+ 24571,
+ 24572,
+ 24573,
+ 24574,
+ 24575,
+ 24576,
+ 24577,
+ 24578,
+ 24579,
+ 24580,
+ 24581,
+ 24582,
+ 24583,
+ 24584,
+ 24585,
+ 24586,
+ 24587,
+ 24588,
+ 24589,
+ 24590,
+ 24591,
+ 24592,
+ 24593,
+ 24594,
+ 24595,
+ 24596,
+ 24597,
+ 24598,
+ 24599,
+ 24600,
+ 24601,
+ 24602,
+ 24603,
+ 24604,
+ 24605,
+ 24606,
+ 24607,
+ 24608,
+ 24609,
+ 24610,
+ 24611,
+ 24612,
+ 24613,
+ 24614,
+ 24615,
+ 24616,
+ 24617,
+ 24618,
+ 24619,
+ 24620,
+ 24621,
+ 24622,
+ 24623,
+ 24624,
+ 24625,
+ 24626,
+ 24627,
+ 24628,
+ 24629,
+ 24630,
+ 24631,
+ 24632,
+ 24633,
+ 24634,
+ 24635,
+ 24636,
+ 24637,
+ 24638,
+ 24639,
+ 24640,
+ 24641,
+ 24642,
+ 24643,
+ 24644,
+ 24645,
+ 24646,
+ 24647,
+ 24648,
+ 24649,
+ 24650,
+ 24651,
+ 24652,
+ 24653,
+ 24654,
+ 24655,
+ 24656,
+ 24657,
+ 24658,
+ 24659,
+ 24660,
+ 24661,
+ 24662,
+ 24663,
+ 24664,
+ 24665,
+ 24666,
+ 24667,
+ 24668,
+ 24669,
+ 24670,
+ 24671,
+ 24672,
+ 24673,
+ 24674,
+ 24675,
+ 24676,
+ 24677,
+ 24678,
+ 24679,
+ 24680,
+ 24681,
+ 24682,
+ 24683,
+ 24684,
+ 24685,
+ 24686,
+ 24687,
+ 24688,
+ 24689,
+ 24690,
+ 24691,
+ 24692,
+ 24693,
+ 24694,
+ 24695,
+ 24696,
+ 24697,
+ 24698,
+ 24699,
+ 24700,
+ 24701,
+ 24702,
+ 24703,
+ 24704,
+ 24705,
+ 24706,
+ 24707,
+ 24708,
+ 24709,
+ 24710,
+ 24711,
+ 24712,
+ 24713,
+ 24714,
+ 24715,
+ 24716,
+ 24717,
+ 24718,
+ 24719,
+ 24720,
+ 24721,
+ 24722,
+ 24723,
+ 24724,
+ 24725,
+ 24726,
+ 24727,
+ 24728,
+ 24729,
+ 24730,
+ 24731,
+ 24732,
+ 24733,
+ 24734,
+ 24735,
+ 24736,
+ 24737,
+ 24738,
+ 24739,
+ 24740,
+ 24741,
+ 24742,
+ 24743,
+ 24744,
+ 24745,
+ 24746,
+ 24747,
+ 24748,
+ 24749,
+ 24750,
+ 24751,
+ 24752,
+ 24753,
+ 24754,
+ 24755,
+ 24756,
+ 24757,
+ 24758,
+ 24759,
+ 24760,
+ 24761,
+ 24762,
+ 24763,
+ 24764,
+ 24765,
+ 24766,
+ 24767,
+ 24768,
+ 24769,
+ 24770,
+ 24771,
+ 24772,
+ 24773,
+ 24774,
+ 24775,
+ 24776,
+ 24777,
+ 24778,
+ 24779,
+ 24780,
+ 24781,
+ 24782,
+ 24783,
+ 24784,
+ 24785,
+ 24786,
+ 24787,
+ 24788,
+ 24789,
+ 24790,
+ 24791,
+ 24792,
+ 24793,
+ 24794,
+ 24795,
+ 24796,
+ 24797,
+ 24798,
+ 24799,
+ 24800,
+ 24801,
+ 24802,
+ 24803,
+ 24804,
+ 24805,
+ 24806,
+ 24807,
+ 24808,
+ 24809,
+ 24810,
+ 24811,
+ 24812,
+ 24813,
+ 24814,
+ 24815,
+ 24816,
+ 24817,
+ 24818,
+ 24819,
+ 24820,
+ 24821,
+ 24822,
+ 24823,
+ 24824,
+ 24825,
+ 24826,
+ 24827,
+ 24828,
+ 24829,
+ 24830,
+ 24831,
+ 24832,
+ 24833,
+ 24834,
+ 24835,
+ 24836,
+ 24837,
+ 24838,
+ 24839,
+ 24840,
+ 24841,
+ 24842,
+ 24843,
+ 24844,
+ 24845,
+ 24846,
+ 24847,
+ 24848,
+ 24849,
+ 24850,
+ 24851,
+ 24852,
+ 24853,
+ 24854,
+ 24855,
+ 24856,
+ 24857,
+ 24858,
+ 24859,
+ 24860,
+ 24861,
+ 24862,
+ 24863,
+ 24864,
+ 24865,
+ 24866,
+ 24867,
+ 24868,
+ 24869,
+ 24870,
+ 24871,
+ 24872,
+ 24873,
+ 24874,
+ 24875,
+ 24876,
+ 24877,
+ 24878,
+ 24879,
+ 24880,
+ 24881,
+ 24882,
+ 24883,
+ 24884,
+ 24885,
+ 24886,
+ 24887,
+ 24888,
+ 24889,
+ 24890,
+ 24891,
+ 24892,
+ 24893,
+ 24894,
+ 24895,
+ 24896,
+ 24897,
+ 24898,
+ 24899,
+ 24900,
+ 24901,
+ 24902,
+ 24903,
+ 24904,
+ 24905,
+ 24906,
+ 24907,
+ 24908,
+ 24909,
+ 24910,
+ 24911,
+ 24912,
+ 24913,
+ 24914,
+ 24915,
+ 24916,
+ 24917,
+ 24918,
+ 24919,
+ 24920,
+ 24921,
+ 24922,
+ 24923,
+ 24924,
+ 24925,
+ 24926,
+ 24927,
+ 24928,
+ 24929,
+ 24930,
+ 24931,
+ 24932,
+ 24933,
+ 24934,
+ 24935,
+ 24936,
+ 24937,
+ 24938,
+ 24939,
+ 24940,
+ 24941,
+ 24942,
+ 24943,
+ 24944,
+ 24945,
+ 24946,
+ 24947,
+ 24948,
+ 24949,
+ 24950,
+ 24951,
+ 24952,
+ 24953,
+ 24954,
+ 24955,
+ 24956,
+ 24957,
+ 24958,
+ 24959,
+ 24960,
+ 24961,
+ 24962,
+ 24963,
+ 24964,
+ 24965,
+ 24966,
+ 24967,
+ 24968,
+ 24969,
+ 24970,
+ 24971,
+ 24972,
+ 24973,
+ 24974,
+ 24975,
+ 24976,
+ 24977,
+ 24978,
+ 24979,
+ 24980,
+ 24981,
+ 24982,
+ 24983,
+ 24984,
+ 24985,
+ 24986,
+ 24987,
+ 24988,
+ 24989,
+ 24990,
+ 24991,
+ 24992,
+ 24993,
+ 24994,
+ 24995,
+ 24996,
+ 24997,
+ 24998,
+ 24999,
+ 25000,
+ 25001,
+ 25002,
+ 25003,
+ 25004,
+ 25005,
+ 25006,
+ 25007,
+ 25008,
+ 25009,
+ 25010,
+ 25011,
+ 25012,
+ 25013,
+ 25014,
+ 25015,
+ 25016,
+ 25017,
+ 25018,
+ 25019,
+ 25020,
+ 25021,
+ 25022,
+ 25023,
+ 25024,
+ 25025,
+ 25026,
+ 25027,
+ 25028,
+ 25029,
+ 25030,
+ 25031,
+ 25032,
+ 25033,
+ 25034,
+ 25035,
+ 25036,
+ 25037,
+ 25038,
+ 25039,
+ 25040,
+ 25041,
+ 25042,
+ 25043,
+ 25044,
+ 25045,
+ 25046,
+ 25047,
+ 25048,
+ 25049,
+ 25050,
+ 25051,
+ 25052,
+ 25053,
+ 25054,
+ 25055,
+ 25056,
+ 25057,
+ 25058,
+ 25059,
+ 25060,
+ 25061,
+ 25062,
+ 25063,
+ 25064,
+ 25065,
+ 25066,
+ 25067,
+ 25068,
+ 25069,
+ 25070,
+ 25071,
+ 25072,
+ 25073,
+ 25074,
+ 25075,
+ 25076,
+ 25077,
+ 25078,
+ 25079,
+ 25080,
+ 25081,
+ 25082,
+ 25083,
+ 25084,
+ 25085,
+ 25086,
+ 25087,
+ 25088,
+ 25089,
+ 25090,
+ 25091,
+ 25092,
+ 25093,
+ 25094,
+ 25095,
+ 25096,
+ 25097,
+ 25098,
+ 25099,
+ 25100,
+ 25101,
+ 25102,
+ 25103,
+ 25104,
+ 25105,
+ 25106,
+ 25107,
+ 25108,
+ 25109,
+ 25110,
+ 25111,
+ 25112,
+ 25113,
+ 25114,
+ 25115,
+ 25116,
+ 25117,
+ 25118,
+ 25119,
+ 25120,
+ 25121,
+ 25122,
+ 25123,
+ 25124,
+ 25125,
+ 25126,
+ 25127,
+ 25128,
+ 25129,
+ 25130,
+ 25131,
+ 25132,
+ 25133,
+ 25134,
+ 25135,
+ 25136,
+ 25137,
+ 25138,
+ 25139,
+ 25140,
+ 25141,
+ 25142,
+ 25143,
+ 25144,
+ 25145,
+ 25146,
+ 25147,
+ 25148,
+ 25149,
+ 25150,
+ 25151,
+ 25152,
+ 25153,
+ 25154,
+ 25155,
+ 25156,
+ 25157,
+ 25158,
+ 25159,
+ 25160,
+ 25161,
+ 25162,
+ 25163,
+ 25164,
+ 25165,
+ 25166,
+ 25167,
+ 25168,
+ 25169,
+ 25170,
+ 25171,
+ 25172,
+ 25173,
+ 25174,
+ 25175,
+ 25176,
+ 25177,
+ 25178,
+ 25179,
+ 25180,
+ 25181,
+ 25182,
+ 25183,
+ 25184,
+ 25185,
+ 25186,
+ 25187,
+ 25188,
+ 25189,
+ 25190,
+ 25191,
+ 25192,
+ 25193,
+ 25194,
+ 25195,
+ 25196,
+ 25197,
+ 25198,
+ 25199,
+ 25200,
+ 25201,
+ 25202,
+ 25203,
+ 25204,
+ 25205,
+ 25206,
+ 25207,
+ 25208,
+ 25209,
+ 25210,
+ 25211,
+ 25212,
+ 25213,
+ 25214,
+ 25215,
+ 25216,
+ 25217,
+ 25218,
+ 25219,
+ 25220,
+ 25221,
+ 25222,
+ 25223,
+ 25224,
+ 25225,
+ 25226,
+ 25227,
+ 25228,
+ 25229,
+ 25230,
+ 25231,
+ 25232,
+ 25233,
+ 25234,
+ 25235,
+ 25236,
+ 25237,
+ 25238,
+ 25239,
+ 25240,
+ 25241,
+ 25242,
+ 25243,
+ 25244,
+ 25245,
+ 25246,
+ 25247,
+ 25248,
+ 25249,
+ 25250,
+ 25251,
+ 25252,
+ 25253,
+ 25254,
+ 25255,
+ 25256,
+ 25257,
+ 25258,
+ 25259,
+ 25260,
+ 25261,
+ 25262,
+ 25263,
+ 25264,
+ 25265,
+ 25266,
+ 25267,
+ 25268,
+ 25269,
+ 25270,
+ 25271,
+ 25272,
+ 25273,
+ 25274,
+ 25275,
+ 25276,
+ 25277,
+ 25278,
+ 25279,
+ 25280,
+ 25281,
+ 25282,
+ 25283,
+ 25284,
+ 25285,
+ 25286,
+ 25287,
+ 25288,
+ 25289,
+ 25290,
+ 25291,
+ 25292,
+ 25293,
+ 25294,
+ 25295,
+ 25296,
+ 25297,
+ 25298,
+ 25299,
+ 25300,
+ 25301,
+ 25302,
+ 25303,
+ 25304,
+ 25305,
+ 25306,
+ 25307,
+ 25308,
+ 25309,
+ 25310,
+ 25311,
+ 25312,
+ 25313,
+ 25314,
+ 25315,
+ 25316,
+ 25317,
+ 25318,
+ 25319,
+ 25320,
+ 25321,
+ 25322,
+ 25323,
+ 25324,
+ 25325,
+ 25326,
+ 25327,
+ 25328,
+ 25329,
+ 25330,
+ 25331,
+ 25332,
+ 25333,
+ 25334,
+ 25335,
+ 25336,
+ 25337,
+ 25338,
+ 25339,
+ 25340,
+ 25341,
+ 25342,
+ 25343,
+ 25344,
+ 25345,
+ 25346,
+ 25347,
+ 25348,
+ 25349,
+ 25350,
+ 25351,
+ 25352,
+ 25353,
+ 25354,
+ 25355,
+ 25356,
+ 25357,
+ 25358,
+ 25359,
+ 25360,
+ 25361,
+ 25362,
+ 25363,
+ 25364,
+ 25365,
+ 25366,
+ 25367,
+ 25368,
+ 25369,
+ 25370,
+ 25371,
+ 25372,
+ 25373,
+ 25374,
+ 25375,
+ 25376,
+ 25377,
+ 25378,
+ 25379,
+ 25380,
+ 25381,
+ 25382,
+ 25383,
+ 25384,
+ 25385,
+ 25386,
+ 25387,
+ 25388,
+ 25389,
+ 25390,
+ 25391,
+ 25392,
+ 25393,
+ 25394,
+ 25395,
+ 25396,
+ 25397,
+ 25398,
+ 25399,
+ 25400,
+ 25401,
+ 25402,
+ 25403,
+ 25404,
+ 25405,
+ 25406,
+ 25407,
+ 25408,
+ 25409,
+ 25410,
+ 25411,
+ 25412,
+ 25413,
+ 25414,
+ 25415,
+ 25416,
+ 25417,
+ 25418,
+ 25419,
+ 25420,
+ 25421,
+ 25422,
+ 25423,
+ 25424,
+ 25425,
+ 25426,
+ 25427,
+ 25428,
+ 25429,
+ 25430,
+ 25431,
+ 25432,
+ 25433,
+ 25434,
+ 25435,
+ 25436,
+ 25437,
+ 25438,
+ 25439,
+ 25440,
+ 25441,
+ 25442,
+ 25443,
+ 25444,
+ 25445,
+ 25446,
+ 25447,
+ 25448,
+ 25449,
+ 25450,
+ 25451,
+ 25452,
+ 25453,
+ 25454,
+ 25455,
+ 25456,
+ 25457,
+ 25458,
+ 25459,
+ 25460,
+ 25461,
+ 25462,
+ 25463,
+ 25464,
+ 25465,
+ 25466,
+ 25467,
+ 25468,
+ 25469,
+ 25470,
+ 25471,
+ 25472,
+ 25473,
+ 25474,
+ 25475,
+ 25476,
+ 25477,
+ 25478,
+ 25479,
+ 25480,
+ 25481,
+ 25482,
+ 25483,
+ 25484,
+ 25485,
+ 25486,
+ 25487,
+ 25488,
+ 25489,
+ 25490,
+ 25491,
+ 25492,
+ 25493,
+ 25494,
+ 25495,
+ 25496,
+ 25497,
+ 25498,
+ 25499,
+ 25500,
+ 25501,
+ 25502,
+ 25503,
+ 25504,
+ 25505,
+ 25506,
+ 25507,
+ 25508,
+ 25509,
+ 25510,
+ 25511,
+ 25512,
+ 25513,
+ 25514,
+ 25515,
+ 25516,
+ 25517,
+ 25518,
+ 25519,
+ 25520,
+ 25521,
+ 25522,
+ 25523,
+ 25524,
+ 25525,
+ 25526,
+ 25527,
+ 25528,
+ 25529,
+ 25530,
+ 25531,
+ 25532,
+ 25533,
+ 25534,
+ 25535,
+ 25536,
+ 25537,
+ 25538,
+ 25539,
+ 25540,
+ 25541,
+ 25542,
+ 25543,
+ 25544,
+ 25545,
+ 25546,
+ 25547,
+ 25548,
+ 25549,
+ 25550,
+ 25551,
+ 25552,
+ 25553,
+ 25554,
+ 25555,
+ 25556,
+ 25557,
+ 25558,
+ 25559,
+ 25560,
+ 25561,
+ 25562,
+ 25563,
+ 25564,
+ 25565,
+ 25566,
+ 25567,
+ 25568,
+ 25569,
+ 25570,
+ 25571,
+ 25572,
+ 25573,
+ 25574,
+ 25575,
+ 25576,
+ 25577,
+ 25578,
+ 25579,
+ 25580,
+ 25581,
+ 25582,
+ 25583,
+ 25584,
+ 25585,
+ 25586,
+ 25587,
+ 25588,
+ 25589,
+ 25590,
+ 25591,
+ 25592,
+ 25593,
+ 25594,
+ 25595,
+ 25596,
+ 25597,
+ 25598,
+ 25599,
+ 25600,
+ 25601,
+ 25602,
+ 25603,
+ 25604,
+ 25605,
+ 25606,
+ 25607,
+ 25608,
+ 25609,
+ 25610,
+ 25611,
+ 25612,
+ 25613,
+ 25614,
+ 25615,
+ 25616,
+ 25617,
+ 25618,
+ 25619,
+ 25620,
+ 25621,
+ 25622,
+ 25623,
+ 25624,
+ 25625,
+ 25626,
+ 25627,
+ 25628,
+ 25629,
+ 25630,
+ 25631,
+ 25632,
+ 25633,
+ 25634,
+ 25635,
+ 25636,
+ 25637,
+ 25638,
+ 25639,
+ 25640,
+ 25641,
+ 25642,
+ 25643,
+ 25644,
+ 25645,
+ 25646,
+ 25647,
+ 25648,
+ 25649,
+ 25650,
+ 25651,
+ 25652,
+ 25653,
+ 25654,
+ 25655,
+ 25656,
+ 25657,
+ 25658,
+ 25659,
+ 25660,
+ 25661,
+ 25662,
+ 25663,
+ 25664,
+ 25665,
+ 25666,
+ 25667,
+ 25668,
+ 25669,
+ 25670,
+ 25671,
+ 25672,
+ 25673,
+ 25674,
+ 25675,
+ 25676,
+ 25677,
+ 25678,
+ 25679,
+ 25680,
+ 25681,
+ 25682,
+ 25683,
+ 25684,
+ 25685,
+ 25686,
+ 25687,
+ 25688,
+ 25689,
+ 25690,
+ 25691,
+ 25692,
+ 25693,
+ 25694,
+ 25695,
+ 25696,
+ 25697,
+ 25698,
+ 25699,
+ 25700,
+ 25701,
+ 25702,
+ 25703,
+ 25704,
+ 25705,
+ 25706,
+ 25707,
+ 25708,
+ 25709,
+ 25710,
+ 25711,
+ 25712,
+ 25713,
+ 25714,
+ 25715,
+ 25716,
+ 25717,
+ 25718,
+ 25719,
+ 25720,
+ 25721,
+ 25722,
+ 25723,
+ 25724,
+ 25725,
+ 25726,
+ 25727,
+ 25728,
+ 25729,
+ 25730,
+ 25731,
+ 25732,
+ 25733,
+ 25734,
+ 25735,
+ 25736,
+ 25737,
+ 25738,
+ 25739,
+ 25740,
+ 25741,
+ 25742,
+ 25743,
+ 25744,
+ 25745,
+ 25746,
+ 25747,
+ 25748,
+ 25749,
+ 25750,
+ 25751,
+ 25752,
+ 25753,
+ 25754,
+ 25755,
+ 25756,
+ 25757,
+ 25758,
+ 25759,
+ 25760,
+ 25761,
+ 25762,
+ 25763,
+ 25764,
+ 25765,
+ 25766,
+ 25767,
+ 25768,
+ 25769,
+ 25770,
+ 25771,
+ 25772,
+ 25773,
+ 25774,
+ 25775,
+ 25776,
+ 25777,
+ 25778,
+ 25779,
+ 25780,
+ 25781,
+ 25782,
+ 25783,
+ 25784,
+ 25785,
+ 25786,
+ 25787,
+ 25788,
+ 25789,
+ 25790,
+ 25791,
+ 25792,
+ 25793,
+ 25794,
+ 25795,
+ 25796,
+ 25797,
+ 25798,
+ 25799,
+ 25800,
+ 25801,
+ 25802,
+ 25803,
+ 25804,
+ 25805,
+ 25806,
+ 25807,
+ 25808,
+ 25809,
+ 25810,
+ 25811,
+ 25812,
+ 25813,
+ 25814,
+ 25815,
+ 25816,
+ 25817,
+ 25818,
+ 25819,
+ 25820,
+ 25821,
+ 25822,
+ 25823,
+ 25824,
+ 25825,
+ 25826,
+ 25827,
+ 25828,
+ 25829,
+ 25830,
+ 25831,
+ 25832,
+ 25833,
+ 25834,
+ 25835,
+ 25836,
+ 25837,
+ 25838,
+ 25839,
+ 25840,
+ 25841,
+ 25842,
+ 25843,
+ 25844,
+ 25845,
+ 25846,
+ 25847,
+ 25848,
+ 25849,
+ 25850,
+ 25851,
+ 25852,
+ 25853,
+ 25854,
+ 25855,
+ 25856,
+ 25857,
+ 25858,
+ 25859,
+ 25860,
+ 25861,
+ 25862,
+ 25863,
+ 25864,
+ 25865,
+ 25866,
+ 25867,
+ 25868,
+ 25869,
+ 25870,
+ 25871,
+ 25872,
+ 25873,
+ 25874,
+ 25875,
+ 25876,
+ 25877,
+ 25878,
+ 25879,
+ 25880,
+ 25881,
+ 25882,
+ 25883,
+ 25884,
+ 25885,
+ 25886,
+ 25887,
+ 25888,
+ 25889,
+ 25890,
+ 25891,
+ 25892,
+ 25893,
+ 25894,
+ 25895,
+ 25896,
+ 25897,
+ 25898,
+ 25899,
+ 25900,
+ 25901,
+ 25902,
+ 25903,
+ 25904,
+ 25905,
+ 25906,
+ 25907,
+ 25908,
+ 25909,
+ 25910,
+ 25911,
+ 25912,
+ 25913,
+ 25914,
+ 25915,
+ 25916,
+ 25917,
+ 25918,
+ 25919,
+ 25920,
+ 25921,
+ 25922,
+ 25923,
+ 25924,
+ 25925,
+ 25926,
+ 25927,
+ 25928,
+ 25929,
+ 25930,
+ 25931,
+ 25932,
+ 25933,
+ 25934,
+ 25935,
+ 25936,
+ 25937,
+ 25938,
+ 25939,
+ 25940,
+ 25941,
+ 25942,
+ 25943,
+ 25944,
+ 25945,
+ 25946,
+ 25947,
+ 25948,
+ 25949,
+ 25950,
+ 25951,
+ 25952,
+ 25953,
+ 25954,
+ 25955,
+ 25956,
+ 25957,
+ 25958,
+ 25959,
+ 25960,
+ 25961,
+ 25962,
+ 25963,
+ 25964,
+ 25965,
+ 25966,
+ 25967,
+ 25968,
+ 25969,
+ 25970,
+ 25971,
+ 25972,
+ 25973,
+ 25974,
+ 25975,
+ 25976,
+ 25977,
+ 25978,
+ 25979,
+ 25980,
+ 25981,
+ 25982,
+ 25983,
+ 25984,
+ 25985,
+ 25986,
+ 25987,
+ 25988,
+ 25989,
+ 25990,
+ 25991,
+ 25992,
+ 25993,
+ 25994,
+ 25995,
+ 25996,
+ 25997,
+ 25998,
+ 25999,
+ 26000,
+ 26001,
+ 26002,
+ 26003,
+ 26004,
+ 26005,
+ 26006,
+ 26007,
+ 26008,
+ 26009,
+ 26010,
+ 26011,
+ 26012,
+ 26013,
+ 26014,
+ 26015,
+ 26016,
+ 26017,
+ 26018,
+ 26019,
+ 26020,
+ 26021,
+ 26022,
+ 26023,
+ 26024,
+ 26025,
+ 26026,
+ 26027,
+ 26028,
+ 26029,
+ 26030,
+ 26031,
+ 26032,
+ 26033,
+ 26034,
+ 26035,
+ 26036,
+ 26037,
+ 26038,
+ 26039,
+ 26040,
+ 26041,
+ 26042,
+ 26043,
+ 26044,
+ 26045,
+ 26046,
+ 26047,
+ 26048,
+ 26049,
+ 26050,
+ 26051,
+ 26052,
+ 26053,
+ 26054,
+ 26055,
+ 26056,
+ 26057,
+ 26058,
+ 26059,
+ 26060,
+ 26061,
+ 26062,
+ 26063,
+ 26064,
+ 26065,
+ 26066,
+ 26067,
+ 26068,
+ 26069,
+ 26070,
+ 26071,
+ 26072,
+ 26073,
+ 26074,
+ 26075,
+ 26076,
+ 26077,
+ 26078,
+ 26079,
+ 26080,
+ 26081,
+ 26082,
+ 26083,
+ 26084,
+ 26085,
+ 26086,
+ 26087,
+ 26088,
+ 26089,
+ 26090,
+ 26091,
+ 26092,
+ 26093,
+ 26094,
+ 26095,
+ 26096,
+ 26097,
+ 26098,
+ 26099,
+ 26100,
+ 26101,
+ 26102,
+ 26103,
+ 26104,
+ 26105,
+ 26106,
+ 26107,
+ 26108,
+ 26109,
+ 26110,
+ 26111,
+ 26112,
+ 26113,
+ 26114,
+ 26115,
+ 26116,
+ 26117,
+ 26118,
+ 26119,
+ 26120,
+ 26121,
+ 26122,
+ 26123,
+ 26124,
+ 26125,
+ 26126,
+ 26127,
+ 26128,
+ 26129,
+ 26130,
+ 26131,
+ 26132,
+ 26133,
+ 26134,
+ 26135,
+ 26136,
+ 26137,
+ 26138,
+ 26139,
+ 26140,
+ 26141,
+ 26142,
+ 26143,
+ 26144,
+ 26145,
+ 26146,
+ 26147,
+ 26148,
+ 26149,
+ 26150,
+ 26151,
+ 26152,
+ 26153,
+ 26154,
+ 26155,
+ 26156,
+ 26157,
+ 26158,
+ 26159,
+ 26160,
+ 26161,
+ 26162,
+ 26163,
+ 26164,
+ 26165,
+ 26166,
+ 26167,
+ 26168,
+ 26169,
+ 26170,
+ 26171,
+ 26172,
+ 26173,
+ 26174,
+ 26175,
+ 26176,
+ 26177,
+ 26178,
+ 26179,
+ 26180,
+ 26181,
+ 26182,
+ 26183,
+ 26184,
+ 26185,
+ 26186,
+ 26187,
+ 26188,
+ 26189,
+ 26190,
+ 26191,
+ 26192,
+ 26193,
+ 26194,
+ 26195,
+ 26196,
+ 26197,
+ 26198,
+ 26199,
+ 26200,
+ 26201,
+ 26202,
+ 26203,
+ 26204,
+ 26205,
+ 26206,
+ 26207,
+ 26208,
+ 26209,
+ 26210,
+ 26211,
+ 26212,
+ 26213,
+ 26214,
+ 26215,
+ 26216,
+ 26217,
+ 26218,
+ 26219,
+ 26220,
+ 26221,
+ 26222,
+ 26223,
+ 26224,
+ 26225,
+ 26226,
+ 26227,
+ 26228,
+ 26229,
+ 26230,
+ 26231,
+ 26232,
+ 26233,
+ 26234,
+ 26235,
+ 26236,
+ 26237,
+ 26238,
+ 26239,
+ 26240,
+ 26241,
+ 26242,
+ 26243,
+ 26244,
+ 26245,
+ 26246,
+ 26247,
+ 26248,
+ 26249,
+ 26250,
+ 26251,
+ 26252,
+ 26253,
+ 26254,
+ 26255,
+ 26256,
+ 26257,
+ 26258,
+ 26259,
+ 26260,
+ 26261,
+ 26262,
+ 26263,
+ 26264,
+ 26265,
+ 26266,
+ 26267,
+ 26268,
+ 26269,
+ 26270,
+ 26271,
+ 26272,
+ 26273,
+ 26274,
+ 26275,
+ 26276,
+ 26277,
+ 26278,
+ 26279,
+ 26280,
+ 26281,
+ 26282,
+ 26283,
+ 26284,
+ 26285,
+ 26286,
+ 26287,
+ 26288,
+ 26289,
+ 26290,
+ 26291,
+ 26292,
+ 26293,
+ 26294,
+ 26295,
+ 26296,
+ 26297,
+ 26298,
+ 26299,
+ 26300,
+ 26301,
+ 26302,
+ 26303,
+ 26304,
+ 26305,
+ 26306,
+ 26307,
+ 26308,
+ 26309,
+ 26310,
+ 26311,
+ 26312,
+ 26313,
+ 26314,
+ 26315,
+ 26316,
+ 26317,
+ 26318,
+ 26319,
+ 26320,
+ 26321,
+ 26322,
+ 26323,
+ 26324,
+ 26325,
+ 26326,
+ 26327,
+ 26328,
+ 26329,
+ 26330,
+ 26331,
+ 26332,
+ 26333,
+ 26334,
+ 26335,
+ 26336,
+ 26337,
+ 26338,
+ 26339,
+ 26340,
+ 26341,
+ 26342,
+ 26343,
+ 26344,
+ 26345,
+ 26346,
+ 26347,
+ 26348,
+ 26349,
+ 26350,
+ 26351,
+ 26352,
+ 26353,
+ 26354,
+ 26355,
+ 26356,
+ 26357,
+ 26358,
+ 26359,
+ 26360,
+ 26361,
+ 26362,
+ 26363,
+ 26364,
+ 26365,
+ 26366,
+ 26367,
+ 26368,
+ 26369,
+ 26370,
+ 26371,
+ 26372,
+ 26373,
+ 26374,
+ 26375,
+ 26376,
+ 26377,
+ 26378,
+ 26379,
+ 26380,
+ 26381,
+ 26382,
+ 26383,
+ 26384,
+ 26385,
+ 26386,
+ 26387,
+ 26388,
+ 26389,
+ 26390,
+ 26391,
+ 26392,
+ 26393,
+ 26394,
+ 26395,
+ 26396,
+ 26397,
+ 26398,
+ 26399,
+ 26400,
+ 26401,
+ 26402,
+ 26403,
+ 26404,
+ 26405,
+ 26406,
+ 26407,
+ 26408,
+ 26409,
+ 26410,
+ 26411,
+ 26412,
+ 26413,
+ 26414,
+ 26415,
+ 26416,
+ 26417,
+ 26418,
+ 26419,
+ 26420,
+ 26421,
+ 26422,
+ 26423,
+ 26424,
+ 26425,
+ 26426,
+ 26427,
+ 26428,
+ 26429,
+ 26430,
+ 26431,
+ 26432,
+ 26433,
+ 26434,
+ 26435,
+ 26436,
+ 26437,
+ 26438,
+ 26439,
+ 26440,
+ 26441,
+ 26442,
+ 26443,
+ 26444,
+ 26445,
+ 26446,
+ 26447,
+ 26448,
+ 26449,
+ 26450,
+ 26451,
+ 26452,
+ 26453,
+ 26454,
+ 26455,
+ 26456,
+ 26457,
+ 26458,
+ 26459,
+ 26460,
+ 26461,
+ 26462,
+ 26463,
+ 26464,
+ 26465,
+ 26466,
+ 26467,
+ 26468,
+ 26469,
+ 26470,
+ 26471,
+ 26472,
+ 26473,
+ 26474,
+ 26475,
+ 26476,
+ 26477,
+ 26478,
+ 26479,
+ 26480,
+ 26481,
+ 26482,
+ 26483,
+ 26484,
+ 26485,
+ 26486,
+ 26487,
+ 26488,
+ 26489,
+ 26490,
+ 26491,
+ 26492,
+ 26493,
+ 26494,
+ 26495,
+ 26496,
+ 26497,
+ 26498,
+ 26499,
+ 26500,
+ 26501,
+ 26502,
+ 26503,
+ 26504,
+ 26505,
+ 26506,
+ 26507,
+ 26508,
+ 26509,
+ 26510,
+ 26511,
+ 26512,
+ 26513,
+ 26514,
+ 26515,
+ 26516,
+ 26517,
+ 26518,
+ 26519,
+ 26520,
+ 26521,
+ 26522,
+ 26523,
+ 26524,
+ 26525,
+ 26526,
+ 26527,
+ 26528,
+ 26529,
+ 26530,
+ 26531,
+ 26532,
+ 26533,
+ 26534,
+ 26535,
+ 26536,
+ 26537,
+ 26538,
+ 26539,
+ 26540,
+ 26541,
+ 26542,
+ 26543,
+ 26544,
+ 26545,
+ 26546,
+ 26547,
+ 26548,
+ 26549,
+ 26550,
+ 26551,
+ 26552,
+ 26553,
+ 26554,
+ 26555,
+ 26556,
+ 26557,
+ 26558,
+ 26559,
+ 26560,
+ 26561,
+ 26562,
+ 26563,
+ 26564,
+ 26565,
+ 26566,
+ 26567,
+ 26568,
+ 26569,
+ 26570,
+ 26571,
+ 26572,
+ 26573,
+ 26574,
+ 26575,
+ 26576,
+ 26577,
+ 26578,
+ 26579,
+ 26580,
+ 26581,
+ 26582,
+ 26583,
+ 26584,
+ 26585,
+ 26586,
+ 26587,
+ 26588,
+ 26589,
+ 26590,
+ 26591,
+ 26592,
+ 26593,
+ 26594,
+ 26595,
+ 26596,
+ 26597,
+ 26598,
+ 26599,
+ 26600,
+ 26601,
+ 26602,
+ 26603,
+ 26604,
+ 26605,
+ 26606,
+ 26607,
+ 26608,
+ 26609,
+ 26610,
+ 26611,
+ 26612,
+ 26613,
+ 26614,
+ 26615,
+ 26616,
+ 26617,
+ 26618,
+ 26619,
+ 26620,
+ 26621,
+ 26622,
+ 26623,
+ 26624,
+ 26625,
+ 26626,
+ 26627,
+ 26628,
+ 26629,
+ 26630,
+ 26631,
+ 26632,
+ 26633,
+ 26634,
+ 26635,
+ 26636,
+ 26637,
+ 26638,
+ 26639,
+ 26640,
+ 26641,
+ 26642,
+ 26643,
+ 26644,
+ 26645,
+ 26646,
+ 26647,
+ 26648,
+ 26649,
+ 26650,
+ 26651,
+ 26652,
+ 26653,
+ 26654,
+ 26655,
+ 26656,
+ 26657,
+ 26658,
+ 26659,
+ 26660,
+ 26661,
+ 26662,
+ 26663,
+ 26664,
+ 26665,
+ 26666,
+ 26667,
+ 26668,
+ 26669,
+ 26670,
+ 26671,
+ 26672,
+ 26673,
+ 26674,
+ 26675,
+ 26676,
+ 26677,
+ 26678,
+ 26679,
+ 26680,
+ 26681,
+ 26682,
+ 26683,
+ 26684,
+ 26685,
+ 26686,
+ 26687,
+ 26688,
+ 26689,
+ 26690,
+ 26691,
+ 26692,
+ 26693,
+ 26694,
+ 26695,
+ 26696,
+ 26697,
+ 26698,
+ 26699,
+ 26700,
+ 26701,
+ 26702,
+ 26703,
+ 26704,
+ 26705,
+ 26706,
+ 26707,
+ 26708,
+ 26709,
+ 26710,
+ 26711,
+ 26712,
+ 26713,
+ 26714,
+ 26715,
+ 26716,
+ 26717,
+ 26718,
+ 26719,
+ 26720,
+ 26721,
+ 26722,
+ 26723,
+ 26724,
+ 26725,
+ 26726,
+ 26727,
+ 26728,
+ 26729,
+ 26730,
+ 26731,
+ 26732,
+ 26733,
+ 26734,
+ 26735,
+ 26736,
+ 26737,
+ 26738,
+ 26739,
+ 26740,
+ 26741,
+ 26742,
+ 26743,
+ 26744,
+ 26745,
+ 26746,
+ 26747,
+ 26748,
+ 26749,
+ 26750,
+ 26751,
+ 26752,
+ 26753,
+ 26754,
+ 26755,
+ 26756,
+ 26757,
+ 26758,
+ 26759,
+ 26760,
+ 26761,
+ 26762,
+ 26763,
+ 26764,
+ 26765,
+ 26766,
+ 26767,
+ 26768,
+ 26769,
+ 26770,
+ 26771,
+ 26772,
+ 26773,
+ 26774,
+ 26775,
+ 26776,
+ 26777,
+ 26778,
+ 26779,
+ 26780,
+ 26781,
+ 26782,
+ 26783,
+ 26784,
+ 26785,
+ 26786,
+ 26787,
+ 26788,
+ 26789,
+ 26790,
+ 26791,
+ 26792,
+ 26793,
+ 26794,
+ 26795,
+ 26796,
+ 26797,
+ 26798,
+ 26799,
+ 26800,
+ 26801,
+ 26802,
+ 26803,
+ 26804,
+ 26805,
+ 26806,
+ 26807,
+ 26808,
+ 26809,
+ 26810,
+ 26811,
+ 26812,
+ 26813,
+ 26814,
+ 26815,
+ 26816,
+ 26817,
+ 26818,
+ 26819,
+ 26820,
+ 26821,
+ 26822,
+ 26823,
+ 26824,
+ 26825,
+ 26826,
+ 26827,
+ 26828,
+ 26829,
+ 26830,
+ 26831,
+ 26832,
+ 26833,
+ 26834,
+ 26835,
+ 26836,
+ 26837,
+ 26838,
+ 26839,
+ 26840,
+ 26841,
+ 26842,
+ 26843,
+ 26844,
+ 26845,
+ 26846,
+ 26847,
+ 26848,
+ 26849,
+ 26850,
+ 26851,
+ 26852,
+ 26853,
+ 26854,
+ 26855,
+ 26856,
+ 26857,
+ 26858,
+ 26859,
+ 26860,
+ 26861,
+ 26862,
+ 26863,
+ 26864,
+ 26865,
+ 26866,
+ 26867,
+ 26868,
+ 26869,
+ 26870,
+ 26871,
+ 26872,
+ 26873,
+ 26874,
+ 26875,
+ 26876,
+ 26877,
+ 26878,
+ 26879,
+ 26880,
+ 26881,
+ 26882,
+ 26883,
+ 26884,
+ 26885,
+ 26886,
+ 26887,
+ 26888,
+ 26889,
+ 26890,
+ 26891,
+ 26892,
+ 26893,
+ 26894,
+ 26895,
+ 26896,
+ 26897,
+ 26898,
+ 26899,
+ 26900,
+ 26901,
+ 26902,
+ 26903,
+ 26904,
+ 26905,
+ 26906,
+ 26907,
+ 26908,
+ 26909,
+ 26910,
+ 26911,
+ 26912,
+ 26913,
+ 26914,
+ 26915,
+ 26916,
+ 26917,
+ 26918,
+ 26919,
+ 26920,
+ 26921,
+ 26922,
+ 26923,
+ 26924,
+ 26925,
+ 26926,
+ 26927,
+ 26928,
+ 26929,
+ 26930,
+ 26931,
+ 26932,
+ 26933,
+ 26934,
+ 26935,
+ 26936,
+ 26937,
+ 26938,
+ 26939,
+ 26940,
+ 26941,
+ 26942,
+ 26943,
+ 26944,
+ 26945,
+ 26946,
+ 26947,
+ 26948,
+ 26949,
+ 26950,
+ 26951,
+ 26952,
+ 26953,
+ 26954,
+ 26955,
+ 26956,
+ 26957,
+ 26958,
+ 26959,
+ 26960,
+ 26961,
+ 26962,
+ 26963,
+ 26964,
+ 26965,
+ 26966,
+ 26967,
+ 26968,
+ 26969,
+ 26970,
+ 26971,
+ 26972,
+ 26973,
+ 26974,
+ 26975,
+ 26976,
+ 26977,
+ 26978,
+ 26979,
+ 26980,
+ 26981,
+ 26982,
+ 26983,
+ 26984,
+ 26985,
+ 26986,
+ 26987,
+ 26988,
+ 26989,
+ 26990,
+ 26991,
+ 26992,
+ 26993,
+ 26994,
+ 26995,
+ 26996,
+ 26997,
+ 26998,
+ 26999,
+ 27000,
+ 27001,
+ 27002,
+ 27003,
+ 27004,
+ 27005,
+ 27006,
+ 27007,
+ 27008,
+ 27009,
+ 27010,
+ 27011,
+ 27012,
+ 27013,
+ 27014,
+ 27015,
+ 27016,
+ 27017,
+ 27018,
+ 27019,
+ 27020,
+ 27021,
+ 27022,
+ 27023,
+ 27024,
+ 27025,
+ 27026,
+ 27027,
+ 27028,
+ 27029,
+ 27030,
+ 27031,
+ 27032,
+ 27033,
+ 27034,
+ 27035,
+ 27036,
+ 27037,
+ 27038,
+ 27039,
+ 27040,
+ 27041,
+ 27042,
+ 27043,
+ 27044,
+ 27045,
+ 27046,
+ 27047,
+ 27048,
+ 27049,
+ 27050,
+ 27051,
+ 27052,
+ 27053,
+ 27054,
+ 27055,
+ 27056,
+ 27057,
+ 27058,
+ 27059,
+ 27060,
+ 27061,
+ 27062,
+ 27063,
+ 27064,
+ 27065,
+ 27066,
+ 27067,
+ 27068,
+ 27069,
+ 27070,
+ 27071,
+ 27072,
+ 27073,
+ 27074,
+ 27075,
+ 27076,
+ 27077,
+ 27078,
+ 27079,
+ 27080,
+ 27081,
+ 27082,
+ 27083,
+ 27084,
+ 27085,
+ 27086,
+ 27087,
+ 27088,
+ 27089,
+ 27090,
+ 27091,
+ 27092,
+ 27093,
+ 27094,
+ 27095,
+ 27096,
+ 27097,
+ 27098,
+ 27099,
+ 27100,
+ 27101,
+ 27102,
+ 27103,
+ 27104,
+ 27105,
+ 27106,
+ 27107,
+ 27108,
+ 27109,
+ 27110,
+ 27111,
+ 27112,
+ 27113,
+ 27114,
+ 27115,
+ 27116,
+ 27117,
+ 27118,
+ 27119,
+ 27120,
+ 27121,
+ 27122,
+ 27123,
+ 27124,
+ 27125,
+ 27126,
+ 27127,
+ 27128,
+ 27129,
+ 27130,
+ 27131,
+ 27132,
+ 27133,
+ 27134,
+ 27135,
+ 27136,
+ 27137,
+ 27138,
+ 27139,
+ 27140,
+ 27141,
+ 27142,
+ 27143,
+ 27144,
+ 27145,
+ 27146,
+ 27147,
+ 27148,
+ 27149,
+ 27150,
+ 27151,
+ 27152,
+ 27153,
+ 27154,
+ 27155,
+ 27156,
+ 27157,
+ 27158,
+ 27159,
+ 27160,
+ 27161,
+ 27162,
+ 27163,
+ 27164,
+ 27165,
+ 27166,
+ 27167,
+ 27168,
+ 27169,
+ 27170,
+ 27171,
+ 27172,
+ 27173,
+ 27174,
+ 27175,
+ 27176,
+ 27177,
+ 27178,
+ 27179,
+ 27180,
+ 27181,
+ 27182,
+ 27183,
+ 27184,
+ 27185,
+ 27186,
+ 27187,
+ 27188,
+ 27189,
+ 27190,
+ 27191,
+ 27192,
+ 27193,
+ 27194,
+ 27195,
+ 27196,
+ 27197,
+ 27198,
+ 27199,
+ 27200,
+ 27201,
+ 27202,
+ 27203,
+ 27204,
+ 27205,
+ 27206,
+ 27207,
+ 27208,
+ 27209,
+ 27210,
+ 27211,
+ 27212,
+ 27213,
+ 27214,
+ 27215,
+ 27216,
+ 27217,
+ 27218,
+ 27219,
+ 27220,
+ 27221,
+ 27222,
+ 27223,
+ 27224,
+ 27225,
+ 27226,
+ 27227,
+ 27228,
+ 27229,
+ 27230,
+ 27231,
+ 27232,
+ 27233,
+ 27234,
+ 27235,
+ 27236,
+ 27237,
+ 27238,
+ 27239,
+ 27240,
+ 27241,
+ 27242,
+ 27243,
+ 27244,
+ 27245,
+ 27246,
+ 27247,
+ 27248,
+ 27249,
+ 27250,
+ 27251,
+ 27252,
+ 27253,
+ 27254,
+ 27255,
+ 27256,
+ 27257,
+ 27258,
+ 27259,
+ 27260,
+ 27261,
+ 27262,
+ 27263,
+ 27264,
+ 27265,
+ 27266,
+ 27267,
+ 27268,
+ 27269,
+ 27270,
+ 27271,
+ 27272,
+ 27273,
+ 27274,
+ 27275,
+ 27276,
+ 27277,
+ 27278,
+ 27279,
+ 27280,
+ 27281,
+ 27282,
+ 27283,
+ 27284,
+ 27285,
+ 27286,
+ 27287,
+ 27288,
+ 27289,
+ 27290,
+ 27291,
+ 27292,
+ 27293,
+ 27294,
+ 27295,
+ 27296,
+ 27297,
+ 27298,
+ 27299,
+ 27300,
+ 27301,
+ 27302,
+ 27303,
+ 27304,
+ 27305,
+ 27306,
+ 27307,
+ 27308,
+ 27309,
+ 27310,
+ 27311,
+ 27312,
+ 27313,
+ 27314,
+ 27315,
+ 27316,
+ 27317,
+ 27318,
+ 27319,
+ 27320,
+ 27321,
+ 27322,
+ 27323,
+ 27324,
+ 27325,
+ 27326,
+ 27327,
+ 27328,
+ 27329,
+ 27330,
+ 27331,
+ 27332,
+ 27333,
+ 27334,
+ 27335,
+ 27336,
+ 27337,
+ 27338,
+ 27339,
+ 27340,
+ 27341,
+ 27342,
+ 27343,
+ 27344,
+ 27345,
+ 27346,
+ 27347,
+ 27348,
+ 27349,
+ 27350,
+ 27351,
+ 27352,
+ 27353,
+ 27354,
+ 27355,
+ 27356,
+ 27357,
+ 27358,
+ 27359,
+ 27360,
+ 27361,
+ 27362,
+ 27363,
+ 27364,
+ 27365,
+ 27366,
+ 27367,
+ 27368,
+ 27369,
+ 27370,
+ 27371,
+ 27372,
+ 27373,
+ 27374,
+ 27375,
+ 27376,
+ 27377,
+ 27378,
+ 27379,
+ 27380,
+ 27381,
+ 27382,
+ 27383,
+ 27384,
+ 27385,
+ 27386,
+ 27387,
+ 27388,
+ 27389,
+ 27390,
+ 27391,
+ 27392,
+ 27393,
+ 27394,
+ 27395,
+ 27396,
+ 27397,
+ 27398,
+ 27399,
+ 27400,
+ 27401,
+ 27402,
+ 27403,
+ 27404,
+ 27405,
+ 27406,
+ 27407,
+ 27408,
+ 27409,
+ 27410,
+ 27411,
+ 27412,
+ 27413,
+ 27414,
+ 27415,
+ 27416,
+ 27417,
+ 27418,
+ 27419,
+ 27420,
+ 27421,
+ 27422,
+ 27423,
+ 27424,
+ 27425,
+ 27426,
+ 27427,
+ 27428,
+ 27429,
+ 27430,
+ 27431,
+ 27432,
+ 27433,
+ 27434,
+ 27435,
+ 27436,
+ 27437,
+ 27438,
+ 27439,
+ 27440,
+ 27441,
+ 27442,
+ 27443,
+ 27444,
+ 27445,
+ 27446,
+ 27447,
+ 27448,
+ 27449,
+ 27450,
+ 27451,
+ 27452,
+ 27453,
+ 27454,
+ 27455,
+ 27456,
+ 27457,
+ 27458,
+ 27459,
+ 27460,
+ 27461,
+ 27462,
+ 27463,
+ 27464,
+ 27465,
+ 27466,
+ 27467,
+ 27468,
+ 27469,
+ 27470,
+ 27471,
+ 27472,
+ 27473,
+ 27474,
+ 27475,
+ 27476,
+ 27477,
+ 27478,
+ 27479,
+ 27480,
+ 27481,
+ 27482,
+ 27483,
+ 27484,
+ 27485,
+ 27486,
+ 27487,
+ 27488,
+ 27489,
+ 27490,
+ 27491,
+ 27492,
+ 27493,
+ 27494,
+ 27495,
+ 27496,
+ 27497,
+ 27498,
+ 27499,
+ 27500,
+ 27501,
+ 27502,
+ 27503,
+ 27504,
+ 27505,
+ 27506,
+ 27507,
+ 27508,
+ 27509,
+ 27510,
+ 27511,
+ 27512,
+ 27513,
+ 27514,
+ 27515,
+ 27516,
+ 27517,
+ 27518,
+ 27519,
+ 27520,
+ 27521,
+ 27522,
+ 27523,
+ 27524,
+ 27525,
+ 27526,
+ 27527,
+ 27528,
+ 27529,
+ 27530,
+ 27531,
+ 27532,
+ 27533,
+ 27534,
+ 27535,
+ 27536,
+ 27537,
+ 27538,
+ 27539,
+ 27540,
+ 27541,
+ 27542,
+ 27543,
+ 27544,
+ 27545,
+ 27546,
+ 27547,
+ 27548,
+ 27549,
+ 27550,
+ 27551,
+ 27552,
+ 27553,
+ 27554,
+ 27555,
+ 27556,
+ 27557,
+ 27558,
+ 27559,
+ 27560,
+ 27561,
+ 27562,
+ 27563,
+ 27564,
+ 27565,
+ 27566,
+ 27567,
+ 27568,
+ 27569,
+ 27570,
+ 27571,
+ 27572,
+ 27573,
+ 27574,
+ 27575,
+ 27576,
+ 27577,
+ 27578,
+ 27579,
+ 27580,
+ 27581,
+ 27582,
+ 27583,
+ 27584,
+ 27585,
+ 27586,
+ 27587,
+ 27588,
+ 27589,
+ 27590,
+ 27591,
+ 27592,
+ 27593,
+ 27594,
+ 27595,
+ 27596,
+ 27597,
+ 27598,
+ 27599,
+ 27600,
+ 27601,
+ 27602,
+ 27603,
+ 27604,
+ 27605,
+ 27606,
+ 27607,
+ 27608,
+ 27609,
+ 27610,
+ 27611,
+ 27612,
+ 27613,
+ 27614,
+ 27615,
+ 27616,
+ 27617,
+ 27618,
+ 27619,
+ 27620,
+ 27621,
+ 27622,
+ 27623,
+ 27624,
+ 27625,
+ 27626,
+ 27627,
+ 27628,
+ 27629,
+ 27630,
+ 27631,
+ 27632,
+ 27633,
+ 27634,
+ 27635,
+ 27636,
+ 27637,
+ 27638,
+ 27639,
+ 27640,
+ 27641,
+ 27642,
+ 27643,
+ 27644,
+ 27645,
+ 27646,
+ 27647,
+ 27648,
+ 27649,
+ 27650,
+ 27651,
+ 27652,
+ 27653,
+ 27654,
+ 27655,
+ 27656,
+ 27657,
+ 27658,
+ 27659,
+ 27660,
+ 27661,
+ 27662,
+ 27663,
+ 27664,
+ 27665,
+ 27666,
+ 27667,
+ 27668,
+ 27669,
+ 27670,
+ 27671,
+ 27672,
+ 27673,
+ 27674,
+ 27675,
+ 27676,
+ 27677,
+ 27678,
+ 27679,
+ 27680,
+ 27681,
+ 27682,
+ 27683,
+ 27684,
+ 27685,
+ 27686,
+ 27687,
+ 27688,
+ 27689,
+ 27690,
+ 27691,
+ 27692,
+ 27693,
+ 27694,
+ 27695,
+ 27696,
+ 27697,
+ 27698,
+ 27699,
+ 27700,
+ 27701,
+ 27702,
+ 27703,
+ 27704,
+ 27705,
+ 27706,
+ 27707,
+ 27708,
+ 27709,
+ 27710,
+ 27711,
+ 27712,
+ 27713,
+ 27714,
+ 27715,
+ 27716,
+ 27717,
+ 27718,
+ 27719,
+ 27720,
+ 27721,
+ 27722,
+ 27723,
+ 27724,
+ 27725,
+ 27726,
+ 27727,
+ 27728,
+ 27729,
+ 27730,
+ 27731,
+ 27732,
+ 27733,
+ 27734,
+ 27735,
+ 27736,
+ 27737,
+ 27738,
+ 27739,
+ 27740,
+ 27741,
+ 27742,
+ 27743,
+ 27744,
+ 27745,
+ 27746,
+ 27747,
+ 27748,
+ 27749,
+ 27750,
+ 27751,
+ 27752,
+ 27753,
+ 27754,
+ 27755,
+ 27756,
+ 27757,
+ 27758,
+ 27759,
+ 27760,
+ 27761,
+ 27762,
+ 27763,
+ 27764,
+ 27765,
+ 27766,
+ 27767,
+ 27768,
+ 27769,
+ 27770,
+ 27771,
+ 27772,
+ 27773,
+ 27774,
+ 27775,
+ 27776,
+ 27777,
+ 27778,
+ 27779,
+ 27780,
+ 27781,
+ 27782,
+ 27783,
+ 27784,
+ 27785,
+ 27786,
+ 27787,
+ 27788,
+ 27789,
+ 27790,
+ 27791,
+ 27792,
+ 27793,
+ 27794,
+ 27795,
+ 27796,
+ 27797,
+ 27798,
+ 27799,
+ 27800,
+ 27801,
+ 27802,
+ 27803,
+ 27804,
+ 27805,
+ 27806,
+ 27807,
+ 27808,
+ 27809,
+ 27810,
+ 27811,
+ 27812,
+ 27813,
+ 27814,
+ 27815,
+ 27816,
+ 27817,
+ 27818,
+ 27819,
+ 27820,
+ 27821,
+ 27822,
+ 27823,
+ 27824,
+ 27825,
+ 27826,
+ 27827,
+ 27828,
+ 27829,
+ 27830,
+ 27831,
+ 27832,
+ 27833,
+ 27834,
+ 27835,
+ 27836,
+ 27837,
+ 27838,
+ 27839,
+ 27840,
+ 27841,
+ 27842,
+ 27843,
+ 27844,
+ 27845,
+ 27846,
+ 27847,
+ 27848,
+ 27849,
+ 27850,
+ 27851,
+ 27852,
+ 27853,
+ 27854,
+ 27855,
+ 27856,
+ 27857,
+ 27858,
+ 27859,
+ 27860,
+ 27861,
+ 27862,
+ 27863,
+ 27864,
+ 27865,
+ 27866,
+ 27867,
+ 27868,
+ 27869,
+ 27870,
+ 27871,
+ 27872,
+ 27873,
+ 27874,
+ 27875,
+ 27876,
+ 27877,
+ 27878,
+ 27879,
+ 27880,
+ 27881,
+ 27882,
+ 27883,
+ 27884,
+ 27885,
+ 27886,
+ 27887,
+ 27888,
+ 27889,
+ 27890,
+ 27891,
+ 27892,
+ 27893,
+ 27894,
+ 27895,
+ 27896,
+ 27897,
+ 27898,
+ 27899,
+ 27900,
+ 27901,
+ 27902,
+ 27903,
+ 27904,
+ 27905,
+ 27906,
+ 27907,
+ 27908,
+ 27909,
+ 27910,
+ 27911,
+ 27912,
+ 27913,
+ 27914,
+ 27915,
+ 27916,
+ 27917,
+ 27918,
+ 27919,
+ 27920,
+ 27921,
+ 27922,
+ 27923,
+ 27924,
+ 27925,
+ 27926,
+ 27927,
+ 27928,
+ 27929,
+ 27930,
+ 27931,
+ 27932,
+ 27933,
+ 27934,
+ 27935,
+ 27936,
+ 27937,
+ 27938,
+ 27939,
+ 27940,
+ 27941,
+ 27942,
+ 27943,
+ 27944,
+ 27945,
+ 27946,
+ 27947,
+ 27948,
+ 27949,
+ 27950,
+ 27951,
+ 27952,
+ 27953,
+ 27954,
+ 27955,
+ 27956,
+ 27957,
+ 27958,
+ 27959,
+ 27960,
+ 27961,
+ 27962,
+ 27963,
+ 27964,
+ 27965,
+ 27966,
+ 27967,
+ 27968,
+ 27969,
+ 27970,
+ 27971,
+ 27972,
+ 27973,
+ 27974,
+ 27975,
+ 27976,
+ 27977,
+ 27978,
+ 27979,
+ 27980,
+ 27981,
+ 27982,
+ 27983,
+ 27984,
+ 27985,
+ 27986,
+ 27987,
+ 27988,
+ 27989,
+ 27990,
+ 27991,
+ 27992,
+ 27993,
+ 27994,
+ 27995,
+ 27996,
+ 27997,
+ 27998,
+ 27999,
+ 28000,
+ 28001,
+ 28002,
+ 28003,
+ 28004,
+ 28005,
+ 28006,
+ 28007,
+ 28008,
+ 28009,
+ 28010,
+ 28011,
+ 28012,
+ 28013,
+ 28014,
+ 28015,
+ 28016,
+ 28017,
+ 28018,
+ 28019,
+ 28020,
+ 28021,
+ 28022,
+ 28023,
+ 28024,
+ 28025,
+ 28026,
+ 28027,
+ 28028,
+ 28029,
+ 28030,
+ 28031,
+ 28032,
+ 28033,
+ 28034,
+ 28035,
+ 28036,
+ 28037,
+ 28038,
+ 28039,
+ 28040,
+ 28041,
+ 28042,
+ 28043,
+ 28044,
+ 28045,
+ 28046,
+ 28047,
+ 28048,
+ 28049,
+ 28050,
+ 28051,
+ 28052,
+ 28053,
+ 28054,
+ 28055,
+ 28056,
+ 28057,
+ 28058,
+ 28059,
+ 28060,
+ 28061,
+ 28062,
+ 28063,
+ 28064,
+ 28065,
+ 28066,
+ 28067,
+ 28068,
+ 28069,
+ 28070,
+ 28071,
+ 28072,
+ 28073,
+ 28074,
+ 28075,
+ 28076,
+ 28077,
+ 28078,
+ 28079,
+ 28080,
+ 28081,
+ 28082,
+ 28083,
+ 28084,
+ 28085,
+ 28086,
+ 28087,
+ 28088,
+ 28089,
+ 28090,
+ 28091,
+ 28092,
+ 28093,
+ 28094,
+ 28095,
+ 28096,
+ 28097,
+ 28098,
+ 28099,
+ 28100,
+ 28101,
+ 28102,
+ 28103,
+ 28104,
+ 28105,
+ 28106,
+ 28107,
+ 28108,
+ 28109,
+ 28110,
+ 28111,
+ 28112,
+ 28113,
+ 28114,
+ 28115,
+ 28116,
+ 28117,
+ 28118,
+ 28119,
+ 28120,
+ 28121,
+ 28122,
+ 28123,
+ 28124,
+ 28125,
+ 28126,
+ 28127,
+ 28128,
+ 28129,
+ 28130,
+ 28131,
+ 28132,
+ 28133,
+ 28134,
+ 28135,
+ 28136,
+ 28137,
+ 28138,
+ 28139,
+ 28140,
+ 28141,
+ 28142,
+ 28143,
+ 28144,
+ 28145,
+ 28146,
+ 28147,
+ 28148,
+ 28149,
+ 28150,
+ 28151,
+ 28152,
+ 28153,
+ 28154,
+ 28155,
+ 28156,
+ 28157,
+ 28158,
+ 28159,
+ 28160,
+ 28161,
+ 28162,
+ 28163,
+ 28164,
+ 28165,
+ 28166,
+ 28167,
+ 28168,
+ 28169,
+ 28170,
+ 28171,
+ 28172,
+ 28173,
+ 28174,
+ 28175,
+ 28176,
+ 28177,
+ 28178,
+ 28179,
+ 28180,
+ 28181,
+ 28182,
+ 28183,
+ 28184,
+ 28185,
+ 28186,
+ 28187,
+ 28188,
+ 28189,
+ 28190,
+ 28191,
+ 28192,
+ 28193,
+ 28194,
+ 28195,
+ 28196,
+ 28197,
+ 28198,
+ 28199,
+ 28200,
+ 28201,
+ 28202,
+ 28203,
+ 28204,
+ 28205,
+ 28206,
+ 28207,
+ 28208,
+ 28209,
+ 28210,
+ 28211,
+ 28212,
+ 28213,
+ 28214,
+ 28215,
+ 28216,
+ 28217,
+ 28218,
+ 28219,
+ 28220,
+ 28221,
+ 28222,
+ 28223,
+ 28224,
+ 28225,
+ 28226,
+ 28227,
+ 28228,
+ 28229,
+ 28230,
+ 28231,
+ 28232,
+ 28233,
+ 28234,
+ 28235,
+ 28236,
+ 28237,
+ 28238,
+ 28239,
+ 28240,
+ 28241,
+ 28242,
+ 28243,
+ 28244,
+ 28245,
+ 28246,
+ 28247,
+ 28248,
+ 28249,
+ 28250,
+ 28251,
+ 28252,
+ 28253,
+ 28254,
+ 28255,
+ 28256,
+ 28257,
+ 28258,
+ 28259,
+ 28260,
+ 28261,
+ 28262,
+ 28263,
+ 28264,
+ 28265,
+ 28266,
+ 28267,
+ 28268,
+ 28269,
+ 28270,
+ 28271,
+ 28272,
+ 28273,
+ 28274,
+ 28275,
+ 28276,
+ 28277,
+ 28278,
+ 28279,
+ 28280,
+ 28281,
+ 28282,
+ 28283,
+ 28284,
+ 28285,
+ 28286,
+ 28287,
+ 28288,
+ 28289,
+ 28290,
+ 28291,
+ 28292,
+ 28293,
+ 28294,
+ 28295,
+ 28296,
+ 28297,
+ 28298,
+ 28299,
+ 28300,
+ 28301,
+ 28302,
+ 28303,
+ 28304,
+ 28305,
+ 28306,
+ 28307,
+ 28308,
+ 28309,
+ 28310,
+ 28311,
+ 28312,
+ 28313,
+ 28314,
+ 28315,
+ 28316,
+ 28317,
+ 28318,
+ 28319,
+ 28320,
+ 28321,
+ 28322,
+ 28323,
+ 28324,
+ 28325,
+ 28326,
+ 28327,
+ 28328,
+ 28329,
+ 28330,
+ 28331,
+ 28332,
+ 28333,
+ 28334,
+ 28335,
+ 28336,
+ 28337,
+ 28338,
+ 28339,
+ 28340,
+ 28341,
+ 28342,
+ 28343,
+ 28344,
+ 28345,
+ 28346,
+ 28347,
+ 28348,
+ 28349,
+ 28350,
+ 28351,
+ 28352,
+ 28353,
+ 28354,
+ 28355,
+ 28356,
+ 28357,
+ 28358,
+ 28359,
+ 28360,
+ 28361,
+ 28362,
+ 28363,
+ 28364,
+ 28365,
+ 28366,
+ 28367,
+ 28368,
+ 28369,
+ 28370,
+ 28371,
+ 28372,
+ 28373,
+ 28374,
+ 28375,
+ 28376,
+ 28377,
+ 28378,
+ 28379,
+ 28380,
+ 28381,
+ 28382,
+ 28383,
+ 28384,
+ 28385,
+ 28386,
+ 28387,
+ 28388,
+ 28389,
+ 28390,
+ 28391,
+ 28392,
+ 28393,
+ 28394,
+ 28395,
+ 28396,
+ 28397,
+ 28398,
+ 28399,
+ 28400,
+ 28401,
+ 28402,
+ 28403,
+ 28404,
+ 28405,
+ 28406,
+ 28407,
+ 28408,
+ 28409,
+ 28410,
+ 28411,
+ 28412,
+ 28413,
+ 28414,
+ 28415,
+ 28416,
+ 28417,
+ 28418,
+ 28419,
+ 28420,
+ 28421,
+ 28422,
+ 28423,
+ 28424,
+ 28425,
+ 28426,
+ 28427,
+ 28428,
+ 28429,
+ 28430,
+ 28431,
+ 28432,
+ 28433,
+ 28434,
+ 28435,
+ 28436,
+ 28437,
+ 28438,
+ 28439,
+ 28440,
+ 28441,
+ 28442,
+ 28443,
+ 28444,
+ 28445,
+ 28446,
+ 28447,
+ 28448,
+ 28449,
+ 28450,
+ 28451,
+ 28452,
+ 28453,
+ 28454,
+ 28455,
+ 28456,
+ 28457,
+ 28458,
+ 28459,
+ 28460,
+ 28461,
+ 28462,
+ 28463,
+ 28464,
+ 28465,
+ 28466,
+ 28467,
+ 28468,
+ 28469,
+ 28470,
+ 28471,
+ 28472,
+ 28473,
+ 28474,
+ 28475,
+ 28476,
+ 28477,
+ 28478,
+ 28479,
+ 28480,
+ 28481,
+ 28482,
+ 28483,
+ 28484,
+ 28485,
+ 28486,
+ 28487,
+ 28488,
+ 28489,
+ 28490,
+ 28491,
+ 28492,
+ 28493,
+ 28494,
+ 28495,
+ 28496,
+ 28497,
+ 28498,
+ 28499,
+ 28500,
+ 28501,
+ 28502,
+ 28503,
+ 28504,
+ 28505,
+ 28506,
+ 28507,
+ 28508,
+ 28509,
+ 28510,
+ 28511,
+ 28512,
+ 28513,
+ 28514,
+ 28515,
+ 28516,
+ 28517,
+ 28518,
+ 28519,
+ 28520,
+ 28521,
+ 28522,
+ 28523,
+ 28524,
+ 28525,
+ 28526,
+ 28527,
+ 28528,
+ 28529,
+ 28530,
+ 28531,
+ 28532,
+ 28533,
+ 28534,
+ 28535,
+ 28536,
+ 28537,
+ 28538,
+ 28539,
+ 28540,
+ 28541,
+ 28542,
+ 28543,
+ 28544,
+ 28545,
+ 28546,
+ 28547,
+ 28548,
+ 28549,
+ 28550,
+ 28551,
+ 28552,
+ 28553,
+ 28554,
+ 28555,
+ 28556,
+ 28557,
+ 28558,
+ 28559,
+ 28560,
+ 28561,
+ 28562,
+ 28563,
+ 28564,
+ 28565,
+ 28566,
+ 28567,
+ 28568,
+ 28569,
+ 28570,
+ 28571,
+ 28572,
+ 28573,
+ 28574,
+ 28575,
+ 28576,
+ 28577,
+ 28578,
+ 28579,
+ 28580,
+ 28581,
+ 28582,
+ 28583,
+ 28584,
+ 28585,
+ 28586,
+ 28587,
+ 28588,
+ 28589,
+ 28590,
+ 28591,
+ 28592,
+ 28593,
+ 28594,
+ 28595,
+ 28596,
+ 28597,
+ 28598,
+ 28599,
+ 28600,
+ 28601,
+ 28602,
+ 28603,
+ 28604,
+ 28605,
+ 28606,
+ 28607,
+ 28608,
+ 28609,
+ 28610,
+ 28611,
+ 28612,
+ 28613,
+ 28614,
+ 28615,
+ 28616,
+ 28617,
+ 28618,
+ 28619,
+ 28620,
+ 28621,
+ 28622,
+ 28623,
+ 28624,
+ 28625,
+ 28626,
+ 28627,
+ 28628,
+ 28629,
+ 28630,
+ 28631,
+ 28632,
+ 28633,
+ 28634,
+ 28635,
+ 28636,
+ 28637,
+ 28638,
+ 28639,
+ 28640,
+ 28641,
+ 28642,
+ 28643,
+ 28644,
+ 28645,
+ 28646,
+ 28647,
+ 28648,
+ 28649,
+ 28650,
+ 28651,
+ 28652,
+ 28653,
+ 28654,
+ 28655,
+ 28656,
+ 28657,
+ 28658,
+ 28659,
+ 28660,
+ 28661,
+ 28662,
+ 28663,
+ 28664,
+ 28665,
+ 28666,
+ 28667,
+ 28668,
+ 28669,
+ 28670,
+ 28671,
+ 28672,
+ 28673,
+ 28674,
+ 28675,
+ 28676,
+ 28677,
+ 28678,
+ 28679,
+ 28680,
+ 28681,
+ 28682,
+ 28683,
+ 28684,
+ 28685,
+ 28686,
+ 28687,
+ 28688,
+ 28689,
+ 28690,
+ 28691,
+ 28692,
+ 28693,
+ 28694,
+ 28695,
+ 28696,
+ 28697,
+ 28698,
+ 28699,
+ 28700,
+ 28701,
+ 28702,
+ 28703,
+ 28704,
+ 28705,
+ 28706,
+ 28707,
+ 28708,
+ 28709,
+ 28710,
+ 28711,
+ 28712,
+ 28713,
+ 28714,
+ 28715,
+ 28716,
+ 28717,
+ 28718,
+ 28719,
+ 28720,
+ 28721,
+ 28722,
+ 28723,
+ 28724,
+ 28725,
+ 28726,
+ 28727,
+ 28728,
+ 28729,
+ 28730,
+ 28731,
+ 28732,
+ 28733,
+ 28734,
+ 28735,
+ 28736,
+ 28737,
+ 28738,
+ 28739,
+ 28740,
+ 28741,
+ 28742,
+ 28743,
+ 28744,
+ 28745,
+ 28746,
+ 28747,
+ 28748,
+ 28749,
+ 28750,
+ 28751,
+ 28752,
+ 28753,
+ 28754,
+ 28755,
+ 28756,
+ 28757,
+ 28758,
+ 28759,
+ 28760,
+ 28761,
+ 28762,
+ 28763,
+ 28764,
+ 28765,
+ 28766,
+ 28767,
+ 28768,
+ 28769,
+ 28770,
+ 28771,
+ 28772,
+ 28773,
+ 28774,
+ 28775,
+ 28776,
+ 28777,
+ 28778,
+ 28779,
+ 28780,
+ 28781,
+ 28782,
+ 28783,
+ 28784,
+ 28785,
+ 28786,
+ 28787,
+ 28788,
+ 28789,
+ 28790,
+ 28791,
+ 28792,
+ 28793,
+ 28794,
+ 28795,
+ 28796,
+ 28797,
+ 28798,
+ 28799,
+ 28800,
+ 28801,
+ 28802,
+ 28803,
+ 28804,
+ 28805,
+ 28806,
+ 28807,
+ 28808,
+ 28809,
+ 28810,
+ 28811,
+ 28812,
+ 28813,
+ 28814,
+ 28815,
+ 28816,
+ 28817,
+ 28818,
+ 28819,
+ 28820,
+ 28821,
+ 28822,
+ 28823,
+ 28824,
+ 28825,
+ 28826,
+ 28827,
+ 28828,
+ 28829,
+ 28830,
+ 28831,
+ 28832,
+ 28833,
+ 28834,
+ 28835,
+ 28836,
+ 28837,
+ 28838,
+ 28839,
+ 28840,
+ 28841,
+ 28842,
+ 28843,
+ 28844,
+ 28845,
+ 28846,
+ 28847,
+ 28848,
+ 28849,
+ 28850,
+ 28851,
+ 28852,
+ 28853,
+ 28854,
+ 28855,
+ 28856,
+ 28857,
+ 28858,
+ 28859,
+ 28860,
+ 28861,
+ 28862,
+ 28863,
+ 28864,
+ 28865,
+ 28866,
+ 28867,
+ 28868,
+ 28869,
+ 28870,
+ 28871,
+ 28872,
+ 28873,
+ 28874,
+ 28875,
+ 28876,
+ 28877,
+ 28878,
+ 28879,
+ 28880,
+ 28881,
+ 28882,
+ 28883,
+ 28884,
+ 28885,
+ 28886,
+ 28887,
+ 28888,
+ 28889,
+ 28890,
+ 28891,
+ 28892,
+ 28893,
+ 28894,
+ 28895,
+ 28896,
+ 28897,
+ 28898,
+ 28899,
+ 28900,
+ 28901,
+ 28902,
+ 28903,
+ 28904,
+ 28905,
+ 28906,
+ 28907,
+ 28908,
+ 28909,
+ 28910,
+ 28911,
+ 28912,
+ 28913,
+ 28914,
+ 28915,
+ 28916,
+ 28917,
+ 28918,
+ 28919,
+ 28920,
+ 28921,
+ 28922,
+ 28923,
+ 28924,
+ 28925,
+ 28926,
+ 28927,
+ 28928,
+ 28929,
+ 28930,
+ 28931,
+ 28932,
+ 28933,
+ 28934,
+ 28935,
+ 28936,
+ 28937,
+ 28938,
+ 28939,
+ 28940,
+ 28941,
+ 28942,
+ 28943,
+ 28944,
+ 28945,
+ 28946,
+ 28947,
+ 28948,
+ 28949,
+ 28950,
+ 28951,
+ 28952,
+ 28953,
+ 28954,
+ 28955,
+ 28956,
+ 28957,
+ 28958,
+ 28959,
+ 28960,
+ 28961,
+ 28962,
+ 28963,
+ 28964,
+ 28965,
+ 28966,
+ 28967,
+ 28968,
+ 28969,
+ 28970,
+ 28971,
+ 28972,
+ 28973,
+ 28974,
+ 28975,
+ 28976,
+ 28977,
+ 28978,
+ 28979,
+ 28980,
+ 28981,
+ 28982,
+ 28983,
+ 28984,
+ 28985,
+ 28986,
+ 28987,
+ 28988,
+ 28989,
+ 28990,
+ 28991,
+ 28992,
+ 28993,
+ 28994,
+ 28995,
+ 28996,
+ 28997,
+ 28998,
+ 28999,
+ 29000,
+ 29001,
+ 29002,
+ 29003,
+ 29004,
+ 29005,
+ 29006,
+ 29007,
+ 29008,
+ 29009,
+ 29010,
+ 29011,
+ 29012,
+ 29013,
+ 29014,
+ 29015,
+ 29016,
+ 29017,
+ 29018,
+ 29019,
+ 29020,
+ 29021,
+ 29022,
+ 29023,
+ 29024,
+ 29025,
+ 29026,
+ 29027,
+ 29028,
+ 29029,
+ 29030,
+ 29031,
+ 29032,
+ 29033,
+ 29034,
+ 29035,
+ 29036,
+ 29037,
+ 29038,
+ 29039,
+ 29040,
+ 29041,
+ 29042,
+ 29043,
+ 29044,
+ 29045,
+ 29046,
+ 29047,
+ 29048,
+ 29049,
+ 29050,
+ 29051,
+ 29052,
+ 29053,
+ 29054,
+ 29055,
+ 29056,
+ 29057,
+ 29058,
+ 29059,
+ 29060,
+ 29061,
+ 29062,
+ 29063,
+ 29064,
+ 29065,
+ 29066,
+ 29067,
+ 29068,
+ 29069,
+ 29070,
+ 29071,
+ 29072,
+ 29073,
+ 29074,
+ 29075,
+ 29076,
+ 29077,
+ 29078,
+ 29079,
+ 29080,
+ 29081,
+ 29082,
+ 29083,
+ 29084,
+ 29085,
+ 29086,
+ 29087,
+ 29088,
+ 29089,
+ 29090,
+ 29091,
+ 29092,
+ 29093,
+ 29094,
+ 29095,
+ 29096,
+ 29097,
+ 29098,
+ 29099,
+ 29100,
+ 29101,
+ 29102,
+ 29103,
+ 29104,
+ 29105,
+ 29106,
+ 29107,
+ 29108,
+ 29109,
+ 29110,
+ 29111,
+ 29112,
+ 29113,
+ 29114,
+ 29115,
+ 29116,
+ 29117,
+ 29118,
+ 29119,
+ 29120,
+ 29121,
+ 29122,
+ 29123,
+ 29124,
+ 29125,
+ 29126,
+ 29127,
+ 29128,
+ 29129,
+ 29130,
+ 29131,
+ 29132,
+ 29133,
+ 29134,
+ 29135,
+ 29136,
+ 29137,
+ 29138,
+ 29139,
+ 29140,
+ 29141,
+ 29142,
+ 29143,
+ 29144,
+ 29145,
+ 29146,
+ 29147,
+ 29148,
+ 29149,
+ 29150,
+ 29151,
+ 29152,
+ 29153,
+ 29154,
+ 29155,
+ 29156,
+ 29157,
+ 29158,
+ 29159,
+ 29160,
+ 29161,
+ 29162,
+ 29163,
+ 29164,
+ 29165,
+ 29166,
+ 29167,
+ 29168,
+ 29169,
+ 29170,
+ 29171,
+ 29172,
+ 29173,
+ 29174,
+ 29175,
+ 29176,
+ 29177,
+ 29178,
+ 29179,
+ 29180,
+ 29181,
+ 29182,
+ 29183,
+ 29184,
+ 29185,
+ 29186,
+ 29187,
+ 29188,
+ 29189,
+ 29190,
+ 29191,
+ 29192,
+ 29193,
+ 29194,
+ 29195,
+ 29196,
+ 29197,
+ 29198,
+ 29199,
+ 29200,
+ 29201,
+ 29202,
+ 29203,
+ 29204,
+ 29205,
+ 29206,
+ 29207,
+ 29208,
+ 29209,
+ 29210,
+ 29211,
+ 29212,
+ 29213,
+ 29214,
+ 29215,
+ 29216,
+ 29217,
+ 29218,
+ 29219,
+ 29220,
+ 29221,
+ 29222,
+ 29223,
+ 29224,
+ 29225,
+ 29226,
+ 29227,
+ 29228,
+ 29229,
+ 29230,
+ 29231,
+ 29232,
+ 29233,
+ 29234,
+ 29235,
+ 29236,
+ 29237,
+ 29238,
+ 29239,
+ 29240,
+ 29241,
+ 29242,
+ 29243,
+ 29244,
+ 29245,
+ 29246,
+ 29247,
+ 29248,
+ 29249,
+ 29250,
+ 29251,
+ 29252,
+ 29253,
+ 29254,
+ 29255,
+ 29256,
+ 29257,
+ 29258,
+ 29259,
+ 29260,
+ 29261,
+ 29262,
+ 29263,
+ 29264,
+ 29265,
+ 29266,
+ 29267,
+ 29268,
+ 29269,
+ 29270,
+ 29271,
+ 29272,
+ 29273,
+ 29274,
+ 29275,
+ 29276,
+ 29277,
+ 29278,
+ 29279,
+ 29280,
+ 29281,
+ 29282,
+ 29283,
+ 29284,
+ 29285,
+ 29286,
+ 29287,
+ 29288,
+ 29289,
+ 29290,
+ 29291,
+ 29292,
+ 29293,
+ 29294,
+ 29295,
+ 29296,
+ 29297,
+ 29298,
+ 29299,
+ 29300,
+ 29301,
+ 29302,
+ 29303,
+ 29304,
+ 29305,
+ 29306,
+ 29307,
+ 29308,
+ 29309,
+ 29310,
+ 29311,
+ 29312,
+ 29313,
+ 29314,
+ 29315,
+ 29316,
+ 29317,
+ 29318,
+ 29319,
+ 29320,
+ 29321,
+ 29322,
+ 29323,
+ 29324,
+ 29325,
+ 29326,
+ 29327,
+ 29328,
+ 29329,
+ 29330,
+ 29331,
+ 29332,
+ 29333,
+ 29334,
+ 29335,
+ 29336,
+ 29337,
+ 29338,
+ 29339,
+ 29340,
+ 29341,
+ 29342,
+ 29343,
+ 29344,
+ 29345,
+ 29346,
+ 29347,
+ 29348,
+ 29349,
+ 29350,
+ 29351,
+ 29352,
+ 29353,
+ 29354,
+ 29355,
+ 29356,
+ 29357,
+ 29358,
+ 29359,
+ 29360,
+ 29361,
+ 29362,
+ 29363,
+ 29364,
+ 29365,
+ 29366,
+ 29367,
+ 29368,
+ 29369,
+ 29370,
+ 29371,
+ 29372,
+ 29373,
+ 29374,
+ 29375,
+ 29376,
+ 29377,
+ 29378,
+ 29379,
+ 29380,
+ 29381,
+ 29382,
+ 29383,
+ 29384,
+ 29385,
+ 29386,
+ 29387,
+ 29388,
+ 29389,
+ 29390,
+ 29391,
+ 29392,
+ 29393,
+ 29394,
+ 29395,
+ 29396,
+ 29397,
+ 29398,
+ 29399,
+ 29400,
+ 29401,
+ 29402,
+ 29403,
+ 29404,
+ 29405,
+ 29406,
+ 29407,
+ 29408,
+ 29409,
+ 29410,
+ 29411,
+ 29412,
+ 29413,
+ 29414,
+ 29415,
+ 29416,
+ 29417,
+ 29418,
+ 29419,
+ 29420,
+ 29421,
+ 29422,
+ 29423,
+ 29424,
+ 29425,
+ 29426,
+ 29427,
+ 29428,
+ 29429,
+ 29430,
+ 29431,
+ 29432,
+ 29433,
+ 29434,
+ 29435,
+ 29436,
+ 29437,
+ 29438,
+ 29439,
+ 29440,
+ 29441,
+ 29442,
+ 29443,
+ 29444,
+ 29445,
+ 29446,
+ 29447,
+ 29448,
+ 29449,
+ 29450,
+ 29451,
+ 29452,
+ 29453,
+ 29454,
+ 29455,
+ 29456,
+ 29457,
+ 29458,
+ 29459,
+ 29460,
+ 29461,
+ 29462,
+ 29463,
+ 29464,
+ 29465,
+ 29466,
+ 29467,
+ 29468,
+ 29469,
+ 29470,
+ 29471,
+ 29472,
+ 29473,
+ 29474,
+ 29475,
+ 29476,
+ 29477,
+ 29478,
+ 29479,
+ 29480,
+ 29481,
+ 29482,
+ 29483,
+ 29484,
+ 29485,
+ 29486,
+ 29487,
+ 29488,
+ 29489,
+ 29490,
+ 29491,
+ 29492,
+ 29493,
+ 29494,
+ 29495,
+ 29496,
+ 29497,
+ 29498,
+ 29499,
+ 29500,
+ 29501,
+ 29502,
+ 29503,
+ 29504,
+ 29505,
+ 29506,
+ 29507,
+ 29508,
+ 29509,
+ 29510,
+ 29511,
+ 29512,
+ 29513,
+ 29514,
+ 29515,
+ 29516,
+ 29517,
+ 29518,
+ 29519,
+ 29520,
+ 29521,
+ 29522,
+ 29523,
+ 29524,
+ 29525,
+ 29526,
+ 29527,
+ 29528,
+ 29529,
+ 29530,
+ 29531,
+ 29532,
+ 29533,
+ 29534,
+ 29535,
+ 29536,
+ 29537,
+ 29538,
+ 29539,
+ 29540,
+ 29541,
+ 29542,
+ 29543,
+ 29544,
+ 29545,
+ 29546,
+ 29547,
+ 29548,
+ 29549,
+ 29550,
+ 29551,
+ 29552,
+ 29553,
+ 29554,
+ 29555,
+ 29556,
+ 29557,
+ 29558,
+ 29559,
+ 29560,
+ 29561,
+ 29562,
+ 29563,
+ 29564,
+ 29565,
+ 29566,
+ 29567,
+ 29568,
+ 29569,
+ 29570,
+ 29571,
+ 29572,
+ 29573,
+ 29574,
+ 29575,
+ 29576,
+ 29577,
+ 29578,
+ 29579,
+ 29580,
+ 29581,
+ 29582,
+ 29583,
+ 29584,
+ 29585,
+ 29586,
+ 29587,
+ 29588,
+ 29589,
+ 29590,
+ 29591,
+ 29592,
+ 29593,
+ 29594,
+ 29595,
+ 29596,
+ 29597,
+ 29598,
+ 29599,
+ 29600,
+ 29601,
+ 29602,
+ 29603,
+ 29604,
+ 29605,
+ 29606,
+ 29607,
+ 29608,
+ 29609,
+ 29610,
+ 29611,
+ 29612,
+ 29613,
+ 29614,
+ 29615,
+ 29616,
+ 29617,
+ 29618,
+ 29619,
+ 29620,
+ 29621,
+ 29622,
+ 29623,
+ 29624,
+ 29625,
+ 29626,
+ 29627,
+ 29628,
+ 29629,
+ 29630,
+ 29631,
+ 29632,
+ 29633,
+ 29634,
+ 29635,
+ 29636,
+ 29637,
+ 29638,
+ 29639,
+ 29640,
+ 29641,
+ 29642,
+ 29643,
+ 29644,
+ 29645,
+ 29646,
+ 29647,
+ 29648,
+ 29649,
+ 29650,
+ 29651,
+ 29652,
+ 29653,
+ 29654,
+ 29655,
+ 29656,
+ 29657,
+ 29658,
+ 29659,
+ 29660,
+ 29661,
+ 29662,
+ 29663,
+ 29664,
+ 29665,
+ 29666,
+ 29667,
+ 29668,
+ 29669,
+ 29670,
+ 29671,
+ 29672,
+ 29673,
+ 29674,
+ 29675,
+ 29676,
+ 29677,
+ 29678,
+ 29679,
+ 29680,
+ 29681,
+ 29682,
+ 29683,
+ 29684,
+ 29685,
+ 29686,
+ 29687,
+ 29688,
+ 29689,
+ 29690,
+ 29691,
+ 29692,
+ 29693,
+ 29694,
+ 29695,
+ 29696,
+ 29697,
+ 29698,
+ 29699,
+ 29700,
+ 29701,
+ 29702,
+ 29703,
+ 29704,
+ 29705,
+ 29706,
+ 29707,
+ 29708,
+ 29709,
+ 29710,
+ 29711,
+ 29712,
+ 29713,
+ 29714,
+ 29715,
+ 29716,
+ 29717,
+ 29718,
+ 29719,
+ 29720,
+ 29721,
+ 29722,
+ 29723,
+ 29724,
+ 29725,
+ 29726,
+ 29727,
+ 29728,
+ 29729,
+ 29730,
+ 29731,
+ 29732,
+ 29733,
+ 29734,
+ 29735,
+ 29736,
+ 29737,
+ 29738,
+ 29739,
+ 29740,
+ 29741,
+ 29742,
+ 29743,
+ 29744,
+ 29745,
+ 29746,
+ 29747,
+ 29748,
+ 29749,
+ 29750,
+ 29751,
+ 29752,
+ 29753,
+ 29754,
+ 29755,
+ 29756,
+ 29757,
+ 29758,
+ 29759,
+ 29760,
+ 29761,
+ 29762,
+ 29763,
+ 29764,
+ 29765,
+ 29766,
+ 29767,
+ 29768,
+ 29769,
+ 29770,
+ 29771,
+ 29772,
+ 29773,
+ 29774,
+ 29775,
+ 29776,
+ 29777,
+ 29778,
+ 29779,
+ 29780,
+ 29781,
+ 29782,
+ 29783,
+ 29784,
+ 29785,
+ 29786,
+ 29787,
+ 29788,
+ 29789,
+ 29790,
+ 29791,
+ 29792,
+ 29793,
+ 29794,
+ 29795,
+ 29796,
+ 29797,
+ 29798,
+ 29799,
+ 29800,
+ 29801,
+ 29802,
+ 29803,
+ 29804,
+ 29805,
+ 29806,
+ 29807,
+ 29808,
+ 29809,
+ 29810,
+ 29811,
+ 29812,
+ 29813,
+ 29814,
+ 29815,
+ 29816,
+ 29817,
+ 29818,
+ 29819,
+ 29820,
+ 29821,
+ 29822,
+ 29823,
+ 29824,
+ 29825,
+ 29826,
+ 29827,
+ 29828,
+ 29829,
+ 29830,
+ 29831,
+ 29832,
+ 29833,
+ 29834,
+ 29835,
+ 29836,
+ 29837,
+ 29838,
+ 29839,
+ 29840,
+ 29841,
+ 29842,
+ 29843,
+ 29844,
+ 29845,
+ 29846,
+ 29847,
+ 29848,
+ 29849,
+ 29850,
+ 29851,
+ 29852,
+ 29853,
+ 29854,
+ 29855,
+ 29856,
+ 29857,
+ 29858,
+ 29859,
+ 29860,
+ 29861,
+ 29862,
+ 29863,
+ 29864,
+ 29865,
+ 29866,
+ 29867,
+ 29868,
+ 29869,
+ 29870,
+ 29871,
+ 29872,
+ 29873,
+ 29874,
+ 29875,
+ 29876,
+ 29877,
+ 29878,
+ 29879,
+ 29880,
+ 29881,
+ 29882,
+ 29883,
+ 29884,
+ 29885,
+ 29886,
+ 29887,
+ 29888,
+ 29889,
+ 29890,
+ 29891,
+ 29892,
+ 29893,
+ 29894,
+ 29895,
+ 29896,
+ 29897,
+ 29898,
+ 29899,
+ 29900,
+ 29901,
+ 29902,
+ 29903,
+ 29904,
+ 29905,
+ 29906,
+ 29907,
+ 29908,
+ 29909,
+ 29910,
+ 29911,
+ 29912,
+ 29913,
+ 29914,
+ 29915,
+ 29916,
+ 29917,
+ 29918,
+ 29919,
+ 29920,
+ 29921,
+ 29922,
+ 29923,
+ 29924,
+ 29925,
+ 29926,
+ 29927,
+ 29928,
+ 29929,
+ 29930,
+ 29931,
+ 29932,
+ 29933,
+ 29934,
+ 29935,
+ 29936,
+ 29937,
+ 29938,
+ 29939,
+ 29940,
+ 29941,
+ 29942,
+ 29943,
+ 29944,
+ 29945,
+ 29946,
+ 29947,
+ 29948,
+ 29949,
+ 29950,
+ 29951,
+ 29952,
+ 29953,
+ 29954,
+ 29955,
+ 29956,
+ 29957,
+ 29958,
+ 29959,
+ 29960,
+ 29961,
+ 29962,
+ 29963,
+ 29964,
+ 29965,
+ 29966,
+ 29967,
+ 29968,
+ 29969,
+ 29970,
+ 29971,
+ 29972,
+ 29973,
+ 29974,
+ 29975,
+ 29976,
+ 29977,
+ 29978,
+ 29979,
+ 29980,
+ 29981,
+ 29982,
+ 29983,
+ 29984,
+ 29985,
+ 29986,
+ 29987,
+ 29988,
+ 29989,
+ 29990,
+ 29991,
+ 29992,
+ 29993,
+ 29994,
+ 29995,
+ 29996,
+ 29997,
+ 29998,
+ 29999,
+ 30000,
+ 30001,
+ 30002,
+ 30003,
+ 30004,
+ 30005,
+ 30006,
+ 30007,
+ 30008,
+ 30009,
+ 30010,
+ 30011,
+ 30012,
+ 30013,
+ 30014,
+ 30015,
+ 30016,
+ 30017,
+ 30018,
+ 30019,
+ 30020,
+ 30021,
+ 30022,
+ 30023,
+ 30024,
+ 30025,
+ 30026,
+ 30027,
+ 30028,
+ 30029,
+ 30030,
+ 30031,
+ 30032,
+ 30033,
+ 30034,
+ 30035,
+ 30036,
+ 30037,
+ 30038,
+ 30039,
+ 30040,
+ 30041,
+ 30042,
+ 30043,
+ 30044,
+ 30045,
+ 30046,
+ 30047,
+ 30048,
+ 30049,
+ 30050,
+ 30051,
+ 30052,
+ 30053,
+ 30054,
+ 30055,
+ 30056,
+ 30057,
+ 30058,
+ 30059,
+ 30060,
+ 30061,
+ 30062,
+ 30063,
+ 30064,
+ 30065,
+ 30066,
+ 30067,
+ 30068,
+ 30069,
+ 30070,
+ 30071,
+ 30072,
+ 30073,
+ 30074,
+ 30075,
+ 30076,
+ 30077,
+ 30078,
+ 30079,
+ 30080,
+ 30081,
+ 30082,
+ 30083,
+ 30084,
+ 30085,
+ 30086,
+ 30087,
+ 30088,
+ 30089,
+ 30090,
+ 30091,
+ 30092,
+ 30093,
+ 30094,
+ 30095,
+ 30096,
+ 30097,
+ 30098,
+ 30099,
+ 30100,
+ 30101,
+ 30102,
+ 30103,
+ 30104,
+ 30105,
+ 30106,
+ 30107,
+ 30108,
+ 30109,
+ 30110,
+ 30111,
+ 30112,
+ 30113,
+ 30114,
+ 30115,
+ 30116,
+ 30117,
+ 30118,
+ 30119,
+ 30120,
+ 30121,
+ 30122,
+ 30123,
+ 30124,
+ 30125,
+ 30126,
+ 30127,
+ 30128,
+ 30129,
+ 30130,
+ 30131,
+ 30132,
+ 30133,
+ 30134,
+ 30135,
+ 30136,
+ 30137,
+ 30138,
+ 30139,
+ 30140,
+ 30141,
+ 30142,
+ 30143,
+ 30144,
+ 30145,
+ 30146,
+ 30147,
+ 30148,
+ 30149,
+ 30150,
+ 30151,
+ 30152,
+ 30153,
+ 30154,
+ 30155,
+ 30156,
+ 30157,
+ 30158,
+ 30159,
+ 30160,
+ 30161,
+ 30162,
+ 30163,
+ 30164,
+ 30165,
+ 30166,
+ 30167,
+ 30168,
+ 30169,
+ 30170,
+ 30171,
+ 30172,
+ 30173,
+ 30174,
+ 30175,
+ 30176,
+ 30177,
+ 30178,
+ 30179,
+ 30180,
+ 30181,
+ 30182,
+ 30183,
+ 30184,
+ 30185,
+ 30186,
+ 30187,
+ 30188,
+ 30189,
+ 30190,
+ 30191,
+ 30192,
+ 30193,
+ 30194,
+ 30195,
+ 30196,
+ 30197,
+ 30198,
+ 30199,
+ 30200,
+ 30201,
+ 30202,
+ 30203,
+ 30204,
+ 30205,
+ 30206,
+ 30207,
+ 30208,
+ 30209,
+ 30210,
+ 30211,
+ 30212,
+ 30213,
+ 30214,
+ 30215,
+ 30216,
+ 30217,
+ 30218,
+ 30219,
+ 30220,
+ 30221,
+ 30222,
+ 30223,
+ 30224,
+ 30225,
+ 30226,
+ 30227,
+ 30228,
+ 30229,
+ 30230,
+ 30231,
+ 30232,
+ 30233,
+ 30234,
+ 30235,
+ 30236,
+ 30237,
+ 30238,
+ 30239,
+ 30240,
+ 30241,
+ 30242,
+ 30243,
+ 30244,
+ 30245,
+ 30246,
+ 30247,
+ 30248,
+ 30249,
+ 30250,
+ 30251,
+ 30252,
+ 30253,
+ 30254,
+ 30255,
+ 30256,
+ 30257,
+ 30258,
+ 30259,
+ 30260,
+ 30261,
+ 30262,
+ 30263,
+ 30264,
+ 30265,
+ 30266,
+ 30267,
+ 30268,
+ 30269,
+ 30270,
+ 30271,
+ 30272,
+ 30273,
+ 30274,
+ 30275,
+ 30276,
+ 30277,
+ 30278,
+ 30279,
+ 30280,
+ 30281,
+ 30282,
+ 30283,
+ 30284,
+ 30285,
+ 30286,
+ 30287,
+ 30288,
+ 30289,
+ 30290,
+ 30291,
+ 30292,
+ 30293,
+ 30294,
+ 30295,
+ 30296,
+ 30297,
+ 30298,
+ 30299,
+ 30300,
+ 30301,
+ 30302,
+ 30303,
+ 30304,
+ 30305,
+ 30306,
+ 30307,
+ 30308,
+ 30309,
+ 30310,
+ 30311,
+ 30312,
+ 30313,
+ 30314,
+ 30315,
+ 30316,
+ 30317,
+ 30318,
+ 30319,
+ 30320,
+ 30321,
+ 30322,
+ 30323,
+ 30324,
+ 30325,
+ 30326,
+ 30327,
+ 30328,
+ 30329,
+ 30330,
+ 30331,
+ 30332,
+ 30333,
+ 30334,
+ 30335,
+ 30336,
+ 30337,
+ 30338,
+ 30339,
+ 30340,
+ 30341,
+ 30342,
+ 30343,
+ 30344,
+ 30345,
+ 30346,
+ 30347,
+ 30348,
+ 30349,
+ 30350,
+ 30351,
+ 30352,
+ 30353,
+ 30354,
+ 30355,
+ 30356,
+ 30357,
+ 30358,
+ 30359,
+ 30360,
+ 30361,
+ 30362,
+ 30363,
+ 30364,
+ 30365,
+ 30366,
+ 30367,
+ 30368,
+ 30369,
+ 30370,
+ 30371,
+ 30372,
+ 30373,
+ 30374,
+ 30375,
+ 30376,
+ 30377,
+ 30378,
+ 30379,
+ 30380,
+ 30381,
+ 30382,
+ 30383,
+ 30384,
+ 30385,
+ 30386,
+ 30387,
+ 30388,
+ 30389,
+ 30390,
+ 30391,
+ 30392,
+ 30393,
+ 30394,
+ 30395,
+ 30396,
+ 30397,
+ 30398,
+ 30399,
+ 30400,
+ 30401,
+ 30402,
+ 30403,
+ 30404,
+ 30405,
+ 30406,
+ 30407,
+ 30408,
+ 30409,
+ 30410,
+ 30411,
+ 30412,
+ 30413,
+ 30414,
+ 30415,
+ 30416,
+ 30417,
+ 30418,
+ 30419,
+ 30420,
+ 30421,
+ 30422,
+ 30423,
+ 30424,
+ 30425,
+ 30426,
+ 30427,
+ 30428,
+ 30429,
+ 30430,
+ 30431,
+ 30432,
+ 30433,
+ 30434,
+ 30435,
+ 30436,
+ 30437,
+ 30438,
+ 30439,
+ 30440,
+ 30441,
+ 30442,
+ 30443,
+ 30444,
+ 30445,
+ 30446,
+ 30447,
+ 30448,
+ 30449,
+ 30450,
+ 30451,
+ 30452,
+ 30453,
+ 30454,
+ 30455,
+ 30456,
+ 30457,
+ 30458,
+ 30459,
+ 30460,
+ 30461,
+ 30462,
+ 30463,
+ 30464,
+ 30465,
+ 30466,
+ 30467,
+ 30468,
+ 30469,
+ 30470,
+ 30471,
+ 30472,
+ 30473,
+ 30474,
+ 30475,
+ 30476,
+ 30477,
+ 30478,
+ 30479,
+ 30480,
+ 30481,
+ 30482,
+ 30483,
+ 30484,
+ 30485,
+ 30486,
+ 30487,
+ 30488,
+ 30489,
+ 30490,
+ 30491,
+ 30492,
+ 30493,
+ 30494,
+ 30495,
+ 30496,
+ 30497,
+ 30498,
+ 30499,
+ 30500,
+ 30501,
+ 30502,
+ 30503,
+ 30504,
+ 30505,
+ 30506,
+ 30507,
+ 30508,
+ 30509,
+ 30510,
+ 30511,
+ 30512,
+ 30513,
+ 30514,
+ 30515,
+ 30516,
+ 30517,
+ 30518,
+ 30519,
+ 30520,
+ 30521,
+ 30522,
+ 30523,
+ 30524,
+ 30525,
+ 30526,
+ 30527,
+ 30528,
+ 30529,
+ 30530,
+ 30531,
+ 30532,
+ 30533,
+ 30534,
+ 30535,
+ 30536,
+ 30537,
+ 30538,
+ 30539,
+ 30540,
+ 30541,
+ 30542,
+ 30543,
+ 30544,
+ 30545,
+ 30546,
+ 30547,
+ 30548,
+ 30549,
+ 30550,
+ 30551,
+ 30552,
+ 30553,
+ 30554,
+ 30555,
+ 30556,
+ 30557,
+ 30558,
+ 30559,
+ 30560,
+ 30561,
+ 30562,
+ 30563,
+ 30564,
+ 30565,
+ 30566,
+ 30567,
+ 30568,
+ 30569,
+ 30570,
+ 30571,
+ 30572,
+ 30573,
+ 30574,
+ 30575,
+ 30576,
+ 30577,
+ 30578,
+ 30579,
+ 30580,
+ 30581,
+ 30582,
+ 30583,
+ 30584,
+ 30585,
+ 30586,
+ 30587,
+ 30588,
+ 30589,
+ 30590,
+ 30591,
+ 30592,
+ 30593,
+ 30594,
+ 30595,
+ 30596,
+ 30597,
+ 30598,
+ 30599,
+ 30600,
+ 30601,
+ 30602,
+ 30603,
+ 30604,
+ 30605,
+ 30606,
+ 30607,
+ 30608,
+ 30609,
+ 30610,
+ 30611,
+ 30612,
+ 30613,
+ 30614,
+ 30615,
+ 30616,
+ 30617,
+ 30618,
+ 30619,
+ 30620,
+ 30621,
+ 30622,
+ 30623,
+ 30624,
+ 30625,
+ 30626,
+ 30627,
+ 30628,
+ 30629,
+ 30630,
+ 30631,
+ 30632,
+ 30633,
+ 30634,
+ 30635,
+ 30636,
+ 30637,
+ 30638,
+ 30639,
+ 30640,
+ 30641,
+ 30642,
+ 30643,
+ 30644,
+ 30645,
+ 30646,
+ 30647,
+ 30648,
+ 30649,
+ 30650,
+ 30651,
+ 30652,
+ 30653,
+ 30654,
+ 30655,
+ 30656,
+ 30657,
+ 30658,
+ 30659,
+ 30660,
+ 30661,
+ 30662,
+ 30663,
+ 30664,
+ 30665,
+ 30666,
+ 30667,
+ 30668,
+ 30669,
+ 30670,
+ 30671,
+ 30672,
+ 30673,
+ 30674,
+ 30675,
+ 30676,
+ 30677,
+ 30678,
+ 30679,
+ 30680,
+ 30681,
+ 30682,
+ 30683,
+ 30684,
+ 30685,
+ 30686,
+ 30687,
+ 30688,
+ 30689,
+ 30690,
+ 30691,
+ 30692,
+ 30693,
+ 30694,
+ 30695,
+ 30696,
+ 30697,
+ 30698,
+ 30699,
+ 30700,
+ 30701,
+ 30702,
+ 30703,
+ 30704,
+ 30705,
+ 30706,
+ 30707,
+ 30708,
+ 30709,
+ 30710,
+ 30711,
+ 30712,
+ 30713,
+ 30714,
+ 30715,
+ 30716,
+ 30717,
+ 30718,
+ 30719,
+ 30720,
+ 30721,
+ 30722,
+ 30723,
+ 30724,
+ 30725,
+ 30726,
+ 30727,
+ 30728,
+ 30729,
+ 30730,
+ 30731,
+ 30732,
+ 30733,
+ 30734,
+ 30735,
+ 30736,
+ 30737,
+ 30738,
+ 30739,
+ 30740,
+ 30741,
+ 30742,
+ 30743,
+ 30744,
+ 30745,
+ 30746,
+ 30747,
+ 30748,
+ 30749,
+ 30750,
+ 30751,
+ 30752,
+ 30753,
+ 30754,
+ 30755,
+ 30756,
+ 30757,
+ 30758,
+ 30759,
+ 30760,
+ 30761,
+ 30762,
+ 30763,
+ 30764,
+ 30765,
+ 30766,
+ 30767,
+ 30768,
+ 30769,
+ 30770,
+ 30771,
+ 30772,
+ 30773,
+ 30774,
+ 30775,
+ 30776,
+ 30777,
+ 30778,
+ 30779,
+ 30780,
+ 30781,
+ 30782,
+ 30783,
+ 30784,
+ 30785,
+ 30786,
+ 30787,
+ 30788,
+ 30789,
+ 30790,
+ 30791,
+ 30792,
+ 30793,
+ 30794,
+ 30795,
+ 30796,
+ 30797,
+ 30798,
+ 30799,
+ 30800,
+ 30801,
+ 30802,
+ 30803,
+ 30804,
+ 30805,
+ 30806,
+ 30807,
+ 30808,
+ 30809,
+ 30810,
+ 30811,
+ 30812,
+ 30813,
+ 30814,
+ 30815,
+ 30816,
+ 30817,
+ 30818,
+ 30819,
+ 30820,
+ 30821,
+ 30822,
+ 30823,
+ 30824,
+ 30825,
+ 30826,
+ 30827,
+ 30828,
+ 30829,
+ 30830,
+ 30831,
+ 30832,
+ 30833,
+ 30834,
+ 30835,
+ 30836,
+ 30837,
+ 30838,
+ 30839,
+ 30840,
+ 30841,
+ 30842,
+ 30843,
+ 30844,
+ 30845,
+ 30846,
+ 30847,
+ 30848,
+ 30849,
+ 30850,
+ 30851,
+ 30852,
+ 30853,
+ 30854,
+ 30855,
+ 30856,
+ 30857,
+ 30858,
+ 30859,
+ 30860,
+ 30861,
+ 30862,
+ 30863,
+ 30864,
+ 30865,
+ 30866,
+ 30867,
+ 30868,
+ 30869,
+ 30870,
+ 30871,
+ 30872,
+ 30873,
+ 30874,
+ 30875,
+ 30876,
+ 30877,
+ 30878,
+ 30879,
+ 30880,
+ 30881,
+ 30882,
+ 30883,
+ 30884,
+ 30885,
+ 30886,
+ 30887,
+ 30888,
+ 30889,
+ 30890,
+ 30891,
+ 30892,
+ 30893,
+ 30894,
+ 30895,
+ 30896,
+ 30897,
+ 30898,
+ 30899,
+ 30900,
+ 30901,
+ 30902,
+ 30903,
+ 30904,
+ 30905,
+ 30906,
+ 30907,
+ 30908,
+ 30909,
+ 30910,
+ 30911,
+ 30912,
+ 30913,
+ 30914,
+ 30915,
+ 30916,
+ 30917,
+ 30918,
+ 30919,
+ 30920,
+ 30921,
+ 30922,
+ 30923,
+ 30924,
+ 30925,
+ 30926,
+ 30927,
+ 30928,
+ 30929,
+ 30930,
+ 30931,
+ 30932,
+ 30933,
+ 30934,
+ 30935,
+ 30936,
+ 30937,
+ 30938,
+ 30939,
+ 30940,
+ 30941,
+ 30942,
+ 30943,
+ 30944,
+ 30945,
+ 30946,
+ 30947,
+ 30948,
+ 30949,
+ 30950,
+ 30951,
+ 30952,
+ 30953,
+ 30954,
+ 30955,
+ 30956,
+ 30957,
+ 30958,
+ 30959,
+ 30960,
+ 30961,
+ 30962,
+ 30963,
+ 30964,
+ 30965,
+ 30966,
+ 30967,
+ 30968,
+ 30969,
+ 30970,
+ 30971,
+ 30972,
+ 30973,
+ 30974,
+ 30975,
+ 30976,
+ 30977,
+ 30978,
+ 30979,
+ 30980,
+ 30981,
+ 30982,
+ 30983,
+ 30984,
+ 30985,
+ 30986,
+ 30987,
+ 30988,
+ 30989,
+ 30990,
+ 30991,
+ 30992,
+ 30993,
+ 30994,
+ 30995,
+ 30996,
+ 30997,
+ 30998,
+ 30999,
+ 31000,
+ 31001,
+ 31002,
+ 31003,
+ 31004,
+ 31005,
+ 31006,
+ 31007,
+ 31008,
+ 31009,
+ 31010,
+ 31011,
+ 31012,
+ 31013,
+ 31014,
+ 31015,
+ 31016,
+ 31017,
+ 31018,
+ 31019,
+ 31020,
+ 31021,
+ 31022,
+ 31023,
+ 31024,
+ 31025,
+ 31026,
+ 31027,
+ 31028,
+ 31029,
+ 31030,
+ 31031,
+ 31032,
+ 31033,
+ 31034,
+ 31035,
+ 31036,
+ 31037,
+ 31038,
+ 31039,
+ 31040,
+ 31041,
+ 31042,
+ 31043,
+ 31044,
+ 31045,
+ 31046,
+ 31047,
+ 31048,
+ 31049,
+ 31050,
+ 31051,
+ 31052,
+ 31053,
+ 31054,
+ 31055,
+ 31056,
+ 31057,
+ 31058,
+ 31059,
+ 31060,
+ 31061,
+ 31062,
+ 31063,
+ 31064,
+ 31065,
+ 31066,
+ 31067,
+ 31068,
+ 31069,
+ 31070,
+ 31071,
+ 31072,
+ 31073,
+ 31074,
+ 31075,
+ 31076,
+ 31077,
+ 31078,
+ 31079,
+ 31080,
+ 31081,
+ 31082,
+ 31083,
+ 31084,
+ 31085,
+ 31086,
+ 31087,
+ 31088,
+ 31089,
+ 31090,
+ 31091,
+ 31092,
+ 31093,
+ 31094,
+ 31095,
+ 31096,
+ 31097,
+ 31098,
+ 31099,
+ 31100,
+ 31101,
+ 31102,
+ 31103,
+ 31104,
+ 31105,
+ 31106,
+ 31107,
+ 31108,
+ 31109,
+ 31110,
+ 31111,
+ 31112,
+ 31113,
+ 31114,
+ 31115,
+ 31116,
+ 31117,
+ 31118,
+ 31119,
+ 31120,
+ 31121,
+ 31122,
+ 31123,
+ 31124,
+ 31125,
+ 31126,
+ 31127,
+ 31128,
+ 31129,
+ 31130,
+ 31131,
+ 31132,
+ 31133,
+ 31134,
+ 31135,
+ 31136,
+ 31137,
+ 31138,
+ 31139,
+ 31140,
+ 31141,
+ 31142,
+ 31143,
+ 31144,
+ 31145,
+ 31146,
+ 31147,
+ 31148,
+ 31149,
+ 31150,
+ 31151,
+ 31152,
+ 31153,
+ 31154,
+ 31155,
+ 31156,
+ 31157,
+ 31158,
+ 31159,
+ 31160,
+ 31161,
+ 31162,
+ 31163,
+ 31164,
+ 31165,
+ 31166,
+ 31167,
+ 31168,
+ 31169,
+ 31170,
+ 31171,
+ 31172,
+ 31173,
+ 31174,
+ 31175,
+ 31176,
+ 31177,
+ 31178,
+ 31179,
+ 31180,
+ 31181,
+ 31182,
+ 31183,
+ 31184,
+ 31185,
+ 31186,
+ 31187,
+ 31188,
+ 31189,
+ 31190,
+ 31191,
+ 31192,
+ 31193,
+ 31194,
+ 31195,
+ 31196,
+ 31197,
+ 31198,
+ 31199,
+ 31200,
+ 31201,
+ 31202,
+ 31203,
+ 31204,
+ 31205,
+ 31206,
+ 31207,
+ 31208,
+ 31209,
+ 31210,
+ 31211,
+ 31212,
+ 31213,
+ 31214,
+ 31215,
+ 31216,
+ 31217,
+ 31218,
+ 31219,
+ 31220,
+ 31221,
+ 31222,
+ 31223,
+ 31224,
+ 31225,
+ 31226,
+ 31227,
+ 31228,
+ 31229,
+ 31230,
+ 31231,
+ 31232,
+ 31233,
+ 31234,
+ 31235,
+ 31236,
+ 31237,
+ 31238,
+ 31239,
+ 31240,
+ 31241,
+ 31242,
+ 31243,
+ 31244,
+ 31245,
+ 31246,
+ 31247,
+ 31248,
+ 31249,
+ 31250,
+ 31251,
+ 31252,
+ 31253,
+ 31254,
+ 31255,
+ 31256,
+ 31257,
+ 31258,
+ 31259,
+ 31260,
+ 31261,
+ 31262,
+ 31263,
+ 31264,
+ 31265,
+ 31266,
+ 31267,
+ 31268,
+ 31269,
+ 31270,
+ 31271,
+ 31272,
+ 31273,
+ 31274,
+ 31275,
+ 31276,
+ 31277,
+ 31278,
+ 31279,
+ 31280,
+ 31281,
+ 31282,
+ 31283,
+ 31284,
+ 31285,
+ 31286,
+ 31287,
+ 31288,
+ 31289,
+ 31290,
+ 31291,
+ 31292,
+ 31293,
+ 31294,
+ 31295,
+ 31296,
+ 31297,
+ 31298,
+ 31299,
+ 31300,
+ 31301,
+ 31302,
+ 31303,
+ 31304,
+ 31305,
+ 31306,
+ 31307,
+ 31308,
+ 31309,
+ 31310,
+ 31311,
+ 31312,
+ 31313,
+ 31314,
+ 31315,
+ 31316,
+ 31317,
+ 31318,
+ 31319,
+ 31320,
+ 31321,
+ 31322,
+ 31323,
+ 31324,
+ 31325,
+ 31326,
+ 31327,
+ 31328,
+ 31329,
+ 31330,
+ 31331,
+ 31332,
+ 31333,
+ 31334,
+ 31335,
+ 31336,
+ 31337,
+ 31338,
+ 31339,
+ 31340,
+ 31341,
+ 31342,
+ 31343,
+ 31344,
+ 31345,
+ 31346,
+ 31347,
+ 31348,
+ 31349,
+ 31350,
+ 31351,
+ 31352,
+ 31353,
+ 31354,
+ 31355,
+ 31356,
+ 31357,
+ 31358,
+ 31359,
+ 31360,
+ 31361,
+ 31362,
+ 31363,
+ 31364,
+ 31365,
+ 31366,
+ 31367,
+ 31368,
+ 31369,
+ 31370,
+ 31371,
+ 31372,
+ 31373,
+ 31374,
+ 31375,
+ 31376,
+ 31377,
+ 31378,
+ 31379,
+ 31380,
+ 31381,
+ 31382,
+ 31383,
+ 31384,
+ 31385,
+ 31386,
+ 31387,
+ 31388,
+ 31389,
+ 31390,
+ 31391,
+ 31392,
+ 31393,
+ 31394,
+ 31395,
+ 31396,
+ 31397,
+ 31398,
+ 31399,
+ 31400,
+ 31401,
+ 31402,
+ 31403,
+ 31404,
+ 31405,
+ 31406,
+ 31407,
+ 31408,
+ 31409,
+ 31410,
+ 31411,
+ 31412,
+ 31413,
+ 31414,
+ 31415,
+ 31416,
+ 31417,
+ 31418,
+ 31419,
+ 31420,
+ 31421,
+ 31422,
+ 31423,
+ 31424,
+ 31425,
+ 31426,
+ 31427,
+ 31428,
+ 31429,
+ 31430,
+ 31431,
+ 31432,
+ 31433,
+ 31434,
+ 31435,
+ 31436,
+ 31437,
+ 31438,
+ 31439,
+ 31440,
+ 31441,
+ 31442,
+ 31443,
+ 31444,
+ 31445,
+ 31446,
+ 31447,
+ 31448,
+ 31449,
+ 31450,
+ 31451,
+ 31452,
+ 31453,
+ 31454,
+ 31455,
+ 31456,
+ 31457,
+ 31458,
+ 31459,
+ 31460,
+ 31461,
+ 31462,
+ 31463,
+ 31464,
+ 31465,
+ 31466,
+ 31467,
+ 31468,
+ 31469,
+ 31470,
+ 31471,
+ 31472,
+ 31473,
+ 31474,
+ 31475,
+ 31476,
+ 31477,
+ 31478,
+ 31479,
+ 31480,
+ 31481,
+ 31482,
+ 31483,
+ 31484,
+ 31485,
+ 31486,
+ 31487,
+ 31488,
+ 31489,
+ 31490,
+ 31491,
+ 31492,
+ 31493,
+ 31494,
+ 31495,
+ 31496,
+ 31497,
+ 31498,
+ 31499,
+ 31500,
+ 31501,
+ 31502,
+ 31503,
+ 31504,
+ 31505,
+ 31506,
+ 31507,
+ 31508,
+ 31509,
+ 31510,
+ 31511,
+ 31512,
+ 31513,
+ 31514,
+ 31515,
+ 31516,
+ 31517,
+ 31518,
+ 31519,
+ 31520,
+ 31521,
+ 31522,
+ 31523,
+ 31524,
+ 31525,
+ 31526,
+ 31527,
+ 31528,
+ 31529,
+ 31530,
+ 31531,
+ 31532,
+ 31533,
+ 31534,
+ 31535,
+ 31536,
+ 31537,
+ 31538,
+ 31539,
+ 31540,
+ 31541,
+ 31542,
+ 31543,
+ 31544,
+ 31545,
+ 31546,
+ 31547,
+ 31548,
+ 31549,
+ 31550,
+ 31551,
+ 31552,
+ 31553,
+ 31554,
+ 31555,
+ 31556,
+ 31557,
+ 31558,
+ 31559,
+ 31560,
+ 31561,
+ 31562,
+ 31563,
+ 31564,
+ 31565,
+ 31566,
+ 31567,
+ 31568,
+ 31569,
+ 31570,
+ 31571,
+ 31572,
+ 31573,
+ 31574,
+ 31575,
+ 31576,
+ 31577,
+ 31578,
+ 31579,
+ 31580,
+ 31581,
+ 31582,
+ 31583,
+ 31584,
+ 31585,
+ 31586,
+ 31587,
+ 31588,
+ 31589,
+ 31590,
+ 31591,
+ 31592,
+ 31593,
+ 31594,
+ 31595,
+ 31596,
+ 31597,
+ 31598,
+ 31599,
+ 31600,
+ 31601,
+ 31602,
+ 31603,
+ 31604,
+ 31605,
+ 31606,
+ 31607,
+ 31608,
+ 31609,
+ 31610,
+ 31611,
+ 31612,
+ 31613,
+ 31614,
+ 31615,
+ 31616,
+ 31617,
+ 31618,
+ 31619,
+ 31620,
+ 31621,
+ 31622,
+ 31623,
+ 31624,
+ 31625,
+ 31626,
+ 31627,
+ 31628,
+ 31629,
+ 31630,
+ 31631,
+ 31632,
+ 31633,
+ 31634,
+ 31635,
+ 31636,
+ 31637,
+ 31638,
+ 31639,
+ 31640,
+ 31641,
+ 31642,
+ 31643,
+ 31644,
+ 31645,
+ 31646,
+ 31647,
+ 31648,
+ 31649,
+ 31650,
+ 31651,
+ 31652,
+ 31653,
+ 31654,
+ 31655,
+ 31656,
+ 31657,
+ 31658,
+ 31659,
+ 31660,
+ 31661,
+ 31662,
+ 31663,
+ 31664,
+ 31665,
+ 31666,
+ 31667,
+ 31668,
+ 31669,
+ 31670,
+ 31671,
+ 31672,
+ 31673,
+ 31674,
+ 31675,
+ 31676,
+ 31677,
+ 31678,
+ 31679,
+ 31680,
+ 31681,
+ 31682,
+ 31683,
+ 31684,
+ 31685,
+ 31686,
+ 31687,
+ 31688,
+ 31689,
+ 31690,
+ 31691,
+ 31692,
+ 31693,
+ 31694,
+ 31695,
+ 31696,
+ 31697,
+ 31698,
+ 31699,
+ 31700,
+ 31701,
+ 31702,
+ 31703,
+ 31704,
+ 31705,
+ 31706,
+ 31707,
+ 31708,
+ 31709,
+ 31710,
+ 31711,
+ 31712,
+ 31713,
+ 31714,
+ 31715,
+ 31716,
+ 31717,
+ 31718,
+ 31719,
+ 31720,
+ 31721,
+ 31722,
+ 31723,
+ 31724,
+ 31725,
+ 31726,
+ 31727,
+ 31728,
+ 31729,
+ 31730,
+ 31731,
+ 31732,
+ 31733,
+ 31734,
+ 31735,
+ 31736,
+ 31737,
+ 31738,
+ 31739,
+ 31740,
+ 31741,
+ 31742,
+ 31743,
+ 31744,
+ 31745,
+ 31746,
+ 31747,
+ 31748,
+ 31749,
+ 31750,
+ 31751,
+ 31752,
+ 31753,
+ 31754,
+ 31755,
+ 31756,
+ 31757,
+ 31758,
+ 31759,
+ 31760,
+ 31761,
+ 31762,
+ 31763,
+ 31764,
+ 31765,
+ 31766,
+ 31767,
+ 31768,
+ 31769,
+ 31770,
+ 31771,
+ 31772,
+ 31773,
+ 31774,
+ 31775,
+ 31776,
+ 31777,
+ 31778,
+ 31779,
+ 31780,
+ 31781,
+ 31782,
+ 31783,
+ 31784,
+ 31785,
+ 31786,
+ 31787,
+ 31788,
+ 31789,
+ 31790,
+ 31791,
+ 31792,
+ 31793,
+ 31794,
+ 31795,
+ 31796,
+ 31797,
+ 31798,
+ 31799,
+ 31800,
+ 31801,
+ 31802,
+ 31803,
+ 31804,
+ 31805,
+ 31806,
+ 31807,
+ 31808,
+ 31809,
+ 31810,
+ 31811,
+ 31812,
+ 31813,
+ 31814,
+ 31815,
+ 31816,
+ 31817,
+ 31818,
+ 31819,
+ 31820,
+ 31821,
+ 31822,
+ 31823,
+ 31824,
+ 31825,
+ 31826,
+ 31827,
+ 31828,
+ 31829,
+ 31830,
+ 31831,
+ 31832,
+ 31833,
+ 31834,
+ 31835,
+ 31836,
+ 31837,
+ 31838,
+ 31839,
+ 31840,
+ 31841,
+ 31842,
+ 31843,
+ 31844,
+ 31845,
+ 31846,
+ 31847,
+ 31848,
+ 31849,
+ 31850,
+ 31851,
+ 31852,
+ 31853,
+ 31854,
+ 31855,
+ 31856,
+ 31857,
+ 31858,
+ 31859,
+ 31860,
+ 31861,
+ 31862,
+ 31863,
+ 31864,
+ 31865,
+ 31866,
+ 31867,
+ 31868,
+ 31869,
+ 31870,
+ 31871,
+ 31872,
+ 31873,
+ 31874,
+ 31875,
+ 31876,
+ 31877,
+ 31878,
+ 31879,
+ 31880,
+ 31881,
+ 31882,
+ 31883,
+ 31884,
+ 31885,
+ 31886,
+ 31887,
+ 31888,
+ 31889,
+ 31890,
+ 31891,
+ 31892,
+ 31893,
+ 31894,
+ 31895,
+ 31896,
+ 31897,
+ 31898,
+ 31899,
+ 31900,
+ 31901,
+ 31902,
+ 31903,
+ 31904,
+ 31905,
+ 31906,
+ 31907,
+ 31908,
+ 31909,
+ 31910,
+ 31911,
+ 31912,
+ 31913,
+ 31914,
+ 31915,
+ 31916,
+ 31917,
+ 31918,
+ 31919,
+ 31920,
+ 31921,
+ 31922,
+ 31923,
+ 31924,
+ 31925,
+ 31926,
+ 31927,
+ 31928,
+ 31929,
+ 31930,
+ 31931,
+ 31932,
+ 31933,
+ 31934,
+ 31935,
+ 31936,
+ 31937,
+ 31938,
+ 31939,
+ 31940,
+ 31941,
+ 31942,
+ 31943,
+ 31944,
+ 31945,
+ 31946,
+ 31947,
+ 31948,
+ 31949,
+ 31950,
+ 31951,
+ 31952,
+ 31953,
+ 31954,
+ 31955,
+ 31956,
+ 31957,
+ 31958,
+ 31959,
+ 31960,
+ 31961,
+ 31962,
+ 31963,
+ 31964,
+ 31965,
+ 31966,
+ 31967,
+ 31968,
+ 31969,
+ 31970,
+ 31971,
+ 31972,
+ 31973,
+ 31974,
+ 31975,
+ 31976,
+ 31977,
+ 31978,
+ 31979,
+ 31980,
+ 31981,
+ 31982,
+ 31983,
+ 31984,
+ 31985,
+ 31986,
+ 31987,
+ 31988,
+ 31989,
+ 31990,
+ 31991,
+ 31992,
+ 31993,
+ 31994,
+ 31995,
+ 31996,
+ 31997,
+ 31998,
+ 31999,
+ 32000,
+ 32001,
+ 32002,
+ 32003,
+ 32004,
+ 32005,
+ 32006,
+ 32007,
+ 32008,
+ 32009,
+ 32010,
+ 32011,
+ 32012,
+ 32013,
+ 32014,
+ 32015,
+ 32016,
+ 32017,
+ 32018,
+ 32019,
+ 32020,
+ 32021,
+ 32022,
+ 32023,
+ 32024,
+ 32025,
+ 32026,
+ 32027,
+ 32028,
+ 32029,
+ 32030,
+ 32031,
+ 32032,
+ 32033,
+ 32034,
+ 32035,
+ 32036,
+ 32037,
+ 32038,
+ 32039,
+ 32040,
+ 32041,
+ 32042,
+ 32043,
+ 32044,
+ 32045,
+ 32046,
+ 32047,
+ 32048,
+ 32049,
+ 32050,
+ 32051,
+ 32052,
+ 32053,
+ 32054,
+ 32055,
+ 32056,
+ 32057,
+ 32058,
+ 32059,
+ 32060,
+ 32061,
+ 32062,
+ 32063,
+ 32064,
+ 32065,
+ 32066,
+ 32067,
+ 32068,
+ 32069,
+ 32070,
+ 32071,
+ 32072,
+ 32073,
+ 32074,
+ 32075,
+ 32076,
+ 32077,
+ 32078,
+ 32079,
+ 32080,
+ 32081,
+ 32082,
+ 32083,
+ 32084,
+ 32085,
+ 32086,
+ 32087,
+ 32088,
+ 32089,
+ 32090,
+ 32091,
+ 32092,
+ 32093,
+ 32094,
+ 32095,
+ 32096,
+ 32097,
+ 32098,
+ 32099,
+ 32100,
+ 32101,
+ 32102,
+ 32103,
+ 32104,
+ 32105,
+ 32106,
+ 32107,
+ 32108,
+ 32109,
+ 32110,
+ 32111,
+ 32112,
+ 32113,
+ 32114,
+ 32115,
+ 32116,
+ 32117,
+ 32118,
+ 32119,
+ 32120,
+ 32121,
+ 32122,
+ 32123,
+ 32124,
+ 32125,
+ 32126,
+ 32127,
+ 32128,
+ 32129,
+ 32130,
+ 32131,
+ 32132,
+ 32133,
+ 32134,
+ 32135,
+ 32136,
+ 32137,
+ 32138,
+ 32139,
+ 32140,
+ 32141,
+ 32142,
+ 32143,
+ 32144,
+ 32145,
+ 32146,
+ 32147,
+ 32148,
+ 32149,
+ 32150,
+ 32151,
+ 32152,
+ 32153,
+ 32154,
+ 32155,
+ 32156,
+ 32157,
+ 32158,
+ 32159,
+ 32160,
+ 32161,
+ 32162,
+ 32163,
+ 32164,
+ 32165,
+ 32166,
+ 32167,
+ 32168,
+ 32169,
+ 32170,
+ 32171,
+ 32172,
+ 32173,
+ 32174,
+ 32175,
+ 32176,
+ 32177,
+ 32178,
+ 32179,
+ 32180,
+ 32181,
+ 32182,
+ 32183,
+ 32184,
+ 32185,
+ 32186,
+ 32187,
+ 32188,
+ 32189,
+ 32190,
+ 32191,
+ 32192,
+ 32193,
+ 32194,
+ 32195,
+ 32196,
+ 32197,
+ 32198,
+ 32199,
+ 32200,
+ 32201,
+ 32202,
+ 32203,
+ 32204,
+ 32205,
+ 32206,
+ 32207,
+ 32208,
+ 32209,
+ 32210,
+ 32211,
+ 32212,
+ 32213,
+ 32214,
+ 32215,
+ 32216,
+ 32217,
+ 32218,
+ 32219,
+ 32220,
+ 32221,
+ 32222,
+ 32223,
+ 32224,
+ 32225,
+ 32226,
+ 32227,
+ 32228,
+ 32229,
+ 32230,
+ 32231,
+ 32232,
+ 32233,
+ 32234,
+ 32235,
+ 32236,
+ 32237,
+ 32238,
+ 32239,
+ 32240,
+ 32241,
+ 32242,
+ 32243,
+ 32244,
+ 32245,
+ 32246,
+ 32247,
+ 32248,
+ 32249,
+ 32250,
+ 32251,
+ 32252,
+ 32253,
+ 32254,
+ 32255,
+ 32256,
+ 32257,
+ 32258,
+ 32259,
+ 32260,
+ 32261,
+ 32262,
+ 32263,
+ 32264,
+ 32265,
+ 32266,
+ 32267,
+ 32268,
+ 32269,
+ 32270,
+ 32271,
+ 32272,
+ 32273,
+ 32274,
+ 32275,
+ 32276,
+ 32277,
+ 32278,
+ 32279,
+ 32280,
+ 32281,
+ 32282,
+ 32283,
+ 32284,
+ 32285,
+ 32286,
+ 32287,
+ 32288,
+ 32289,
+ 32290,
+ 32291,
+ 32292,
+ 32293,
+ 32294,
+ 32295,
+ 32296,
+ 32297,
+ 32298,
+ 32299,
+ 32300,
+ 32301,
+ 32302,
+ 32303,
+ 32304,
+ 32305,
+ 32306,
+ 32307,
+ 32308,
+ 32309,
+ 32310,
+ 32311,
+ 32312,
+ 32313,
+ 32314,
+ 32315,
+ 32316,
+ 32317,
+ 32318,
+ 32319,
+ 32320,
+ 32321,
+ 32322,
+ 32323,
+ 32324,
+ 32325,
+ 32326,
+ 32327,
+ 32328,
+ 32329,
+ 32330,
+ 32331,
+ 32332,
+ 32333,
+ 32334,
+ 32335,
+ 32336,
+ 32337,
+ 32338,
+ 32339,
+ 32340,
+ 32341,
+ 32342,
+ 32343,
+ 32344,
+ 32345,
+ 32346,
+ 32347,
+ 32348,
+ 32349,
+ 32350,
+ 32351,
+ 32352,
+ 32353,
+ 32354,
+ 32355,
+ 32356,
+ 32357,
+ 32358,
+ 32359,
+ 32360,
+ 32361,
+ 32362,
+ 32363,
+ 32364,
+ 32365,
+ 32366,
+ 32367,
+ 32368,
+ 32369,
+ 32370,
+ 32371,
+ 32372,
+ 32373,
+ 32374,
+ 32375,
+ 32376,
+ 32377,
+ 32378,
+ 32379,
+ 32380,
+ 32381,
+ 32382,
+ 32383,
+ 32384,
+ 32385,
+ 32386,
+ 32387,
+ 32388,
+ 32389,
+ 32390,
+ 32391,
+ 32392,
+ 32393,
+ 32394,
+ 32395,
+ 32396,
+ 32397,
+ 32398,
+ 32399,
+ 32400,
+ 32401,
+ 32402,
+ 32403,
+ 32404,
+ 32405,
+ 32406,
+ 32407,
+ 32408,
+ 32409,
+ 32410,
+ 32411,
+ 32412,
+ 32413,
+ 32414,
+ 32415,
+ 32416,
+ 32417,
+ 32418,
+ 32419,
+ 32420,
+ 32421,
+ 32422,
+ 32423,
+ 32424,
+ 32425,
+ 32426,
+ 32427,
+ 32428,
+ 32429,
+ 32430,
+ 32431,
+ 32432,
+ 32433,
+ 32434,
+ 32435,
+ 32436,
+ 32437,
+ 32438,
+ 32439,
+ 32440,
+ 32441,
+ 32442,
+ 32443,
+ 32444,
+ 32445,
+ 32446,
+ 32447,
+ 32448,
+ 32449,
+ 32450,
+ 32451,
+ 32452,
+ 32453,
+ 32454,
+ 32455,
+ 32456,
+ 32457,
+ 32458,
+ 32459,
+ 32460,
+ 32461,
+ 32462,
+ 32463,
+ 32464,
+ 32465,
+ 32466,
+ 32467,
+ 32468,
+ 32469,
+ 32470,
+ 32471,
+ 32472,
+ 32473,
+ 32474,
+ 32475,
+ 32476,
+ 32477,
+ 32478,
+ 32479,
+ 32480,
+ 32481,
+ 32482,
+ 32483,
+ 32484,
+ 32485,
+ 32486,
+ 32487,
+ 32488,
+ 32489,
+ 32490,
+ 32491,
+ 32492,
+ 32493,
+ 32494,
+ 32495,
+ 32496,
+ 32497,
+ 32498,
+ 32499,
+ 32500,
+ 32501,
+ 32502,
+ 32503,
+ 32504,
+ 32505,
+ 32506,
+ 32507,
+ 32508,
+ 32509,
+ 32510,
+ 32511,
+ 32512,
+ 32513,
+ 32514,
+ 32515,
+ 32516,
+ 32517,
+ 32518,
+ 32519,
+ 32520,
+ 32521,
+ 32522,
+ 32523,
+ 32524,
+ 32525,
+ 32526,
+ 32527,
+ 32528,
+ 32529,
+ 32530,
+ 32531,
+ 32532,
+ 32533,
+ 32534,
+ 32535,
+ 32536,
+ 32537,
+ 32538,
+ 32539,
+ 32540,
+ 32541,
+ 32542,
+ 32543,
+ 32544,
+ 32545,
+ 32546,
+ 32547,
+ 32548,
+ 32549,
+ 32550,
+ 32551,
+ 32552,
+ 32553,
+ 32554,
+ 32555,
+ 32556,
+ 32557,
+ 32558,
+ 32559,
+ 32560,
+ 32561,
+ 32562,
+ 32563,
+ 32564,
+ 32565,
+ 32566,
+ 32567,
+ 32568,
+ 32569,
+ 32570,
+ 32571,
+ 32572,
+ 32573,
+ 32574,
+ 32575,
+ 32576,
+ 32577,
+ 32578,
+ 32579,
+ 32580,
+ 32581,
+ 32582,
+ 32583,
+ 32584,
+ 32585,
+ 32586,
+ 32587,
+ 32588,
+ 32589,
+ 32590,
+ 32591,
+ 32592,
+ 32593,
+ 32594,
+ 32595,
+ 32596,
+ 32597,
+ 32598,
+ 32599,
+ 32600,
+ 32601,
+ 32602,
+ 32603,
+ 32604,
+ 32605,
+ 32606,
+ 32607,
+ 32608,
+ 32609,
+ 32610,
+ 32611,
+ 32612,
+ 32613,
+ 32614,
+ 32615,
+ 32616,
+ 32617,
+ 32618,
+ 32619,
+ 32620,
+ 32621,
+ 32622,
+ 32623,
+ 32624,
+ 32625,
+ 32626,
+ 32627,
+ 32628,
+ 32629,
+ 32630,
+ 32631,
+ 32632,
+ 32633,
+ 32634,
+ 32635,
+ 32636,
+ 32637,
+ 32638,
+ 32639,
+ 32640,
+ 32641,
+ 32642,
+ 32643,
+ 32644,
+ 32645,
+ 32646,
+ 32647,
+ 32648,
+ 32649,
+ 32650,
+ 32651,
+ 32652,
+ 32653,
+ 32654,
+ 32655,
+ 32656,
+ 32657,
+ 32658,
+ 32659,
+ 32660,
+ 32661,
+ 32662,
+ 32663,
+ 32664,
+ 32665,
+ 32666,
+ 32667,
+ 32668,
+ 32669,
+ 32670,
+ 32671,
+ 32672,
+ 32673,
+ 32674,
+ 32675,
+ 32676,
+ 32677,
+ 32678,
+ 32679,
+ 32680,
+ 32681,
+ 32682,
+ 32683,
+ 32684,
+ 32685,
+ 32686,
+ 32687,
+ 32688,
+ 32689,
+ 32690,
+ 32691,
+ 32692,
+ 32693,
+ 32694,
+ 32695,
+ 32696,
+ 32697,
+ 32698,
+ 32699,
+ 32700,
+ 32701,
+ 32702,
+ 32703,
+ 32704,
+ 32705,
+ 32706,
+ 32707,
+ 32708,
+ 32709,
+ 32710,
+ 32711,
+ 32712,
+ 32713,
+ 32714,
+ 32715,
+ 32716,
+ 32717,
+ 32718,
+ 32719,
+ 32720,
+ 32721,
+ 32722,
+ 32723,
+ 32724,
+ 32725,
+ 32726,
+ 32727,
+ 32728,
+ 32729,
+ 32730,
+ 32731,
+ 32732,
+ 32733,
+ 32734,
+ 32735,
+ 32736,
+ 32737,
+ 32738,
+ 32739,
+ 32740,
+ 32741,
+ 32742,
+ 32743,
+ 32744,
+ 32745,
+ 32746,
+ 32747,
+ 32748,
+ 32749,
+ 32750,
+ 32751,
+ 32752,
+ 32753,
+ 32754,
+ 32755,
+ 32756,
+ 32757,
+ 32758,
+ 32759,
+ 32760,
+ 32761,
+ 32762,
+ 32763,
+ 32764,
+ 32765,
+ 32766,
+ 32767,
+ 32768,
+ 32769,
+ 32770,
+ 32771,
+ 32772,
+ 32773,
+ 32774,
+ 32775,
+ 32776,
+ 32777,
+ 32778,
+ 32779,
+ 32780,
+ 32781,
+ 32782,
+ 32783,
+ 32784,
+ 32785,
+ 32786,
+ 32787,
+ 32788,
+ 32789,
+ 32790,
+ 32791,
+ 32792,
+ 32793,
+ 32794,
+ 32795,
+ 32796,
+ 32797,
+ 32798,
+ 32799,
+ 32800,
+ 32801,
+ 32802,
+ 32803,
+ 32804,
+ 32805,
+ 32806,
+ 32807,
+ 32808,
+ 32809,
+ 32810,
+ 32811,
+ 32812,
+ 32813,
+ 32814,
+ 32815,
+ 32816,
+ 32817,
+ 32818,
+ 32819,
+ 32820,
+ 32821,
+ 32822,
+ 32823,
+ 32824,
+ 32825,
+ 32826,
+ 32827,
+ 32828,
+ 32829,
+ 32830,
+ 32831,
+ 32832,
+ 32833,
+ 32834,
+ 32835,
+ 32836,
+ 32837,
+ 32838,
+ 32839,
+ 32840,
+ 32841,
+ 32842,
+ 32843,
+ 32844,
+ 32845,
+ 32846,
+ 32847,
+ 32848,
+ 32849,
+ 32850,
+ 32851,
+ 32852,
+ 32853,
+ 32854,
+ 32855,
+ 32856,
+ 32857,
+ 32858,
+ 32859,
+ 32860,
+ 32861,
+ 32862,
+ 32863,
+ 32864,
+ 32865,
+ 32866,
+ 32867,
+ 32868,
+ 32869,
+ 32870,
+ 32871,
+ 32872,
+ 32873,
+ 32874,
+ 32875,
+ 32876,
+ 32877,
+ 32878,
+ 32879,
+ 32880,
+ 32881,
+ 32882,
+ 32883,
+ 32884,
+ 32885,
+ 32886,
+ 32887,
+ 32888,
+ 32889,
+ 32890,
+ 32891,
+ 32892,
+ 32893,
+ 32894,
+ 32895,
+ 32896,
+ 32897,
+ 32898,
+ 32899,
+ 32900,
+ 32901,
+ 32902,
+ 32903,
+ 32904,
+ 32905,
+ 32906,
+ 32907,
+ 32908,
+ 32909,
+ 32910,
+ 32911,
+ 32912,
+ 32913,
+ 32914,
+ 32915,
+ 32916,
+ 32917,
+ 32918,
+ 32919,
+ 32920,
+ 32921,
+ 32922,
+ 32923,
+ 32924,
+ 32925,
+ 32926,
+ 32927,
+ 32928,
+ 32929,
+ 32930,
+ 32931,
+ 32932,
+ 32933,
+ 32934,
+ 32935,
+ 32936,
+ 32937,
+ 32938,
+ 32939,
+ 32940,
+ 32941,
+ 32942,
+ 32943,
+ 32944,
+ 32945,
+ 32946,
+ 32947,
+ 32948,
+ 32949,
+ 32950,
+ 32951,
+ 32952,
+ 32953,
+ 32954,
+ 32955,
+ 32956,
+ 32957,
+ 32958,
+ 32959,
+ 32960,
+ 32961,
+ 32962,
+ 32963,
+ 32964,
+ 32965,
+ 32966,
+ 32967,
+ 32968,
+ 32969,
+ 32970,
+ 32971,
+ 32972,
+ 32973,
+ 32974,
+ 32975,
+ 32976,
+ 32977,
+ 32978,
+ 32979,
+ 32980,
+ 32981,
+ 32982,
+ 32983,
+ 32984,
+ 32985,
+ 32986,
+ 32987,
+ 32988,
+ 32989,
+ 32990,
+ 32991,
+ 32992,
+ 32993,
+ 32994,
+ 32995,
+ 32996,
+ 32997,
+ 32998,
+ 32999,
+ 33000,
+ 33001,
+ 33002,
+ 33003,
+ 33004,
+ 33005,
+ 33006,
+ 33007,
+ 33008,
+ 33009,
+ 33010,
+ 33011,
+ 33012,
+ 33013,
+ 33014,
+ 33015,
+ 33016,
+ 33017,
+ 33018,
+ 33019,
+ 33020,
+ 33021,
+ 33022,
+ 33023,
+ 33024,
+ 33025,
+ 33026,
+ 33027,
+ 33028,
+ 33029,
+ 33030,
+ 33031,
+ 33032,
+ 33033,
+ 33034,
+ 33035,
+ 33036,
+ 33037,
+ 33038,
+ 33039,
+ 33040,
+ 33041,
+ 33042,
+ 33043,
+ 33044,
+ 33045,
+ 33046,
+ 33047,
+ 33048,
+ 33049,
+ 33050,
+ 33051,
+ 33052,
+ 33053,
+ 33054,
+ 33055,
+ 33056,
+ 33057,
+ 33058,
+ 33059,
+ 33060,
+ 33061,
+ 33062,
+ 33063,
+ 33064,
+ 33065,
+ 33066,
+ 33067,
+ 33068,
+ 33069,
+ 33070,
+ 33071,
+ 33072,
+ 33073,
+ 33074,
+ 33075,
+ 33076,
+ 33077,
+ 33078,
+ 33079,
+ 33080,
+ 33081,
+ 33082,
+ 33083,
+ 33084,
+ 33085,
+ 33086,
+ 33087,
+ 33088,
+ 33089,
+ 33090,
+ 33091,
+ 33092,
+ 33093,
+ 33094,
+ 33095,
+ 33096,
+ 33097,
+ 33098,
+ 33099,
+ 33100,
+ 33101,
+ 33102,
+ 33103,
+ 33104,
+ 33105,
+ 33106,
+ 33107,
+ 33108,
+ 33109,
+ 33110,
+ 33111,
+ 33112,
+ 33113,
+ 33114,
+ 33115,
+ 33116,
+ 33117,
+ 33118,
+ 33119,
+ 33120,
+ 33121,
+ 33122,
+ 33123,
+ 33124,
+ 33125,
+ 33126,
+ 33127,
+ 33128,
+ 33129,
+ 33130,
+ 33131,
+ 33132,
+ 33133,
+ 33134,
+ 33135,
+ 33136,
+ 33137,
+ 33138,
+ 33139,
+ 33140,
+ 33141,
+ 33142,
+ 33143,
+ 33144,
+ 33145,
+ 33146,
+ 33147,
+ 33148,
+ 33149,
+ 33150,
+ 33151,
+ 33152,
+ 33153,
+ 33154,
+ 33155,
+ 33156,
+ 33157,
+ 33158,
+ 33159,
+ 33160,
+ 33161,
+ 33162,
+ 33163,
+ 33164,
+ 33165,
+ 33166,
+ 33167,
+ 33168,
+ 33169,
+ 33170,
+ 33171,
+ 33172,
+ 33173,
+ 33174,
+ 33175,
+ 33176,
+ 33177,
+ 33178,
+ 33179,
+ 33180,
+ 33181,
+ 33182,
+ 33183,
+ 33184,
+ 33185,
+ 33186,
+ 33187,
+ 33188,
+ 33189,
+ 33190,
+ 33191,
+ 33192,
+ 33193,
+ 33194,
+ 33195,
+ 33196,
+ 33197,
+ 33198,
+ 33199,
+ 33200,
+ 33201,
+ 33202,
+ 33203,
+ 33204,
+ 33205,
+ 33206,
+ 33207,
+ 33208,
+ 33209,
+ 33210,
+ 33211,
+ 33212,
+ 33213,
+ 33214,
+ 33215,
+ 33216,
+ 33217,
+ 33218,
+ 33219,
+ 33220,
+ 33221,
+ 33222,
+ 33223,
+ 33224,
+ 33225,
+ 33226,
+ 33227,
+ 33228,
+ 33229,
+ 33230,
+ 33231,
+ 33232,
+ 33233,
+ 33234,
+ 33235,
+ 33236,
+ 33237,
+ 33238,
+ 33239,
+ 33240,
+ 33241,
+ 33242,
+ 33243,
+ 33244,
+ 33245,
+ 33246,
+ 33247,
+ 33248,
+ 33249,
+ 33250,
+ 33251,
+ 33252,
+ 33253,
+ 33254,
+ 33255,
+ 33256,
+ 33257,
+ 33258,
+ 33259,
+ 33260,
+ 33261,
+ 33262,
+ 33263,
+ 33264,
+ 33265,
+ 33266,
+ 33267,
+ 33268,
+ 33269,
+ 33270,
+ 33271,
+ 33272,
+ 33273,
+ 33274,
+ 33275,
+ 33276,
+ 33277,
+ 33278,
+ 33279,
+ 33280,
+ 33281,
+ 33282,
+ 33283,
+ 33284,
+ 33285,
+ 33286,
+ 33287,
+ 33288,
+ 33289,
+ 33290,
+ 33291,
+ 33292,
+ 33293,
+ 33294,
+ 33295,
+ 33296,
+ 33297,
+ 33298,
+ 33299,
+ 33300,
+ 33301,
+ 33302,
+ 33303,
+ 33304,
+ 33305,
+ 33306,
+ 33307,
+ 33308,
+ 33309,
+ 33310,
+ 33311,
+ 33312,
+ 33313,
+ 33314,
+ 33315,
+ 33316,
+ 33317,
+ 33318,
+ 33319,
+ 33320,
+ 33321,
+ 33322,
+ 33323,
+ 33324,
+ 33325,
+ 33326,
+ 33327,
+ 33328,
+ 33329,
+ 33330,
+ 33331,
+ 33332,
+ 33333,
+ 33334,
+ 33335,
+ 33336,
+ 33337,
+ 33338,
+ 33339,
+ 33340,
+ 33341,
+ 33342,
+ 33343,
+ 33344,
+ 33345,
+ 33346,
+ 33347,
+ 33348,
+ 33349,
+ 33350,
+ 33351,
+ 33352,
+ 33353,
+ 33354,
+ 33355,
+ 33356,
+ 33357,
+ 33358,
+ 33359,
+ 33360,
+ 33361,
+ 33362,
+ 33363,
+ 33364,
+ 33365,
+ 33366,
+ 33367,
+ 33368,
+ 33369,
+ 33370,
+ 33371,
+ 33372,
+ 33373,
+ 33374,
+ 33375,
+ 33376,
+ 33377,
+ 33378,
+ 33379,
+ 33380,
+ 33381,
+ 33382,
+ 33383,
+ 33384,
+ 33385,
+ 33386,
+ 33387,
+ 33388,
+ 33389,
+ 33390,
+ 33391,
+ 33392,
+ 33393,
+ 33394,
+ 33395,
+ 33396,
+ 33397,
+ 33398,
+ 33399,
+ 33400,
+ 33401,
+ 33402,
+ 33403,
+ 33404,
+ 33405,
+ 33406,
+ 33407,
+ 33408,
+ 33409,
+ 33410,
+ 33411,
+ 33412,
+ 33413,
+ 33414,
+ 33415,
+ 33416,
+ 33417,
+ 33418,
+ 33419,
+ 33420,
+ 33421,
+ 33422,
+ 33423,
+ 33424,
+ 33425,
+ 33426,
+ 33427,
+ 33428,
+ 33429,
+ 33430,
+ 33431,
+ 33432,
+ 33433,
+ 33434,
+ 33435,
+ 33436,
+ 33437,
+ 33438,
+ 33439,
+ 33440,
+ 33441,
+ 33442,
+ 33443,
+ 33444,
+ 33445,
+ 33446,
+ 33447,
+ 33448,
+ 33449,
+ 33450,
+ 33451,
+ 33452,
+ 33453,
+ 33454,
+ 33455,
+ 33456,
+ 33457,
+ 33458,
+ 33459,
+ 33460,
+ 33461,
+ 33462,
+ 33463,
+ 33464,
+ 33465,
+ 33466,
+ 33467,
+ 33468,
+ 33469,
+ 33470,
+ 33471,
+ 33472,
+ 33473,
+ 33474,
+ 33475,
+ 33476,
+ 33477,
+ 33478,
+ 33479,
+ 33480,
+ 33481,
+ 33482,
+ 33483,
+ 33484,
+ 33485,
+ 33486,
+ 33487,
+ 33488,
+ 33489,
+ 33490,
+ 33491,
+ 33492,
+ 33493,
+ 33494,
+ 33495,
+ 33496,
+ 33497,
+ 33498,
+ 33499,
+ 33500,
+ 33501,
+ 33502,
+ 33503,
+ 33504,
+ 33505,
+ 33506,
+ 33507,
+ 33508,
+ 33509,
+ 33510,
+ 33511,
+ 33512,
+ 33513,
+ 33514,
+ 33515,
+ 33516,
+ 33517,
+ 33518,
+ 33519,
+ 33520,
+ 33521,
+ 33522,
+ 33523,
+ 33524,
+ 33525,
+ 33526,
+ 33527,
+ 33528,
+ 33529,
+ 33530,
+ 33531,
+ 33532,
+ 33533,
+ 33534,
+ 33535,
+ 33536,
+ 33537,
+ 33538,
+ 33539,
+ 33540,
+ 33541,
+ 33542,
+ 33543,
+ 33544,
+ 33545,
+ 33546,
+ 33547,
+ 33548,
+ 33549,
+ 33550,
+ 33551,
+ 33552,
+ 33553,
+ 33554,
+ 33555,
+ 33556,
+ 33557,
+ 33558,
+ 33559,
+ 33560,
+ 33561,
+ 33562,
+ 33563,
+ 33564,
+ 33565,
+ 33566,
+ 33567,
+ 33568,
+ 33569,
+ 33570,
+ 33571,
+ 33572,
+ 33573,
+ 33574,
+ 33575,
+ 33576,
+ 33577,
+ 33578,
+ 33579,
+ 33580,
+ 33581,
+ 33582,
+ 33583,
+ 33584,
+ 33585,
+ 33586,
+ 33587,
+ 33588,
+ 33589,
+ 33590,
+ 33591,
+ 33592,
+ 33593,
+ 33594,
+ 33595,
+ 33596,
+ 33597,
+ 33598,
+ 33599,
+ 33600,
+ 33601,
+ 33602,
+ 33603,
+ 33604,
+ 33605,
+ 33606,
+ 33607,
+ 33608,
+ 33609,
+ 33610,
+ 33611,
+ 33612,
+ 33613,
+ 33614,
+ 33615,
+ 33616,
+ 33617,
+ 33618,
+ 33619,
+ 33620,
+ 33621,
+ 33622,
+ 33623,
+ 33624,
+ 33625,
+ 33626,
+ 33627,
+ 33628,
+ 33629,
+ 33630,
+ 33631,
+ 33632,
+ 33633,
+ 33634,
+ 33635,
+ 33636,
+ 33637,
+ 33638,
+ 33639,
+ 33640,
+ 33641,
+ 33642,
+ 33643,
+ 33644,
+ 33645,
+ 33646,
+ 33647,
+ 33648,
+ 33649,
+ 33650,
+ 33651,
+ 33652,
+ 33653,
+ 33654,
+ 33655,
+ 33656,
+ 33657,
+ 33658,
+ 33659,
+ 33660,
+ 33661,
+ 33662,
+ 33663,
+ 33664,
+ 33665,
+ 33666,
+ 33667,
+ 33668,
+ 33669,
+ 33670,
+ 33671,
+ 33672,
+ 33673,
+ 33674,
+ 33675,
+ 33676,
+ 33677,
+ 33678,
+ 33679,
+ 33680,
+ 33681,
+ 33682,
+ 33683,
+ 33684,
+ 33685,
+ 33686,
+ 33687,
+ 33688,
+ 33689,
+ 33690,
+ 33691,
+ 33692,
+ 33693,
+ 33694,
+ 33695,
+ 33696,
+ 33697,
+ 33698,
+ 33699,
+ 33700,
+ 33701,
+ 33702,
+ 33703,
+ 33704,
+ 33705,
+ 33706,
+ 33707,
+ 33708,
+ 33709,
+ 33710,
+ 33711,
+ 33712,
+ 33713,
+ 33714,
+ 33715,
+ 33716,
+ 33717,
+ 33718,
+ 33719,
+ 33720,
+ 33721,
+ 33722,
+ 33723,
+ 33724,
+ 33725,
+ 33726,
+ 33727,
+ 33728,
+ 33729,
+ 33730,
+ 33731,
+ 33732,
+ 33733,
+ 33734,
+ 33735,
+ 33736,
+ 33737,
+ 33738,
+ 33739,
+ 33740,
+ 33741,
+ 33742,
+ 33743,
+ 33744,
+ 33745,
+ 33746,
+ 33747,
+ 33748,
+ 33749,
+ 33750,
+ 33751,
+ 33752,
+ 33753,
+ 33754,
+ 33755,
+ 33756,
+ 33757,
+ 33758,
+ 33759,
+ 33760,
+ 33761,
+ 33762,
+ 33763,
+ 33764,
+ 33765,
+ 33766,
+ 33767,
+ 33768,
+ 33769,
+ 33770,
+ 33771,
+ 33772,
+ 33773,
+ 33774,
+ 33775,
+ 33776,
+ 33777,
+ 33778,
+ 33779,
+ 33780,
+ 33781,
+ 33782,
+ 33783,
+ 33784,
+ 33785,
+ 33786,
+ 33787,
+ 33788,
+ 33789,
+ 33790,
+ 33791,
+ 33792,
+ 33793,
+ 33794,
+ 33795,
+ 33796,
+ 33797,
+ 33798,
+ 33799,
+ 33800,
+ 33801,
+ 33802,
+ 33803,
+ 33804,
+ 33805,
+ 33806,
+ 33807,
+ 33808,
+ 33809,
+ 33810,
+ 33811,
+ 33812,
+ 33813,
+ 33814,
+ 33815,
+ 33816,
+ 33817,
+ 33818,
+ 33819,
+ 33820,
+ 33821,
+ 33822,
+ 33823,
+ 33824,
+ 33825,
+ 33826,
+ 33827,
+ 33828,
+ 33829,
+ 33830,
+ 33831,
+ 33832,
+ 33833,
+ 33834,
+ 33835,
+ 33836,
+ 33837,
+ 33838,
+ 33839,
+ 33840,
+ 33841,
+ 33842,
+ 33843,
+ 33844,
+ 33845,
+ 33846,
+ 33847,
+ 33848,
+ 33849,
+ 33850,
+ 33851,
+ 33852,
+ 33853,
+ 33854,
+ 33855,
+ 33856,
+ 33857,
+ 33858,
+ 33859,
+ 33860,
+ 33861,
+ 33862,
+ 33863,
+ 33864,
+ 33865,
+ 33866,
+ 33867,
+ 33868,
+ 33869,
+ 33870,
+ 33871,
+ 33872,
+ 33873,
+ 33874,
+ 33875,
+ 33876,
+ 33877,
+ 33878,
+ 33879,
+ 33880,
+ 33881,
+ 33882,
+ 33883,
+ 33884,
+ 33885,
+ 33886,
+ 33887,
+ 33888,
+ 33889,
+ 33890,
+ 33891,
+ 33892,
+ 33893,
+ 33894,
+ 33895,
+ 33896,
+ 33897,
+ 33898,
+ 33899,
+ 33900,
+ 33901,
+ 33902,
+ 33903,
+ 33904,
+ 33905,
+ 33906,
+ 33907,
+ 33908,
+ 33909,
+ 33910,
+ 33911,
+ 33912,
+ 33913,
+ 33914,
+ 33915,
+ 33916,
+ 33917,
+ 33918,
+ 33919,
+ 33920,
+ 33921,
+ 33922,
+ 33923,
+ 33924,
+ 33925,
+ 33926,
+ 33927,
+ 33928,
+ 33929,
+ 33930,
+ 33931,
+ 33932,
+ 33933,
+ 33934,
+ 33935,
+ 33936,
+ 33937,
+ 33938,
+ 33939,
+ 33940,
+ 33941,
+ 33942,
+ 33943,
+ 33944,
+ 33945,
+ 33946,
+ 33947,
+ 33948,
+ 33949,
+ 33950,
+ 33951,
+ 33952,
+ 33953,
+ 33954,
+ 33955,
+ 33956,
+ 33957,
+ 33958,
+ 33959,
+ 33960,
+ 33961,
+ 33962,
+ 33963,
+ 33964,
+ 33965,
+ 33966,
+ 33967,
+ 33968,
+ 33969,
+ 33970,
+ 33971,
+ 33972,
+ 33973,
+ 33974,
+ 33975,
+ 33976,
+ 33977,
+ 33978,
+ 33979,
+ 33980,
+ 33981,
+ 33982,
+ 33983,
+ 33984,
+ 33985,
+ 33986,
+ 33987,
+ 33988,
+ 33989,
+ 33990,
+ 33991,
+ 33992,
+ 33993,
+ 33994,
+ 33995,
+ 33996,
+ 33997,
+ 33998,
+ 33999,
+ 34000,
+ 34001,
+ 34002,
+ 34003,
+ 34004,
+ 34005,
+ 34006,
+ 34007,
+ 34008,
+ 34009,
+ 34010,
+ 34011,
+ 34012,
+ 34013,
+ 34014,
+ 34015,
+ 34016,
+ 34017,
+ 34018,
+ 34019,
+ 34020,
+ 34021,
+ 34022,
+ 34023,
+ 34024,
+ 34025,
+ 34026,
+ 34027,
+ 34028,
+ 34029,
+ 34030,
+ 34031,
+ 34032,
+ 34033,
+ 34034,
+ 34035,
+ 34036,
+ 34037,
+ 34038,
+ 34039,
+ 34040,
+ 34041,
+ 34042,
+ 34043,
+ 34044,
+ 34045,
+ 34046,
+ 34047,
+ 34048,
+ 34049,
+ 34050,
+ 34051,
+ 34052,
+ 34053,
+ 34054,
+ 34055,
+ 34056,
+ 34057,
+ 34058,
+ 34059,
+ 34060,
+ 34061,
+ 34062,
+ 34063,
+ 34064,
+ 34065,
+ 34066,
+ 34067,
+ 34068,
+ 34069,
+ 34070,
+ 34071,
+ 34072,
+ 34073,
+ 34074,
+ 34075,
+ 34076,
+ 34077,
+ 34078,
+ 34079,
+ 34080,
+ 34081,
+ 34082,
+ 34083,
+ 34084,
+ 34085,
+ 34086,
+ 34087,
+ 34088,
+ 34089,
+ 34090,
+ 34091,
+ 34092,
+ 34093,
+ 34094,
+ 34095,
+ 34096,
+ 34097,
+ 34098,
+ 34099,
+ 34100,
+ 34101,
+ 34102,
+ 34103,
+ 34104,
+ 34105,
+ 34106,
+ 34107,
+ 34108,
+ 34109,
+ 34110,
+ 34111,
+ 34112,
+ 34113,
+ 34114,
+ 34115,
+ 34116,
+ 34117,
+ 34118,
+ 34119,
+ 34120,
+ 34121,
+ 34122,
+ 34123,
+ 34124,
+ 34125,
+ 34126,
+ 34127,
+ 34128,
+ 34129,
+ 34130,
+ 34131,
+ 34132,
+ 34133,
+ 34134,
+ 34135,
+ 34136,
+ 34137,
+ 34138,
+ 34139,
+ 34140,
+ 34141,
+ 34142,
+ 34143,
+ 34144,
+ 34145,
+ 34146,
+ 34147,
+ 34148,
+ 34149,
+ 34150,
+ 34151,
+ 34152,
+ 34153,
+ 34154,
+ 34155,
+ 34156,
+ 34157,
+ 34158,
+ 34159,
+ 34160,
+ 34161,
+ 34162,
+ 34163,
+ 34164,
+ 34165,
+ 34166,
+ 34167,
+ 34168,
+ 34169,
+ 34170,
+ 34171,
+ 34172,
+ 34173,
+ 34174,
+ 34175,
+ 34176,
+ 34177,
+ 34178,
+ 34179,
+ 34180,
+ 34181,
+ 34182,
+ 34183,
+ 34184,
+ 34185,
+ 34186,
+ 34187,
+ 34188,
+ 34189,
+ 34190,
+ 34191,
+ 34192,
+ 34193,
+ 34194,
+ 34195,
+ 34196,
+ 34197,
+ 34198,
+ 34199,
+ 34200,
+ 34201,
+ 34202,
+ 34203,
+ 34204,
+ 34205,
+ 34206,
+ 34207,
+ 34208,
+ 34209,
+ 34210,
+ 34211,
+ 34212,
+ 34213,
+ 34214,
+ 34215,
+ 34216,
+ 34217,
+ 34218,
+ 34219,
+ 34220,
+ 34221,
+ 34222,
+ 34223,
+ 34224,
+ 34225,
+ 34226,
+ 34227,
+ 34228,
+ 34229,
+ 34230,
+ 34231,
+ 34232,
+ 34233,
+ 34234,
+ 34235,
+ 34236,
+ 34237,
+ 34238,
+ 34239,
+ 34240,
+ 34241,
+ 34242,
+ 34243,
+ 34244,
+ 34245,
+ 34246,
+ 34247,
+ 34248,
+ 34249,
+ 34250,
+ 34251,
+ 34252,
+ 34253,
+ 34254,
+ 34255,
+ 34256,
+ 34257,
+ 34258,
+ 34259,
+ 34260,
+ 34261,
+ 34262,
+ 34263,
+ 34264,
+ 34265,
+ 34266,
+ 34267,
+ 34268,
+ 34269,
+ 34270,
+ 34271,
+ 34272,
+ 34273,
+ 34274,
+ 34275,
+ 34276,
+ 34277,
+ 34278,
+ 34279,
+ 34280,
+ 34281,
+ 34282,
+ 34283,
+ 34284,
+ 34285,
+ 34286,
+ 34287,
+ 34288,
+ 34289,
+ 34290,
+ 34291,
+ 34292,
+ 34293,
+ 34294,
+ 34295,
+ 34296,
+ 34297,
+ 34298,
+ 34299,
+ 34300,
+ 34301,
+ 34302,
+ 34303,
+ 34304,
+ 34305,
+ 34306,
+ 34307,
+ 34308,
+ 34309,
+ 34310,
+ 34311,
+ 34312,
+ 34313,
+ 34314,
+ 34315,
+ 34316,
+ 34317,
+ 34318,
+ 34319,
+ 34320,
+ 34321,
+ 34322,
+ 34323,
+ 34324,
+ 34325,
+ 34326,
+ 34327,
+ 34328,
+ 34329,
+ 34330,
+ 34331,
+ 34332,
+ 34333,
+ 34334,
+ 34335,
+ 34336,
+ 34337,
+ 34338,
+ 34339,
+ 34340,
+ 34341,
+ 34342,
+ 34343,
+ 34344,
+ 34345,
+ 34346,
+ 34347,
+ 34348,
+ 34349,
+ 34350,
+ 34351,
+ 34352,
+ 34353,
+ 34354,
+ 34355,
+ 34356,
+ 34357,
+ 34358,
+ 34359,
+ 34360,
+ 34361,
+ 34362,
+ 34363,
+ 34364,
+ 34365,
+ 34366,
+ 34367,
+ 34368,
+ 34369,
+ 34370,
+ 34371,
+ 34372,
+ 34373,
+ 34374,
+ 34375,
+ 34376,
+ 34377,
+ 34378,
+ 34379,
+ 34380,
+ 34381,
+ 34382,
+ 34383,
+ 34384,
+ 34385,
+ 34386,
+ 34387,
+ 34388,
+ 34389,
+ 34390,
+ 34391,
+ 34392,
+ 34393,
+ 34394,
+ 34395,
+ 34396,
+ 34397,
+ 34398,
+ 34399,
+ 34400,
+ 34401,
+ 34402,
+ 34403,
+ 34404,
+ 34405,
+ 34406,
+ 34407,
+ 34408,
+ 34409,
+ 34410,
+ 34411,
+ 34412,
+ 34413,
+ 34414,
+ 34415,
+ 34416,
+ 34417,
+ 34418,
+ 34419,
+ 34420,
+ 34421,
+ 34422,
+ 34423,
+ 34424,
+ 34425,
+ 34426,
+ 34427,
+ 34428,
+ 34429,
+ 34430,
+ 34431,
+ 34432,
+ 34433,
+ 34434,
+ 34435,
+ 34436,
+ 34437,
+ 34438,
+ 34439,
+ 34440,
+ 34441,
+ 34442,
+ 34443,
+ 34444,
+ 34445,
+ 34446,
+ 34447,
+ 34448,
+ 34449,
+ 34450,
+ 34451,
+ 34452,
+ 34453,
+ 34454,
+ 34455,
+ 34456,
+ 34457,
+ 34458,
+ 34459,
+ 34460,
+ 34461,
+ 34462,
+ 34463,
+ 34464,
+ 34465,
+ 34466,
+ 34467,
+ 34468,
+ 34469,
+ 34470,
+ 34471,
+ 34472,
+ 34473,
+ 34474,
+ 34475,
+ 34476,
+ 34477,
+ 34478,
+ 34479,
+ 34480,
+ 34481,
+ 34482,
+ 34483,
+ 34484,
+ 34485,
+ 34486,
+ 34487,
+ 34488,
+ 34489,
+ 34490,
+ 34491,
+ 34492,
+ 34493,
+ 34494,
+ 34495,
+ 34496,
+ 34497,
+ 34498,
+ 34499,
+ 34500,
+ 34501,
+ 34502,
+ 34503,
+ 34504,
+ 34505,
+ 34506,
+ 34507,
+ 34508,
+ 34509,
+ 34510,
+ 34511,
+ 34512,
+ 34513,
+ 34514,
+ 34515,
+ 34516,
+ 34517,
+ 34518,
+ 34519,
+ 34520,
+ 34521,
+ 34522,
+ 34523,
+ 34524,
+ 34525,
+ 34526,
+ 34527,
+ 34528,
+ 34529,
+ 34530,
+ 34531,
+ 34532,
+ 34533,
+ 34534,
+ 34535,
+ 34536,
+ 34537,
+ 34538,
+ 34539,
+ 34540,
+ 34541,
+ 34542,
+ 34543,
+ 34544,
+ 34545,
+ 34546,
+ 34547,
+ 34548,
+ 34549,
+ 34550,
+ 34551,
+ 34552,
+ 34553,
+ 34554,
+ 34555,
+ 34556,
+ 34557,
+ 34558,
+ 34559,
+ 34560,
+ 34561,
+ 34562,
+ 34563,
+ 34564,
+ 34565,
+ 34566,
+ 34567,
+ 34568,
+ 34569,
+ 34570,
+ 34571,
+ 34572,
+ 34573,
+ 34574,
+ 34575,
+ 34576,
+ 34577,
+ 34578,
+ 34579,
+ 34580,
+ 34581,
+ 34582,
+ 34583,
+ 34584,
+ 34585,
+ 34586,
+ 34587,
+ 34588,
+ 34589,
+ 34590,
+ 34591,
+ 34592,
+ 34593,
+ 34594,
+ 34595,
+ 34596,
+ 34597,
+ 34598,
+ 34599,
+ 34600,
+ 34601,
+ 34602,
+ 34603,
+ 34604,
+ 34605,
+ 34606,
+ 34607,
+ 34608,
+ 34609,
+ 34610,
+ 34611,
+ 34612,
+ 34613,
+ 34614,
+ 34615,
+ 34616,
+ 34617,
+ 34618,
+ 34619,
+ 34620,
+ 34621,
+ 34622,
+ 34623,
+ 34624,
+ 34625,
+ 34626,
+ 34627,
+ 34628,
+ 34629,
+ 34630,
+ 34631,
+ 34632,
+ 34633,
+ 34634,
+ 34635,
+ 34636,
+ 34637,
+ 34638,
+ 34639,
+ 34640,
+ 34641,
+ 34642,
+ 34643,
+ 34644,
+ 34645,
+ 34646,
+ 34647,
+ 34648,
+ 34649,
+ 34650,
+ 34651,
+ 34652,
+ 34653,
+ 34654,
+ 34655,
+ 34656,
+ 34657,
+ 34658,
+ 34659,
+ 34660,
+ 34661,
+ 34662,
+ 34663,
+ 34664,
+ 34665,
+ 34666,
+ 34667,
+ 34668,
+ 34669,
+ 34670,
+ 34671,
+ 34672,
+ 34673,
+ 34674,
+ 34675,
+ 34676,
+ 34677,
+ 34678,
+ 34679,
+ 34680,
+ 34681,
+ 34682,
+ 34683,
+ 34684,
+ 34685,
+ 34686,
+ 34687,
+ 34688,
+ 34689,
+ 34690,
+ 34691,
+ 34692,
+ 34693,
+ 34694,
+ 34695,
+ 34696,
+ 34697,
+ 34698,
+ 34699,
+ 34700,
+ 34701,
+ 34702,
+ 34703,
+ 34704,
+ 34705,
+ 34706,
+ 34707,
+ 34708,
+ 34709,
+ 34710,
+ 34711,
+ 34712,
+ 34713,
+ 34714,
+ 34715,
+ 34716,
+ 34717,
+ 34718,
+ 34719,
+ 34720,
+ 34721,
+ 34722,
+ 34723,
+ 34724,
+ 34725,
+ 34726,
+ 34727,
+ 34728,
+ 34729,
+ 34730,
+ 34731,
+ 34732,
+ 34733,
+ 34734,
+ 34735,
+ 34736,
+ 34737,
+ 34738,
+ 34739,
+ 34740,
+ 34741,
+ 34742,
+ 34743,
+ 34744,
+ 34745,
+ 34746,
+ 34747,
+ 34748,
+ 34749,
+ 34750,
+ 34751,
+ 34752,
+ 34753,
+ 34754,
+ 34755,
+ 34756,
+ 34757,
+ 34758,
+ 34759,
+ 34760,
+ 34761,
+ 34762,
+ 34763,
+ 34764,
+ 34765,
+ 34766,
+ 34767,
+ 34768,
+ 34769,
+ 34770,
+ 34771,
+ 34772,
+ 34773,
+ 34774,
+ 34775,
+ 34776,
+ 34777,
+ 34778,
+ 34779,
+ 34780,
+ 34781,
+ 34782,
+ 34783,
+ 34784,
+ 34785,
+ 34786,
+ 34787,
+ 34788,
+ 34789,
+ 34790,
+ 34791,
+ 34792,
+ 34793,
+ 34794,
+ 34795,
+ 34796,
+ 34797,
+ 34798,
+ 34799,
+ 34800,
+ 34801,
+ 34802,
+ 34803,
+ 34804,
+ 34805,
+ 34806,
+ 34807,
+ 34808,
+ 34809,
+ 34810,
+ 34811,
+ 34812,
+ 34813,
+ 34814,
+ 34815,
+ 34816,
+ 34817,
+ 34818,
+ 34819,
+ 34820,
+ 34821,
+ 34822,
+ 34823,
+ 34824,
+ 34825,
+ 34826,
+ 34827,
+ 34828,
+ 34829,
+ 34830,
+ 34831,
+ 34832,
+ 34833,
+ 34834,
+ 34835,
+ 34836,
+ 34837,
+ 34838,
+ 34839,
+ 34840,
+ 34841,
+ 34842,
+ 34843,
+ 34844,
+ 34845,
+ 34846,
+ 34847,
+ 34848,
+ 34849,
+ 34850,
+ 34851,
+ 34852,
+ 34853,
+ 34854,
+ 34855,
+ 34856,
+ 34857,
+ 34858,
+ 34859,
+ 34860,
+ 34861,
+ 34862,
+ 34863,
+ 34864,
+ 34865,
+ 34866,
+ 34867,
+ 34868,
+ 34869,
+ 34870,
+ 34871,
+ 34872,
+ 34873,
+ 34874,
+ 34875,
+ 34876,
+ 34877,
+ 34878,
+ 34879,
+ 34880,
+ 34881,
+ 34882,
+ 34883,
+ 34884,
+ 34885,
+ 34886,
+ 34887,
+ 34888,
+ 34889,
+ 34890,
+ 34891,
+ 34892,
+ 34893,
+ 34894,
+ 34895,
+ 34896,
+ 34897,
+ 34898,
+ 34899,
+ 34900,
+ 34901,
+ 34902,
+ 34903,
+ 34904,
+ 34905,
+ 34906,
+ 34907,
+ 34908,
+ 34909,
+ 34910,
+ 34911,
+ 34912,
+ 34913,
+ 34914,
+ 34915,
+ 34916,
+ 34917,
+ 34918,
+ 34919,
+ 34920,
+ 34921,
+ 34922,
+ 34923,
+ 34924,
+ 34925,
+ 34926,
+ 34927,
+ 34928,
+ 34929,
+ 34930,
+ 34931,
+ 34932,
+ 34933,
+ 34934,
+ 34935,
+ 34936,
+ 34937,
+ 34938,
+ 34939,
+ 34940,
+ 34941,
+ 34942,
+ 34943,
+ 34944,
+ 34945,
+ 34946,
+ 34947,
+ 34948,
+ 34949,
+ 34950,
+ 34951,
+ 34952,
+ 34953,
+ 34954,
+ 34955,
+ 34956,
+ 34957,
+ 34958,
+ 34959,
+ 34960,
+ 34961,
+ 34962,
+ 34963,
+ 34964,
+ 34965,
+ 34966,
+ 34967,
+ 34968,
+ 34969,
+ 34970,
+ 34971,
+ 34972,
+ 34973,
+ 34974,
+ 34975,
+ 34976,
+ 34977,
+ 34978,
+ 34979,
+ 34980,
+ 34981,
+ 34982,
+ 34983,
+ 34984,
+ 34985,
+ 34986,
+ 34987,
+ 34988,
+ 34989,
+ 34990,
+ 34991,
+ 34992,
+ 34993,
+ 34994,
+ 34995,
+ 34996,
+ 34997,
+ 34998,
+ 34999,
+ 35000,
+ 35001,
+ 35002,
+ 35003,
+ 35004,
+ 35005,
+ 35006,
+ 35007,
+ 35008,
+ 35009,
+ 35010,
+ 35011,
+ 35012,
+ 35013,
+ 35014,
+ 35015,
+ 35016,
+ 35017,
+ 35018,
+ 35019,
+ 35020,
+ 35021,
+ 35022,
+ 35023,
+ 35024,
+ 35025,
+ 35026,
+ 35027,
+ 35028,
+ 35029,
+ 35030,
+ 35031,
+ 35032,
+ 35033,
+ 35034,
+ 35035,
+ 35036,
+ 35037,
+ 35038,
+ 35039,
+ 35040,
+ 35041,
+ 35042,
+ 35043,
+ 35044,
+ 35045,
+ 35046,
+ 35047,
+ 35048,
+ 35049,
+ 35050,
+ 35051,
+ 35052,
+ 35053,
+ 35054,
+ 35055,
+ 35056,
+ 35057,
+ 35058,
+ 35059,
+ 35060,
+ 35061,
+ 35062,
+ 35063,
+ 35064,
+ 35065,
+ 35066,
+ 35067,
+ 35068,
+ 35069,
+ 35070,
+ 35071,
+ 35072,
+ 35073,
+ 35074,
+ 35075,
+ 35076,
+ 35077,
+ 35078,
+ 35079,
+ 35080,
+ 35081,
+ 35082,
+ 35083,
+ 35084,
+ 35085,
+ 35086,
+ 35087,
+ 35088,
+ 35089,
+ 35090,
+ 35091,
+ 35092,
+ 35093,
+ 35094,
+ 35095,
+ 35096,
+ 35097,
+ 35098,
+ 35099,
+ 35100,
+ 35101,
+ 35102,
+ 35103,
+ 35104,
+ 35105,
+ 35106,
+ 35107,
+ 35108,
+ 35109,
+ 35110,
+ 35111,
+ 35112,
+ 35113,
+ 35114,
+ 35115,
+ 35116,
+ 35117,
+ 35118,
+ 35119,
+ 35120,
+ 35121,
+ 35122,
+ 35123,
+ 35124,
+ 35125,
+ 35126,
+ 35127,
+ 35128,
+ 35129,
+ 35130,
+ 35131,
+ 35132,
+ 35133,
+ 35134,
+ 35135,
+ 35136,
+ 35137,
+ 35138,
+ 35139,
+ 35140,
+ 35141,
+ 35142,
+ 35143,
+ 35144,
+ 35145,
+ 35146,
+ 35147,
+ 35148,
+ 35149,
+ 35150,
+ 35151,
+ 35152,
+ 35153,
+ 35154,
+ 35155,
+ 35156,
+ 35157,
+ 35158,
+ 35159,
+ 35160,
+ 35161,
+ 35162,
+ 35163,
+ 35164,
+ 35165,
+ 35166,
+ 35167,
+ 35168,
+ 35169,
+ 35170,
+ 35171,
+ 35172,
+ 35173,
+ 35174,
+ 35175,
+ 35176,
+ 35177,
+ 35178,
+ 35179,
+ 35180,
+ 35181,
+ 35182,
+ 35183,
+ 35184,
+ 35185,
+ 35186,
+ 35187,
+ 35188,
+ 35189,
+ 35190,
+ 35191,
+ 35192,
+ 35193,
+ 35194,
+ 35195,
+ 35196,
+ 35197,
+ 35198,
+ 35199,
+ 35200,
+ 35201,
+ 35202,
+ 35203,
+ 35204,
+ 35205,
+ 35206,
+ 35207,
+ 35208,
+ 35209,
+ 35210,
+ 35211,
+ 35212,
+ 35213,
+ 35214,
+ 35215,
+ 35216,
+ 35217,
+ 35218,
+ 35219,
+ 35220,
+ 35221,
+ 35222,
+ 35223,
+ 35224,
+ 35225,
+ 35226,
+ 35227,
+ 35228,
+ 35229,
+ 35230,
+ 35231,
+ 35232,
+ 35233,
+ 35234,
+ 35235,
+ 35236,
+ 35237,
+ 35238,
+ 35239,
+ 35240,
+ 35241,
+ 35242,
+ 35243,
+ 35244,
+ 35245,
+ 35246,
+ 35247,
+ 35248,
+ 35249,
+ 35250,
+ 35251,
+ 35252,
+ 35253,
+ 35254,
+ 35255,
+ 35256,
+ 35257,
+ 35258,
+ 35259,
+ 35260,
+ 35261,
+ 35262,
+ 35263,
+ 35264,
+ 35265,
+ 35266,
+ 35267,
+ 35268,
+ 35269,
+ 35270,
+ 35271,
+ 35272,
+ 35273,
+ 35274,
+ 35275,
+ 35276,
+ 35277,
+ 35278,
+ 35279,
+ 35280,
+ 35281,
+ 35282,
+ 35283,
+ 35284,
+ 35285,
+ 35286,
+ 35287,
+ 35288,
+ 35289,
+ 35290,
+ 35291,
+ 35292,
+ 35293,
+ 35294,
+ 35295,
+ 35296,
+ 35297,
+ 35298,
+ 35299,
+ 35300,
+ 35301,
+ 35302,
+ 35303,
+ 35304,
+ 35305,
+ 35306,
+ 35307,
+ 35308,
+ 35309,
+ 35310,
+ 35311,
+ 35312,
+ 35313,
+ 35314,
+ 35315,
+ 35316,
+ 35317,
+ 35318,
+ 35319,
+ 35320,
+ 35321,
+ 35322,
+ 35323,
+ 35324,
+ 35325,
+ 35326,
+ 35327,
+ 35328,
+ 35329,
+ 35330,
+ 35331,
+ 35332,
+ 35333,
+ 35334,
+ 35335,
+ 35336,
+ 35337,
+ 35338,
+ 35339,
+ 35340,
+ 35341,
+ 35342,
+ 35343,
+ 35344,
+ 35345,
+ 35346,
+ 35347,
+ 35348,
+ 35349,
+ 35350,
+ 35351,
+ 35352,
+ 35353,
+ 35354,
+ 35355,
+ 35356,
+ 35357,
+ 35358,
+ 35359,
+ 35360,
+ 35361,
+ 35362,
+ 35363,
+ 35364,
+ 35365,
+ 35366,
+ 35367,
+ 35368,
+ 35369,
+ 35370,
+ 35371,
+ 35372,
+ 35373,
+ 35374,
+ 35375,
+ 35376,
+ 35377,
+ 35378,
+ 35379,
+ 35380,
+ 35381,
+ 35382,
+ 35383,
+ 35384,
+ 35385,
+ 35386,
+ 35387,
+ 35388,
+ 35389,
+ 35390,
+ 35391,
+ 35392,
+ 35393,
+ 35394,
+ 35395,
+ 35396,
+ 35397,
+ 35398,
+ 35399,
+ 35400,
+ 35401,
+ 35402,
+ 35403,
+ 35404,
+ 35405,
+ 35406,
+ 35407,
+ 35408,
+ 35409,
+ 35410,
+ 35411,
+ 35412,
+ 35413,
+ 35414,
+ 35415,
+ 35416,
+ 35417,
+ 35418,
+ 35419,
+ 35420,
+ 35421,
+ 35422,
+ 35423,
+ 35424,
+ 35425,
+ 35426,
+ 35427,
+ 35428,
+ 35429,
+ 35430,
+ 35431,
+ 35432,
+ 35433,
+ 35434,
+ 35435,
+ 35436,
+ 35437,
+ 35438,
+ 35439,
+ 35440,
+ 35441,
+ 35442,
+ 35443,
+ 35444,
+ 35445,
+ 35446,
+ 35447,
+ 35448,
+ 35449,
+ 35450,
+ 35451,
+ 35452,
+ 35453,
+ 35454,
+ 35455,
+ 35456,
+ 35457,
+ 35458,
+ 35459,
+ 35460,
+ 35461,
+ 35462,
+ 35463,
+ 35464,
+ 35465,
+ 35466,
+ 35467,
+ 35468,
+ 35469,
+ 35470,
+ 35471,
+ 35472,
+ 35473,
+ 35474,
+ 35475,
+ 35476,
+ 35477,
+ 35478,
+ 35479,
+ 35480,
+ 35481,
+ 35482,
+ 35483,
+ 35484,
+ 35485,
+ 35486,
+ 35487,
+ 35488,
+ 35489,
+ 35490,
+ 35491,
+ 35492,
+ 35493,
+ 35494,
+ 35495,
+ 35496,
+ 35497,
+ 35498,
+ 35499,
+ 35500,
+ 35501,
+ 35502,
+ 35503,
+ 35504,
+ 35505,
+ 35506,
+ 35507,
+ 35508,
+ 35509,
+ 35510,
+ 35511,
+ 35512,
+ 35513,
+ 35514,
+ 35515,
+ 35516,
+ 35517,
+ 35518,
+ 35519,
+ 35520,
+ 35521,
+ 35522,
+ 35523,
+ 35524,
+ 35525,
+ 35526,
+ 35527,
+ 35528,
+ 35529,
+ 35530,
+ 35531,
+ 35532,
+ 35533,
+ 35534,
+ 35535,
+ 35536,
+ 35537,
+ 35538,
+ 35539,
+ 35540,
+ 35541,
+ 35542,
+ 35543,
+ 35544,
+ 35545,
+ 35546,
+ 35547,
+ 35548,
+ 35549,
+ 35550,
+ 35551,
+ 35552,
+ 35553,
+ 35554,
+ 35555,
+ 35556,
+ 35557,
+ 35558,
+ 35559,
+ 35560,
+ 35561,
+ 35562,
+ 35563,
+ 35564,
+ 35565,
+ 35566,
+ 35567,
+ 35568,
+ 35569,
+ 35570,
+ 35571,
+ 35572,
+ 35573,
+ 35574,
+ 35575,
+ 35576,
+ 35577,
+ 35578,
+ 35579,
+ 35580,
+ 35581,
+ 35582,
+ 35583,
+ 35584,
+ 35585,
+ 35586,
+ 35587,
+ 35588,
+ 35589,
+ 35590,
+ 35591,
+ 35592,
+ 35593,
+ 35594,
+ 35595,
+ 35596,
+ 35597,
+ 35598,
+ 35599,
+ 35600,
+ 35601,
+ 35602,
+ 35603,
+ 35604,
+ 35605,
+ 35606,
+ 35607,
+ 35608,
+ 35609,
+ 35610,
+ 35611,
+ 35612,
+ 35613,
+ 35614,
+ 35615,
+ 35616,
+ 35617,
+ 35618,
+ 35619,
+ 35620,
+ 35621,
+ 35622,
+ 35623,
+ 35624,
+ 35625,
+ 35626,
+ 35627,
+ 35628,
+ 35629,
+ 35630,
+ 35631,
+ 35632,
+ 35633,
+ 35634,
+ 35635,
+ 35636,
+ 35637,
+ 35638,
+ 35639,
+ 35640,
+ 35641,
+ 35642,
+ 35643,
+ 35644,
+ 35645,
+ 35646,
+ 35647,
+ 35648,
+ 35649,
+ 35650,
+ 35651,
+ 35652,
+ 35653,
+ 35654,
+ 35655,
+ 35656,
+ 35657,
+ 35658,
+ 35659,
+ 35660,
+ 35661,
+ 35662,
+ 35663,
+ 35664,
+ 35665,
+ 35666,
+ 35667,
+ 35668,
+ 35669,
+ 35670,
+ 35671,
+ 35672,
+ 35673,
+ 35674,
+ 35675,
+ 35676,
+ 35677,
+ 35678,
+ 35679,
+ 35680,
+ 35681,
+ 35682,
+ 35683,
+ 35684,
+ 35685,
+ 35686,
+ 35687,
+ 35688,
+ 35689,
+ 35690,
+ 35691,
+ 35692,
+ 35693,
+ 35694,
+ 35695,
+ 35696,
+ 35697,
+ 35698,
+ 35699,
+ 35700,
+ 35701,
+ 35702,
+ 35703,
+ 35704,
+ 35705,
+ 35706,
+ 35707,
+ 35708,
+ 35709,
+ 35710,
+ 35711,
+ 35712,
+ 35713,
+ 35714,
+ 35715,
+ 35716,
+ 35717,
+ 35718,
+ 35719,
+ 35720,
+ 35721,
+ 35722,
+ 35723,
+ 35724,
+ 35725,
+ 35726,
+ 35727,
+ 35728,
+ 35729,
+ 35730,
+ 35731,
+ 35732,
+ 35733,
+ 35734,
+ 35735,
+ 35736,
+ 35737,
+ 35738,
+ 35739,
+ 35740,
+ 35741,
+ 35742,
+ 35743,
+ 35744,
+ 35745,
+ 35746,
+ 35747,
+ 35748,
+ 35749,
+ 35750,
+ 35751,
+ 35752,
+ 35753,
+ 35754,
+ 35755,
+ 35756,
+ 35757,
+ 35758,
+ 35759,
+ 35760,
+ 35761,
+ 35762,
+ 35763,
+ 35764,
+ 35765,
+ 35766,
+ 35767,
+ 35768,
+ 35769,
+ 35770,
+ 35771,
+ 35772,
+ 35773,
+ 35774,
+ 35775,
+ 35776,
+ 35777,
+ 35778,
+ 35779,
+ 35780,
+ 35781,
+ 35782,
+ 35783,
+ 35784,
+ 35785,
+ 35786,
+ 35787,
+ 35788,
+ 35789,
+ 35790,
+ 35791,
+ 35792,
+ 35793,
+ 35794,
+ 35795,
+ 35796,
+ 35797,
+ 35798,
+ 35799,
+ 35800,
+ 35801,
+ 35802,
+ 35803,
+ 35804,
+ 35805,
+ 35806,
+ 35807,
+ 35808,
+ 35809,
+ 35810,
+ 35811,
+ 35812,
+ 35813,
+ 35814,
+ 35815,
+ 35816,
+ 35817,
+ 35818,
+ 35819,
+ 35820,
+ 35821,
+ 35822,
+ 35823,
+ 35824,
+ 35825,
+ 35826,
+ 35827,
+ 35828,
+ 35829,
+ 35830,
+ 35831,
+ 35832,
+ 35833,
+ 35834,
+ 35835,
+ 35836,
+ 35837,
+ 35838,
+ 35839,
+ 35840,
+ 35841,
+ 35842,
+ 35843,
+ 35844,
+ 35845,
+ 35846,
+ 35847,
+ 35848,
+ 35849,
+ 35850,
+ 35851,
+ 35852,
+ 35853,
+ 35854,
+ 35855,
+ 35856,
+ 35857,
+ 35858,
+ 35859,
+ 35860,
+ 35861,
+ 35862,
+ 35863,
+ 35864,
+ 35865,
+ 35866,
+ 35867,
+ 35868,
+ 35869,
+ 35870,
+ 35871,
+ 35872,
+ 35873,
+ 35874,
+ 35875,
+ 35876,
+ 35877,
+ 35878,
+ 35879,
+ 35880,
+ 35881,
+ 35882,
+ 35883,
+ 35884,
+ 35885,
+ 35886,
+ 35887,
+ 35888,
+ 35889,
+ 35890,
+ 35891,
+ 35892,
+ 35893,
+ 35894,
+ 35895,
+ 35896,
+ 35897,
+ 35898,
+ 35899,
+ 35900,
+ 35901,
+ 35902,
+ 35903,
+ 35904,
+ 35905,
+ 35906,
+ 35907,
+ 35908,
+ 35909,
+ 35910,
+ 35911,
+ 35912,
+ 35913,
+ 35914,
+ 35915,
+ 35916,
+ 35917,
+ 35918,
+ 35919,
+ 35920,
+ 35921,
+ 35922,
+ 35923,
+ 35924,
+ 35925,
+ 35926,
+ 35927,
+ 35928,
+ 35929,
+ 35930,
+ 35931,
+ 35932,
+ 35933,
+ 35934,
+ 35935,
+ 35936,
+ 35937,
+ 35938,
+ 35939,
+ 35940,
+ 35941,
+ 35942,
+ 35943,
+ 35944,
+ 35945,
+ 35946,
+ 35947,
+ 35948,
+ 35949,
+ 35950,
+ 35951,
+ 35952,
+ 35953,
+ 35954,
+ 35955,
+ 35956,
+ 35957,
+ 35958,
+ 35959,
+ 35960,
+ 35961,
+ 35962,
+ 35963,
+ 35964,
+ 35965,
+ 35966,
+ 35967,
+ 35968,
+ 35969,
+ 35970,
+ 35971,
+ 35972,
+ 35973,
+ 35974,
+ 35975,
+ 35976,
+ 35977,
+ 35978,
+ 35979,
+ 35980,
+ 35981,
+ 35982,
+ 35983,
+ 35984,
+ 35985,
+ 35986,
+ 35987,
+ 35988,
+ 35989,
+ 35990,
+ 35991,
+ 35992,
+ 35993,
+ 35994,
+ 35995,
+ 35996,
+ 35997,
+ 35998,
+ 35999,
+ 36000,
+ 36001,
+ 36002,
+ 36003,
+ 36004,
+ 36005,
+ 36006,
+ 36007,
+ 36008,
+ 36009,
+ 36010,
+ 36011,
+ 36012,
+ 36013,
+ 36014,
+ 36015,
+ 36016,
+ 36017,
+ 36018,
+ 36019,
+ 36020,
+ 36021,
+ 36022,
+ 36023,
+ 36024,
+ 36025,
+ 36026,
+ 36027,
+ 36028,
+ 36029,
+ 36030,
+ 36031,
+ 36032,
+ 36033,
+ 36034,
+ 36035,
+ 36036,
+ 36037,
+ 36038,
+ 36039,
+ 36040,
+ 36041,
+ 36042,
+ 36043,
+ 36044,
+ 36045,
+ 36046,
+ 36047,
+ 36048,
+ 36049,
+ 36050,
+ 36051,
+ 36052,
+ 36053,
+ 36054,
+ 36055,
+ 36056,
+ 36057,
+ 36058,
+ 36059,
+ 36060,
+ 36061,
+ 36062,
+ 36063,
+ 36064,
+ 36065,
+ 36066,
+ 36067,
+ 36068,
+ 36069,
+ 36070,
+ 36071,
+ 36072,
+ 36073,
+ 36074,
+ 36075,
+ 36076,
+ 36077,
+ 36078,
+ 36079,
+ 36080,
+ 36081,
+ 36082,
+ 36083,
+ 36084,
+ 36085,
+ 36086,
+ 36087,
+ 36088,
+ 36089,
+ 36090,
+ 36091,
+ 36092,
+ 36093,
+ 36094,
+ 36095,
+ 36096,
+ 36097,
+ 36098,
+ 36099,
+ 36100,
+ 36101,
+ 36102,
+ 36103,
+ 36104,
+ 36105,
+ 36106,
+ 36107,
+ 36108,
+ 36109,
+ 36110,
+ 36111,
+ 36112,
+ 36113,
+ 36114,
+ 36115,
+ 36116,
+ 36117,
+ 36118,
+ 36119,
+ 36120,
+ 36121,
+ 36122,
+ 36123,
+ 36124,
+ 36125,
+ 36126,
+ 36127,
+ 36128,
+ 36129,
+ 36130,
+ 36131,
+ 36132,
+ 36133,
+ 36134,
+ 36135,
+ 36136,
+ 36137,
+ 36138,
+ 36139,
+ 36140,
+ 36141,
+ 36142,
+ 36143,
+ 36144,
+ 36145,
+ 36146,
+ 36147,
+ 36148,
+ 36149,
+ 36150,
+ 36151,
+ 36152,
+ 36153,
+ 36154,
+ 36155,
+ 36156,
+ 36157,
+ 36158,
+ 36159,
+ 36160,
+ 36161,
+ 36162,
+ 36163,
+ 36164,
+ 36165,
+ 36166,
+ 36167,
+ 36168,
+ 36169,
+ 36170,
+ 36171,
+ 36172,
+ 36173,
+ 36174,
+ 36175,
+ 36176,
+ 36177,
+ 36178,
+ 36179,
+ 36180,
+ 36181,
+ 36182,
+ 36183,
+ 36184,
+ 36185,
+ 36186,
+ 36187,
+ 36188,
+ 36189,
+ 36190,
+ 36191,
+ 36192,
+ 36193,
+ 36194,
+ 36195,
+ 36196,
+ 36197,
+ 36198,
+ 36199,
+ 36200,
+ 36201,
+ 36202,
+ 36203,
+ 36204,
+ 36205,
+ 36206,
+ 36207,
+ 36208,
+ 36209,
+ 36210,
+ 36211,
+ 36212,
+ 36213,
+ 36214,
+ 36215,
+ 36216,
+ 36217,
+ 36218,
+ 36219,
+ 36220,
+ 36221,
+ 36222,
+ 36223,
+ 36224,
+ 36225,
+ 36226,
+ 36227,
+ 36228,
+ 36229,
+ 36230,
+ 36231,
+ 36232,
+ 36233,
+ 36234,
+ 36235,
+ 36236,
+ 36237,
+ 36238,
+ 36239,
+ 36240,
+ 36241,
+ 36242,
+ 36243,
+ 36244,
+ 36245,
+ 36246,
+ 36247,
+ 36248,
+ 36249,
+ 36250,
+ 36251,
+ 36252,
+ 36253,
+ 36254,
+ 36255,
+ 36256,
+ 36257,
+ 36258,
+ 36259,
+ 36260,
+ 36261,
+ 36262,
+ 36263,
+ 36264,
+ 36265,
+ 36266,
+ 36267,
+ 36268,
+ 36269,
+ 36270,
+ 36271,
+ 36272,
+ 36273,
+ 36274,
+ 36275,
+ 36276,
+ 36277,
+ 36278,
+ 36279,
+ 36280,
+ 36281,
+ 36282,
+ 36283,
+ 36284,
+ 36285,
+ 36286,
+ 36287,
+ 36288,
+ 36289,
+ 36290,
+ 36291,
+ 36292,
+ 36293,
+ 36294,
+ 36295,
+ 36296,
+ 36297,
+ 36298,
+ 36299,
+ 36300,
+ 36301,
+ 36302,
+ 36303,
+ 36304,
+ 36305,
+ 36306,
+ 36307,
+ 36308,
+ 36309,
+ 36310,
+ 36311,
+ 36312,
+ 36313,
+ 36314,
+ 36315,
+ 36316,
+ 36317,
+ 36318,
+ 36319,
+ 36320,
+ 36321,
+ 36322,
+ 36323,
+ 36324,
+ 36325,
+ 36326,
+ 36327,
+ 36328,
+ 36329,
+ 36330,
+ 36331,
+ 36332,
+ 36333,
+ 36334,
+ 36335,
+ 36336,
+ 36337,
+ 36338,
+ 36339,
+ 36340,
+ 36341,
+ 36342,
+ 36343,
+ 36344,
+ 36345,
+ 36346,
+ 36347,
+ 36348,
+ 36349,
+ 36350,
+ 36351,
+ 36352,
+ 36353,
+ 36354,
+ 36355,
+ 36356,
+ 36357,
+ 36358,
+ 36359,
+ 36360,
+ 36361,
+ 36362,
+ 36363,
+ 36364,
+ 36365,
+ 36366,
+ 36367,
+ 36368,
+ 36369,
+ 36370,
+ 36371,
+ 36372,
+ 36373,
+ 36374,
+ 36375,
+ 36376,
+ 36377,
+ 36378,
+ 36379,
+ 36380,
+ 36381,
+ 36382,
+ 36383,
+ 36384,
+ 36385,
+ 36386,
+ 36387,
+ 36388,
+ 36389,
+ 36390,
+ 36391,
+ 36392,
+ 36393,
+ 36394,
+ 36395,
+ 36396,
+ 36397,
+ 36398,
+ 36399,
+ 36400,
+ 36401,
+ 36402,
+ 36403,
+ 36404,
+ 36405,
+ 36406,
+ 36407,
+ 36408,
+ 36409,
+ 36410,
+ 36411,
+ 36412,
+ 36413,
+ 36414,
+ 36415,
+ 36416,
+ 36417,
+ 36418,
+ 36419,
+ 36420,
+ 36421,
+ 36422,
+ 36423,
+ 36424,
+ 36425,
+ 36426,
+ 36427,
+ 36428,
+ 36429,
+ 36430,
+ 36431,
+ 36432,
+ 36433,
+ 36434,
+ 36435,
+ 36436,
+ 36437,
+ 36438,
+ 36439,
+ 36440,
+ 36441,
+ 36442,
+ 36443,
+ 36444,
+ 36445,
+ 36446,
+ 36447,
+ 36448,
+ 36449,
+ 36450,
+ 36451,
+ 36452,
+ 36453,
+ 36454,
+ 36455,
+ 36456,
+ 36457,
+ 36458,
+ 36459,
+ 36460,
+ 36461,
+ 36462,
+ 36463,
+ 36464,
+ 36465,
+ 36466,
+ 36467,
+ 36468,
+ 36469,
+ 36470,
+ 36471,
+ 36472,
+ 36473,
+ 36474,
+ 36475,
+ 36476,
+ 36477,
+ 36478,
+ 36479,
+ 36480,
+ 36481,
+ 36482,
+ 36483,
+ 36484,
+ 36485,
+ 36486,
+ 36487,
+ 36488,
+ 36489,
+ 36490,
+ 36491,
+ 36492,
+ 36493,
+ 36494,
+ 36495,
+ 36496,
+ 36497,
+ 36498,
+ 36499,
+ 36500,
+ 36501,
+ 36502,
+ 36503,
+ 36504,
+ 36505,
+ 36506,
+ 36507,
+ 36508,
+ 36509,
+ 36510,
+ 36511,
+ 36512,
+ 36513,
+ 36514,
+ 36515,
+ 36516,
+ 36517,
+ 36518,
+ 36519,
+ 36520,
+ 36521,
+ 36522,
+ 36523,
+ 36524,
+ 36525,
+ 36526,
+ 36527,
+ 36528,
+ 36529,
+ 36530,
+ 36531,
+ 36532,
+ 36533,
+ 36534,
+ 36535,
+ 36536,
+ 36537,
+ 36538,
+ 36539,
+ 36540,
+ 36541,
+ 36542,
+ 36543,
+ 36544,
+ 36545,
+ 36546,
+ 36547,
+ 36548,
+ 36549,
+ 36550,
+ 36551,
+ 36552,
+ 36553,
+ 36554,
+ 36555,
+ 36556,
+ 36557,
+ 36558,
+ 36559,
+ 36560,
+ 36561,
+ 36562,
+ 36563,
+ 36564,
+ 36565,
+ 36566,
+ 36567,
+ 36568,
+ 36569,
+ 36570,
+ 36571,
+ 36572,
+ 36573,
+ 36574,
+ 36575,
+ 36576,
+ 36577,
+ 36578,
+ 36579,
+ 36580,
+ 36581,
+ 36582,
+ 36583,
+ 36584,
+ 36585,
+ 36586,
+ 36587,
+ 36588,
+ 36589,
+ 36590,
+ 36591,
+ 36592,
+ 36593,
+ 36594,
+ 36595,
+ 36596,
+ 36597,
+ 36598,
+ 36599,
+ 36600,
+ 36601,
+ 36602,
+ 36603,
+ 36604,
+ 36605,
+ 36606,
+ 36607,
+ 36608,
+ 36609,
+ 36610,
+ 36611,
+ 36612,
+ 36613,
+ 36614,
+ 36615,
+ 36616,
+ 36617,
+ 36618,
+ 36619,
+ 36620,
+ 36621,
+ 36622,
+ 36623,
+ 36624,
+ 36625,
+ 36626,
+ 36627,
+ 36628,
+ 36629,
+ 36630,
+ 36631,
+ 36632,
+ 36633,
+ 36634,
+ 36635,
+ 36636,
+ 36637,
+ 36638,
+ 36639,
+ 36640,
+ 36641,
+ 36642,
+ 36643,
+ 36644,
+ 36645,
+ 36646,
+ 36647,
+ 36648,
+ 36649,
+ 36650,
+ 36651,
+ 36652,
+ 36653,
+ 36654,
+ 36655,
+ 36656,
+ 36657,
+ 36658,
+ 36659,
+ 36660,
+ 36661,
+ 36662,
+ 36663,
+ 36664,
+ 36665,
+ 36666,
+ 36667,
+ 36668,
+ 36669,
+ 36670,
+ 36671,
+ 36672,
+ 36673,
+ 36674,
+ 36675,
+ 36676,
+ 36677,
+ 36678,
+ 36679,
+ 36680,
+ 36681,
+ 36682,
+ 36683,
+ 36684,
+ 36685,
+ 36686,
+ 36687,
+ 36688,
+ 36689,
+ 36690,
+ 36691,
+ 36692,
+ 36693,
+ 36694,
+ 36695,
+ 36696,
+ 36697,
+ 36698,
+ 36699,
+ 36700,
+ 36701,
+ 36702,
+ 36703,
+ 36704,
+ 36705,
+ 36706,
+ 36707,
+ 36708,
+ 36709,
+ 36710,
+ 36711,
+ 36712,
+ 36713,
+ 36714,
+ 36715,
+ 36716,
+ 36717,
+ 36718,
+ 36719,
+ 36720,
+ 36721,
+ 36722,
+ 36723,
+ 36724,
+ 36725,
+ 36726,
+ 36727,
+ 36728,
+ 36729,
+ 36730,
+ 36731,
+ 36732,
+ 36733,
+ 36734,
+ 36735,
+ 36736,
+ 36737,
+ 36738,
+ 36739,
+ 36740,
+ 36741,
+ 36742,
+ 36743,
+ 36744,
+ 36745,
+ 36746,
+ 36747,
+ 36748,
+ 36749,
+ 36750,
+ 36751,
+ 36752,
+ 36753,
+ 36754,
+ 36755,
+ 36756,
+ 36757,
+ 36758,
+ 36759,
+ 36760,
+ 36761,
+ 36762,
+ 36763,
+ 36764,
+ 36765,
+ 36766,
+ 36767,
+ 36768,
+ 36769,
+ 36770,
+ 36771,
+ 36772,
+ 36773,
+ 36774,
+ 36775,
+ 36776,
+ 36777,
+ 36778,
+ 36779,
+ 36780,
+ 36781,
+ 36782,
+ 36783,
+ 36784,
+ 36785,
+ 36786,
+ 36787,
+ 36788,
+ 36789,
+ 36790,
+ 36791,
+ 36792,
+ 36793,
+ 36794,
+ 36795,
+ 36796,
+ 36797,
+ 36798,
+ 36799,
+ 36800,
+ 36801,
+ 36802,
+ 36803,
+ 36804,
+ 36805,
+ 36806,
+ 36807,
+ 36808,
+ 36809,
+ 36810,
+ 36811,
+ 36812,
+ 36813,
+ 36814,
+ 36815,
+ 36816,
+ 36817,
+ 36818,
+ 36819,
+ 36820,
+ 36821,
+ 36822,
+ 36823,
+ 36824,
+ 36825,
+ 36826,
+ 36827,
+ 36828,
+ 36829,
+ 36830,
+ 36831,
+ 36832,
+ 36833,
+ 36834,
+ 36835,
+ 36836,
+ 36837,
+ 36838,
+ 36839,
+ 36840,
+ 36841,
+ 36842,
+ 36843,
+ 36844,
+ 36845,
+ 36846,
+ 36847,
+ 36848,
+ 36849,
+ 36850,
+ 36851,
+ 36852,
+ 36853,
+ 36854,
+ 36855,
+ 36856,
+ 36857,
+ 36858,
+ 36859,
+ 36860,
+ 36861,
+ 36862,
+ 36863,
+ 36864,
+ 36865,
+ 36866,
+ 36867,
+ 36868,
+ 36869,
+ 36870,
+ 36871,
+ 36872,
+ 36873,
+ 36874,
+ 36875,
+ 36876,
+ 36877,
+ 36878,
+ 36879,
+ 36880,
+ 36881,
+ 36882,
+ 36883,
+ 36884,
+ 36885,
+ 36886,
+ 36887,
+ 36888,
+ 36889,
+ 36890,
+ 36891,
+ 36892,
+ 36893,
+ 36894,
+ 36895,
+ 36896,
+ 36897,
+ 36898,
+ 36899,
+ 36900,
+ 36901,
+ 36902,
+ 36903,
+ 36904,
+ 36905,
+ 36906,
+ 36907,
+ 36908,
+ 36909,
+ 36910,
+ 36911,
+ 36912,
+ 36913,
+ 36914,
+ 36915,
+ 36916,
+ 36917,
+ 36918,
+ 36919,
+ 36920,
+ 36921,
+ 36922,
+ 36923,
+ 36924,
+ 36925,
+ 36926,
+ 36927,
+ 36928,
+ 36929,
+ 36930,
+ 36931,
+ 36932,
+ 36933,
+ 36934,
+ 36935,
+ 36936,
+ 36937,
+ 36938,
+ 36939,
+ 36940,
+ 36941,
+ 36942,
+ 36943,
+ 36944,
+ 36945,
+ 36946,
+ 36947,
+ 36948,
+ 36949,
+ 36950,
+ 36951,
+ 36952,
+ 36953,
+ 36954,
+ 36955,
+ 36956,
+ 36957,
+ 36958,
+ 36959,
+ 36960,
+ 36961,
+ 36962,
+ 36963,
+ 36964,
+ 36965,
+ 36966,
+ 36967,
+ 36968,
+ 36969,
+ 36970,
+ 36971,
+ 36972,
+ 36973,
+ 36974,
+ 36975,
+ 36976,
+ 36977,
+ 36978,
+ 36979,
+ 36980,
+ 36981,
+ 36982,
+ 36983,
+ 36984,
+ 36985,
+ 36986,
+ 36987,
+ 36988,
+ 36989,
+ 36990,
+ 36991,
+ 36992,
+ 36993,
+ 36994,
+ 36995,
+ 36996,
+ 36997,
+ 36998,
+ 36999,
+ 37000,
+ 37001,
+ 37002,
+ 37003,
+ 37004,
+ 37005,
+ 37006,
+ 37007,
+ 37008,
+ 37009,
+ 37010,
+ 37011,
+ 37012,
+ 37013,
+ 37014,
+ 37015,
+ 37016,
+ 37017,
+ 37018,
+ 37019,
+ 37020,
+ 37021,
+ 37022,
+ 37023,
+ 37024,
+ 37025,
+ 37026,
+ 37027,
+ 37028,
+ 37029,
+ 37030,
+ 37031,
+ 37032,
+ 37033,
+ 37034,
+ 37035,
+ 37036,
+ 37037,
+ 37038,
+ 37039,
+ 37040,
+ 37041,
+ 37042,
+ 37043,
+ 37044,
+ 37045,
+ 37046,
+ 37047,
+ 37048,
+ 37049,
+ 37050,
+ 37051,
+ 37052,
+ 37053,
+ 37054,
+ 37055,
+ 37056,
+ 37057,
+ 37058,
+ 37059,
+ 37060,
+ 37061,
+ 37062,
+ 37063,
+ 37064,
+ 37065,
+ 37066,
+ 37067,
+ 37068,
+ 37069,
+ 37070,
+ 37071,
+ 37072,
+ 37073,
+ 37074,
+ 37075,
+ 37076,
+ 37077,
+ 37078,
+ 37079,
+ 37080,
+ 37081,
+ 37082,
+ 37083,
+ 37084,
+ 37085,
+ 37086,
+ 37087,
+ 37088,
+ 37089,
+ 37090,
+ 37091,
+ 37092,
+ 37093,
+ 37094,
+ 37095,
+ 37096,
+ 37097,
+ 37098,
+ 37099,
+ 37100,
+ 37101,
+ 37102,
+ 37103,
+ 37104,
+ 37105,
+ 37106,
+ 37107,
+ 37108,
+ 37109,
+ 37110,
+ 37111,
+ 37112,
+ 37113,
+ 37114,
+ 37115,
+ 37116,
+ 37117,
+ 37118,
+ 37119,
+ 37120,
+ 37121,
+ 37122,
+ 37123,
+ 37124,
+ 37125,
+ 37126,
+ 37127,
+ 37128,
+ 37129,
+ 37130,
+ 37131,
+ 37132,
+ 37133,
+ 37134,
+ 37135,
+ 37136,
+ 37137,
+ 37138,
+ 37139,
+ 37140,
+ 37141,
+ 37142,
+ 37143,
+ 37144,
+ 37145,
+ 37146,
+ 37147,
+ 37148,
+ 37149,
+ 37150,
+ 37151,
+ 37152,
+ 37153,
+ 37154,
+ 37155,
+ 37156,
+ 37157,
+ 37158,
+ 37159,
+ 37160,
+ 37161,
+ 37162,
+ 37163,
+ 37164,
+ 37165,
+ 37166,
+ 37167,
+ 37168,
+ 37169,
+ 37170,
+ 37171,
+ 37172,
+ 37173,
+ 37174,
+ 37175,
+ 37176,
+ 37177,
+ 37178,
+ 37179,
+ 37180,
+ 37181,
+ 37182,
+ 37183,
+ 37184,
+ 37185,
+ 37186,
+ 37187,
+ 37188,
+ 37189,
+ 37190,
+ 37191,
+ 37192,
+ 37193,
+ 37194,
+ 37195,
+ 37196,
+ 37197,
+ 37198,
+ 37199,
+ 37200,
+ 37201,
+ 37202,
+ 37203,
+ 37204,
+ 37205,
+ 37206,
+ 37207,
+ 37208,
+ 37209,
+ 37210,
+ 37211,
+ 37212,
+ 37213,
+ 37214,
+ 37215,
+ 37216,
+ 37217,
+ 37218,
+ 37219,
+ 37220,
+ 37221,
+ 37222,
+ 37223,
+ 37224,
+ 37225,
+ 37226,
+ 37227,
+ 37228,
+ 37229,
+ 37230,
+ 37231,
+ 37232,
+ 37233,
+ 37234,
+ 37235,
+ 37236,
+ 37237,
+ 37238,
+ 37239,
+ 37240,
+ 37241,
+ 37242,
+ 37243,
+ 37244,
+ 37245,
+ 37246,
+ 37247,
+ 37248,
+ 37249,
+ 37250,
+ 37251,
+ 37252,
+ 37253,
+ 37254,
+ 37255,
+ 37256,
+ 37257,
+ 37258,
+ 37259,
+ 37260,
+ 37261,
+ 37262,
+ 37263,
+ 37264,
+ 37265,
+ 37266,
+ 37267,
+ 37268,
+ 37269,
+ 37270,
+ 37271,
+ 37272,
+ 37273,
+ 37274,
+ 37275,
+ 37276,
+ 37277,
+ 37278,
+ 37279,
+ 37280,
+ 37281,
+ 37282,
+ 37283,
+ 37284,
+ 37285,
+ 37286,
+ 37287,
+ 37288,
+ 37289,
+ 37290,
+ 37291,
+ 37292,
+ 37293,
+ 37294,
+ 37295,
+ 37296,
+ 37297,
+ 37298,
+ 37299,
+ 37300,
+ 37301,
+ 37302,
+ 37303,
+ 37304,
+ 37305,
+ 37306,
+ 37307,
+ 37308,
+ 37309,
+ 37310,
+ 37311,
+ 37312,
+ 37313,
+ 37314,
+ 37315,
+ 37316,
+ 37317,
+ 37318,
+ 37319,
+ 37320,
+ 37321,
+ 37322,
+ 37323,
+ 37324,
+ 37325,
+ 37326,
+ 37327,
+ 37328,
+ 37329,
+ 37330,
+ 37331,
+ 37332,
+ 37333,
+ 37334,
+ 37335,
+ 37336,
+ 37337,
+ 37338,
+ 37339,
+ 37340,
+ 37341,
+ 37342,
+ 37343,
+ 37344,
+ 37345,
+ 37346,
+ 37347,
+ 37348,
+ 37349,
+ 37350,
+ 37351,
+ 37352,
+ 37353,
+ 37354,
+ 37355,
+ 37356,
+ 37357,
+ 37358,
+ 37359,
+ 37360,
+ 37361,
+ 37362,
+ 37363,
+ 37364,
+ 37365,
+ 37366,
+ 37367,
+ 37368,
+ 37369,
+ 37370,
+ 37371,
+ 37372,
+ 37373,
+ 37374,
+ 37375,
+ 37376,
+ 37377,
+ 37378,
+ 37379,
+ 37380,
+ 37381,
+ 37382,
+ 37383,
+ 37384,
+ 37385,
+ 37386,
+ 37387,
+ 37388,
+ 37389,
+ 37390,
+ 37391,
+ 37392,
+ 37393,
+ 37394,
+ 37395,
+ 37396,
+ 37397,
+ 37398,
+ 37399,
+ 37400,
+ 37401,
+ 37402,
+ 37403,
+ 37404,
+ 37405,
+ 37406,
+ 37407,
+ 37408,
+ 37409,
+ 37410,
+ 37411,
+ 37412,
+ 37413,
+ 37414,
+ 37415,
+ 37416,
+ 37417,
+ 37418,
+ 37419,
+ 37420,
+ 37421,
+ 37422,
+ 37423,
+ 37424,
+ 37425,
+ 37426,
+ 37427,
+ 37428,
+ 37429,
+ 37430,
+ 37431,
+ 37432,
+ 37433,
+ 37434,
+ 37435,
+ 37436,
+ 37437,
+ 37438,
+ 37439,
+ 37440,
+ 37441,
+ 37442,
+ 37443,
+ 37444,
+ 37445,
+ 37446,
+ 37447,
+ 37448,
+ 37449,
+ 37450,
+ 37451,
+ 37452,
+ 37453,
+ 37454,
+ 37455,
+ 37456,
+ 37457,
+ 37458,
+ 37459,
+ 37460,
+ 37461,
+ 37462,
+ 37463,
+ 37464,
+ 37465,
+ 37466,
+ 37467,
+ 37468,
+ 37469,
+ 37470,
+ 37471,
+ 37472,
+ 37473,
+ 37474,
+ 37475,
+ 37476,
+ 37477,
+ 37478,
+ 37479,
+ 37480,
+ 37481,
+ 37482,
+ 37483,
+ 37484,
+ 37485,
+ 37486,
+ 37487,
+ 37488,
+ 37489,
+ 37490,
+ 37491,
+ 37492,
+ 37493,
+ 37494,
+ 37495,
+ 37496,
+ 37497,
+ 37498,
+ 37499,
+ 37500,
+ 37501,
+ 37502,
+ 37503,
+ 37504,
+ 37505,
+ 37506,
+ 37507,
+ 37508,
+ 37509,
+ 37510,
+ 37511,
+ 37512,
+ 37513,
+ 37514,
+ 37515,
+ 37516,
+ 37517,
+ 37518,
+ 37519,
+ 37520,
+ 37521,
+ 37522,
+ 37523,
+ 37524,
+ 37525,
+ 37526,
+ 37527,
+ 37528,
+ 37529,
+ 37530,
+ 37531,
+ 37532,
+ 37533,
+ 37534,
+ 37535,
+ 37536,
+ 37537,
+ 37538,
+ 37539,
+ 37540,
+ 37541,
+ 37542,
+ 37543,
+ 37544,
+ 37545,
+ 37546,
+ 37547,
+ 37548,
+ 37549,
+ 37550,
+ 37551,
+ 37552,
+ 37553,
+ 37554,
+ 37555,
+ 37556,
+ 37557,
+ 37558,
+ 37559,
+ 37560,
+ 37561,
+ 37562,
+ 37563,
+ 37564,
+ 37565,
+ 37566,
+ 37567,
+ 37568,
+ 37569,
+ 37570,
+ 37571,
+ 37572,
+ 37573,
+ 37574,
+ 37575,
+ 37576,
+ 37577,
+ 37578,
+ 37579,
+ 37580,
+ 37581,
+ 37582,
+ 37583,
+ 37584,
+ 37585,
+ 37586,
+ 37587,
+ 37588,
+ 37589,
+ 37590,
+ 37591,
+ 37592,
+ 37593,
+ 37594,
+ 37595,
+ 37596,
+ 37597,
+ 37598,
+ 37599,
+ 37600,
+ 37601,
+ 37602,
+ 37603,
+ 37604,
+ 37605,
+ 37606,
+ 37607,
+ 37608,
+ 37609,
+ 37610,
+ 37611,
+ 37612,
+ 37613,
+ 37614,
+ 37615,
+ 37616,
+ 37617,
+ 37618,
+ 37619,
+ 37620,
+ 37621,
+ 37622,
+ 37623,
+ 37624,
+ 37625,
+ 37626,
+ 37627,
+ 37628,
+ 37629,
+ 37630,
+ 37631,
+ 37632,
+ 37633,
+ 37634,
+ 37635,
+ 37636,
+ 37637,
+ 37638,
+ 37639,
+ 37640,
+ 37641,
+ 37642,
+ 37643,
+ 37644,
+ 37645,
+ 37646,
+ 37647,
+ 37648,
+ 37649,
+ 37650,
+ 37651,
+ 37652,
+ 37653,
+ 37654,
+ 37655,
+ 37656,
+ 37657,
+ 37658,
+ 37659,
+ 37660,
+ 37661,
+ 37662,
+ 37663,
+ 37664,
+ 37665,
+ 37666,
+ 37667,
+ 37668,
+ 37669,
+ 37670,
+ 37671,
+ 37672,
+ 37673,
+ 37674,
+ 37675,
+ 37676,
+ 37677,
+ 37678,
+ 37679,
+ 37680,
+ 37681,
+ 37682,
+ 37683,
+ 37684,
+ 37685,
+ 37686,
+ 37687,
+ 37688,
+ 37689,
+ 37690,
+ 37691,
+ 37692,
+ 37693,
+ 37694,
+ 37695,
+ 37696,
+ 37697,
+ 37698,
+ 37699,
+ 37700,
+ 37701,
+ 37702,
+ 37703,
+ 37704,
+ 37705,
+ 37706,
+ 37707,
+ 37708,
+ 37709,
+ 37710,
+ 37711,
+ 37712,
+ 37713,
+ 37714,
+ 37715,
+ 37716,
+ 37717,
+ 37718,
+ 37719,
+ 37720,
+ 37721,
+ 37722,
+ 37723,
+ 37724,
+ 37725,
+ 37726,
+ 37727,
+ 37728,
+ 37729,
+ 37730,
+ 37731,
+ 37732,
+ 37733,
+ 37734,
+ 37735,
+ 37736,
+ 37737,
+ 37738,
+ 37739,
+ 37740,
+ 37741,
+ 37742,
+ 37743,
+ 37744,
+ 37745,
+ 37746,
+ 37747,
+ 37748,
+ 37749,
+ 37750,
+ 37751,
+ 37752,
+ 37753,
+ 37754,
+ 37755,
+ 37756,
+ 37757,
+ 37758,
+ 37759,
+ 37760,
+ 37761,
+ 37762,
+ 37763,
+ 37764,
+ 37765,
+ 37766,
+ 37767,
+ 37768,
+ 37769,
+ 37770,
+ 37771,
+ 37772,
+ 37773,
+ 37774,
+ 37775,
+ 37776,
+ 37777,
+ 37778,
+ 37779,
+ 37780,
+ 37781,
+ 37782,
+ 37783,
+ 37784,
+ 37785,
+ 37786,
+ 37787,
+ 37788,
+ 37789,
+ 37790,
+ 37791,
+ 37792,
+ 37793,
+ 37794,
+ 37795,
+ 37796,
+ 37797,
+ 37798,
+ 37799,
+ 37800,
+ 37801,
+ 37802,
+ 37803,
+ 37804,
+ 37805,
+ 37806,
+ 37807,
+ 37808,
+ 37809,
+ 37810,
+ 37811,
+ 37812,
+ 37813,
+ 37814,
+ 37815,
+ 37816,
+ 37817,
+ 37818,
+ 37819,
+ 37820,
+ 37821,
+ 37822,
+ 37823,
+ 37824,
+ 37825,
+ 37826,
+ 37827,
+ 37828,
+ 37829,
+ 37830,
+ 37831,
+ 37832,
+ 37833,
+ 37834,
+ 37835,
+ 37836,
+ 37837,
+ 37838,
+ 37839,
+ 37840,
+ 37841,
+ 37842,
+ 37843,
+ 37844,
+ 37845,
+ 37846,
+ 37847,
+ 37848,
+ 37849,
+ 37850,
+ 37851,
+ 37852,
+ 37853,
+ 37854,
+ 37855,
+ 37856,
+ 37857,
+ 37858,
+ 37859,
+ 37860,
+ 37861,
+ 37862,
+ 37863,
+ 37864,
+ 37865,
+ 37866,
+ 37867,
+ 37868,
+ 37869,
+ 37870,
+ 37871,
+ 37872,
+ 37873,
+ 37874,
+ 37875,
+ 37876,
+ 37877,
+ 37878,
+ 37879,
+ 37880,
+ 37881,
+ 37882,
+ 37883,
+ 37884,
+ 37885,
+ 37886,
+ 37887,
+ 37888,
+ 37889,
+ 37890,
+ 37891,
+ 37892,
+ 37893,
+ 37894,
+ 37895,
+ 37896,
+ 37897,
+ 37898,
+ 37899,
+ 37900,
+ 37901,
+ 37902,
+ 37903,
+ 37904,
+ 37905,
+ 37906,
+ 37907,
+ 37908,
+ 37909,
+ 37910,
+ 37911,
+ 37912,
+ 37913,
+ 37914,
+ 37915,
+ 37916,
+ 37917,
+ 37918,
+ 37919,
+ 37920,
+ 37921,
+ 37922,
+ 37923,
+ 37924,
+ 37925,
+ 37926,
+ 37927,
+ 37928,
+ 37929,
+ 37930,
+ 37931,
+ 37932,
+ 37933,
+ 37934,
+ 37935,
+ 37936,
+ 37937,
+ 37938,
+ 37939,
+ 37940,
+ 37941,
+ 37942,
+ 37943,
+ 37944,
+ 37945,
+ 37946,
+ 37947,
+ 37948,
+ 37949,
+ 37950,
+ 37951,
+ 37952,
+ 37953,
+ 37954,
+ 37955,
+ 37956,
+ 37957,
+ 37958,
+ 37959,
+ 37960,
+ 37961,
+ 37962,
+ 37963,
+ 37964,
+ 37965,
+ 37966,
+ 37967,
+ 37968,
+ 37969,
+ 37970,
+ 37971,
+ 37972,
+ 37973,
+ 37974,
+ 37975,
+ 37976,
+ 37977,
+ 37978,
+ 37979,
+ 37980,
+ 37981,
+ 37982,
+ 37983,
+ 37984,
+ 37985,
+ 37986,
+ 37987,
+ 37988,
+ 37989,
+ 37990,
+ 37991,
+ 37992,
+ 37993,
+ 37994,
+ 37995,
+ 37996,
+ 37997,
+ 37998,
+ 37999,
+ 38000,
+ 38001,
+ 38002,
+ 38003,
+ 38004,
+ 38005,
+ 38006,
+ 38007,
+ 38008,
+ 38009,
+ 38010,
+ 38011,
+ 38012,
+ 38013,
+ 38014,
+ 38015,
+ 38016,
+ 38017,
+ 38018,
+ 38019,
+ 38020,
+ 38021,
+ 38022,
+ 38023,
+ 38024,
+ 38025,
+ 38026,
+ 38027,
+ 38028,
+ 38029,
+ 38030,
+ 38031,
+ 38032,
+ 38033,
+ 38034,
+ 38035,
+ 38036,
+ 38037,
+ 38038,
+ 38039,
+ 38040,
+ 38041,
+ 38042,
+ 38043,
+ 38044,
+ 38045,
+ 38046,
+ 38047,
+ 38048,
+ 38049,
+ 38050,
+ 38051,
+ 38052,
+ 38053,
+ 38054,
+ 38055,
+ 38056,
+ 38057,
+ 38058,
+ 38059,
+ 38060,
+ 38061,
+ 38062,
+ 38063,
+ 38064,
+ 38065,
+ 38066,
+ 38067,
+ 38068,
+ 38069,
+ 38070,
+ 38071,
+ 38072,
+ 38073,
+ 38074,
+ 38075,
+ 38076,
+ 38077,
+ 38078,
+ 38079,
+ 38080,
+ 38081,
+ 38082,
+ 38083,
+ 38084,
+ 38085,
+ 38086,
+ 38087,
+ 38088,
+ 38089,
+ 38090,
+ 38091,
+ 38092,
+ 38093,
+ 38094,
+ 38095,
+ 38096,
+ 38097,
+ 38098,
+ 38099,
+ 38100,
+ 38101,
+ 38102,
+ 38103,
+ 38104,
+ 38105,
+ 38106,
+ 38107,
+ 38108,
+ 38109,
+ 38110,
+ 38111,
+ 38112,
+ 38113,
+ 38114,
+ 38115,
+ 38116,
+ 38117,
+ 38118,
+ 38119,
+ 38120,
+ 38121,
+ 38122,
+ 38123,
+ 38124,
+ 38125,
+ 38126,
+ 38127,
+ 38128,
+ 38129,
+ 38130,
+ 38131,
+ 38132,
+ 38133,
+ 38134,
+ 38135,
+ 38136,
+ 38137,
+ 38138,
+ 38139,
+ 38140,
+ 38141,
+ 38142,
+ 38143,
+ 38144,
+ 38145,
+ 38146,
+ 38147,
+ 38148,
+ 38149,
+ 38150,
+ 38151,
+ 38152,
+ 38153,
+ 38154,
+ 38155,
+ 38156,
+ 38157,
+ 38158,
+ 38159,
+ 38160,
+ 38161,
+ 38162,
+ 38163,
+ 38164,
+ 38165,
+ 38166,
+ 38167,
+ 38168,
+ 38169,
+ 38170,
+ 38171,
+ 38172,
+ 38173,
+ 38174,
+ 38175,
+ 38176,
+ 38177,
+ 38178,
+ 38179,
+ 38180,
+ 38181,
+ 38182,
+ 38183,
+ 38184,
+ 38185,
+ 38186,
+ 38187,
+ 38188,
+ 38189,
+ 38190,
+ 38191,
+ 38192,
+ 38193,
+ 38194,
+ 38195,
+ 38196,
+ 38197,
+ 38198,
+ 38199,
+ 38200,
+ 38201,
+ 38202,
+ 38203,
+ 38204,
+ 38205,
+ 38206,
+ 38207,
+ 38208,
+ 38209,
+ 38210,
+ 38211,
+ 38212,
+ 38213,
+ 38214,
+ 38215,
+ 38216,
+ 38217,
+ 38218,
+ 38219,
+ 38220,
+ 38221,
+ 38222,
+ 38223,
+ 38224,
+ 38225,
+ 38226,
+ 38227,
+ 38228,
+ 38229,
+ 38230,
+ 38231,
+ 38232,
+ 38233,
+ 38234,
+ 38235,
+ 38236,
+ 38237,
+ 38238,
+ 38239,
+ 38240,
+ 38241,
+ 38242,
+ 38243,
+ 38244,
+ 38245,
+ 38246,
+ 38247,
+ 38248,
+ 38249,
+ 38250,
+ 38251,
+ 38252,
+ 38253,
+ 38254,
+ 38255,
+ 38256,
+ 38257,
+ 38258,
+ 38259,
+ 38260,
+ 38261,
+ 38262,
+ 38263,
+ 38264,
+ 38265,
+ 38266,
+ 38267,
+ 38268,
+ 38269,
+ 38270,
+ 38271,
+ 38272,
+ 38273,
+ 38274,
+ 38275,
+ 38276,
+ 38277,
+ 38278,
+ 38279,
+ 38280,
+ 38281,
+ 38282,
+ 38283,
+ 38284,
+ 38285,
+ 38286,
+ 38287,
+ 38288,
+ 38289,
+ 38290,
+ 38291,
+ 38292,
+ 38293,
+ 38294,
+ 38295,
+ 38296,
+ 38297,
+ 38298,
+ 38299,
+ 38300,
+ 38301,
+ 38302,
+ 38303,
+ 38304,
+ 38305,
+ 38306,
+ 38307,
+ 38308,
+ 38309,
+ 38310,
+ 38311,
+ 38312,
+ 38313,
+ 38314,
+ 38315,
+ 38316,
+ 38317,
+ 38318,
+ 38319,
+ 38320,
+ 38321,
+ 38322,
+ 38323,
+ 38324,
+ 38325,
+ 38326,
+ 38327,
+ 38328,
+ 38329,
+ 38330,
+ 38331,
+ 38332,
+ 38333,
+ 38334,
+ 38335,
+ 38336,
+ 38337,
+ 38338,
+ 38339,
+ 38340,
+ 38341,
+ 38342,
+ 38343,
+ 38344,
+ 38345,
+ 38346,
+ 38347,
+ 38348,
+ 38349,
+ 38350,
+ 38351,
+ 38352,
+ 38353,
+ 38354,
+ 38355,
+ 38356,
+ 38357,
+ 38358,
+ 38359,
+ 38360,
+ 38361,
+ 38362,
+ 38363,
+ 38364,
+ 38365,
+ 38366,
+ 38367,
+ 38368,
+ 38369,
+ 38370,
+ 38371,
+ 38372,
+ 38373,
+ 38374,
+ 38375,
+ 38376,
+ 38377,
+ 38378,
+ 38379,
+ 38380,
+ 38381,
+ 38382,
+ 38383,
+ 38384,
+ 38385,
+ 38386,
+ 38387,
+ 38388,
+ 38389,
+ 38390,
+ 38391,
+ 38392,
+ 38393,
+ 38394,
+ 38395,
+ 38396,
+ 38397,
+ 38398,
+ 38399,
+ 38400,
+ 38401,
+ 38402,
+ 38403,
+ 38404,
+ 38405,
+ 38406,
+ 38407,
+ 38408,
+ 38409,
+ 38410,
+ 38411,
+ 38412,
+ 38413,
+ 38414,
+ 38415,
+ 38416,
+ 38417,
+ 38418,
+ 38419,
+ 38420,
+ 38421,
+ 38422,
+ 38423,
+ 38424,
+ 38425,
+ 38426,
+ 38427,
+ 38428,
+ 38429,
+ 38430,
+ 38431,
+ 38432,
+ 38433,
+ 38434,
+ 38435,
+ 38436,
+ 38437,
+ 38438,
+ 38439,
+ 38440,
+ 38441,
+ 38442,
+ 38443,
+ 38444,
+ 38445,
+ 38446,
+ 38447,
+ 38448,
+ 38449,
+ 38450,
+ 38451,
+ 38452,
+ 38453,
+ 38454,
+ 38455,
+ 38456,
+ 38457,
+ 38458,
+ 38459,
+ 38460,
+ 38461,
+ 38462,
+ 38463,
+ 38464,
+ 38465,
+ 38466,
+ 38467,
+ 38468,
+ 38469,
+ 38470,
+ 38471,
+ 38472,
+ 38473,
+ 38474,
+ 38475,
+ 38476,
+ 38477,
+ 38478,
+ 38479,
+ 38480,
+ 38481,
+ 38482,
+ 38483,
+ 38484,
+ 38485,
+ 38486,
+ 38487,
+ 38488,
+ 38489,
+ 38490,
+ 38491,
+ 38492,
+ 38493,
+ 38494,
+ 38495,
+ 38496,
+ 38497,
+ 38498,
+ 38499,
+ 38500,
+ 38501,
+ 38502,
+ 38503,
+ 38504,
+ 38505,
+ 38506,
+ 38507,
+ 38508,
+ 38509,
+ 38510,
+ 38511,
+ 38512,
+ 38513,
+ 38514,
+ 38515,
+ 38516,
+ 38517,
+ 38518,
+ 38519,
+ 38520,
+ 38521,
+ 38522,
+ 38523,
+ 38524,
+ 38525,
+ 38526,
+ 38527,
+ 38528,
+ 38529,
+ 38530,
+ 38531,
+ 38532,
+ 38533,
+ 38534,
+ 38535,
+ 38536,
+ 38537,
+ 38538,
+ 38539,
+ 38540,
+ 38541,
+ 38542,
+ 38543,
+ 38544,
+ 38545,
+ 38546,
+ 38547,
+ 38548,
+ 38549,
+ 38550,
+ 38551,
+ 38552,
+ 38553,
+ 38554,
+ 38555,
+ 38556,
+ 38557,
+ 38558,
+ 38559,
+ 38560,
+ 38561,
+ 38562,
+ 38563,
+ 38564,
+ 38565,
+ 38566,
+ 38567,
+ 38568,
+ 38569,
+ 38570,
+ 38571,
+ 38572,
+ 38573,
+ 38574,
+ 38575,
+ 38576,
+ 38577,
+ 38578,
+ 38579,
+ 38580,
+ 38581,
+ 38582,
+ 38583,
+ 38584,
+ 38585,
+ 38586,
+ 38587,
+ 38588,
+ 38589,
+ 38590,
+ 38591,
+ 38592,
+ 38593,
+ 38594,
+ 38595,
+ 38596,
+ 38597,
+ 38598,
+ 38599,
+ 38600,
+ 38601,
+ 38602,
+ 38603,
+ 38604,
+ 38605,
+ 38606,
+ 38607,
+ 38608,
+ 38609,
+ 38610,
+ 38611,
+ 38612,
+ 38613,
+ 38614,
+ 38615,
+ 38616,
+ 38617,
+ 38618,
+ 38619,
+ 38620,
+ 38621,
+ 38622,
+ 38623,
+ 38624,
+ 38625,
+ 38626,
+ 38627,
+ 38628,
+ 38629,
+ 38630,
+ 38631,
+ 38632,
+ 38633,
+ 38634,
+ 38635,
+ 38636,
+ 38637,
+ 38638,
+ 38639,
+ 38640,
+ 38641,
+ 38642,
+ 38643,
+ 38644,
+ 38645,
+ 38646,
+ 38647,
+ 38648,
+ 38649,
+ 38650,
+ 38651,
+ 38652,
+ 38653,
+ 38654,
+ 38655,
+ 38656,
+ 38657,
+ 38658,
+ 38659,
+ 38660,
+ 38661,
+ 38662,
+ 38663,
+ 38664,
+ 38665,
+ 38666,
+ 38667,
+ 38668,
+ 38669,
+ 38670,
+ 38671,
+ 38672,
+ 38673,
+ 38674,
+ 38675,
+ 38676,
+ 38677,
+ 38678,
+ 38679,
+ 38680,
+ 38681,
+ 38682,
+ 38683,
+ 38684,
+ 38685,
+ 38686,
+ 38687,
+ 38688,
+ 38689,
+ 38690,
+ 38691,
+ 38692,
+ 38693,
+ 38694,
+ 38695,
+ 38696,
+ 38697,
+ 38698,
+ 38699,
+ 38700,
+ 38701,
+ 38702,
+ 38703,
+ 38704,
+ 38705,
+ 38706,
+ 38707,
+ 38708,
+ 38709,
+ 38710,
+ 38711,
+ 38712,
+ 38713,
+ 38714,
+ 38715,
+ 38716,
+ 38717,
+ 38718,
+ 38719,
+ 38720,
+ 38721,
+ 38722,
+ 38723,
+ 38724,
+ 38725,
+ 38726,
+ 38727,
+ 38728,
+ 38729,
+ 38730,
+ 38731,
+ 38732,
+ 38733,
+ 38734,
+ 38735,
+ 38736,
+ 38737,
+ 38738,
+ 38739,
+ 38740,
+ 38741,
+ 38742,
+ 38743,
+ 38744,
+ 38745,
+ 38746,
+ 38747,
+ 38748,
+ 38749,
+ 38750,
+ 38751,
+ 38752,
+ 38753,
+ 38754,
+ 38755,
+ 38756,
+ 38757,
+ 38758,
+ 38759,
+ 38760,
+ 38761,
+ 38762,
+ 38763,
+ 38764,
+ 38765,
+ 38766,
+ 38767,
+ 38768,
+ 38769,
+ 38770,
+ 38771,
+ 38772,
+ 38773,
+ 38774,
+ 38775,
+ 38776,
+ 38777,
+ 38778,
+ 38779,
+ 38780,
+ 38781,
+ 38782,
+ 38783,
+ 38784,
+ 38785,
+ 38786,
+ 38787,
+ 38788,
+ 38789,
+ 38790,
+ 38791,
+ 38792,
+ 38793,
+ 38794,
+ 38795,
+ 38796,
+ 38797,
+ 38798,
+ 38799,
+ 38800,
+ 38801,
+ 38802,
+ 38803,
+ 38804,
+ 38805,
+ 38806,
+ 38807,
+ 38808,
+ 38809,
+ 38810,
+ 38811,
+ 38812,
+ 38813,
+ 38814,
+ 38815,
+ 38816,
+ 38817,
+ 38818,
+ 38819,
+ 38820,
+ 38821,
+ 38822,
+ 38823,
+ 38824,
+ 38825,
+ 38826,
+ 38827,
+ 38828,
+ 38829,
+ 38830,
+ 38831,
+ 38832,
+ 38833,
+ 38834,
+ 38835,
+ 38836,
+ 38837,
+ 38838,
+ 38839,
+ 38840,
+ 38841,
+ 38842,
+ 38843,
+ 38844,
+ 38845,
+ 38846,
+ 38847,
+ 38848,
+ 38849,
+ 38850,
+ 38851,
+ 38852,
+ 38853,
+ 38854,
+ 38855,
+ 38856,
+ 38857,
+ 38858,
+ 38859,
+ 38860,
+ 38861,
+ 38862,
+ 38863,
+ 38864,
+ 38865,
+ 38866,
+ 38867,
+ 38868,
+ 38869,
+ 38870,
+ 38871,
+ 38872,
+ 38873,
+ 38874,
+ 38875,
+ 38876,
+ 38877,
+ 38878,
+ 38879,
+ 38880,
+ 38881,
+ 38882,
+ 38883,
+ 38884,
+ 38885,
+ 38886,
+ 38887,
+ 38888,
+ 38889,
+ 38890,
+ 38891,
+ 38892,
+ 38893,
+ 38894,
+ 38895,
+ 38896,
+ 38897,
+ 38898,
+ 38899,
+ 38900,
+ 38901,
+ 38902,
+ 38903,
+ 38904,
+ 38905,
+ 38906,
+ 38907,
+ 38908,
+ 38909,
+ 38910,
+ 38911,
+ 38912,
+ 38913,
+ 38914,
+ 38915,
+ 38916,
+ 38917,
+ 38918,
+ 38919,
+ 38920,
+ 38921,
+ 38922,
+ 38923,
+ 38924,
+ 38925,
+ 38926,
+ 38927,
+ 38928,
+ 38929,
+ 38930,
+ 38931,
+ 38932,
+ 38933,
+ 38934,
+ 38935,
+ 38936,
+ 38937,
+ 38938,
+ 38939,
+ 38940,
+ 38941,
+ 38942,
+ 38943,
+ 38944,
+ 38945,
+ 38946,
+ 38947,
+ 38948,
+ 38949,
+ 38950,
+ 38951,
+ 38952,
+ 38953,
+ 38954,
+ 38955,
+ 38956,
+ 38957,
+ 38958,
+ 38959,
+ 38960,
+ 38961,
+ 38962,
+ 38963,
+ 38964,
+ 38965,
+ 38966,
+ 38967,
+ 38968,
+ 38969,
+ 38970,
+ 38971,
+ 38972,
+ 38973,
+ 38974,
+ 38975,
+ 38976,
+ 38977,
+ 38978,
+ 38979,
+ 38980,
+ 38981,
+ 38982,
+ 38983,
+ 38984,
+ 38985,
+ 38986,
+ 38987,
+ 38988,
+ 38989,
+ 38990,
+ 38991,
+ 38992,
+ 38993,
+ 38994,
+ 38995,
+ 38996,
+ 38997,
+ 38998,
+ 38999,
+ 39000,
+ 39001,
+ 39002,
+ 39003,
+ 39004,
+ 39005,
+ 39006,
+ 39007,
+ 39008,
+ 39009,
+ 39010,
+ 39011,
+ 39012,
+ 39013,
+ 39014,
+ 39015,
+ 39016,
+ 39017,
+ 39018,
+ 39019,
+ 39020,
+ 39021,
+ 39022,
+ 39023,
+ 39024,
+ 39025,
+ 39026,
+ 39027,
+ 39028,
+ 39029,
+ 39030,
+ 39031,
+ 39032,
+ 39033,
+ 39034,
+ 39035,
+ 39036,
+ 39037,
+ 39038,
+ 39039,
+ 39040,
+ 39041,
+ 39042,
+ 39043,
+ 39044,
+ 39045,
+ 39046,
+ 39047,
+ 39048,
+ 39049,
+ 39050,
+ 39051,
+ 39052,
+ 39053,
+ 39054,
+ 39055,
+ 39056,
+ 39057,
+ 39058,
+ 39059,
+ 39060,
+ 39061,
+ 39062,
+ 39063,
+ 39064,
+ 39065,
+ 39066,
+ 39067,
+ 39068,
+ 39069,
+ 39070,
+ 39071,
+ 39072,
+ 39073,
+ 39074,
+ 39075,
+ 39076,
+ 39077,
+ 39078,
+ 39079,
+ 39080,
+ 39081,
+ 39082,
+ 39083,
+ 39084,
+ 39085,
+ 39086,
+ 39087,
+ 39088,
+ 39089,
+ 39090,
+ 39091,
+ 39092,
+ 39093,
+ 39094,
+ 39095,
+ 39096,
+ 39097,
+ 39098,
+ 39099,
+ 39100,
+ 39101,
+ 39102,
+ 39103,
+ 39104,
+ 39105,
+ 39106,
+ 39107,
+ 39108,
+ 39109,
+ 39110,
+ 39111,
+ 39112,
+ 39113,
+ 39114,
+ 39115,
+ 39116,
+ 39117,
+ 39118,
+ 39119,
+ 39120,
+ 39121,
+ 39122,
+ 39123,
+ 39124,
+ 39125,
+ 39126,
+ 39127,
+ 39128,
+ 39129,
+ 39130,
+ 39131,
+ 39132,
+ 39133,
+ 39134,
+ 39135,
+ 39136,
+ 39137,
+ 39138,
+ 39139,
+ 39140,
+ 39141,
+ 39142,
+ 39143,
+ 39144,
+ 39145,
+ 39146,
+ 39147,
+ 39148,
+ 39149,
+ 39150,
+ 39151,
+ 39152,
+ 39153,
+ 39154,
+ 39155,
+ 39156,
+ 39157,
+ 39158,
+ 39159,
+ 39160,
+ 39161,
+ 39162,
+ 39163,
+ 39164,
+ 39165,
+ 39166,
+ 39167,
+ 39168,
+ 39169,
+ 39170,
+ 39171,
+ 39172,
+ 39173,
+ 39174,
+ 39175,
+ 39176,
+ 39177,
+ 39178,
+ 39179,
+ 39180,
+ 39181,
+ 39182,
+ 39183,
+ 39184,
+ 39185,
+ 39186,
+ 39187,
+ 39188,
+ 39189,
+ 39190,
+ 39191,
+ 39192,
+ 39193,
+ 39194,
+ 39195,
+ 39196,
+ 39197,
+ 39198,
+ 39199,
+ 39200,
+ 39201,
+ 39202,
+ 39203,
+ 39204,
+ 39205,
+ 39206,
+ 39207,
+ 39208,
+ 39209,
+ 39210,
+ 39211,
+ 39212,
+ 39213,
+ 39214,
+ 39215,
+ 39216,
+ 39217,
+ 39218,
+ 39219,
+ 39220,
+ 39221,
+ 39222,
+ 39223,
+ 39224,
+ 39225,
+ 39226,
+ 39227,
+ 39228,
+ 39229,
+ 39230,
+ 39231,
+ 39232,
+ 39233,
+ 39234,
+ 39235,
+ 39236,
+ 39237,
+ 39238,
+ 39239,
+ 39240,
+ 39241,
+ 39242,
+ 39243,
+ 39244,
+ 39245,
+ 39246,
+ 39247,
+ 39248,
+ 39249,
+ 39250,
+ 39251,
+ 39252,
+ 39253,
+ 39254,
+ 39255,
+ 39256,
+ 39257,
+ 39258,
+ 39259,
+ 39260,
+ 39261,
+ 39262,
+ 39263,
+ 39264,
+ 39265,
+ 39266,
+ 39267,
+ 39268,
+ 39269,
+ 39270,
+ 39271,
+ 39272,
+ 39273,
+ 39274,
+ 39275,
+ 39276,
+ 39277,
+ 39278,
+ 39279,
+ 39280,
+ 39281,
+ 39282,
+ 39283,
+ 39284,
+ 39285,
+ 39286,
+ 39287,
+ 39288,
+ 39289,
+ 39290,
+ 39291,
+ 39292,
+ 39293,
+ 39294,
+ 39295,
+ 39296,
+ 39297,
+ 39298,
+ 39299,
+ 39300,
+ 39301,
+ 39302,
+ 39303,
+ 39304,
+ 39305,
+ 39306,
+ 39307,
+ 39308,
+ 39309,
+ 39310,
+ 39311,
+ 39312,
+ 39313,
+ 39314,
+ 39315,
+ 39316,
+ 39317,
+ 39318,
+ 39319,
+ 39320,
+ 39321,
+ 39322,
+ 39323,
+ 39324,
+ 39325,
+ 39326,
+ 39327,
+ 39328,
+ 39329,
+ 39330,
+ 39331,
+ 39332,
+ 39333,
+ 39334,
+ 39335,
+ 39336,
+ 39337,
+ 39338,
+ 39339,
+ 39340,
+ 39341,
+ 39342,
+ 39343,
+ 39344,
+ 39345,
+ 39346,
+ 39347,
+ 39348,
+ 39349,
+ 39350,
+ 39351,
+ 39352,
+ 39353,
+ 39354,
+ 39355,
+ 39356,
+ 39357,
+ 39358,
+ 39359,
+ 39360,
+ 39361,
+ 39362,
+ 39363,
+ 39364,
+ 39365,
+ 39366,
+ 39367,
+ 39368,
+ 39369,
+ 39370,
+ 39371,
+ 39372,
+ 39373,
+ 39374,
+ 39375,
+ 39376,
+ 39377,
+ 39378,
+ 39379,
+ 39380,
+ 39381,
+ 39382,
+ 39383,
+ 39384,
+ 39385,
+ 39386,
+ 39387,
+ 39388,
+ 39389,
+ 39390,
+ 39391,
+ 39392,
+ 39393,
+ 39394,
+ 39395,
+ 39396,
+ 39397,
+ 39398,
+ 39399,
+ 39400,
+ 39401,
+ 39402,
+ 39403,
+ 39404,
+ 39405,
+ 39406,
+ 39407,
+ 39408,
+ 39409,
+ 39410,
+ 39411,
+ 39412,
+ 39413,
+ 39414,
+ 39415,
+ 39416,
+ 39417,
+ 39418,
+ 39419,
+ 39420,
+ 39421,
+ 39422,
+ 39423,
+ 39424,
+ 39425,
+ 39426,
+ 39427,
+ 39428,
+ 39429,
+ 39430,
+ 39431,
+ 39432,
+ 39433,
+ 39434,
+ 39435,
+ 39436,
+ 39437,
+ 39438,
+ 39439,
+ 39440,
+ 39441,
+ 39442,
+ 39443,
+ 39444,
+ 39445,
+ 39446,
+ 39447,
+ 39448,
+ 39449,
+ 39450,
+ 39451,
+ 39452,
+ 39453,
+ 39454,
+ 39455,
+ 39456,
+ 39457,
+ 39458,
+ 39459,
+ 39460,
+ 39461,
+ 39462,
+ 39463,
+ 39464,
+ 39465,
+ 39466,
+ 39467,
+ 39468,
+ 39469,
+ 39470,
+ 39471,
+ 39472,
+ 39473,
+ 39474,
+ 39475,
+ 39476,
+ 39477,
+ 39478,
+ 39479,
+ 39480,
+ 39481,
+ 39482,
+ 39483,
+ 39484,
+ 39485,
+ 39486,
+ 39487,
+ 39488,
+ 39489,
+ 39490,
+ 39491,
+ 39492,
+ 39493,
+ 39494,
+ 39495,
+ 39496,
+ 39497,
+ 39498,
+ 39499,
+ 39500,
+ 39501,
+ 39502,
+ 39503,
+ 39504,
+ 39505,
+ 39506,
+ 39507,
+ 39508,
+ 39509,
+ 39510,
+ 39511,
+ 39512,
+ 39513,
+ 39514,
+ 39515,
+ 39516,
+ 39517,
+ 39518,
+ 39519,
+ 39520,
+ 39521,
+ 39522,
+ 39523,
+ 39524,
+ 39525,
+ 39526,
+ 39527,
+ 39528,
+ 39529,
+ 39530,
+ 39531,
+ 39532,
+ 39533,
+ 39534,
+ 39535,
+ 39536,
+ 39537,
+ 39538,
+ 39539,
+ 39540,
+ 39541,
+ 39542,
+ 39543,
+ 39544,
+ 39545,
+ 39546,
+ 39547,
+ 39548,
+ 39549,
+ 39550,
+ 39551,
+ 39552,
+ 39553,
+ 39554,
+ 39555,
+ 39556,
+ 39557,
+ 39558,
+ 39559,
+ 39560,
+ 39561,
+ 39562,
+ 39563,
+ 39564,
+ 39565,
+ 39566,
+ 39567,
+ 39568,
+ 39569,
+ 39570,
+ 39571,
+ 39572,
+ 39573,
+ 39574,
+ 39575,
+ 39576,
+ 39577,
+ 39578,
+ 39579,
+ 39580,
+ 39581,
+ 39582,
+ 39583,
+ 39584,
+ 39585,
+ 39586,
+ 39587,
+ 39588,
+ 39589,
+ 39590,
+ 39591,
+ 39592,
+ 39593,
+ 39594,
+ 39595,
+ 39596,
+ 39597,
+ 39598,
+ 39599,
+ 39600,
+ 39601,
+ 39602,
+ 39603,
+ 39604,
+ 39605,
+ 39606,
+ 39607,
+ 39608,
+ 39609,
+ 39610,
+ 39611,
+ 39612,
+ 39613,
+ 39614,
+ 39615,
+ 39616,
+ 39617,
+ 39618,
+ 39619,
+ 39620,
+ 39621,
+ 39622,
+ 39623,
+ 39624,
+ 39625,
+ 39626,
+ 39627,
+ 39628,
+ 39629,
+ 39630,
+ 39631,
+ 39632,
+ 39633,
+ 39634,
+ 39635,
+ 39636,
+ 39637,
+ 39638,
+ 39639,
+ 39640,
+ 39641,
+ 39642,
+ 39643,
+ 39644,
+ 39645,
+ 39646,
+ 39647,
+ 39648,
+ 39649,
+ 39650,
+ 39651,
+ 39652,
+ 39653,
+ 39654,
+ 39655,
+ 39656,
+ 39657,
+ 39658,
+ 39659,
+ 39660,
+ 39661,
+ 39662,
+ 39663,
+ 39664,
+ 39665,
+ 39666,
+ 39667,
+ 39668,
+ 39669,
+ 39670,
+ 39671,
+ 39672,
+ 39673,
+ 39674,
+ 39675,
+ 39676,
+ 39677,
+ 39678,
+ 39679,
+ 39680,
+ 39681,
+ 39682,
+ 39683,
+ 39684,
+ 39685,
+ 39686,
+ 39687,
+ 39688,
+ 39689,
+ 39690,
+ 39691,
+ 39692,
+ 39693,
+ 39694,
+ 39695,
+ 39696,
+ 39697,
+ 39698,
+ 39699,
+ 39700,
+ 39701,
+ 39702,
+ 39703,
+ 39704,
+ 39705,
+ 39706,
+ 39707,
+ 39708,
+ 39709,
+ 39710,
+ 39711,
+ 39712,
+ 39713,
+ 39714,
+ 39715,
+ 39716,
+ 39717,
+ 39718,
+ 39719,
+ 39720,
+ 39721,
+ 39722,
+ 39723,
+ 39724,
+ 39725,
+ 39726,
+ 39727,
+ 39728,
+ 39729,
+ 39730,
+ 39731,
+ 39732,
+ 39733,
+ 39734,
+ 39735,
+ 39736,
+ 39737,
+ 39738,
+ 39739,
+ 39740,
+ 39741,
+ 39742,
+ 39743,
+ 39744,
+ 39745,
+ 39746,
+ 39747,
+ 39748,
+ 39749,
+ 39750,
+ 39751,
+ 39752,
+ 39753,
+ 39754,
+ 39755,
+ 39756,
+ 39757,
+ 39758,
+ 39759,
+ 39760,
+ 39761,
+ 39762,
+ 39763,
+ 39764,
+ 39765,
+ 39766,
+ 39767,
+ 39768,
+ 39769,
+ 39770,
+ 39771,
+ 39772,
+ 39773,
+ 39774,
+ 39775,
+ 39776,
+ 39777,
+ 39778,
+ 39779,
+ 39780,
+ 39781,
+ 39782,
+ 39783,
+ 39784,
+ 39785,
+ 39786,
+ 39787,
+ 39788,
+ 39789,
+ 39790,
+ 39791,
+ 39792,
+ 39793,
+ 39794,
+ 39795,
+ 39796,
+ 39797,
+ 39798,
+ 39799,
+ 39800,
+ 39801,
+ 39802,
+ 39803,
+ 39804,
+ 39805,
+ 39806,
+ 39807,
+ 39808,
+ 39809,
+ 39810,
+ 39811,
+ 39812,
+ 39813,
+ 39814,
+ 39815,
+ 39816,
+ 39817,
+ 39818,
+ 39819,
+ 39820,
+ 39821,
+ 39822,
+ 39823,
+ 39824,
+ 39825,
+ 39826,
+ 39827,
+ 39828,
+ 39829,
+ 39830,
+ 39831,
+ 39832,
+ 39833,
+ 39834,
+ 39835,
+ 39836,
+ 39837,
+ 39838,
+ 39839,
+ 39840,
+ 39841,
+ 39842,
+ 39843,
+ 39844,
+ 39845,
+ 39846,
+ 39847,
+ 39848,
+ 39849,
+ 39850,
+ 39851,
+ 39852,
+ 39853,
+ 39854,
+ 39855,
+ 39856,
+ 39857,
+ 39858,
+ 39859,
+ 39860,
+ 39861,
+ 39862,
+ 39863,
+ 39864,
+ 39865,
+ 39866,
+ 39867,
+ 39868,
+ 39869,
+ 39870,
+ 39871,
+ 39872,
+ 39873,
+ 39874,
+ 39875,
+ 39876,
+ 39877,
+ 39878,
+ 39879,
+ 39880,
+ 39881,
+ 39882,
+ 39883,
+ 39884,
+ 39885,
+ 39886,
+ 39887,
+ 39888,
+ 39889,
+ 39890,
+ 39891,
+ 39892,
+ 39893,
+ 39894,
+ 39895,
+ 39896,
+ 39897,
+ 39898,
+ 39899,
+ 39900,
+ 39901,
+ 39902,
+ 39903,
+ 39904,
+ 39905,
+ 39906,
+ 39907,
+ 39908,
+ 39909,
+ 39910,
+ 39911,
+ 39912,
+ 39913,
+ 39914,
+ 39915,
+ 39916,
+ 39917,
+ 39918,
+ 39919,
+ 39920,
+ 39921,
+ 39922,
+ 39923,
+ 39924,
+ 39925,
+ 39926,
+ 39927,
+ 39928,
+ 39929,
+ 39930,
+ 39931,
+ 39932,
+ 39933,
+ 39934,
+ 39935,
+ 39936,
+ 39937,
+ 39938,
+ 39939,
+ 39940,
+ 39941,
+ 39942,
+ 39943,
+ 39944,
+ 39945,
+ 39946,
+ 39947,
+ 39948,
+ 39949,
+ 39950,
+ 39951,
+ 39952,
+ 39953,
+ 39954,
+ 39955,
+ 39956,
+ 39957,
+ 39958,
+ 39959,
+ 39960,
+ 39961,
+ 39962,
+ 39963,
+ 39964,
+ 39965,
+ 39966,
+ 39967,
+ 39968,
+ 39969,
+ 39970,
+ 39971,
+ 39972,
+ 39973,
+ 39974,
+ 39975,
+ 39976,
+ 39977,
+ 39978,
+ 39979,
+ 39980,
+ 39981,
+ 39982,
+ 39983,
+ 39984,
+ 39985,
+ 39986,
+ 39987,
+ 39988,
+ 39989,
+ 39990,
+ 39991,
+ 39992,
+ 39993,
+ 39994,
+ 39995,
+ 39996,
+ 39997,
+ 39998,
+ 39999,
+ 40000,
+ 40001,
+ 40002,
+ 40003,
+ 40004,
+ 40005,
+ 40006,
+ 40007,
+ 40008,
+ 40009,
+ 40010,
+ 40011,
+ 40012,
+ 40013,
+ 40014,
+ 40015,
+ 40016,
+ 40017,
+ 40018,
+ 40019,
+ 40020,
+ 40021,
+ 40022,
+ 40023,
+ 40024,
+ 40025,
+ 40026,
+ 40027,
+ 40028,
+ 40029,
+ 40030,
+ 40031,
+ 40032,
+ 40033,
+ 40034,
+ 40035,
+ 40036,
+ 40037,
+ 40038,
+ 40039,
+ 40040,
+ 40041,
+ 40042,
+ 40043,
+ 40044,
+ 40045,
+ 40046,
+ 40047,
+ 40048,
+ 40049,
+ 40050,
+ 40051,
+ 40052,
+ 40053,
+ 40054,
+ 40055,
+ 40056,
+ 40057,
+ 40058,
+ 40059,
+ 40060,
+ 40061,
+ 40062,
+ 40063,
+ 40064,
+ 40065,
+ 40066,
+ 40067,
+ 40068,
+ 40069,
+ 40070,
+ 40071,
+ 40072,
+ 40073,
+ 40074,
+ 40075,
+ 40076,
+ 40077,
+ 40078,
+ 40079,
+ 40080,
+ 40081,
+ 40082,
+ 40083,
+ 40084,
+ 40085,
+ 40086,
+ 40087,
+ 40088,
+ 40089,
+ 40090,
+ 40091,
+ 40092,
+ 40093,
+ 40094,
+ 40095,
+ 40096,
+ 40097,
+ 40098,
+ 40099,
+ 40100,
+ 40101,
+ 40102,
+ 40103,
+ 40104,
+ 40105,
+ 40106,
+ 40107,
+ 40108,
+ 40109,
+ 40110,
+ 40111,
+ 40112,
+ 40113,
+ 40114,
+ 40115,
+ 40116,
+ 40117,
+ 40118,
+ 40119,
+ 40120,
+ 40121,
+ 40122,
+ 40123,
+ 40124,
+ 40125,
+ 40126,
+ 40127,
+ 40128,
+ 40129,
+ 40130,
+ 40131,
+ 40132,
+ 40133,
+ 40134,
+ 40135,
+ 40136,
+ 40137,
+ 40138,
+ 40139,
+ 40140,
+ 40141,
+ 40142,
+ 40143,
+ 40144,
+ 40145,
+ 40146,
+ 40147,
+ 40148,
+ 40149,
+ 40150,
+ 40151,
+ 40152,
+ 40153,
+ 40154,
+ 40155,
+ 40156,
+ 40157,
+ 40158,
+ 40159,
+ 40160,
+ 40161,
+ 40162,
+ 40163,
+ 40164,
+ 40165,
+ 40166,
+ 40167,
+ 40168,
+ 40169,
+ 40170,
+ 40171,
+ 40172,
+ 40173,
+ 40174,
+ 40175,
+ 40176,
+ 40177,
+ 40178,
+ 40179,
+ 40180,
+ 40181,
+ 40182,
+ 40183,
+ 40184,
+ 40185,
+ 40186,
+ 40187,
+ 40188,
+ 40189,
+ 40190,
+ 40191,
+ 40192,
+ 40193,
+ 40194,
+ 40195,
+ 40196,
+ 40197,
+ 40198,
+ 40199,
+ 40200,
+ 40201,
+ 40202,
+ 40203,
+ 40204,
+ 40205,
+ 40206,
+ 40207,
+ 40208,
+ 40209,
+ 40210,
+ 40211,
+ 40212,
+ 40213,
+ 40214,
+ 40215,
+ 40216,
+ 40217,
+ 40218,
+ 40219,
+ 40220,
+ 40221,
+ 40222,
+ 40223,
+ 40224,
+ 40225,
+ 40226,
+ 40227,
+ 40228,
+ 40229,
+ 40230,
+ 40231,
+ 40232,
+ 40233,
+ 40234,
+ 40235,
+ 40236,
+ 40237,
+ 40238,
+ 40239,
+ 40240,
+ 40241,
+ 40242,
+ 40243,
+ 40244,
+ 40245,
+ 40246,
+ 40247,
+ 40248,
+ 40249,
+ 40250,
+ 40251,
+ 40252,
+ 40253,
+ 40254,
+ 40255,
+ 40256,
+ 40257,
+ 40258,
+ 40259,
+ 40260,
+ 40261,
+ 40262,
+ 40263,
+ 40264,
+ 40265,
+ 40266,
+ 40267,
+ 40268,
+ 40269,
+ 40270,
+ 40271,
+ 40272,
+ 40273,
+ 40274,
+ 40275,
+ 40276,
+ 40277,
+ 40278,
+ 40279,
+ 40280,
+ 40281,
+ 40282,
+ 40283,
+ 40284,
+ 40285,
+ 40286,
+ 40287,
+ 40288,
+ 40289,
+ 40290,
+ 40291,
+ 40292,
+ 40293,
+ 40294,
+ 40295,
+ 40296,
+ 40297,
+ 40298,
+ 40299,
+ 40300,
+ 40301,
+ 40302,
+ 40303,
+ 40304,
+ 40305,
+ 40306,
+ 40307,
+ 40308,
+ 40309,
+ 40310,
+ 40311,
+ 40312,
+ 40313,
+ 40314,
+ 40315,
+ 40316,
+ 40317,
+ 40318,
+ 40319,
+ 40320,
+ 40321,
+ 40322,
+ 40323,
+ 40324,
+ 40325,
+ 40326,
+ 40327,
+ 40328,
+ 40329,
+ 40330,
+ 40331,
+ 40332,
+ 40333,
+ 40334,
+ 40335,
+ 40336,
+ 40337,
+ 40338,
+ 40339,
+ 40340,
+ 40341,
+ 40342,
+ 40343,
+ 40344,
+ 40345,
+ 40346,
+ 40347,
+ 40348,
+ 40349,
+ 40350,
+ 40351,
+ 40352,
+ 40353,
+ 40354,
+ 40355,
+ 40356,
+ 40357,
+ 40358,
+ 40359,
+ 40360,
+ 40361,
+ 40362,
+ 40363,
+ 40364,
+ 40365,
+ 40366,
+ 40367,
+ 40368,
+ 40369,
+ 40370,
+ 40371,
+ 40372,
+ 40373,
+ 40374,
+ 40375,
+ 40376,
+ 40377,
+ 40378,
+ 40379,
+ 40380,
+ 40381,
+ 40382,
+ 40383,
+ 40384,
+ 40385,
+ 40386,
+ 40387,
+ 40388,
+ 40389,
+ 40390,
+ 40391,
+ 40392,
+ 40393,
+ 40394,
+ 40395,
+ 40396,
+ 40397,
+ 40398,
+ 40399,
+ 40400,
+ 40401,
+ 40402,
+ 40403,
+ 40404,
+ 40405,
+ 40406,
+ 40407,
+ 40408,
+ 40409,
+ 40410,
+ 40411,
+ 40412,
+ 40413,
+ 40414,
+ 40415,
+ 40416,
+ 40417,
+ 40418,
+ 40419,
+ 40420,
+ 40421,
+ 40422,
+ 40423,
+ 40424,
+ 40425,
+ 40426,
+ 40427,
+ 40428,
+ 40429,
+ 40430,
+ 40431,
+ 40432,
+ 40433,
+ 40434,
+ 40435,
+ 40436,
+ 40437,
+ 40438,
+ 40439,
+ 40440,
+ 40441,
+ 40442,
+ 40443,
+ 40444,
+ 40445,
+ 40446,
+ 40447,
+ 40448,
+ 40449,
+ 40450,
+ 40451,
+ 40452,
+ 40453,
+ 40454,
+ 40455,
+ 40456,
+ 40457,
+ 40458,
+ 40459,
+ 40460,
+ 40461,
+ 40462,
+ 40463,
+ 40464,
+ 40465,
+ 40466,
+ 40467,
+ 40468,
+ 40469,
+ 40470,
+ 40471,
+ 40472,
+ 40473,
+ 40474,
+ 40475,
+ 40476,
+ 40477,
+ 40478,
+ 40479,
+ 40480,
+ 40481,
+ 40482,
+ 40483,
+ 40484,
+ 40485,
+ 40486,
+ 40487,
+ 40488,
+ 40489,
+ 40490,
+ 40491,
+ 40492,
+ 40493,
+ 40494,
+ 40495,
+ 40496,
+ 40497,
+ 40498,
+ 40499,
+ 40500,
+ 40501,
+ 40502,
+ 40503,
+ 40504,
+ 40505,
+ 40506,
+ 40507,
+ 40508,
+ 40509,
+ 40510,
+ 40511,
+ 40512,
+ 40513,
+ 40514,
+ 40515,
+ 40516,
+ 40517,
+ 40518,
+ 40519,
+ 40520,
+ 40521,
+ 40522,
+ 40523,
+ 40524,
+ 40525,
+ 40526,
+ 40527,
+ 40528,
+ 40529,
+ 40530,
+ 40531,
+ 40532,
+ 40533,
+ 40534,
+ 40535,
+ 40536,
+ 40537,
+ 40538,
+ 40539,
+ 40540,
+ 40541,
+ 40542,
+ 40543,
+ 40544,
+ 40545,
+ 40546,
+ 40547,
+ 40548,
+ 40549,
+ 40550,
+ 40551,
+ 40552,
+ 40553,
+ 40554,
+ 40555,
+ 40556,
+ 40557,
+ 40558,
+ 40559,
+ 40560,
+ 40561,
+ 40562,
+ 40563,
+ 40564,
+ 40565,
+ 40566,
+ 40567,
+ 40568,
+ 40569,
+ 40570,
+ 40571,
+ 40572,
+ 40573,
+ 40574,
+ 40575,
+ 40576,
+ 40577,
+ 40578,
+ 40579,
+ 40580,
+ 40581,
+ 40582,
+ 40583,
+ 40584,
+ 40585,
+ 40586,
+ 40587,
+ 40588,
+ 40589,
+ 40590,
+ 40591,
+ 40592,
+ 40593,
+ 40594,
+ 40595,
+ 40596,
+ 40597,
+ 40598,
+ 40599,
+ 40600,
+ 40601,
+ 40602,
+ 40603,
+ 40604,
+ 40605,
+ 40606,
+ 40607,
+ 40608,
+ 40609,
+ 40610,
+ 40611,
+ 40612,
+ 40613,
+ 40614,
+ 40615,
+ 40616,
+ 40617,
+ 40618,
+ 40619,
+ 40620,
+ 40621,
+ 40622,
+ 40623,
+ 40624,
+ 40625,
+ 40626,
+ 40627,
+ 40628,
+ 40629,
+ 40630,
+ 40631,
+ 40632,
+ 40633,
+ 40634,
+ 40635,
+ 40636,
+ 40637,
+ 40638,
+ 40639,
+ 40640,
+ 40641,
+ 40642,
+ 40643,
+ 40644,
+ 40645,
+ 40646,
+ 40647,
+ 40648,
+ 40649,
+ 40650,
+ 40651,
+ 40652,
+ 40653,
+ 40654,
+ 40655,
+ 40656,
+ 40657,
+ 40658,
+ 40659,
+ 40660,
+ 40661,
+ 40662,
+ 40663,
+ 40664,
+ 40665,
+ 40666,
+ 40667,
+ 40668,
+ 40669,
+ 40670,
+ 40671,
+ 40672,
+ 40673,
+ 40674,
+ 40675,
+ 40676,
+ 40677,
+ 40678,
+ 40679,
+ 40680,
+ 40681,
+ 40682,
+ 40683,
+ 40684,
+ 40685,
+ 40686,
+ 40687,
+ 40688,
+ 40689,
+ 40690,
+ 40691,
+ 40692,
+ 40693,
+ 40694,
+ 40695,
+ 40696,
+ 40697,
+ 40698,
+ 40699,
+ 40700,
+ 40701,
+ 40702,
+ 40703,
+ 40704,
+ 40705,
+ 40706,
+ 40707,
+ 40708,
+ 40709,
+ 40710,
+ 40711,
+ 40712,
+ 40713,
+ 40714,
+ 40715,
+ 40716,
+ 40717,
+ 40718,
+ 40719,
+ 40720,
+ 40721,
+ 40722,
+ 40723,
+ 40724,
+ 40725,
+ 40726,
+ 40727,
+ 40728,
+ 40729,
+ 40730,
+ 40731,
+ 40732,
+ 40733,
+ 40734,
+ 40735,
+ 40736,
+ 40737,
+ 40738,
+ 40739,
+ 40740,
+ 40741,
+ 40742,
+ 40743,
+ 40744,
+ 40745,
+ 40746,
+ 40747,
+ 40748,
+ 40749,
+ 40750,
+ 40751,
+ 40752,
+ 40753,
+ 40754,
+ 40755,
+ 40756,
+ 40757,
+ 40758,
+ 40759,
+ 40760,
+ 40761,
+ 40762,
+ 40763,
+ 40764,
+ 40765,
+ 40766,
+ 40767,
+ 40768,
+ 40769,
+ 40770,
+ 40771,
+ 40772,
+ 40773,
+ 40774,
+ 40775,
+ 40776,
+ 40777,
+ 40778,
+ 40779,
+ 40780,
+ 40781,
+ 40782,
+ 40783,
+ 40784,
+ 40785,
+ 40786,
+ 40787,
+ 40788,
+ 40789,
+ 40790,
+ 40791,
+ 40792,
+ 40793,
+ 40794,
+ 40795,
+ 40796,
+ 40797,
+ 40798,
+ 40799,
+ 40800,
+ 40801,
+ 40802,
+ 40803,
+ 40804,
+ 40805,
+ 40806,
+ 40807,
+ 40808,
+ 40809,
+ 40810,
+ 40811,
+ 40812,
+ 40813,
+ 40814,
+ 40815,
+ 40816,
+ 40817,
+ 40818,
+ 40819,
+ 40820,
+ 40821,
+ 40822,
+ 40823,
+ 40824,
+ 40825,
+ 40826,
+ 40827,
+ 40828,
+ 40829,
+ 40830,
+ 40831,
+ 40832,
+ 40833,
+ 40834,
+ 40835,
+ 40836,
+ 40837,
+ 40838,
+ 40839,
+ 40840,
+ 40841,
+ 40842,
+ 40843,
+ 40844,
+ 40845,
+ 40846,
+ 40847,
+ 40848,
+ 40849,
+ 40850,
+ 40851,
+ 40852,
+ 40853,
+ 40854,
+ 40855,
+ 40856,
+ 40857,
+ 40858,
+ 40859,
+ 40860,
+ 40861,
+ 40862,
+ 40863,
+ 40864,
+ 40865,
+ 40866,
+ 40867,
+ 40868,
+ 40869,
+ 40870,
+ 40871,
+ 40872,
+ 40873,
+ 40874,
+ 40875,
+ 40876,
+ 40877,
+ 40878,
+ 40879,
+ 40880,
+ 40881,
+ 40882,
+ 40883,
+ 40884,
+ 40885,
+ 40886,
+ 40887,
+ 40888,
+ 40889,
+ 40890,
+ 40891,
+ 40892,
+ 40893,
+ 40894,
+ 40895,
+ 40896,
+ 40897,
+ 40898,
+ 40899,
+ 40900,
+ 40901,
+ 40902,
+ 40903,
+ 40904,
+ 40905,
+ 40906,
+ 40907,
+ 40908,
+ 40960,
+ 40961,
+ 40962,
+ 40963,
+ 40964,
+ 40965,
+ 40966,
+ 40967,
+ 40968,
+ 40969,
+ 40970,
+ 40971,
+ 40972,
+ 40973,
+ 40974,
+ 40975,
+ 40976,
+ 40977,
+ 40978,
+ 40979,
+ 40980,
+ 40981,
+ 40982,
+ 40983,
+ 40984,
+ 40985,
+ 40986,
+ 40987,
+ 40988,
+ 40989,
+ 40990,
+ 40991,
+ 40992,
+ 40993,
+ 40994,
+ 40995,
+ 40996,
+ 40997,
+ 40998,
+ 40999,
+ 41000,
+ 41001,
+ 41002,
+ 41003,
+ 41004,
+ 41005,
+ 41006,
+ 41007,
+ 41008,
+ 41009,
+ 41010,
+ 41011,
+ 41012,
+ 41013,
+ 41014,
+ 41015,
+ 41016,
+ 41017,
+ 41018,
+ 41019,
+ 41020,
+ 41021,
+ 41022,
+ 41023,
+ 41024,
+ 41025,
+ 41026,
+ 41027,
+ 41028,
+ 41029,
+ 41030,
+ 41031,
+ 41032,
+ 41033,
+ 41034,
+ 41035,
+ 41036,
+ 41037,
+ 41038,
+ 41039,
+ 41040,
+ 41041,
+ 41042,
+ 41043,
+ 41044,
+ 41045,
+ 41046,
+ 41047,
+ 41048,
+ 41049,
+ 41050,
+ 41051,
+ 41052,
+ 41053,
+ 41054,
+ 41055,
+ 41056,
+ 41057,
+ 41058,
+ 41059,
+ 41060,
+ 41061,
+ 41062,
+ 41063,
+ 41064,
+ 41065,
+ 41066,
+ 41067,
+ 41068,
+ 41069,
+ 41070,
+ 41071,
+ 41072,
+ 41073,
+ 41074,
+ 41075,
+ 41076,
+ 41077,
+ 41078,
+ 41079,
+ 41080,
+ 41081,
+ 41082,
+ 41083,
+ 41084,
+ 41085,
+ 41086,
+ 41087,
+ 41088,
+ 41089,
+ 41090,
+ 41091,
+ 41092,
+ 41093,
+ 41094,
+ 41095,
+ 41096,
+ 41097,
+ 41098,
+ 41099,
+ 41100,
+ 41101,
+ 41102,
+ 41103,
+ 41104,
+ 41105,
+ 41106,
+ 41107,
+ 41108,
+ 41109,
+ 41110,
+ 41111,
+ 41112,
+ 41113,
+ 41114,
+ 41115,
+ 41116,
+ 41117,
+ 41118,
+ 41119,
+ 41120,
+ 41121,
+ 41122,
+ 41123,
+ 41124,
+ 41125,
+ 41126,
+ 41127,
+ 41128,
+ 41129,
+ 41130,
+ 41131,
+ 41132,
+ 41133,
+ 41134,
+ 41135,
+ 41136,
+ 41137,
+ 41138,
+ 41139,
+ 41140,
+ 41141,
+ 41142,
+ 41143,
+ 41144,
+ 41145,
+ 41146,
+ 41147,
+ 41148,
+ 41149,
+ 41150,
+ 41151,
+ 41152,
+ 41153,
+ 41154,
+ 41155,
+ 41156,
+ 41157,
+ 41158,
+ 41159,
+ 41160,
+ 41161,
+ 41162,
+ 41163,
+ 41164,
+ 41165,
+ 41166,
+ 41167,
+ 41168,
+ 41169,
+ 41170,
+ 41171,
+ 41172,
+ 41173,
+ 41174,
+ 41175,
+ 41176,
+ 41177,
+ 41178,
+ 41179,
+ 41180,
+ 41181,
+ 41182,
+ 41183,
+ 41184,
+ 41185,
+ 41186,
+ 41187,
+ 41188,
+ 41189,
+ 41190,
+ 41191,
+ 41192,
+ 41193,
+ 41194,
+ 41195,
+ 41196,
+ 41197,
+ 41198,
+ 41199,
+ 41200,
+ 41201,
+ 41202,
+ 41203,
+ 41204,
+ 41205,
+ 41206,
+ 41207,
+ 41208,
+ 41209,
+ 41210,
+ 41211,
+ 41212,
+ 41213,
+ 41214,
+ 41215,
+ 41216,
+ 41217,
+ 41218,
+ 41219,
+ 41220,
+ 41221,
+ 41222,
+ 41223,
+ 41224,
+ 41225,
+ 41226,
+ 41227,
+ 41228,
+ 41229,
+ 41230,
+ 41231,
+ 41232,
+ 41233,
+ 41234,
+ 41235,
+ 41236,
+ 41237,
+ 41238,
+ 41239,
+ 41240,
+ 41241,
+ 41242,
+ 41243,
+ 41244,
+ 41245,
+ 41246,
+ 41247,
+ 41248,
+ 41249,
+ 41250,
+ 41251,
+ 41252,
+ 41253,
+ 41254,
+ 41255,
+ 41256,
+ 41257,
+ 41258,
+ 41259,
+ 41260,
+ 41261,
+ 41262,
+ 41263,
+ 41264,
+ 41265,
+ 41266,
+ 41267,
+ 41268,
+ 41269,
+ 41270,
+ 41271,
+ 41272,
+ 41273,
+ 41274,
+ 41275,
+ 41276,
+ 41277,
+ 41278,
+ 41279,
+ 41280,
+ 41281,
+ 41282,
+ 41283,
+ 41284,
+ 41285,
+ 41286,
+ 41287,
+ 41288,
+ 41289,
+ 41290,
+ 41291,
+ 41292,
+ 41293,
+ 41294,
+ 41295,
+ 41296,
+ 41297,
+ 41298,
+ 41299,
+ 41300,
+ 41301,
+ 41302,
+ 41303,
+ 41304,
+ 41305,
+ 41306,
+ 41307,
+ 41308,
+ 41309,
+ 41310,
+ 41311,
+ 41312,
+ 41313,
+ 41314,
+ 41315,
+ 41316,
+ 41317,
+ 41318,
+ 41319,
+ 41320,
+ 41321,
+ 41322,
+ 41323,
+ 41324,
+ 41325,
+ 41326,
+ 41327,
+ 41328,
+ 41329,
+ 41330,
+ 41331,
+ 41332,
+ 41333,
+ 41334,
+ 41335,
+ 41336,
+ 41337,
+ 41338,
+ 41339,
+ 41340,
+ 41341,
+ 41342,
+ 41343,
+ 41344,
+ 41345,
+ 41346,
+ 41347,
+ 41348,
+ 41349,
+ 41350,
+ 41351,
+ 41352,
+ 41353,
+ 41354,
+ 41355,
+ 41356,
+ 41357,
+ 41358,
+ 41359,
+ 41360,
+ 41361,
+ 41362,
+ 41363,
+ 41364,
+ 41365,
+ 41366,
+ 41367,
+ 41368,
+ 41369,
+ 41370,
+ 41371,
+ 41372,
+ 41373,
+ 41374,
+ 41375,
+ 41376,
+ 41377,
+ 41378,
+ 41379,
+ 41380,
+ 41381,
+ 41382,
+ 41383,
+ 41384,
+ 41385,
+ 41386,
+ 41387,
+ 41388,
+ 41389,
+ 41390,
+ 41391,
+ 41392,
+ 41393,
+ 41394,
+ 41395,
+ 41396,
+ 41397,
+ 41398,
+ 41399,
+ 41400,
+ 41401,
+ 41402,
+ 41403,
+ 41404,
+ 41405,
+ 41406,
+ 41407,
+ 41408,
+ 41409,
+ 41410,
+ 41411,
+ 41412,
+ 41413,
+ 41414,
+ 41415,
+ 41416,
+ 41417,
+ 41418,
+ 41419,
+ 41420,
+ 41421,
+ 41422,
+ 41423,
+ 41424,
+ 41425,
+ 41426,
+ 41427,
+ 41428,
+ 41429,
+ 41430,
+ 41431,
+ 41432,
+ 41433,
+ 41434,
+ 41435,
+ 41436,
+ 41437,
+ 41438,
+ 41439,
+ 41440,
+ 41441,
+ 41442,
+ 41443,
+ 41444,
+ 41445,
+ 41446,
+ 41447,
+ 41448,
+ 41449,
+ 41450,
+ 41451,
+ 41452,
+ 41453,
+ 41454,
+ 41455,
+ 41456,
+ 41457,
+ 41458,
+ 41459,
+ 41460,
+ 41461,
+ 41462,
+ 41463,
+ 41464,
+ 41465,
+ 41466,
+ 41467,
+ 41468,
+ 41469,
+ 41470,
+ 41471,
+ 41472,
+ 41473,
+ 41474,
+ 41475,
+ 41476,
+ 41477,
+ 41478,
+ 41479,
+ 41480,
+ 41481,
+ 41482,
+ 41483,
+ 41484,
+ 41485,
+ 41486,
+ 41487,
+ 41488,
+ 41489,
+ 41490,
+ 41491,
+ 41492,
+ 41493,
+ 41494,
+ 41495,
+ 41496,
+ 41497,
+ 41498,
+ 41499,
+ 41500,
+ 41501,
+ 41502,
+ 41503,
+ 41504,
+ 41505,
+ 41506,
+ 41507,
+ 41508,
+ 41509,
+ 41510,
+ 41511,
+ 41512,
+ 41513,
+ 41514,
+ 41515,
+ 41516,
+ 41517,
+ 41518,
+ 41519,
+ 41520,
+ 41521,
+ 41522,
+ 41523,
+ 41524,
+ 41525,
+ 41526,
+ 41527,
+ 41528,
+ 41529,
+ 41530,
+ 41531,
+ 41532,
+ 41533,
+ 41534,
+ 41535,
+ 41536,
+ 41537,
+ 41538,
+ 41539,
+ 41540,
+ 41541,
+ 41542,
+ 41543,
+ 41544,
+ 41545,
+ 41546,
+ 41547,
+ 41548,
+ 41549,
+ 41550,
+ 41551,
+ 41552,
+ 41553,
+ 41554,
+ 41555,
+ 41556,
+ 41557,
+ 41558,
+ 41559,
+ 41560,
+ 41561,
+ 41562,
+ 41563,
+ 41564,
+ 41565,
+ 41566,
+ 41567,
+ 41568,
+ 41569,
+ 41570,
+ 41571,
+ 41572,
+ 41573,
+ 41574,
+ 41575,
+ 41576,
+ 41577,
+ 41578,
+ 41579,
+ 41580,
+ 41581,
+ 41582,
+ 41583,
+ 41584,
+ 41585,
+ 41586,
+ 41587,
+ 41588,
+ 41589,
+ 41590,
+ 41591,
+ 41592,
+ 41593,
+ 41594,
+ 41595,
+ 41596,
+ 41597,
+ 41598,
+ 41599,
+ 41600,
+ 41601,
+ 41602,
+ 41603,
+ 41604,
+ 41605,
+ 41606,
+ 41607,
+ 41608,
+ 41609,
+ 41610,
+ 41611,
+ 41612,
+ 41613,
+ 41614,
+ 41615,
+ 41616,
+ 41617,
+ 41618,
+ 41619,
+ 41620,
+ 41621,
+ 41622,
+ 41623,
+ 41624,
+ 41625,
+ 41626,
+ 41627,
+ 41628,
+ 41629,
+ 41630,
+ 41631,
+ 41632,
+ 41633,
+ 41634,
+ 41635,
+ 41636,
+ 41637,
+ 41638,
+ 41639,
+ 41640,
+ 41641,
+ 41642,
+ 41643,
+ 41644,
+ 41645,
+ 41646,
+ 41647,
+ 41648,
+ 41649,
+ 41650,
+ 41651,
+ 41652,
+ 41653,
+ 41654,
+ 41655,
+ 41656,
+ 41657,
+ 41658,
+ 41659,
+ 41660,
+ 41661,
+ 41662,
+ 41663,
+ 41664,
+ 41665,
+ 41666,
+ 41667,
+ 41668,
+ 41669,
+ 41670,
+ 41671,
+ 41672,
+ 41673,
+ 41674,
+ 41675,
+ 41676,
+ 41677,
+ 41678,
+ 41679,
+ 41680,
+ 41681,
+ 41682,
+ 41683,
+ 41684,
+ 41685,
+ 41686,
+ 41687,
+ 41688,
+ 41689,
+ 41690,
+ 41691,
+ 41692,
+ 41693,
+ 41694,
+ 41695,
+ 41696,
+ 41697,
+ 41698,
+ 41699,
+ 41700,
+ 41701,
+ 41702,
+ 41703,
+ 41704,
+ 41705,
+ 41706,
+ 41707,
+ 41708,
+ 41709,
+ 41710,
+ 41711,
+ 41712,
+ 41713,
+ 41714,
+ 41715,
+ 41716,
+ 41717,
+ 41718,
+ 41719,
+ 41720,
+ 41721,
+ 41722,
+ 41723,
+ 41724,
+ 41725,
+ 41726,
+ 41727,
+ 41728,
+ 41729,
+ 41730,
+ 41731,
+ 41732,
+ 41733,
+ 41734,
+ 41735,
+ 41736,
+ 41737,
+ 41738,
+ 41739,
+ 41740,
+ 41741,
+ 41742,
+ 41743,
+ 41744,
+ 41745,
+ 41746,
+ 41747,
+ 41748,
+ 41749,
+ 41750,
+ 41751,
+ 41752,
+ 41753,
+ 41754,
+ 41755,
+ 41756,
+ 41757,
+ 41758,
+ 41759,
+ 41760,
+ 41761,
+ 41762,
+ 41763,
+ 41764,
+ 41765,
+ 41766,
+ 41767,
+ 41768,
+ 41769,
+ 41770,
+ 41771,
+ 41772,
+ 41773,
+ 41774,
+ 41775,
+ 41776,
+ 41777,
+ 41778,
+ 41779,
+ 41780,
+ 41781,
+ 41782,
+ 41783,
+ 41784,
+ 41785,
+ 41786,
+ 41787,
+ 41788,
+ 41789,
+ 41790,
+ 41791,
+ 41792,
+ 41793,
+ 41794,
+ 41795,
+ 41796,
+ 41797,
+ 41798,
+ 41799,
+ 41800,
+ 41801,
+ 41802,
+ 41803,
+ 41804,
+ 41805,
+ 41806,
+ 41807,
+ 41808,
+ 41809,
+ 41810,
+ 41811,
+ 41812,
+ 41813,
+ 41814,
+ 41815,
+ 41816,
+ 41817,
+ 41818,
+ 41819,
+ 41820,
+ 41821,
+ 41822,
+ 41823,
+ 41824,
+ 41825,
+ 41826,
+ 41827,
+ 41828,
+ 41829,
+ 41830,
+ 41831,
+ 41832,
+ 41833,
+ 41834,
+ 41835,
+ 41836,
+ 41837,
+ 41838,
+ 41839,
+ 41840,
+ 41841,
+ 41842,
+ 41843,
+ 41844,
+ 41845,
+ 41846,
+ 41847,
+ 41848,
+ 41849,
+ 41850,
+ 41851,
+ 41852,
+ 41853,
+ 41854,
+ 41855,
+ 41856,
+ 41857,
+ 41858,
+ 41859,
+ 41860,
+ 41861,
+ 41862,
+ 41863,
+ 41864,
+ 41865,
+ 41866,
+ 41867,
+ 41868,
+ 41869,
+ 41870,
+ 41871,
+ 41872,
+ 41873,
+ 41874,
+ 41875,
+ 41876,
+ 41877,
+ 41878,
+ 41879,
+ 41880,
+ 41881,
+ 41882,
+ 41883,
+ 41884,
+ 41885,
+ 41886,
+ 41887,
+ 41888,
+ 41889,
+ 41890,
+ 41891,
+ 41892,
+ 41893,
+ 41894,
+ 41895,
+ 41896,
+ 41897,
+ 41898,
+ 41899,
+ 41900,
+ 41901,
+ 41902,
+ 41903,
+ 41904,
+ 41905,
+ 41906,
+ 41907,
+ 41908,
+ 41909,
+ 41910,
+ 41911,
+ 41912,
+ 41913,
+ 41914,
+ 41915,
+ 41916,
+ 41917,
+ 41918,
+ 41919,
+ 41920,
+ 41921,
+ 41922,
+ 41923,
+ 41924,
+ 41925,
+ 41926,
+ 41927,
+ 41928,
+ 41929,
+ 41930,
+ 41931,
+ 41932,
+ 41933,
+ 41934,
+ 41935,
+ 41936,
+ 41937,
+ 41938,
+ 41939,
+ 41940,
+ 41941,
+ 41942,
+ 41943,
+ 41944,
+ 41945,
+ 41946,
+ 41947,
+ 41948,
+ 41949,
+ 41950,
+ 41951,
+ 41952,
+ 41953,
+ 41954,
+ 41955,
+ 41956,
+ 41957,
+ 41958,
+ 41959,
+ 41960,
+ 41961,
+ 41962,
+ 41963,
+ 41964,
+ 41965,
+ 41966,
+ 41967,
+ 41968,
+ 41969,
+ 41970,
+ 41971,
+ 41972,
+ 41973,
+ 41974,
+ 41975,
+ 41976,
+ 41977,
+ 41978,
+ 41979,
+ 41980,
+ 41981,
+ 41982,
+ 41983,
+ 41984,
+ 41985,
+ 41986,
+ 41987,
+ 41988,
+ 41989,
+ 41990,
+ 41991,
+ 41992,
+ 41993,
+ 41994,
+ 41995,
+ 41996,
+ 41997,
+ 41998,
+ 41999,
+ 42000,
+ 42001,
+ 42002,
+ 42003,
+ 42004,
+ 42005,
+ 42006,
+ 42007,
+ 42008,
+ 42009,
+ 42010,
+ 42011,
+ 42012,
+ 42013,
+ 42014,
+ 42015,
+ 42016,
+ 42017,
+ 42018,
+ 42019,
+ 42020,
+ 42021,
+ 42022,
+ 42023,
+ 42024,
+ 42025,
+ 42026,
+ 42027,
+ 42028,
+ 42029,
+ 42030,
+ 42031,
+ 42032,
+ 42033,
+ 42034,
+ 42035,
+ 42036,
+ 42037,
+ 42038,
+ 42039,
+ 42040,
+ 42041,
+ 42042,
+ 42043,
+ 42044,
+ 42045,
+ 42046,
+ 42047,
+ 42048,
+ 42049,
+ 42050,
+ 42051,
+ 42052,
+ 42053,
+ 42054,
+ 42055,
+ 42056,
+ 42057,
+ 42058,
+ 42059,
+ 42060,
+ 42061,
+ 42062,
+ 42063,
+ 42064,
+ 42065,
+ 42066,
+ 42067,
+ 42068,
+ 42069,
+ 42070,
+ 42071,
+ 42072,
+ 42073,
+ 42074,
+ 42075,
+ 42076,
+ 42077,
+ 42078,
+ 42079,
+ 42080,
+ 42081,
+ 42082,
+ 42083,
+ 42084,
+ 42085,
+ 42086,
+ 42087,
+ 42088,
+ 42089,
+ 42090,
+ 42091,
+ 42092,
+ 42093,
+ 42094,
+ 42095,
+ 42096,
+ 42097,
+ 42098,
+ 42099,
+ 42100,
+ 42101,
+ 42102,
+ 42103,
+ 42104,
+ 42105,
+ 42106,
+ 42107,
+ 42108,
+ 42109,
+ 42110,
+ 42111,
+ 42112,
+ 42113,
+ 42114,
+ 42115,
+ 42116,
+ 42117,
+ 42118,
+ 42119,
+ 42120,
+ 42121,
+ 42122,
+ 42123,
+ 42124,
+ 42192,
+ 42193,
+ 42194,
+ 42195,
+ 42196,
+ 42197,
+ 42198,
+ 42199,
+ 42200,
+ 42201,
+ 42202,
+ 42203,
+ 42204,
+ 42205,
+ 42206,
+ 42207,
+ 42208,
+ 42209,
+ 42210,
+ 42211,
+ 42212,
+ 42213,
+ 42214,
+ 42215,
+ 42216,
+ 42217,
+ 42218,
+ 42219,
+ 42220,
+ 42221,
+ 42222,
+ 42223,
+ 42224,
+ 42225,
+ 42226,
+ 42227,
+ 42228,
+ 42229,
+ 42230,
+ 42231,
+ 42232,
+ 42233,
+ 42234,
+ 42235,
+ 42236,
+ 42237,
+ 42240,
+ 42241,
+ 42242,
+ 42243,
+ 42244,
+ 42245,
+ 42246,
+ 42247,
+ 42248,
+ 42249,
+ 42250,
+ 42251,
+ 42252,
+ 42253,
+ 42254,
+ 42255,
+ 42256,
+ 42257,
+ 42258,
+ 42259,
+ 42260,
+ 42261,
+ 42262,
+ 42263,
+ 42264,
+ 42265,
+ 42266,
+ 42267,
+ 42268,
+ 42269,
+ 42270,
+ 42271,
+ 42272,
+ 42273,
+ 42274,
+ 42275,
+ 42276,
+ 42277,
+ 42278,
+ 42279,
+ 42280,
+ 42281,
+ 42282,
+ 42283,
+ 42284,
+ 42285,
+ 42286,
+ 42287,
+ 42288,
+ 42289,
+ 42290,
+ 42291,
+ 42292,
+ 42293,
+ 42294,
+ 42295,
+ 42296,
+ 42297,
+ 42298,
+ 42299,
+ 42300,
+ 42301,
+ 42302,
+ 42303,
+ 42304,
+ 42305,
+ 42306,
+ 42307,
+ 42308,
+ 42309,
+ 42310,
+ 42311,
+ 42312,
+ 42313,
+ 42314,
+ 42315,
+ 42316,
+ 42317,
+ 42318,
+ 42319,
+ 42320,
+ 42321,
+ 42322,
+ 42323,
+ 42324,
+ 42325,
+ 42326,
+ 42327,
+ 42328,
+ 42329,
+ 42330,
+ 42331,
+ 42332,
+ 42333,
+ 42334,
+ 42335,
+ 42336,
+ 42337,
+ 42338,
+ 42339,
+ 42340,
+ 42341,
+ 42342,
+ 42343,
+ 42344,
+ 42345,
+ 42346,
+ 42347,
+ 42348,
+ 42349,
+ 42350,
+ 42351,
+ 42352,
+ 42353,
+ 42354,
+ 42355,
+ 42356,
+ 42357,
+ 42358,
+ 42359,
+ 42360,
+ 42361,
+ 42362,
+ 42363,
+ 42364,
+ 42365,
+ 42366,
+ 42367,
+ 42368,
+ 42369,
+ 42370,
+ 42371,
+ 42372,
+ 42373,
+ 42374,
+ 42375,
+ 42376,
+ 42377,
+ 42378,
+ 42379,
+ 42380,
+ 42381,
+ 42382,
+ 42383,
+ 42384,
+ 42385,
+ 42386,
+ 42387,
+ 42388,
+ 42389,
+ 42390,
+ 42391,
+ 42392,
+ 42393,
+ 42394,
+ 42395,
+ 42396,
+ 42397,
+ 42398,
+ 42399,
+ 42400,
+ 42401,
+ 42402,
+ 42403,
+ 42404,
+ 42405,
+ 42406,
+ 42407,
+ 42408,
+ 42409,
+ 42410,
+ 42411,
+ 42412,
+ 42413,
+ 42414,
+ 42415,
+ 42416,
+ 42417,
+ 42418,
+ 42419,
+ 42420,
+ 42421,
+ 42422,
+ 42423,
+ 42424,
+ 42425,
+ 42426,
+ 42427,
+ 42428,
+ 42429,
+ 42430,
+ 42431,
+ 42432,
+ 42433,
+ 42434,
+ 42435,
+ 42436,
+ 42437,
+ 42438,
+ 42439,
+ 42440,
+ 42441,
+ 42442,
+ 42443,
+ 42444,
+ 42445,
+ 42446,
+ 42447,
+ 42448,
+ 42449,
+ 42450,
+ 42451,
+ 42452,
+ 42453,
+ 42454,
+ 42455,
+ 42456,
+ 42457,
+ 42458,
+ 42459,
+ 42460,
+ 42461,
+ 42462,
+ 42463,
+ 42464,
+ 42465,
+ 42466,
+ 42467,
+ 42468,
+ 42469,
+ 42470,
+ 42471,
+ 42472,
+ 42473,
+ 42474,
+ 42475,
+ 42476,
+ 42477,
+ 42478,
+ 42479,
+ 42480,
+ 42481,
+ 42482,
+ 42483,
+ 42484,
+ 42485,
+ 42486,
+ 42487,
+ 42488,
+ 42489,
+ 42490,
+ 42491,
+ 42492,
+ 42493,
+ 42494,
+ 42495,
+ 42496,
+ 42497,
+ 42498,
+ 42499,
+ 42500,
+ 42501,
+ 42502,
+ 42503,
+ 42504,
+ 42505,
+ 42506,
+ 42507,
+ 42508,
+ 42512,
+ 42513,
+ 42514,
+ 42515,
+ 42516,
+ 42517,
+ 42518,
+ 42519,
+ 42520,
+ 42521,
+ 42522,
+ 42523,
+ 42524,
+ 42525,
+ 42526,
+ 42527,
+ 42538,
+ 42539,
+ 42560,
+ 42561,
+ 42562,
+ 42563,
+ 42564,
+ 42565,
+ 42566,
+ 42567,
+ 42568,
+ 42569,
+ 42570,
+ 42571,
+ 42572,
+ 42573,
+ 42574,
+ 42575,
+ 42576,
+ 42577,
+ 42578,
+ 42579,
+ 42580,
+ 42581,
+ 42582,
+ 42583,
+ 42584,
+ 42585,
+ 42586,
+ 42587,
+ 42588,
+ 42589,
+ 42590,
+ 42591,
+ 42592,
+ 42593,
+ 42594,
+ 42595,
+ 42596,
+ 42597,
+ 42598,
+ 42599,
+ 42600,
+ 42601,
+ 42602,
+ 42603,
+ 42604,
+ 42605,
+ 42606,
+ 42623,
+ 42624,
+ 42625,
+ 42626,
+ 42627,
+ 42628,
+ 42629,
+ 42630,
+ 42631,
+ 42632,
+ 42633,
+ 42634,
+ 42635,
+ 42636,
+ 42637,
+ 42638,
+ 42639,
+ 42640,
+ 42641,
+ 42642,
+ 42643,
+ 42644,
+ 42645,
+ 42646,
+ 42647,
+ 42656,
+ 42657,
+ 42658,
+ 42659,
+ 42660,
+ 42661,
+ 42662,
+ 42663,
+ 42664,
+ 42665,
+ 42666,
+ 42667,
+ 42668,
+ 42669,
+ 42670,
+ 42671,
+ 42672,
+ 42673,
+ 42674,
+ 42675,
+ 42676,
+ 42677,
+ 42678,
+ 42679,
+ 42680,
+ 42681,
+ 42682,
+ 42683,
+ 42684,
+ 42685,
+ 42686,
+ 42687,
+ 42688,
+ 42689,
+ 42690,
+ 42691,
+ 42692,
+ 42693,
+ 42694,
+ 42695,
+ 42696,
+ 42697,
+ 42698,
+ 42699,
+ 42700,
+ 42701,
+ 42702,
+ 42703,
+ 42704,
+ 42705,
+ 42706,
+ 42707,
+ 42708,
+ 42709,
+ 42710,
+ 42711,
+ 42712,
+ 42713,
+ 42714,
+ 42715,
+ 42716,
+ 42717,
+ 42718,
+ 42719,
+ 42720,
+ 42721,
+ 42722,
+ 42723,
+ 42724,
+ 42725,
+ 42726,
+ 42727,
+ 42728,
+ 42729,
+ 42730,
+ 42731,
+ 42732,
+ 42733,
+ 42734,
+ 42735,
+ 42775,
+ 42776,
+ 42777,
+ 42778,
+ 42779,
+ 42780,
+ 42781,
+ 42782,
+ 42783,
+ 42786,
+ 42787,
+ 42788,
+ 42789,
+ 42790,
+ 42791,
+ 42792,
+ 42793,
+ 42794,
+ 42795,
+ 42796,
+ 42797,
+ 42798,
+ 42799,
+ 42800,
+ 42801,
+ 42802,
+ 42803,
+ 42804,
+ 42805,
+ 42806,
+ 42807,
+ 42808,
+ 42809,
+ 42810,
+ 42811,
+ 42812,
+ 42813,
+ 42814,
+ 42815,
+ 42816,
+ 42817,
+ 42818,
+ 42819,
+ 42820,
+ 42821,
+ 42822,
+ 42823,
+ 42824,
+ 42825,
+ 42826,
+ 42827,
+ 42828,
+ 42829,
+ 42830,
+ 42831,
+ 42832,
+ 42833,
+ 42834,
+ 42835,
+ 42836,
+ 42837,
+ 42838,
+ 42839,
+ 42840,
+ 42841,
+ 42842,
+ 42843,
+ 42844,
+ 42845,
+ 42846,
+ 42847,
+ 42848,
+ 42849,
+ 42850,
+ 42851,
+ 42852,
+ 42853,
+ 42854,
+ 42855,
+ 42856,
+ 42857,
+ 42858,
+ 42859,
+ 42860,
+ 42861,
+ 42862,
+ 42863,
+ 42864,
+ 42865,
+ 42866,
+ 42867,
+ 42868,
+ 42869,
+ 42870,
+ 42871,
+ 42872,
+ 42873,
+ 42874,
+ 42875,
+ 42876,
+ 42877,
+ 42878,
+ 42879,
+ 42880,
+ 42881,
+ 42882,
+ 42883,
+ 42884,
+ 42885,
+ 42886,
+ 42887,
+ 42888,
+ 42891,
+ 42892,
+ 42893,
+ 42894,
+ 42896,
+ 42897,
+ 42898,
+ 42899,
+ 42912,
+ 42913,
+ 42914,
+ 42915,
+ 42916,
+ 42917,
+ 42918,
+ 42919,
+ 42920,
+ 42921,
+ 42922,
+ 43000,
+ 43001,
+ 43002,
+ 43003,
+ 43004,
+ 43005,
+ 43006,
+ 43007,
+ 43008,
+ 43009,
+ 43011,
+ 43012,
+ 43013,
+ 43015,
+ 43016,
+ 43017,
+ 43018,
+ 43020,
+ 43021,
+ 43022,
+ 43023,
+ 43024,
+ 43025,
+ 43026,
+ 43027,
+ 43028,
+ 43029,
+ 43030,
+ 43031,
+ 43032,
+ 43033,
+ 43034,
+ 43035,
+ 43036,
+ 43037,
+ 43038,
+ 43039,
+ 43040,
+ 43041,
+ 43042,
+ 43072,
+ 43073,
+ 43074,
+ 43075,
+ 43076,
+ 43077,
+ 43078,
+ 43079,
+ 43080,
+ 43081,
+ 43082,
+ 43083,
+ 43084,
+ 43085,
+ 43086,
+ 43087,
+ 43088,
+ 43089,
+ 43090,
+ 43091,
+ 43092,
+ 43093,
+ 43094,
+ 43095,
+ 43096,
+ 43097,
+ 43098,
+ 43099,
+ 43100,
+ 43101,
+ 43102,
+ 43103,
+ 43104,
+ 43105,
+ 43106,
+ 43107,
+ 43108,
+ 43109,
+ 43110,
+ 43111,
+ 43112,
+ 43113,
+ 43114,
+ 43115,
+ 43116,
+ 43117,
+ 43118,
+ 43119,
+ 43120,
+ 43121,
+ 43122,
+ 43123,
+ 43138,
+ 43139,
+ 43140,
+ 43141,
+ 43142,
+ 43143,
+ 43144,
+ 43145,
+ 43146,
+ 43147,
+ 43148,
+ 43149,
+ 43150,
+ 43151,
+ 43152,
+ 43153,
+ 43154,
+ 43155,
+ 43156,
+ 43157,
+ 43158,
+ 43159,
+ 43160,
+ 43161,
+ 43162,
+ 43163,
+ 43164,
+ 43165,
+ 43166,
+ 43167,
+ 43168,
+ 43169,
+ 43170,
+ 43171,
+ 43172,
+ 43173,
+ 43174,
+ 43175,
+ 43176,
+ 43177,
+ 43178,
+ 43179,
+ 43180,
+ 43181,
+ 43182,
+ 43183,
+ 43184,
+ 43185,
+ 43186,
+ 43187,
+ 43250,
+ 43251,
+ 43252,
+ 43253,
+ 43254,
+ 43255,
+ 43259,
+ 43274,
+ 43275,
+ 43276,
+ 43277,
+ 43278,
+ 43279,
+ 43280,
+ 43281,
+ 43282,
+ 43283,
+ 43284,
+ 43285,
+ 43286,
+ 43287,
+ 43288,
+ 43289,
+ 43290,
+ 43291,
+ 43292,
+ 43293,
+ 43294,
+ 43295,
+ 43296,
+ 43297,
+ 43298,
+ 43299,
+ 43300,
+ 43301,
+ 43312,
+ 43313,
+ 43314,
+ 43315,
+ 43316,
+ 43317,
+ 43318,
+ 43319,
+ 43320,
+ 43321,
+ 43322,
+ 43323,
+ 43324,
+ 43325,
+ 43326,
+ 43327,
+ 43328,
+ 43329,
+ 43330,
+ 43331,
+ 43332,
+ 43333,
+ 43334,
+ 43360,
+ 43361,
+ 43362,
+ 43363,
+ 43364,
+ 43365,
+ 43366,
+ 43367,
+ 43368,
+ 43369,
+ 43370,
+ 43371,
+ 43372,
+ 43373,
+ 43374,
+ 43375,
+ 43376,
+ 43377,
+ 43378,
+ 43379,
+ 43380,
+ 43381,
+ 43382,
+ 43383,
+ 43384,
+ 43385,
+ 43386,
+ 43387,
+ 43388,
+ 43396,
+ 43397,
+ 43398,
+ 43399,
+ 43400,
+ 43401,
+ 43402,
+ 43403,
+ 43404,
+ 43405,
+ 43406,
+ 43407,
+ 43408,
+ 43409,
+ 43410,
+ 43411,
+ 43412,
+ 43413,
+ 43414,
+ 43415,
+ 43416,
+ 43417,
+ 43418,
+ 43419,
+ 43420,
+ 43421,
+ 43422,
+ 43423,
+ 43424,
+ 43425,
+ 43426,
+ 43427,
+ 43428,
+ 43429,
+ 43430,
+ 43431,
+ 43432,
+ 43433,
+ 43434,
+ 43435,
+ 43436,
+ 43437,
+ 43438,
+ 43439,
+ 43440,
+ 43441,
+ 43442,
+ 43471,
+ 43520,
+ 43521,
+ 43522,
+ 43523,
+ 43524,
+ 43525,
+ 43526,
+ 43527,
+ 43528,
+ 43529,
+ 43530,
+ 43531,
+ 43532,
+ 43533,
+ 43534,
+ 43535,
+ 43536,
+ 43537,
+ 43538,
+ 43539,
+ 43540,
+ 43541,
+ 43542,
+ 43543,
+ 43544,
+ 43545,
+ 43546,
+ 43547,
+ 43548,
+ 43549,
+ 43550,
+ 43551,
+ 43552,
+ 43553,
+ 43554,
+ 43555,
+ 43556,
+ 43557,
+ 43558,
+ 43559,
+ 43560,
+ 43584,
+ 43585,
+ 43586,
+ 43588,
+ 43589,
+ 43590,
+ 43591,
+ 43592,
+ 43593,
+ 43594,
+ 43595,
+ 43616,
+ 43617,
+ 43618,
+ 43619,
+ 43620,
+ 43621,
+ 43622,
+ 43623,
+ 43624,
+ 43625,
+ 43626,
+ 43627,
+ 43628,
+ 43629,
+ 43630,
+ 43631,
+ 43632,
+ 43633,
+ 43634,
+ 43635,
+ 43636,
+ 43637,
+ 43638,
+ 43642,
+ 43648,
+ 43649,
+ 43650,
+ 43651,
+ 43652,
+ 43653,
+ 43654,
+ 43655,
+ 43656,
+ 43657,
+ 43658,
+ 43659,
+ 43660,
+ 43661,
+ 43662,
+ 43663,
+ 43664,
+ 43665,
+ 43666,
+ 43667,
+ 43668,
+ 43669,
+ 43670,
+ 43671,
+ 43672,
+ 43673,
+ 43674,
+ 43675,
+ 43676,
+ 43677,
+ 43678,
+ 43679,
+ 43680,
+ 43681,
+ 43682,
+ 43683,
+ 43684,
+ 43685,
+ 43686,
+ 43687,
+ 43688,
+ 43689,
+ 43690,
+ 43691,
+ 43692,
+ 43693,
+ 43694,
+ 43695,
+ 43697,
+ 43701,
+ 43702,
+ 43705,
+ 43706,
+ 43707,
+ 43708,
+ 43709,
+ 43712,
+ 43714,
+ 43739,
+ 43740,
+ 43741,
+ 43744,
+ 43745,
+ 43746,
+ 43747,
+ 43748,
+ 43749,
+ 43750,
+ 43751,
+ 43752,
+ 43753,
+ 43754,
+ 43762,
+ 43763,
+ 43764,
+ 43777,
+ 43778,
+ 43779,
+ 43780,
+ 43781,
+ 43782,
+ 43785,
+ 43786,
+ 43787,
+ 43788,
+ 43789,
+ 43790,
+ 43793,
+ 43794,
+ 43795,
+ 43796,
+ 43797,
+ 43798,
+ 43808,
+ 43809,
+ 43810,
+ 43811,
+ 43812,
+ 43813,
+ 43814,
+ 43816,
+ 43817,
+ 43818,
+ 43819,
+ 43820,
+ 43821,
+ 43822,
+ 43968,
+ 43969,
+ 43970,
+ 43971,
+ 43972,
+ 43973,
+ 43974,
+ 43975,
+ 43976,
+ 43977,
+ 43978,
+ 43979,
+ 43980,
+ 43981,
+ 43982,
+ 43983,
+ 43984,
+ 43985,
+ 43986,
+ 43987,
+ 43988,
+ 43989,
+ 43990,
+ 43991,
+ 43992,
+ 43993,
+ 43994,
+ 43995,
+ 43996,
+ 43997,
+ 43998,
+ 43999,
+ 44000,
+ 44001,
+ 44002,
+ 44032,
+ 44033,
+ 44034,
+ 44035,
+ 44036,
+ 44037,
+ 44038,
+ 44039,
+ 44040,
+ 44041,
+ 44042,
+ 44043,
+ 44044,
+ 44045,
+ 44046,
+ 44047,
+ 44048,
+ 44049,
+ 44050,
+ 44051,
+ 44052,
+ 44053,
+ 44054,
+ 44055,
+ 44056,
+ 44057,
+ 44058,
+ 44059,
+ 44060,
+ 44061,
+ 44062,
+ 44063,
+ 44064,
+ 44065,
+ 44066,
+ 44067,
+ 44068,
+ 44069,
+ 44070,
+ 44071,
+ 44072,
+ 44073,
+ 44074,
+ 44075,
+ 44076,
+ 44077,
+ 44078,
+ 44079,
+ 44080,
+ 44081,
+ 44082,
+ 44083,
+ 44084,
+ 44085,
+ 44086,
+ 44087,
+ 44088,
+ 44089,
+ 44090,
+ 44091,
+ 44092,
+ 44093,
+ 44094,
+ 44095,
+ 44096,
+ 44097,
+ 44098,
+ 44099,
+ 44100,
+ 44101,
+ 44102,
+ 44103,
+ 44104,
+ 44105,
+ 44106,
+ 44107,
+ 44108,
+ 44109,
+ 44110,
+ 44111,
+ 44112,
+ 44113,
+ 44114,
+ 44115,
+ 44116,
+ 44117,
+ 44118,
+ 44119,
+ 44120,
+ 44121,
+ 44122,
+ 44123,
+ 44124,
+ 44125,
+ 44126,
+ 44127,
+ 44128,
+ 44129,
+ 44130,
+ 44131,
+ 44132,
+ 44133,
+ 44134,
+ 44135,
+ 44136,
+ 44137,
+ 44138,
+ 44139,
+ 44140,
+ 44141,
+ 44142,
+ 44143,
+ 44144,
+ 44145,
+ 44146,
+ 44147,
+ 44148,
+ 44149,
+ 44150,
+ 44151,
+ 44152,
+ 44153,
+ 44154,
+ 44155,
+ 44156,
+ 44157,
+ 44158,
+ 44159,
+ 44160,
+ 44161,
+ 44162,
+ 44163,
+ 44164,
+ 44165,
+ 44166,
+ 44167,
+ 44168,
+ 44169,
+ 44170,
+ 44171,
+ 44172,
+ 44173,
+ 44174,
+ 44175,
+ 44176,
+ 44177,
+ 44178,
+ 44179,
+ 44180,
+ 44181,
+ 44182,
+ 44183,
+ 44184,
+ 44185,
+ 44186,
+ 44187,
+ 44188,
+ 44189,
+ 44190,
+ 44191,
+ 44192,
+ 44193,
+ 44194,
+ 44195,
+ 44196,
+ 44197,
+ 44198,
+ 44199,
+ 44200,
+ 44201,
+ 44202,
+ 44203,
+ 44204,
+ 44205,
+ 44206,
+ 44207,
+ 44208,
+ 44209,
+ 44210,
+ 44211,
+ 44212,
+ 44213,
+ 44214,
+ 44215,
+ 44216,
+ 44217,
+ 44218,
+ 44219,
+ 44220,
+ 44221,
+ 44222,
+ 44223,
+ 44224,
+ 44225,
+ 44226,
+ 44227,
+ 44228,
+ 44229,
+ 44230,
+ 44231,
+ 44232,
+ 44233,
+ 44234,
+ 44235,
+ 44236,
+ 44237,
+ 44238,
+ 44239,
+ 44240,
+ 44241,
+ 44242,
+ 44243,
+ 44244,
+ 44245,
+ 44246,
+ 44247,
+ 44248,
+ 44249,
+ 44250,
+ 44251,
+ 44252,
+ 44253,
+ 44254,
+ 44255,
+ 44256,
+ 44257,
+ 44258,
+ 44259,
+ 44260,
+ 44261,
+ 44262,
+ 44263,
+ 44264,
+ 44265,
+ 44266,
+ 44267,
+ 44268,
+ 44269,
+ 44270,
+ 44271,
+ 44272,
+ 44273,
+ 44274,
+ 44275,
+ 44276,
+ 44277,
+ 44278,
+ 44279,
+ 44280,
+ 44281,
+ 44282,
+ 44283,
+ 44284,
+ 44285,
+ 44286,
+ 44287,
+ 44288,
+ 44289,
+ 44290,
+ 44291,
+ 44292,
+ 44293,
+ 44294,
+ 44295,
+ 44296,
+ 44297,
+ 44298,
+ 44299,
+ 44300,
+ 44301,
+ 44302,
+ 44303,
+ 44304,
+ 44305,
+ 44306,
+ 44307,
+ 44308,
+ 44309,
+ 44310,
+ 44311,
+ 44312,
+ 44313,
+ 44314,
+ 44315,
+ 44316,
+ 44317,
+ 44318,
+ 44319,
+ 44320,
+ 44321,
+ 44322,
+ 44323,
+ 44324,
+ 44325,
+ 44326,
+ 44327,
+ 44328,
+ 44329,
+ 44330,
+ 44331,
+ 44332,
+ 44333,
+ 44334,
+ 44335,
+ 44336,
+ 44337,
+ 44338,
+ 44339,
+ 44340,
+ 44341,
+ 44342,
+ 44343,
+ 44344,
+ 44345,
+ 44346,
+ 44347,
+ 44348,
+ 44349,
+ 44350,
+ 44351,
+ 44352,
+ 44353,
+ 44354,
+ 44355,
+ 44356,
+ 44357,
+ 44358,
+ 44359,
+ 44360,
+ 44361,
+ 44362,
+ 44363,
+ 44364,
+ 44365,
+ 44366,
+ 44367,
+ 44368,
+ 44369,
+ 44370,
+ 44371,
+ 44372,
+ 44373,
+ 44374,
+ 44375,
+ 44376,
+ 44377,
+ 44378,
+ 44379,
+ 44380,
+ 44381,
+ 44382,
+ 44383,
+ 44384,
+ 44385,
+ 44386,
+ 44387,
+ 44388,
+ 44389,
+ 44390,
+ 44391,
+ 44392,
+ 44393,
+ 44394,
+ 44395,
+ 44396,
+ 44397,
+ 44398,
+ 44399,
+ 44400,
+ 44401,
+ 44402,
+ 44403,
+ 44404,
+ 44405,
+ 44406,
+ 44407,
+ 44408,
+ 44409,
+ 44410,
+ 44411,
+ 44412,
+ 44413,
+ 44414,
+ 44415,
+ 44416,
+ 44417,
+ 44418,
+ 44419,
+ 44420,
+ 44421,
+ 44422,
+ 44423,
+ 44424,
+ 44425,
+ 44426,
+ 44427,
+ 44428,
+ 44429,
+ 44430,
+ 44431,
+ 44432,
+ 44433,
+ 44434,
+ 44435,
+ 44436,
+ 44437,
+ 44438,
+ 44439,
+ 44440,
+ 44441,
+ 44442,
+ 44443,
+ 44444,
+ 44445,
+ 44446,
+ 44447,
+ 44448,
+ 44449,
+ 44450,
+ 44451,
+ 44452,
+ 44453,
+ 44454,
+ 44455,
+ 44456,
+ 44457,
+ 44458,
+ 44459,
+ 44460,
+ 44461,
+ 44462,
+ 44463,
+ 44464,
+ 44465,
+ 44466,
+ 44467,
+ 44468,
+ 44469,
+ 44470,
+ 44471,
+ 44472,
+ 44473,
+ 44474,
+ 44475,
+ 44476,
+ 44477,
+ 44478,
+ 44479,
+ 44480,
+ 44481,
+ 44482,
+ 44483,
+ 44484,
+ 44485,
+ 44486,
+ 44487,
+ 44488,
+ 44489,
+ 44490,
+ 44491,
+ 44492,
+ 44493,
+ 44494,
+ 44495,
+ 44496,
+ 44497,
+ 44498,
+ 44499,
+ 44500,
+ 44501,
+ 44502,
+ 44503,
+ 44504,
+ 44505,
+ 44506,
+ 44507,
+ 44508,
+ 44509,
+ 44510,
+ 44511,
+ 44512,
+ 44513,
+ 44514,
+ 44515,
+ 44516,
+ 44517,
+ 44518,
+ 44519,
+ 44520,
+ 44521,
+ 44522,
+ 44523,
+ 44524,
+ 44525,
+ 44526,
+ 44527,
+ 44528,
+ 44529,
+ 44530,
+ 44531,
+ 44532,
+ 44533,
+ 44534,
+ 44535,
+ 44536,
+ 44537,
+ 44538,
+ 44539,
+ 44540,
+ 44541,
+ 44542,
+ 44543,
+ 44544,
+ 44545,
+ 44546,
+ 44547,
+ 44548,
+ 44549,
+ 44550,
+ 44551,
+ 44552,
+ 44553,
+ 44554,
+ 44555,
+ 44556,
+ 44557,
+ 44558,
+ 44559,
+ 44560,
+ 44561,
+ 44562,
+ 44563,
+ 44564,
+ 44565,
+ 44566,
+ 44567,
+ 44568,
+ 44569,
+ 44570,
+ 44571,
+ 44572,
+ 44573,
+ 44574,
+ 44575,
+ 44576,
+ 44577,
+ 44578,
+ 44579,
+ 44580,
+ 44581,
+ 44582,
+ 44583,
+ 44584,
+ 44585,
+ 44586,
+ 44587,
+ 44588,
+ 44589,
+ 44590,
+ 44591,
+ 44592,
+ 44593,
+ 44594,
+ 44595,
+ 44596,
+ 44597,
+ 44598,
+ 44599,
+ 44600,
+ 44601,
+ 44602,
+ 44603,
+ 44604,
+ 44605,
+ 44606,
+ 44607,
+ 44608,
+ 44609,
+ 44610,
+ 44611,
+ 44612,
+ 44613,
+ 44614,
+ 44615,
+ 44616,
+ 44617,
+ 44618,
+ 44619,
+ 44620,
+ 44621,
+ 44622,
+ 44623,
+ 44624,
+ 44625,
+ 44626,
+ 44627,
+ 44628,
+ 44629,
+ 44630,
+ 44631,
+ 44632,
+ 44633,
+ 44634,
+ 44635,
+ 44636,
+ 44637,
+ 44638,
+ 44639,
+ 44640,
+ 44641,
+ 44642,
+ 44643,
+ 44644,
+ 44645,
+ 44646,
+ 44647,
+ 44648,
+ 44649,
+ 44650,
+ 44651,
+ 44652,
+ 44653,
+ 44654,
+ 44655,
+ 44656,
+ 44657,
+ 44658,
+ 44659,
+ 44660,
+ 44661,
+ 44662,
+ 44663,
+ 44664,
+ 44665,
+ 44666,
+ 44667,
+ 44668,
+ 44669,
+ 44670,
+ 44671,
+ 44672,
+ 44673,
+ 44674,
+ 44675,
+ 44676,
+ 44677,
+ 44678,
+ 44679,
+ 44680,
+ 44681,
+ 44682,
+ 44683,
+ 44684,
+ 44685,
+ 44686,
+ 44687,
+ 44688,
+ 44689,
+ 44690,
+ 44691,
+ 44692,
+ 44693,
+ 44694,
+ 44695,
+ 44696,
+ 44697,
+ 44698,
+ 44699,
+ 44700,
+ 44701,
+ 44702,
+ 44703,
+ 44704,
+ 44705,
+ 44706,
+ 44707,
+ 44708,
+ 44709,
+ 44710,
+ 44711,
+ 44712,
+ 44713,
+ 44714,
+ 44715,
+ 44716,
+ 44717,
+ 44718,
+ 44719,
+ 44720,
+ 44721,
+ 44722,
+ 44723,
+ 44724,
+ 44725,
+ 44726,
+ 44727,
+ 44728,
+ 44729,
+ 44730,
+ 44731,
+ 44732,
+ 44733,
+ 44734,
+ 44735,
+ 44736,
+ 44737,
+ 44738,
+ 44739,
+ 44740,
+ 44741,
+ 44742,
+ 44743,
+ 44744,
+ 44745,
+ 44746,
+ 44747,
+ 44748,
+ 44749,
+ 44750,
+ 44751,
+ 44752,
+ 44753,
+ 44754,
+ 44755,
+ 44756,
+ 44757,
+ 44758,
+ 44759,
+ 44760,
+ 44761,
+ 44762,
+ 44763,
+ 44764,
+ 44765,
+ 44766,
+ 44767,
+ 44768,
+ 44769,
+ 44770,
+ 44771,
+ 44772,
+ 44773,
+ 44774,
+ 44775,
+ 44776,
+ 44777,
+ 44778,
+ 44779,
+ 44780,
+ 44781,
+ 44782,
+ 44783,
+ 44784,
+ 44785,
+ 44786,
+ 44787,
+ 44788,
+ 44789,
+ 44790,
+ 44791,
+ 44792,
+ 44793,
+ 44794,
+ 44795,
+ 44796,
+ 44797,
+ 44798,
+ 44799,
+ 44800,
+ 44801,
+ 44802,
+ 44803,
+ 44804,
+ 44805,
+ 44806,
+ 44807,
+ 44808,
+ 44809,
+ 44810,
+ 44811,
+ 44812,
+ 44813,
+ 44814,
+ 44815,
+ 44816,
+ 44817,
+ 44818,
+ 44819,
+ 44820,
+ 44821,
+ 44822,
+ 44823,
+ 44824,
+ 44825,
+ 44826,
+ 44827,
+ 44828,
+ 44829,
+ 44830,
+ 44831,
+ 44832,
+ 44833,
+ 44834,
+ 44835,
+ 44836,
+ 44837,
+ 44838,
+ 44839,
+ 44840,
+ 44841,
+ 44842,
+ 44843,
+ 44844,
+ 44845,
+ 44846,
+ 44847,
+ 44848,
+ 44849,
+ 44850,
+ 44851,
+ 44852,
+ 44853,
+ 44854,
+ 44855,
+ 44856,
+ 44857,
+ 44858,
+ 44859,
+ 44860,
+ 44861,
+ 44862,
+ 44863,
+ 44864,
+ 44865,
+ 44866,
+ 44867,
+ 44868,
+ 44869,
+ 44870,
+ 44871,
+ 44872,
+ 44873,
+ 44874,
+ 44875,
+ 44876,
+ 44877,
+ 44878,
+ 44879,
+ 44880,
+ 44881,
+ 44882,
+ 44883,
+ 44884,
+ 44885,
+ 44886,
+ 44887,
+ 44888,
+ 44889,
+ 44890,
+ 44891,
+ 44892,
+ 44893,
+ 44894,
+ 44895,
+ 44896,
+ 44897,
+ 44898,
+ 44899,
+ 44900,
+ 44901,
+ 44902,
+ 44903,
+ 44904,
+ 44905,
+ 44906,
+ 44907,
+ 44908,
+ 44909,
+ 44910,
+ 44911,
+ 44912,
+ 44913,
+ 44914,
+ 44915,
+ 44916,
+ 44917,
+ 44918,
+ 44919,
+ 44920,
+ 44921,
+ 44922,
+ 44923,
+ 44924,
+ 44925,
+ 44926,
+ 44927,
+ 44928,
+ 44929,
+ 44930,
+ 44931,
+ 44932,
+ 44933,
+ 44934,
+ 44935,
+ 44936,
+ 44937,
+ 44938,
+ 44939,
+ 44940,
+ 44941,
+ 44942,
+ 44943,
+ 44944,
+ 44945,
+ 44946,
+ 44947,
+ 44948,
+ 44949,
+ 44950,
+ 44951,
+ 44952,
+ 44953,
+ 44954,
+ 44955,
+ 44956,
+ 44957,
+ 44958,
+ 44959,
+ 44960,
+ 44961,
+ 44962,
+ 44963,
+ 44964,
+ 44965,
+ 44966,
+ 44967,
+ 44968,
+ 44969,
+ 44970,
+ 44971,
+ 44972,
+ 44973,
+ 44974,
+ 44975,
+ 44976,
+ 44977,
+ 44978,
+ 44979,
+ 44980,
+ 44981,
+ 44982,
+ 44983,
+ 44984,
+ 44985,
+ 44986,
+ 44987,
+ 44988,
+ 44989,
+ 44990,
+ 44991,
+ 44992,
+ 44993,
+ 44994,
+ 44995,
+ 44996,
+ 44997,
+ 44998,
+ 44999,
+ 45000,
+ 45001,
+ 45002,
+ 45003,
+ 45004,
+ 45005,
+ 45006,
+ 45007,
+ 45008,
+ 45009,
+ 45010,
+ 45011,
+ 45012,
+ 45013,
+ 45014,
+ 45015,
+ 45016,
+ 45017,
+ 45018,
+ 45019,
+ 45020,
+ 45021,
+ 45022,
+ 45023,
+ 45024,
+ 45025,
+ 45026,
+ 45027,
+ 45028,
+ 45029,
+ 45030,
+ 45031,
+ 45032,
+ 45033,
+ 45034,
+ 45035,
+ 45036,
+ 45037,
+ 45038,
+ 45039,
+ 45040,
+ 45041,
+ 45042,
+ 45043,
+ 45044,
+ 45045,
+ 45046,
+ 45047,
+ 45048,
+ 45049,
+ 45050,
+ 45051,
+ 45052,
+ 45053,
+ 45054,
+ 45055,
+ 45056,
+ 45057,
+ 45058,
+ 45059,
+ 45060,
+ 45061,
+ 45062,
+ 45063,
+ 45064,
+ 45065,
+ 45066,
+ 45067,
+ 45068,
+ 45069,
+ 45070,
+ 45071,
+ 45072,
+ 45073,
+ 45074,
+ 45075,
+ 45076,
+ 45077,
+ 45078,
+ 45079,
+ 45080,
+ 45081,
+ 45082,
+ 45083,
+ 45084,
+ 45085,
+ 45086,
+ 45087,
+ 45088,
+ 45089,
+ 45090,
+ 45091,
+ 45092,
+ 45093,
+ 45094,
+ 45095,
+ 45096,
+ 45097,
+ 45098,
+ 45099,
+ 45100,
+ 45101,
+ 45102,
+ 45103,
+ 45104,
+ 45105,
+ 45106,
+ 45107,
+ 45108,
+ 45109,
+ 45110,
+ 45111,
+ 45112,
+ 45113,
+ 45114,
+ 45115,
+ 45116,
+ 45117,
+ 45118,
+ 45119,
+ 45120,
+ 45121,
+ 45122,
+ 45123,
+ 45124,
+ 45125,
+ 45126,
+ 45127,
+ 45128,
+ 45129,
+ 45130,
+ 45131,
+ 45132,
+ 45133,
+ 45134,
+ 45135,
+ 45136,
+ 45137,
+ 45138,
+ 45139,
+ 45140,
+ 45141,
+ 45142,
+ 45143,
+ 45144,
+ 45145,
+ 45146,
+ 45147,
+ 45148,
+ 45149,
+ 45150,
+ 45151,
+ 45152,
+ 45153,
+ 45154,
+ 45155,
+ 45156,
+ 45157,
+ 45158,
+ 45159,
+ 45160,
+ 45161,
+ 45162,
+ 45163,
+ 45164,
+ 45165,
+ 45166,
+ 45167,
+ 45168,
+ 45169,
+ 45170,
+ 45171,
+ 45172,
+ 45173,
+ 45174,
+ 45175,
+ 45176,
+ 45177,
+ 45178,
+ 45179,
+ 45180,
+ 45181,
+ 45182,
+ 45183,
+ 45184,
+ 45185,
+ 45186,
+ 45187,
+ 45188,
+ 45189,
+ 45190,
+ 45191,
+ 45192,
+ 45193,
+ 45194,
+ 45195,
+ 45196,
+ 45197,
+ 45198,
+ 45199,
+ 45200,
+ 45201,
+ 45202,
+ 45203,
+ 45204,
+ 45205,
+ 45206,
+ 45207,
+ 45208,
+ 45209,
+ 45210,
+ 45211,
+ 45212,
+ 45213,
+ 45214,
+ 45215,
+ 45216,
+ 45217,
+ 45218,
+ 45219,
+ 45220,
+ 45221,
+ 45222,
+ 45223,
+ 45224,
+ 45225,
+ 45226,
+ 45227,
+ 45228,
+ 45229,
+ 45230,
+ 45231,
+ 45232,
+ 45233,
+ 45234,
+ 45235,
+ 45236,
+ 45237,
+ 45238,
+ 45239,
+ 45240,
+ 45241,
+ 45242,
+ 45243,
+ 45244,
+ 45245,
+ 45246,
+ 45247,
+ 45248,
+ 45249,
+ 45250,
+ 45251,
+ 45252,
+ 45253,
+ 45254,
+ 45255,
+ 45256,
+ 45257,
+ 45258,
+ 45259,
+ 45260,
+ 45261,
+ 45262,
+ 45263,
+ 45264,
+ 45265,
+ 45266,
+ 45267,
+ 45268,
+ 45269,
+ 45270,
+ 45271,
+ 45272,
+ 45273,
+ 45274,
+ 45275,
+ 45276,
+ 45277,
+ 45278,
+ 45279,
+ 45280,
+ 45281,
+ 45282,
+ 45283,
+ 45284,
+ 45285,
+ 45286,
+ 45287,
+ 45288,
+ 45289,
+ 45290,
+ 45291,
+ 45292,
+ 45293,
+ 45294,
+ 45295,
+ 45296,
+ 45297,
+ 45298,
+ 45299,
+ 45300,
+ 45301,
+ 45302,
+ 45303,
+ 45304,
+ 45305,
+ 45306,
+ 45307,
+ 45308,
+ 45309,
+ 45310,
+ 45311,
+ 45312,
+ 45313,
+ 45314,
+ 45315,
+ 45316,
+ 45317,
+ 45318,
+ 45319,
+ 45320,
+ 45321,
+ 45322,
+ 45323,
+ 45324,
+ 45325,
+ 45326,
+ 45327,
+ 45328,
+ 45329,
+ 45330,
+ 45331,
+ 45332,
+ 45333,
+ 45334,
+ 45335,
+ 45336,
+ 45337,
+ 45338,
+ 45339,
+ 45340,
+ 45341,
+ 45342,
+ 45343,
+ 45344,
+ 45345,
+ 45346,
+ 45347,
+ 45348,
+ 45349,
+ 45350,
+ 45351,
+ 45352,
+ 45353,
+ 45354,
+ 45355,
+ 45356,
+ 45357,
+ 45358,
+ 45359,
+ 45360,
+ 45361,
+ 45362,
+ 45363,
+ 45364,
+ 45365,
+ 45366,
+ 45367,
+ 45368,
+ 45369,
+ 45370,
+ 45371,
+ 45372,
+ 45373,
+ 45374,
+ 45375,
+ 45376,
+ 45377,
+ 45378,
+ 45379,
+ 45380,
+ 45381,
+ 45382,
+ 45383,
+ 45384,
+ 45385,
+ 45386,
+ 45387,
+ 45388,
+ 45389,
+ 45390,
+ 45391,
+ 45392,
+ 45393,
+ 45394,
+ 45395,
+ 45396,
+ 45397,
+ 45398,
+ 45399,
+ 45400,
+ 45401,
+ 45402,
+ 45403,
+ 45404,
+ 45405,
+ 45406,
+ 45407,
+ 45408,
+ 45409,
+ 45410,
+ 45411,
+ 45412,
+ 45413,
+ 45414,
+ 45415,
+ 45416,
+ 45417,
+ 45418,
+ 45419,
+ 45420,
+ 45421,
+ 45422,
+ 45423,
+ 45424,
+ 45425,
+ 45426,
+ 45427,
+ 45428,
+ 45429,
+ 45430,
+ 45431,
+ 45432,
+ 45433,
+ 45434,
+ 45435,
+ 45436,
+ 45437,
+ 45438,
+ 45439,
+ 45440,
+ 45441,
+ 45442,
+ 45443,
+ 45444,
+ 45445,
+ 45446,
+ 45447,
+ 45448,
+ 45449,
+ 45450,
+ 45451,
+ 45452,
+ 45453,
+ 45454,
+ 45455,
+ 45456,
+ 45457,
+ 45458,
+ 45459,
+ 45460,
+ 45461,
+ 45462,
+ 45463,
+ 45464,
+ 45465,
+ 45466,
+ 45467,
+ 45468,
+ 45469,
+ 45470,
+ 45471,
+ 45472,
+ 45473,
+ 45474,
+ 45475,
+ 45476,
+ 45477,
+ 45478,
+ 45479,
+ 45480,
+ 45481,
+ 45482,
+ 45483,
+ 45484,
+ 45485,
+ 45486,
+ 45487,
+ 45488,
+ 45489,
+ 45490,
+ 45491,
+ 45492,
+ 45493,
+ 45494,
+ 45495,
+ 45496,
+ 45497,
+ 45498,
+ 45499,
+ 45500,
+ 45501,
+ 45502,
+ 45503,
+ 45504,
+ 45505,
+ 45506,
+ 45507,
+ 45508,
+ 45509,
+ 45510,
+ 45511,
+ 45512,
+ 45513,
+ 45514,
+ 45515,
+ 45516,
+ 45517,
+ 45518,
+ 45519,
+ 45520,
+ 45521,
+ 45522,
+ 45523,
+ 45524,
+ 45525,
+ 45526,
+ 45527,
+ 45528,
+ 45529,
+ 45530,
+ 45531,
+ 45532,
+ 45533,
+ 45534,
+ 45535,
+ 45536,
+ 45537,
+ 45538,
+ 45539,
+ 45540,
+ 45541,
+ 45542,
+ 45543,
+ 45544,
+ 45545,
+ 45546,
+ 45547,
+ 45548,
+ 45549,
+ 45550,
+ 45551,
+ 45552,
+ 45553,
+ 45554,
+ 45555,
+ 45556,
+ 45557,
+ 45558,
+ 45559,
+ 45560,
+ 45561,
+ 45562,
+ 45563,
+ 45564,
+ 45565,
+ 45566,
+ 45567,
+ 45568,
+ 45569,
+ 45570,
+ 45571,
+ 45572,
+ 45573,
+ 45574,
+ 45575,
+ 45576,
+ 45577,
+ 45578,
+ 45579,
+ 45580,
+ 45581,
+ 45582,
+ 45583,
+ 45584,
+ 45585,
+ 45586,
+ 45587,
+ 45588,
+ 45589,
+ 45590,
+ 45591,
+ 45592,
+ 45593,
+ 45594,
+ 45595,
+ 45596,
+ 45597,
+ 45598,
+ 45599,
+ 45600,
+ 45601,
+ 45602,
+ 45603,
+ 45604,
+ 45605,
+ 45606,
+ 45607,
+ 45608,
+ 45609,
+ 45610,
+ 45611,
+ 45612,
+ 45613,
+ 45614,
+ 45615,
+ 45616,
+ 45617,
+ 45618,
+ 45619,
+ 45620,
+ 45621,
+ 45622,
+ 45623,
+ 45624,
+ 45625,
+ 45626,
+ 45627,
+ 45628,
+ 45629,
+ 45630,
+ 45631,
+ 45632,
+ 45633,
+ 45634,
+ 45635,
+ 45636,
+ 45637,
+ 45638,
+ 45639,
+ 45640,
+ 45641,
+ 45642,
+ 45643,
+ 45644,
+ 45645,
+ 45646,
+ 45647,
+ 45648,
+ 45649,
+ 45650,
+ 45651,
+ 45652,
+ 45653,
+ 45654,
+ 45655,
+ 45656,
+ 45657,
+ 45658,
+ 45659,
+ 45660,
+ 45661,
+ 45662,
+ 45663,
+ 45664,
+ 45665,
+ 45666,
+ 45667,
+ 45668,
+ 45669,
+ 45670,
+ 45671,
+ 45672,
+ 45673,
+ 45674,
+ 45675,
+ 45676,
+ 45677,
+ 45678,
+ 45679,
+ 45680,
+ 45681,
+ 45682,
+ 45683,
+ 45684,
+ 45685,
+ 45686,
+ 45687,
+ 45688,
+ 45689,
+ 45690,
+ 45691,
+ 45692,
+ 45693,
+ 45694,
+ 45695,
+ 45696,
+ 45697,
+ 45698,
+ 45699,
+ 45700,
+ 45701,
+ 45702,
+ 45703,
+ 45704,
+ 45705,
+ 45706,
+ 45707,
+ 45708,
+ 45709,
+ 45710,
+ 45711,
+ 45712,
+ 45713,
+ 45714,
+ 45715,
+ 45716,
+ 45717,
+ 45718,
+ 45719,
+ 45720,
+ 45721,
+ 45722,
+ 45723,
+ 45724,
+ 45725,
+ 45726,
+ 45727,
+ 45728,
+ 45729,
+ 45730,
+ 45731,
+ 45732,
+ 45733,
+ 45734,
+ 45735,
+ 45736,
+ 45737,
+ 45738,
+ 45739,
+ 45740,
+ 45741,
+ 45742,
+ 45743,
+ 45744,
+ 45745,
+ 45746,
+ 45747,
+ 45748,
+ 45749,
+ 45750,
+ 45751,
+ 45752,
+ 45753,
+ 45754,
+ 45755,
+ 45756,
+ 45757,
+ 45758,
+ 45759,
+ 45760,
+ 45761,
+ 45762,
+ 45763,
+ 45764,
+ 45765,
+ 45766,
+ 45767,
+ 45768,
+ 45769,
+ 45770,
+ 45771,
+ 45772,
+ 45773,
+ 45774,
+ 45775,
+ 45776,
+ 45777,
+ 45778,
+ 45779,
+ 45780,
+ 45781,
+ 45782,
+ 45783,
+ 45784,
+ 45785,
+ 45786,
+ 45787,
+ 45788,
+ 45789,
+ 45790,
+ 45791,
+ 45792,
+ 45793,
+ 45794,
+ 45795,
+ 45796,
+ 45797,
+ 45798,
+ 45799,
+ 45800,
+ 45801,
+ 45802,
+ 45803,
+ 45804,
+ 45805,
+ 45806,
+ 45807,
+ 45808,
+ 45809,
+ 45810,
+ 45811,
+ 45812,
+ 45813,
+ 45814,
+ 45815,
+ 45816,
+ 45817,
+ 45818,
+ 45819,
+ 45820,
+ 45821,
+ 45822,
+ 45823,
+ 45824,
+ 45825,
+ 45826,
+ 45827,
+ 45828,
+ 45829,
+ 45830,
+ 45831,
+ 45832,
+ 45833,
+ 45834,
+ 45835,
+ 45836,
+ 45837,
+ 45838,
+ 45839,
+ 45840,
+ 45841,
+ 45842,
+ 45843,
+ 45844,
+ 45845,
+ 45846,
+ 45847,
+ 45848,
+ 45849,
+ 45850,
+ 45851,
+ 45852,
+ 45853,
+ 45854,
+ 45855,
+ 45856,
+ 45857,
+ 45858,
+ 45859,
+ 45860,
+ 45861,
+ 45862,
+ 45863,
+ 45864,
+ 45865,
+ 45866,
+ 45867,
+ 45868,
+ 45869,
+ 45870,
+ 45871,
+ 45872,
+ 45873,
+ 45874,
+ 45875,
+ 45876,
+ 45877,
+ 45878,
+ 45879,
+ 45880,
+ 45881,
+ 45882,
+ 45883,
+ 45884,
+ 45885,
+ 45886,
+ 45887,
+ 45888,
+ 45889,
+ 45890,
+ 45891,
+ 45892,
+ 45893,
+ 45894,
+ 45895,
+ 45896,
+ 45897,
+ 45898,
+ 45899,
+ 45900,
+ 45901,
+ 45902,
+ 45903,
+ 45904,
+ 45905,
+ 45906,
+ 45907,
+ 45908,
+ 45909,
+ 45910,
+ 45911,
+ 45912,
+ 45913,
+ 45914,
+ 45915,
+ 45916,
+ 45917,
+ 45918,
+ 45919,
+ 45920,
+ 45921,
+ 45922,
+ 45923,
+ 45924,
+ 45925,
+ 45926,
+ 45927,
+ 45928,
+ 45929,
+ 45930,
+ 45931,
+ 45932,
+ 45933,
+ 45934,
+ 45935,
+ 45936,
+ 45937,
+ 45938,
+ 45939,
+ 45940,
+ 45941,
+ 45942,
+ 45943,
+ 45944,
+ 45945,
+ 45946,
+ 45947,
+ 45948,
+ 45949,
+ 45950,
+ 45951,
+ 45952,
+ 45953,
+ 45954,
+ 45955,
+ 45956,
+ 45957,
+ 45958,
+ 45959,
+ 45960,
+ 45961,
+ 45962,
+ 45963,
+ 45964,
+ 45965,
+ 45966,
+ 45967,
+ 45968,
+ 45969,
+ 45970,
+ 45971,
+ 45972,
+ 45973,
+ 45974,
+ 45975,
+ 45976,
+ 45977,
+ 45978,
+ 45979,
+ 45980,
+ 45981,
+ 45982,
+ 45983,
+ 45984,
+ 45985,
+ 45986,
+ 45987,
+ 45988,
+ 45989,
+ 45990,
+ 45991,
+ 45992,
+ 45993,
+ 45994,
+ 45995,
+ 45996,
+ 45997,
+ 45998,
+ 45999,
+ 46000,
+ 46001,
+ 46002,
+ 46003,
+ 46004,
+ 46005,
+ 46006,
+ 46007,
+ 46008,
+ 46009,
+ 46010,
+ 46011,
+ 46012,
+ 46013,
+ 46014,
+ 46015,
+ 46016,
+ 46017,
+ 46018,
+ 46019,
+ 46020,
+ 46021,
+ 46022,
+ 46023,
+ 46024,
+ 46025,
+ 46026,
+ 46027,
+ 46028,
+ 46029,
+ 46030,
+ 46031,
+ 46032,
+ 46033,
+ 46034,
+ 46035,
+ 46036,
+ 46037,
+ 46038,
+ 46039,
+ 46040,
+ 46041,
+ 46042,
+ 46043,
+ 46044,
+ 46045,
+ 46046,
+ 46047,
+ 46048,
+ 46049,
+ 46050,
+ 46051,
+ 46052,
+ 46053,
+ 46054,
+ 46055,
+ 46056,
+ 46057,
+ 46058,
+ 46059,
+ 46060,
+ 46061,
+ 46062,
+ 46063,
+ 46064,
+ 46065,
+ 46066,
+ 46067,
+ 46068,
+ 46069,
+ 46070,
+ 46071,
+ 46072,
+ 46073,
+ 46074,
+ 46075,
+ 46076,
+ 46077,
+ 46078,
+ 46079,
+ 46080,
+ 46081,
+ 46082,
+ 46083,
+ 46084,
+ 46085,
+ 46086,
+ 46087,
+ 46088,
+ 46089,
+ 46090,
+ 46091,
+ 46092,
+ 46093,
+ 46094,
+ 46095,
+ 46096,
+ 46097,
+ 46098,
+ 46099,
+ 46100,
+ 46101,
+ 46102,
+ 46103,
+ 46104,
+ 46105,
+ 46106,
+ 46107,
+ 46108,
+ 46109,
+ 46110,
+ 46111,
+ 46112,
+ 46113,
+ 46114,
+ 46115,
+ 46116,
+ 46117,
+ 46118,
+ 46119,
+ 46120,
+ 46121,
+ 46122,
+ 46123,
+ 46124,
+ 46125,
+ 46126,
+ 46127,
+ 46128,
+ 46129,
+ 46130,
+ 46131,
+ 46132,
+ 46133,
+ 46134,
+ 46135,
+ 46136,
+ 46137,
+ 46138,
+ 46139,
+ 46140,
+ 46141,
+ 46142,
+ 46143,
+ 46144,
+ 46145,
+ 46146,
+ 46147,
+ 46148,
+ 46149,
+ 46150,
+ 46151,
+ 46152,
+ 46153,
+ 46154,
+ 46155,
+ 46156,
+ 46157,
+ 46158,
+ 46159,
+ 46160,
+ 46161,
+ 46162,
+ 46163,
+ 46164,
+ 46165,
+ 46166,
+ 46167,
+ 46168,
+ 46169,
+ 46170,
+ 46171,
+ 46172,
+ 46173,
+ 46174,
+ 46175,
+ 46176,
+ 46177,
+ 46178,
+ 46179,
+ 46180,
+ 46181,
+ 46182,
+ 46183,
+ 46184,
+ 46185,
+ 46186,
+ 46187,
+ 46188,
+ 46189,
+ 46190,
+ 46191,
+ 46192,
+ 46193,
+ 46194,
+ 46195,
+ 46196,
+ 46197,
+ 46198,
+ 46199,
+ 46200,
+ 46201,
+ 46202,
+ 46203,
+ 46204,
+ 46205,
+ 46206,
+ 46207,
+ 46208,
+ 46209,
+ 46210,
+ 46211,
+ 46212,
+ 46213,
+ 46214,
+ 46215,
+ 46216,
+ 46217,
+ 46218,
+ 46219,
+ 46220,
+ 46221,
+ 46222,
+ 46223,
+ 46224,
+ 46225,
+ 46226,
+ 46227,
+ 46228,
+ 46229,
+ 46230,
+ 46231,
+ 46232,
+ 46233,
+ 46234,
+ 46235,
+ 46236,
+ 46237,
+ 46238,
+ 46239,
+ 46240,
+ 46241,
+ 46242,
+ 46243,
+ 46244,
+ 46245,
+ 46246,
+ 46247,
+ 46248,
+ 46249,
+ 46250,
+ 46251,
+ 46252,
+ 46253,
+ 46254,
+ 46255,
+ 46256,
+ 46257,
+ 46258,
+ 46259,
+ 46260,
+ 46261,
+ 46262,
+ 46263,
+ 46264,
+ 46265,
+ 46266,
+ 46267,
+ 46268,
+ 46269,
+ 46270,
+ 46271,
+ 46272,
+ 46273,
+ 46274,
+ 46275,
+ 46276,
+ 46277,
+ 46278,
+ 46279,
+ 46280,
+ 46281,
+ 46282,
+ 46283,
+ 46284,
+ 46285,
+ 46286,
+ 46287,
+ 46288,
+ 46289,
+ 46290,
+ 46291,
+ 46292,
+ 46293,
+ 46294,
+ 46295,
+ 46296,
+ 46297,
+ 46298,
+ 46299,
+ 46300,
+ 46301,
+ 46302,
+ 46303,
+ 46304,
+ 46305,
+ 46306,
+ 46307,
+ 46308,
+ 46309,
+ 46310,
+ 46311,
+ 46312,
+ 46313,
+ 46314,
+ 46315,
+ 46316,
+ 46317,
+ 46318,
+ 46319,
+ 46320,
+ 46321,
+ 46322,
+ 46323,
+ 46324,
+ 46325,
+ 46326,
+ 46327,
+ 46328,
+ 46329,
+ 46330,
+ 46331,
+ 46332,
+ 46333,
+ 46334,
+ 46335,
+ 46336,
+ 46337,
+ 46338,
+ 46339,
+ 46340,
+ 46341,
+ 46342,
+ 46343,
+ 46344,
+ 46345,
+ 46346,
+ 46347,
+ 46348,
+ 46349,
+ 46350,
+ 46351,
+ 46352,
+ 46353,
+ 46354,
+ 46355,
+ 46356,
+ 46357,
+ 46358,
+ 46359,
+ 46360,
+ 46361,
+ 46362,
+ 46363,
+ 46364,
+ 46365,
+ 46366,
+ 46367,
+ 46368,
+ 46369,
+ 46370,
+ 46371,
+ 46372,
+ 46373,
+ 46374,
+ 46375,
+ 46376,
+ 46377,
+ 46378,
+ 46379,
+ 46380,
+ 46381,
+ 46382,
+ 46383,
+ 46384,
+ 46385,
+ 46386,
+ 46387,
+ 46388,
+ 46389,
+ 46390,
+ 46391,
+ 46392,
+ 46393,
+ 46394,
+ 46395,
+ 46396,
+ 46397,
+ 46398,
+ 46399,
+ 46400,
+ 46401,
+ 46402,
+ 46403,
+ 46404,
+ 46405,
+ 46406,
+ 46407,
+ 46408,
+ 46409,
+ 46410,
+ 46411,
+ 46412,
+ 46413,
+ 46414,
+ 46415,
+ 46416,
+ 46417,
+ 46418,
+ 46419,
+ 46420,
+ 46421,
+ 46422,
+ 46423,
+ 46424,
+ 46425,
+ 46426,
+ 46427,
+ 46428,
+ 46429,
+ 46430,
+ 46431,
+ 46432,
+ 46433,
+ 46434,
+ 46435,
+ 46436,
+ 46437,
+ 46438,
+ 46439,
+ 46440,
+ 46441,
+ 46442,
+ 46443,
+ 46444,
+ 46445,
+ 46446,
+ 46447,
+ 46448,
+ 46449,
+ 46450,
+ 46451,
+ 46452,
+ 46453,
+ 46454,
+ 46455,
+ 46456,
+ 46457,
+ 46458,
+ 46459,
+ 46460,
+ 46461,
+ 46462,
+ 46463,
+ 46464,
+ 46465,
+ 46466,
+ 46467,
+ 46468,
+ 46469,
+ 46470,
+ 46471,
+ 46472,
+ 46473,
+ 46474,
+ 46475,
+ 46476,
+ 46477,
+ 46478,
+ 46479,
+ 46480,
+ 46481,
+ 46482,
+ 46483,
+ 46484,
+ 46485,
+ 46486,
+ 46487,
+ 46488,
+ 46489,
+ 46490,
+ 46491,
+ 46492,
+ 46493,
+ 46494,
+ 46495,
+ 46496,
+ 46497,
+ 46498,
+ 46499,
+ 46500,
+ 46501,
+ 46502,
+ 46503,
+ 46504,
+ 46505,
+ 46506,
+ 46507,
+ 46508,
+ 46509,
+ 46510,
+ 46511,
+ 46512,
+ 46513,
+ 46514,
+ 46515,
+ 46516,
+ 46517,
+ 46518,
+ 46519,
+ 46520,
+ 46521,
+ 46522,
+ 46523,
+ 46524,
+ 46525,
+ 46526,
+ 46527,
+ 46528,
+ 46529,
+ 46530,
+ 46531,
+ 46532,
+ 46533,
+ 46534,
+ 46535,
+ 46536,
+ 46537,
+ 46538,
+ 46539,
+ 46540,
+ 46541,
+ 46542,
+ 46543,
+ 46544,
+ 46545,
+ 46546,
+ 46547,
+ 46548,
+ 46549,
+ 46550,
+ 46551,
+ 46552,
+ 46553,
+ 46554,
+ 46555,
+ 46556,
+ 46557,
+ 46558,
+ 46559,
+ 46560,
+ 46561,
+ 46562,
+ 46563,
+ 46564,
+ 46565,
+ 46566,
+ 46567,
+ 46568,
+ 46569,
+ 46570,
+ 46571,
+ 46572,
+ 46573,
+ 46574,
+ 46575,
+ 46576,
+ 46577,
+ 46578,
+ 46579,
+ 46580,
+ 46581,
+ 46582,
+ 46583,
+ 46584,
+ 46585,
+ 46586,
+ 46587,
+ 46588,
+ 46589,
+ 46590,
+ 46591,
+ 46592,
+ 46593,
+ 46594,
+ 46595,
+ 46596,
+ 46597,
+ 46598,
+ 46599,
+ 46600,
+ 46601,
+ 46602,
+ 46603,
+ 46604,
+ 46605,
+ 46606,
+ 46607,
+ 46608,
+ 46609,
+ 46610,
+ 46611,
+ 46612,
+ 46613,
+ 46614,
+ 46615,
+ 46616,
+ 46617,
+ 46618,
+ 46619,
+ 46620,
+ 46621,
+ 46622,
+ 46623,
+ 46624,
+ 46625,
+ 46626,
+ 46627,
+ 46628,
+ 46629,
+ 46630,
+ 46631,
+ 46632,
+ 46633,
+ 46634,
+ 46635,
+ 46636,
+ 46637,
+ 46638,
+ 46639,
+ 46640,
+ 46641,
+ 46642,
+ 46643,
+ 46644,
+ 46645,
+ 46646,
+ 46647,
+ 46648,
+ 46649,
+ 46650,
+ 46651,
+ 46652,
+ 46653,
+ 46654,
+ 46655,
+ 46656,
+ 46657,
+ 46658,
+ 46659,
+ 46660,
+ 46661,
+ 46662,
+ 46663,
+ 46664,
+ 46665,
+ 46666,
+ 46667,
+ 46668,
+ 46669,
+ 46670,
+ 46671,
+ 46672,
+ 46673,
+ 46674,
+ 46675,
+ 46676,
+ 46677,
+ 46678,
+ 46679,
+ 46680,
+ 46681,
+ 46682,
+ 46683,
+ 46684,
+ 46685,
+ 46686,
+ 46687,
+ 46688,
+ 46689,
+ 46690,
+ 46691,
+ 46692,
+ 46693,
+ 46694,
+ 46695,
+ 46696,
+ 46697,
+ 46698,
+ 46699,
+ 46700,
+ 46701,
+ 46702,
+ 46703,
+ 46704,
+ 46705,
+ 46706,
+ 46707,
+ 46708,
+ 46709,
+ 46710,
+ 46711,
+ 46712,
+ 46713,
+ 46714,
+ 46715,
+ 46716,
+ 46717,
+ 46718,
+ 46719,
+ 46720,
+ 46721,
+ 46722,
+ 46723,
+ 46724,
+ 46725,
+ 46726,
+ 46727,
+ 46728,
+ 46729,
+ 46730,
+ 46731,
+ 46732,
+ 46733,
+ 46734,
+ 46735,
+ 46736,
+ 46737,
+ 46738,
+ 46739,
+ 46740,
+ 46741,
+ 46742,
+ 46743,
+ 46744,
+ 46745,
+ 46746,
+ 46747,
+ 46748,
+ 46749,
+ 46750,
+ 46751,
+ 46752,
+ 46753,
+ 46754,
+ 46755,
+ 46756,
+ 46757,
+ 46758,
+ 46759,
+ 46760,
+ 46761,
+ 46762,
+ 46763,
+ 46764,
+ 46765,
+ 46766,
+ 46767,
+ 46768,
+ 46769,
+ 46770,
+ 46771,
+ 46772,
+ 46773,
+ 46774,
+ 46775,
+ 46776,
+ 46777,
+ 46778,
+ 46779,
+ 46780,
+ 46781,
+ 46782,
+ 46783,
+ 46784,
+ 46785,
+ 46786,
+ 46787,
+ 46788,
+ 46789,
+ 46790,
+ 46791,
+ 46792,
+ 46793,
+ 46794,
+ 46795,
+ 46796,
+ 46797,
+ 46798,
+ 46799,
+ 46800,
+ 46801,
+ 46802,
+ 46803,
+ 46804,
+ 46805,
+ 46806,
+ 46807,
+ 46808,
+ 46809,
+ 46810,
+ 46811,
+ 46812,
+ 46813,
+ 46814,
+ 46815,
+ 46816,
+ 46817,
+ 46818,
+ 46819,
+ 46820,
+ 46821,
+ 46822,
+ 46823,
+ 46824,
+ 46825,
+ 46826,
+ 46827,
+ 46828,
+ 46829,
+ 46830,
+ 46831,
+ 46832,
+ 46833,
+ 46834,
+ 46835,
+ 46836,
+ 46837,
+ 46838,
+ 46839,
+ 46840,
+ 46841,
+ 46842,
+ 46843,
+ 46844,
+ 46845,
+ 46846,
+ 46847,
+ 46848,
+ 46849,
+ 46850,
+ 46851,
+ 46852,
+ 46853,
+ 46854,
+ 46855,
+ 46856,
+ 46857,
+ 46858,
+ 46859,
+ 46860,
+ 46861,
+ 46862,
+ 46863,
+ 46864,
+ 46865,
+ 46866,
+ 46867,
+ 46868,
+ 46869,
+ 46870,
+ 46871,
+ 46872,
+ 46873,
+ 46874,
+ 46875,
+ 46876,
+ 46877,
+ 46878,
+ 46879,
+ 46880,
+ 46881,
+ 46882,
+ 46883,
+ 46884,
+ 46885,
+ 46886,
+ 46887,
+ 46888,
+ 46889,
+ 46890,
+ 46891,
+ 46892,
+ 46893,
+ 46894,
+ 46895,
+ 46896,
+ 46897,
+ 46898,
+ 46899,
+ 46900,
+ 46901,
+ 46902,
+ 46903,
+ 46904,
+ 46905,
+ 46906,
+ 46907,
+ 46908,
+ 46909,
+ 46910,
+ 46911,
+ 46912,
+ 46913,
+ 46914,
+ 46915,
+ 46916,
+ 46917,
+ 46918,
+ 46919,
+ 46920,
+ 46921,
+ 46922,
+ 46923,
+ 46924,
+ 46925,
+ 46926,
+ 46927,
+ 46928,
+ 46929,
+ 46930,
+ 46931,
+ 46932,
+ 46933,
+ 46934,
+ 46935,
+ 46936,
+ 46937,
+ 46938,
+ 46939,
+ 46940,
+ 46941,
+ 46942,
+ 46943,
+ 46944,
+ 46945,
+ 46946,
+ 46947,
+ 46948,
+ 46949,
+ 46950,
+ 46951,
+ 46952,
+ 46953,
+ 46954,
+ 46955,
+ 46956,
+ 46957,
+ 46958,
+ 46959,
+ 46960,
+ 46961,
+ 46962,
+ 46963,
+ 46964,
+ 46965,
+ 46966,
+ 46967,
+ 46968,
+ 46969,
+ 46970,
+ 46971,
+ 46972,
+ 46973,
+ 46974,
+ 46975,
+ 46976,
+ 46977,
+ 46978,
+ 46979,
+ 46980,
+ 46981,
+ 46982,
+ 46983,
+ 46984,
+ 46985,
+ 46986,
+ 46987,
+ 46988,
+ 46989,
+ 46990,
+ 46991,
+ 46992,
+ 46993,
+ 46994,
+ 46995,
+ 46996,
+ 46997,
+ 46998,
+ 46999,
+ 47000,
+ 47001,
+ 47002,
+ 47003,
+ 47004,
+ 47005,
+ 47006,
+ 47007,
+ 47008,
+ 47009,
+ 47010,
+ 47011,
+ 47012,
+ 47013,
+ 47014,
+ 47015,
+ 47016,
+ 47017,
+ 47018,
+ 47019,
+ 47020,
+ 47021,
+ 47022,
+ 47023,
+ 47024,
+ 47025,
+ 47026,
+ 47027,
+ 47028,
+ 47029,
+ 47030,
+ 47031,
+ 47032,
+ 47033,
+ 47034,
+ 47035,
+ 47036,
+ 47037,
+ 47038,
+ 47039,
+ 47040,
+ 47041,
+ 47042,
+ 47043,
+ 47044,
+ 47045,
+ 47046,
+ 47047,
+ 47048,
+ 47049,
+ 47050,
+ 47051,
+ 47052,
+ 47053,
+ 47054,
+ 47055,
+ 47056,
+ 47057,
+ 47058,
+ 47059,
+ 47060,
+ 47061,
+ 47062,
+ 47063,
+ 47064,
+ 47065,
+ 47066,
+ 47067,
+ 47068,
+ 47069,
+ 47070,
+ 47071,
+ 47072,
+ 47073,
+ 47074,
+ 47075,
+ 47076,
+ 47077,
+ 47078,
+ 47079,
+ 47080,
+ 47081,
+ 47082,
+ 47083,
+ 47084,
+ 47085,
+ 47086,
+ 47087,
+ 47088,
+ 47089,
+ 47090,
+ 47091,
+ 47092,
+ 47093,
+ 47094,
+ 47095,
+ 47096,
+ 47097,
+ 47098,
+ 47099,
+ 47100,
+ 47101,
+ 47102,
+ 47103,
+ 47104,
+ 47105,
+ 47106,
+ 47107,
+ 47108,
+ 47109,
+ 47110,
+ 47111,
+ 47112,
+ 47113,
+ 47114,
+ 47115,
+ 47116,
+ 47117,
+ 47118,
+ 47119,
+ 47120,
+ 47121,
+ 47122,
+ 47123,
+ 47124,
+ 47125,
+ 47126,
+ 47127,
+ 47128,
+ 47129,
+ 47130,
+ 47131,
+ 47132,
+ 47133,
+ 47134,
+ 47135,
+ 47136,
+ 47137,
+ 47138,
+ 47139,
+ 47140,
+ 47141,
+ 47142,
+ 47143,
+ 47144,
+ 47145,
+ 47146,
+ 47147,
+ 47148,
+ 47149,
+ 47150,
+ 47151,
+ 47152,
+ 47153,
+ 47154,
+ 47155,
+ 47156,
+ 47157,
+ 47158,
+ 47159,
+ 47160,
+ 47161,
+ 47162,
+ 47163,
+ 47164,
+ 47165,
+ 47166,
+ 47167,
+ 47168,
+ 47169,
+ 47170,
+ 47171,
+ 47172,
+ 47173,
+ 47174,
+ 47175,
+ 47176,
+ 47177,
+ 47178,
+ 47179,
+ 47180,
+ 47181,
+ 47182,
+ 47183,
+ 47184,
+ 47185,
+ 47186,
+ 47187,
+ 47188,
+ 47189,
+ 47190,
+ 47191,
+ 47192,
+ 47193,
+ 47194,
+ 47195,
+ 47196,
+ 47197,
+ 47198,
+ 47199,
+ 47200,
+ 47201,
+ 47202,
+ 47203,
+ 47204,
+ 47205,
+ 47206,
+ 47207,
+ 47208,
+ 47209,
+ 47210,
+ 47211,
+ 47212,
+ 47213,
+ 47214,
+ 47215,
+ 47216,
+ 47217,
+ 47218,
+ 47219,
+ 47220,
+ 47221,
+ 47222,
+ 47223,
+ 47224,
+ 47225,
+ 47226,
+ 47227,
+ 47228,
+ 47229,
+ 47230,
+ 47231,
+ 47232,
+ 47233,
+ 47234,
+ 47235,
+ 47236,
+ 47237,
+ 47238,
+ 47239,
+ 47240,
+ 47241,
+ 47242,
+ 47243,
+ 47244,
+ 47245,
+ 47246,
+ 47247,
+ 47248,
+ 47249,
+ 47250,
+ 47251,
+ 47252,
+ 47253,
+ 47254,
+ 47255,
+ 47256,
+ 47257,
+ 47258,
+ 47259,
+ 47260,
+ 47261,
+ 47262,
+ 47263,
+ 47264,
+ 47265,
+ 47266,
+ 47267,
+ 47268,
+ 47269,
+ 47270,
+ 47271,
+ 47272,
+ 47273,
+ 47274,
+ 47275,
+ 47276,
+ 47277,
+ 47278,
+ 47279,
+ 47280,
+ 47281,
+ 47282,
+ 47283,
+ 47284,
+ 47285,
+ 47286,
+ 47287,
+ 47288,
+ 47289,
+ 47290,
+ 47291,
+ 47292,
+ 47293,
+ 47294,
+ 47295,
+ 47296,
+ 47297,
+ 47298,
+ 47299,
+ 47300,
+ 47301,
+ 47302,
+ 47303,
+ 47304,
+ 47305,
+ 47306,
+ 47307,
+ 47308,
+ 47309,
+ 47310,
+ 47311,
+ 47312,
+ 47313,
+ 47314,
+ 47315,
+ 47316,
+ 47317,
+ 47318,
+ 47319,
+ 47320,
+ 47321,
+ 47322,
+ 47323,
+ 47324,
+ 47325,
+ 47326,
+ 47327,
+ 47328,
+ 47329,
+ 47330,
+ 47331,
+ 47332,
+ 47333,
+ 47334,
+ 47335,
+ 47336,
+ 47337,
+ 47338,
+ 47339,
+ 47340,
+ 47341,
+ 47342,
+ 47343,
+ 47344,
+ 47345,
+ 47346,
+ 47347,
+ 47348,
+ 47349,
+ 47350,
+ 47351,
+ 47352,
+ 47353,
+ 47354,
+ 47355,
+ 47356,
+ 47357,
+ 47358,
+ 47359,
+ 47360,
+ 47361,
+ 47362,
+ 47363,
+ 47364,
+ 47365,
+ 47366,
+ 47367,
+ 47368,
+ 47369,
+ 47370,
+ 47371,
+ 47372,
+ 47373,
+ 47374,
+ 47375,
+ 47376,
+ 47377,
+ 47378,
+ 47379,
+ 47380,
+ 47381,
+ 47382,
+ 47383,
+ 47384,
+ 47385,
+ 47386,
+ 47387,
+ 47388,
+ 47389,
+ 47390,
+ 47391,
+ 47392,
+ 47393,
+ 47394,
+ 47395,
+ 47396,
+ 47397,
+ 47398,
+ 47399,
+ 47400,
+ 47401,
+ 47402,
+ 47403,
+ 47404,
+ 47405,
+ 47406,
+ 47407,
+ 47408,
+ 47409,
+ 47410,
+ 47411,
+ 47412,
+ 47413,
+ 47414,
+ 47415,
+ 47416,
+ 47417,
+ 47418,
+ 47419,
+ 47420,
+ 47421,
+ 47422,
+ 47423,
+ 47424,
+ 47425,
+ 47426,
+ 47427,
+ 47428,
+ 47429,
+ 47430,
+ 47431,
+ 47432,
+ 47433,
+ 47434,
+ 47435,
+ 47436,
+ 47437,
+ 47438,
+ 47439,
+ 47440,
+ 47441,
+ 47442,
+ 47443,
+ 47444,
+ 47445,
+ 47446,
+ 47447,
+ 47448,
+ 47449,
+ 47450,
+ 47451,
+ 47452,
+ 47453,
+ 47454,
+ 47455,
+ 47456,
+ 47457,
+ 47458,
+ 47459,
+ 47460,
+ 47461,
+ 47462,
+ 47463,
+ 47464,
+ 47465,
+ 47466,
+ 47467,
+ 47468,
+ 47469,
+ 47470,
+ 47471,
+ 47472,
+ 47473,
+ 47474,
+ 47475,
+ 47476,
+ 47477,
+ 47478,
+ 47479,
+ 47480,
+ 47481,
+ 47482,
+ 47483,
+ 47484,
+ 47485,
+ 47486,
+ 47487,
+ 47488,
+ 47489,
+ 47490,
+ 47491,
+ 47492,
+ 47493,
+ 47494,
+ 47495,
+ 47496,
+ 47497,
+ 47498,
+ 47499,
+ 47500,
+ 47501,
+ 47502,
+ 47503,
+ 47504,
+ 47505,
+ 47506,
+ 47507,
+ 47508,
+ 47509,
+ 47510,
+ 47511,
+ 47512,
+ 47513,
+ 47514,
+ 47515,
+ 47516,
+ 47517,
+ 47518,
+ 47519,
+ 47520,
+ 47521,
+ 47522,
+ 47523,
+ 47524,
+ 47525,
+ 47526,
+ 47527,
+ 47528,
+ 47529,
+ 47530,
+ 47531,
+ 47532,
+ 47533,
+ 47534,
+ 47535,
+ 47536,
+ 47537,
+ 47538,
+ 47539,
+ 47540,
+ 47541,
+ 47542,
+ 47543,
+ 47544,
+ 47545,
+ 47546,
+ 47547,
+ 47548,
+ 47549,
+ 47550,
+ 47551,
+ 47552,
+ 47553,
+ 47554,
+ 47555,
+ 47556,
+ 47557,
+ 47558,
+ 47559,
+ 47560,
+ 47561,
+ 47562,
+ 47563,
+ 47564,
+ 47565,
+ 47566,
+ 47567,
+ 47568,
+ 47569,
+ 47570,
+ 47571,
+ 47572,
+ 47573,
+ 47574,
+ 47575,
+ 47576,
+ 47577,
+ 47578,
+ 47579,
+ 47580,
+ 47581,
+ 47582,
+ 47583,
+ 47584,
+ 47585,
+ 47586,
+ 47587,
+ 47588,
+ 47589,
+ 47590,
+ 47591,
+ 47592,
+ 47593,
+ 47594,
+ 47595,
+ 47596,
+ 47597,
+ 47598,
+ 47599,
+ 47600,
+ 47601,
+ 47602,
+ 47603,
+ 47604,
+ 47605,
+ 47606,
+ 47607,
+ 47608,
+ 47609,
+ 47610,
+ 47611,
+ 47612,
+ 47613,
+ 47614,
+ 47615,
+ 47616,
+ 47617,
+ 47618,
+ 47619,
+ 47620,
+ 47621,
+ 47622,
+ 47623,
+ 47624,
+ 47625,
+ 47626,
+ 47627,
+ 47628,
+ 47629,
+ 47630,
+ 47631,
+ 47632,
+ 47633,
+ 47634,
+ 47635,
+ 47636,
+ 47637,
+ 47638,
+ 47639,
+ 47640,
+ 47641,
+ 47642,
+ 47643,
+ 47644,
+ 47645,
+ 47646,
+ 47647,
+ 47648,
+ 47649,
+ 47650,
+ 47651,
+ 47652,
+ 47653,
+ 47654,
+ 47655,
+ 47656,
+ 47657,
+ 47658,
+ 47659,
+ 47660,
+ 47661,
+ 47662,
+ 47663,
+ 47664,
+ 47665,
+ 47666,
+ 47667,
+ 47668,
+ 47669,
+ 47670,
+ 47671,
+ 47672,
+ 47673,
+ 47674,
+ 47675,
+ 47676,
+ 47677,
+ 47678,
+ 47679,
+ 47680,
+ 47681,
+ 47682,
+ 47683,
+ 47684,
+ 47685,
+ 47686,
+ 47687,
+ 47688,
+ 47689,
+ 47690,
+ 47691,
+ 47692,
+ 47693,
+ 47694,
+ 47695,
+ 47696,
+ 47697,
+ 47698,
+ 47699,
+ 47700,
+ 47701,
+ 47702,
+ 47703,
+ 47704,
+ 47705,
+ 47706,
+ 47707,
+ 47708,
+ 47709,
+ 47710,
+ 47711,
+ 47712,
+ 47713,
+ 47714,
+ 47715,
+ 47716,
+ 47717,
+ 47718,
+ 47719,
+ 47720,
+ 47721,
+ 47722,
+ 47723,
+ 47724,
+ 47725,
+ 47726,
+ 47727,
+ 47728,
+ 47729,
+ 47730,
+ 47731,
+ 47732,
+ 47733,
+ 47734,
+ 47735,
+ 47736,
+ 47737,
+ 47738,
+ 47739,
+ 47740,
+ 47741,
+ 47742,
+ 47743,
+ 47744,
+ 47745,
+ 47746,
+ 47747,
+ 47748,
+ 47749,
+ 47750,
+ 47751,
+ 47752,
+ 47753,
+ 47754,
+ 47755,
+ 47756,
+ 47757,
+ 47758,
+ 47759,
+ 47760,
+ 47761,
+ 47762,
+ 47763,
+ 47764,
+ 47765,
+ 47766,
+ 47767,
+ 47768,
+ 47769,
+ 47770,
+ 47771,
+ 47772,
+ 47773,
+ 47774,
+ 47775,
+ 47776,
+ 47777,
+ 47778,
+ 47779,
+ 47780,
+ 47781,
+ 47782,
+ 47783,
+ 47784,
+ 47785,
+ 47786,
+ 47787,
+ 47788,
+ 47789,
+ 47790,
+ 47791,
+ 47792,
+ 47793,
+ 47794,
+ 47795,
+ 47796,
+ 47797,
+ 47798,
+ 47799,
+ 47800,
+ 47801,
+ 47802,
+ 47803,
+ 47804,
+ 47805,
+ 47806,
+ 47807,
+ 47808,
+ 47809,
+ 47810,
+ 47811,
+ 47812,
+ 47813,
+ 47814,
+ 47815,
+ 47816,
+ 47817,
+ 47818,
+ 47819,
+ 47820,
+ 47821,
+ 47822,
+ 47823,
+ 47824,
+ 47825,
+ 47826,
+ 47827,
+ 47828,
+ 47829,
+ 47830,
+ 47831,
+ 47832,
+ 47833,
+ 47834,
+ 47835,
+ 47836,
+ 47837,
+ 47838,
+ 47839,
+ 47840,
+ 47841,
+ 47842,
+ 47843,
+ 47844,
+ 47845,
+ 47846,
+ 47847,
+ 47848,
+ 47849,
+ 47850,
+ 47851,
+ 47852,
+ 47853,
+ 47854,
+ 47855,
+ 47856,
+ 47857,
+ 47858,
+ 47859,
+ 47860,
+ 47861,
+ 47862,
+ 47863,
+ 47864,
+ 47865,
+ 47866,
+ 47867,
+ 47868,
+ 47869,
+ 47870,
+ 47871,
+ 47872,
+ 47873,
+ 47874,
+ 47875,
+ 47876,
+ 47877,
+ 47878,
+ 47879,
+ 47880,
+ 47881,
+ 47882,
+ 47883,
+ 47884,
+ 47885,
+ 47886,
+ 47887,
+ 47888,
+ 47889,
+ 47890,
+ 47891,
+ 47892,
+ 47893,
+ 47894,
+ 47895,
+ 47896,
+ 47897,
+ 47898,
+ 47899,
+ 47900,
+ 47901,
+ 47902,
+ 47903,
+ 47904,
+ 47905,
+ 47906,
+ 47907,
+ 47908,
+ 47909,
+ 47910,
+ 47911,
+ 47912,
+ 47913,
+ 47914,
+ 47915,
+ 47916,
+ 47917,
+ 47918,
+ 47919,
+ 47920,
+ 47921,
+ 47922,
+ 47923,
+ 47924,
+ 47925,
+ 47926,
+ 47927,
+ 47928,
+ 47929,
+ 47930,
+ 47931,
+ 47932,
+ 47933,
+ 47934,
+ 47935,
+ 47936,
+ 47937,
+ 47938,
+ 47939,
+ 47940,
+ 47941,
+ 47942,
+ 47943,
+ 47944,
+ 47945,
+ 47946,
+ 47947,
+ 47948,
+ 47949,
+ 47950,
+ 47951,
+ 47952,
+ 47953,
+ 47954,
+ 47955,
+ 47956,
+ 47957,
+ 47958,
+ 47959,
+ 47960,
+ 47961,
+ 47962,
+ 47963,
+ 47964,
+ 47965,
+ 47966,
+ 47967,
+ 47968,
+ 47969,
+ 47970,
+ 47971,
+ 47972,
+ 47973,
+ 47974,
+ 47975,
+ 47976,
+ 47977,
+ 47978,
+ 47979,
+ 47980,
+ 47981,
+ 47982,
+ 47983,
+ 47984,
+ 47985,
+ 47986,
+ 47987,
+ 47988,
+ 47989,
+ 47990,
+ 47991,
+ 47992,
+ 47993,
+ 47994,
+ 47995,
+ 47996,
+ 47997,
+ 47998,
+ 47999,
+ 48000,
+ 48001,
+ 48002,
+ 48003,
+ 48004,
+ 48005,
+ 48006,
+ 48007,
+ 48008,
+ 48009,
+ 48010,
+ 48011,
+ 48012,
+ 48013,
+ 48014,
+ 48015,
+ 48016,
+ 48017,
+ 48018,
+ 48019,
+ 48020,
+ 48021,
+ 48022,
+ 48023,
+ 48024,
+ 48025,
+ 48026,
+ 48027,
+ 48028,
+ 48029,
+ 48030,
+ 48031,
+ 48032,
+ 48033,
+ 48034,
+ 48035,
+ 48036,
+ 48037,
+ 48038,
+ 48039,
+ 48040,
+ 48041,
+ 48042,
+ 48043,
+ 48044,
+ 48045,
+ 48046,
+ 48047,
+ 48048,
+ 48049,
+ 48050,
+ 48051,
+ 48052,
+ 48053,
+ 48054,
+ 48055,
+ 48056,
+ 48057,
+ 48058,
+ 48059,
+ 48060,
+ 48061,
+ 48062,
+ 48063,
+ 48064,
+ 48065,
+ 48066,
+ 48067,
+ 48068,
+ 48069,
+ 48070,
+ 48071,
+ 48072,
+ 48073,
+ 48074,
+ 48075,
+ 48076,
+ 48077,
+ 48078,
+ 48079,
+ 48080,
+ 48081,
+ 48082,
+ 48083,
+ 48084,
+ 48085,
+ 48086,
+ 48087,
+ 48088,
+ 48089,
+ 48090,
+ 48091,
+ 48092,
+ 48093,
+ 48094,
+ 48095,
+ 48096,
+ 48097,
+ 48098,
+ 48099,
+ 48100,
+ 48101,
+ 48102,
+ 48103,
+ 48104,
+ 48105,
+ 48106,
+ 48107,
+ 48108,
+ 48109,
+ 48110,
+ 48111,
+ 48112,
+ 48113,
+ 48114,
+ 48115,
+ 48116,
+ 48117,
+ 48118,
+ 48119,
+ 48120,
+ 48121,
+ 48122,
+ 48123,
+ 48124,
+ 48125,
+ 48126,
+ 48127,
+ 48128,
+ 48129,
+ 48130,
+ 48131,
+ 48132,
+ 48133,
+ 48134,
+ 48135,
+ 48136,
+ 48137,
+ 48138,
+ 48139,
+ 48140,
+ 48141,
+ 48142,
+ 48143,
+ 48144,
+ 48145,
+ 48146,
+ 48147,
+ 48148,
+ 48149,
+ 48150,
+ 48151,
+ 48152,
+ 48153,
+ 48154,
+ 48155,
+ 48156,
+ 48157,
+ 48158,
+ 48159,
+ 48160,
+ 48161,
+ 48162,
+ 48163,
+ 48164,
+ 48165,
+ 48166,
+ 48167,
+ 48168,
+ 48169,
+ 48170,
+ 48171,
+ 48172,
+ 48173,
+ 48174,
+ 48175,
+ 48176,
+ 48177,
+ 48178,
+ 48179,
+ 48180,
+ 48181,
+ 48182,
+ 48183,
+ 48184,
+ 48185,
+ 48186,
+ 48187,
+ 48188,
+ 48189,
+ 48190,
+ 48191,
+ 48192,
+ 48193,
+ 48194,
+ 48195,
+ 48196,
+ 48197,
+ 48198,
+ 48199,
+ 48200,
+ 48201,
+ 48202,
+ 48203,
+ 48204,
+ 48205,
+ 48206,
+ 48207,
+ 48208,
+ 48209,
+ 48210,
+ 48211,
+ 48212,
+ 48213,
+ 48214,
+ 48215,
+ 48216,
+ 48217,
+ 48218,
+ 48219,
+ 48220,
+ 48221,
+ 48222,
+ 48223,
+ 48224,
+ 48225,
+ 48226,
+ 48227,
+ 48228,
+ 48229,
+ 48230,
+ 48231,
+ 48232,
+ 48233,
+ 48234,
+ 48235,
+ 48236,
+ 48237,
+ 48238,
+ 48239,
+ 48240,
+ 48241,
+ 48242,
+ 48243,
+ 48244,
+ 48245,
+ 48246,
+ 48247,
+ 48248,
+ 48249,
+ 48250,
+ 48251,
+ 48252,
+ 48253,
+ 48254,
+ 48255,
+ 48256,
+ 48257,
+ 48258,
+ 48259,
+ 48260,
+ 48261,
+ 48262,
+ 48263,
+ 48264,
+ 48265,
+ 48266,
+ 48267,
+ 48268,
+ 48269,
+ 48270,
+ 48271,
+ 48272,
+ 48273,
+ 48274,
+ 48275,
+ 48276,
+ 48277,
+ 48278,
+ 48279,
+ 48280,
+ 48281,
+ 48282,
+ 48283,
+ 48284,
+ 48285,
+ 48286,
+ 48287,
+ 48288,
+ 48289,
+ 48290,
+ 48291,
+ 48292,
+ 48293,
+ 48294,
+ 48295,
+ 48296,
+ 48297,
+ 48298,
+ 48299,
+ 48300,
+ 48301,
+ 48302,
+ 48303,
+ 48304,
+ 48305,
+ 48306,
+ 48307,
+ 48308,
+ 48309,
+ 48310,
+ 48311,
+ 48312,
+ 48313,
+ 48314,
+ 48315,
+ 48316,
+ 48317,
+ 48318,
+ 48319,
+ 48320,
+ 48321,
+ 48322,
+ 48323,
+ 48324,
+ 48325,
+ 48326,
+ 48327,
+ 48328,
+ 48329,
+ 48330,
+ 48331,
+ 48332,
+ 48333,
+ 48334,
+ 48335,
+ 48336,
+ 48337,
+ 48338,
+ 48339,
+ 48340,
+ 48341,
+ 48342,
+ 48343,
+ 48344,
+ 48345,
+ 48346,
+ 48347,
+ 48348,
+ 48349,
+ 48350,
+ 48351,
+ 48352,
+ 48353,
+ 48354,
+ 48355,
+ 48356,
+ 48357,
+ 48358,
+ 48359,
+ 48360,
+ 48361,
+ 48362,
+ 48363,
+ 48364,
+ 48365,
+ 48366,
+ 48367,
+ 48368,
+ 48369,
+ 48370,
+ 48371,
+ 48372,
+ 48373,
+ 48374,
+ 48375,
+ 48376,
+ 48377,
+ 48378,
+ 48379,
+ 48380,
+ 48381,
+ 48382,
+ 48383,
+ 48384,
+ 48385,
+ 48386,
+ 48387,
+ 48388,
+ 48389,
+ 48390,
+ 48391,
+ 48392,
+ 48393,
+ 48394,
+ 48395,
+ 48396,
+ 48397,
+ 48398,
+ 48399,
+ 48400,
+ 48401,
+ 48402,
+ 48403,
+ 48404,
+ 48405,
+ 48406,
+ 48407,
+ 48408,
+ 48409,
+ 48410,
+ 48411,
+ 48412,
+ 48413,
+ 48414,
+ 48415,
+ 48416,
+ 48417,
+ 48418,
+ 48419,
+ 48420,
+ 48421,
+ 48422,
+ 48423,
+ 48424,
+ 48425,
+ 48426,
+ 48427,
+ 48428,
+ 48429,
+ 48430,
+ 48431,
+ 48432,
+ 48433,
+ 48434,
+ 48435,
+ 48436,
+ 48437,
+ 48438,
+ 48439,
+ 48440,
+ 48441,
+ 48442,
+ 48443,
+ 48444,
+ 48445,
+ 48446,
+ 48447,
+ 48448,
+ 48449,
+ 48450,
+ 48451,
+ 48452,
+ 48453,
+ 48454,
+ 48455,
+ 48456,
+ 48457,
+ 48458,
+ 48459,
+ 48460,
+ 48461,
+ 48462,
+ 48463,
+ 48464,
+ 48465,
+ 48466,
+ 48467,
+ 48468,
+ 48469,
+ 48470,
+ 48471,
+ 48472,
+ 48473,
+ 48474,
+ 48475,
+ 48476,
+ 48477,
+ 48478,
+ 48479,
+ 48480,
+ 48481,
+ 48482,
+ 48483,
+ 48484,
+ 48485,
+ 48486,
+ 48487,
+ 48488,
+ 48489,
+ 48490,
+ 48491,
+ 48492,
+ 48493,
+ 48494,
+ 48495,
+ 48496,
+ 48497,
+ 48498,
+ 48499,
+ 48500,
+ 48501,
+ 48502,
+ 48503,
+ 48504,
+ 48505,
+ 48506,
+ 48507,
+ 48508,
+ 48509,
+ 48510,
+ 48511,
+ 48512,
+ 48513,
+ 48514,
+ 48515,
+ 48516,
+ 48517,
+ 48518,
+ 48519,
+ 48520,
+ 48521,
+ 48522,
+ 48523,
+ 48524,
+ 48525,
+ 48526,
+ 48527,
+ 48528,
+ 48529,
+ 48530,
+ 48531,
+ 48532,
+ 48533,
+ 48534,
+ 48535,
+ 48536,
+ 48537,
+ 48538,
+ 48539,
+ 48540,
+ 48541,
+ 48542,
+ 48543,
+ 48544,
+ 48545,
+ 48546,
+ 48547,
+ 48548,
+ 48549,
+ 48550,
+ 48551,
+ 48552,
+ 48553,
+ 48554,
+ 48555,
+ 48556,
+ 48557,
+ 48558,
+ 48559,
+ 48560,
+ 48561,
+ 48562,
+ 48563,
+ 48564,
+ 48565,
+ 48566,
+ 48567,
+ 48568,
+ 48569,
+ 48570,
+ 48571,
+ 48572,
+ 48573,
+ 48574,
+ 48575,
+ 48576,
+ 48577,
+ 48578,
+ 48579,
+ 48580,
+ 48581,
+ 48582,
+ 48583,
+ 48584,
+ 48585,
+ 48586,
+ 48587,
+ 48588,
+ 48589,
+ 48590,
+ 48591,
+ 48592,
+ 48593,
+ 48594,
+ 48595,
+ 48596,
+ 48597,
+ 48598,
+ 48599,
+ 48600,
+ 48601,
+ 48602,
+ 48603,
+ 48604,
+ 48605,
+ 48606,
+ 48607,
+ 48608,
+ 48609,
+ 48610,
+ 48611,
+ 48612,
+ 48613,
+ 48614,
+ 48615,
+ 48616,
+ 48617,
+ 48618,
+ 48619,
+ 48620,
+ 48621,
+ 48622,
+ 48623,
+ 48624,
+ 48625,
+ 48626,
+ 48627,
+ 48628,
+ 48629,
+ 48630,
+ 48631,
+ 48632,
+ 48633,
+ 48634,
+ 48635,
+ 48636,
+ 48637,
+ 48638,
+ 48639,
+ 48640,
+ 48641,
+ 48642,
+ 48643,
+ 48644,
+ 48645,
+ 48646,
+ 48647,
+ 48648,
+ 48649,
+ 48650,
+ 48651,
+ 48652,
+ 48653,
+ 48654,
+ 48655,
+ 48656,
+ 48657,
+ 48658,
+ 48659,
+ 48660,
+ 48661,
+ 48662,
+ 48663,
+ 48664,
+ 48665,
+ 48666,
+ 48667,
+ 48668,
+ 48669,
+ 48670,
+ 48671,
+ 48672,
+ 48673,
+ 48674,
+ 48675,
+ 48676,
+ 48677,
+ 48678,
+ 48679,
+ 48680,
+ 48681,
+ 48682,
+ 48683,
+ 48684,
+ 48685,
+ 48686,
+ 48687,
+ 48688,
+ 48689,
+ 48690,
+ 48691,
+ 48692,
+ 48693,
+ 48694,
+ 48695,
+ 48696,
+ 48697,
+ 48698,
+ 48699,
+ 48700,
+ 48701,
+ 48702,
+ 48703,
+ 48704,
+ 48705,
+ 48706,
+ 48707,
+ 48708,
+ 48709,
+ 48710,
+ 48711,
+ 48712,
+ 48713,
+ 48714,
+ 48715,
+ 48716,
+ 48717,
+ 48718,
+ 48719,
+ 48720,
+ 48721,
+ 48722,
+ 48723,
+ 48724,
+ 48725,
+ 48726,
+ 48727,
+ 48728,
+ 48729,
+ 48730,
+ 48731,
+ 48732,
+ 48733,
+ 48734,
+ 48735,
+ 48736,
+ 48737,
+ 48738,
+ 48739,
+ 48740,
+ 48741,
+ 48742,
+ 48743,
+ 48744,
+ 48745,
+ 48746,
+ 48747,
+ 48748,
+ 48749,
+ 48750,
+ 48751,
+ 48752,
+ 48753,
+ 48754,
+ 48755,
+ 48756,
+ 48757,
+ 48758,
+ 48759,
+ 48760,
+ 48761,
+ 48762,
+ 48763,
+ 48764,
+ 48765,
+ 48766,
+ 48767,
+ 48768,
+ 48769,
+ 48770,
+ 48771,
+ 48772,
+ 48773,
+ 48774,
+ 48775,
+ 48776,
+ 48777,
+ 48778,
+ 48779,
+ 48780,
+ 48781,
+ 48782,
+ 48783,
+ 48784,
+ 48785,
+ 48786,
+ 48787,
+ 48788,
+ 48789,
+ 48790,
+ 48791,
+ 48792,
+ 48793,
+ 48794,
+ 48795,
+ 48796,
+ 48797,
+ 48798,
+ 48799,
+ 48800,
+ 48801,
+ 48802,
+ 48803,
+ 48804,
+ 48805,
+ 48806,
+ 48807,
+ 48808,
+ 48809,
+ 48810,
+ 48811,
+ 48812,
+ 48813,
+ 48814,
+ 48815,
+ 48816,
+ 48817,
+ 48818,
+ 48819,
+ 48820,
+ 48821,
+ 48822,
+ 48823,
+ 48824,
+ 48825,
+ 48826,
+ 48827,
+ 48828,
+ 48829,
+ 48830,
+ 48831,
+ 48832,
+ 48833,
+ 48834,
+ 48835,
+ 48836,
+ 48837,
+ 48838,
+ 48839,
+ 48840,
+ 48841,
+ 48842,
+ 48843,
+ 48844,
+ 48845,
+ 48846,
+ 48847,
+ 48848,
+ 48849,
+ 48850,
+ 48851,
+ 48852,
+ 48853,
+ 48854,
+ 48855,
+ 48856,
+ 48857,
+ 48858,
+ 48859,
+ 48860,
+ 48861,
+ 48862,
+ 48863,
+ 48864,
+ 48865,
+ 48866,
+ 48867,
+ 48868,
+ 48869,
+ 48870,
+ 48871,
+ 48872,
+ 48873,
+ 48874,
+ 48875,
+ 48876,
+ 48877,
+ 48878,
+ 48879,
+ 48880,
+ 48881,
+ 48882,
+ 48883,
+ 48884,
+ 48885,
+ 48886,
+ 48887,
+ 48888,
+ 48889,
+ 48890,
+ 48891,
+ 48892,
+ 48893,
+ 48894,
+ 48895,
+ 48896,
+ 48897,
+ 48898,
+ 48899,
+ 48900,
+ 48901,
+ 48902,
+ 48903,
+ 48904,
+ 48905,
+ 48906,
+ 48907,
+ 48908,
+ 48909,
+ 48910,
+ 48911,
+ 48912,
+ 48913,
+ 48914,
+ 48915,
+ 48916,
+ 48917,
+ 48918,
+ 48919,
+ 48920,
+ 48921,
+ 48922,
+ 48923,
+ 48924,
+ 48925,
+ 48926,
+ 48927,
+ 48928,
+ 48929,
+ 48930,
+ 48931,
+ 48932,
+ 48933,
+ 48934,
+ 48935,
+ 48936,
+ 48937,
+ 48938,
+ 48939,
+ 48940,
+ 48941,
+ 48942,
+ 48943,
+ 48944,
+ 48945,
+ 48946,
+ 48947,
+ 48948,
+ 48949,
+ 48950,
+ 48951,
+ 48952,
+ 48953,
+ 48954,
+ 48955,
+ 48956,
+ 48957,
+ 48958,
+ 48959,
+ 48960,
+ 48961,
+ 48962,
+ 48963,
+ 48964,
+ 48965,
+ 48966,
+ 48967,
+ 48968,
+ 48969,
+ 48970,
+ 48971,
+ 48972,
+ 48973,
+ 48974,
+ 48975,
+ 48976,
+ 48977,
+ 48978,
+ 48979,
+ 48980,
+ 48981,
+ 48982,
+ 48983,
+ 48984,
+ 48985,
+ 48986,
+ 48987,
+ 48988,
+ 48989,
+ 48990,
+ 48991,
+ 48992,
+ 48993,
+ 48994,
+ 48995,
+ 48996,
+ 48997,
+ 48998,
+ 48999,
+ 49000,
+ 49001,
+ 49002,
+ 49003,
+ 49004,
+ 49005,
+ 49006,
+ 49007,
+ 49008,
+ 49009,
+ 49010,
+ 49011,
+ 49012,
+ 49013,
+ 49014,
+ 49015,
+ 49016,
+ 49017,
+ 49018,
+ 49019,
+ 49020,
+ 49021,
+ 49022,
+ 49023,
+ 49024,
+ 49025,
+ 49026,
+ 49027,
+ 49028,
+ 49029,
+ 49030,
+ 49031,
+ 49032,
+ 49033,
+ 49034,
+ 49035,
+ 49036,
+ 49037,
+ 49038,
+ 49039,
+ 49040,
+ 49041,
+ 49042,
+ 49043,
+ 49044,
+ 49045,
+ 49046,
+ 49047,
+ 49048,
+ 49049,
+ 49050,
+ 49051,
+ 49052,
+ 49053,
+ 49054,
+ 49055,
+ 49056,
+ 49057,
+ 49058,
+ 49059,
+ 49060,
+ 49061,
+ 49062,
+ 49063,
+ 49064,
+ 49065,
+ 49066,
+ 49067,
+ 49068,
+ 49069,
+ 49070,
+ 49071,
+ 49072,
+ 49073,
+ 49074,
+ 49075,
+ 49076,
+ 49077,
+ 49078,
+ 49079,
+ 49080,
+ 49081,
+ 49082,
+ 49083,
+ 49084,
+ 49085,
+ 49086,
+ 49087,
+ 49088,
+ 49089,
+ 49090,
+ 49091,
+ 49092,
+ 49093,
+ 49094,
+ 49095,
+ 49096,
+ 49097,
+ 49098,
+ 49099,
+ 49100,
+ 49101,
+ 49102,
+ 49103,
+ 49104,
+ 49105,
+ 49106,
+ 49107,
+ 49108,
+ 49109,
+ 49110,
+ 49111,
+ 49112,
+ 49113,
+ 49114,
+ 49115,
+ 49116,
+ 49117,
+ 49118,
+ 49119,
+ 49120,
+ 49121,
+ 49122,
+ 49123,
+ 49124,
+ 49125,
+ 49126,
+ 49127,
+ 49128,
+ 49129,
+ 49130,
+ 49131,
+ 49132,
+ 49133,
+ 49134,
+ 49135,
+ 49136,
+ 49137,
+ 49138,
+ 49139,
+ 49140,
+ 49141,
+ 49142,
+ 49143,
+ 49144,
+ 49145,
+ 49146,
+ 49147,
+ 49148,
+ 49149,
+ 49150,
+ 49151,
+ 49152,
+ 49153,
+ 49154,
+ 49155,
+ 49156,
+ 49157,
+ 49158,
+ 49159,
+ 49160,
+ 49161,
+ 49162,
+ 49163,
+ 49164,
+ 49165,
+ 49166,
+ 49167,
+ 49168,
+ 49169,
+ 49170,
+ 49171,
+ 49172,
+ 49173,
+ 49174,
+ 49175,
+ 49176,
+ 49177,
+ 49178,
+ 49179,
+ 49180,
+ 49181,
+ 49182,
+ 49183,
+ 49184,
+ 49185,
+ 49186,
+ 49187,
+ 49188,
+ 49189,
+ 49190,
+ 49191,
+ 49192,
+ 49193,
+ 49194,
+ 49195,
+ 49196,
+ 49197,
+ 49198,
+ 49199,
+ 49200,
+ 49201,
+ 49202,
+ 49203,
+ 49204,
+ 49205,
+ 49206,
+ 49207,
+ 49208,
+ 49209,
+ 49210,
+ 49211,
+ 49212,
+ 49213,
+ 49214,
+ 49215,
+ 49216,
+ 49217,
+ 49218,
+ 49219,
+ 49220,
+ 49221,
+ 49222,
+ 49223,
+ 49224,
+ 49225,
+ 49226,
+ 49227,
+ 49228,
+ 49229,
+ 49230,
+ 49231,
+ 49232,
+ 49233,
+ 49234,
+ 49235,
+ 49236,
+ 49237,
+ 49238,
+ 49239,
+ 49240,
+ 49241,
+ 49242,
+ 49243,
+ 49244,
+ 49245,
+ 49246,
+ 49247,
+ 49248,
+ 49249,
+ 49250,
+ 49251,
+ 49252,
+ 49253,
+ 49254,
+ 49255,
+ 49256,
+ 49257,
+ 49258,
+ 49259,
+ 49260,
+ 49261,
+ 49262,
+ 49263,
+ 49264,
+ 49265,
+ 49266,
+ 49267,
+ 49268,
+ 49269,
+ 49270,
+ 49271,
+ 49272,
+ 49273,
+ 49274,
+ 49275,
+ 49276,
+ 49277,
+ 49278,
+ 49279,
+ 49280,
+ 49281,
+ 49282,
+ 49283,
+ 49284,
+ 49285,
+ 49286,
+ 49287,
+ 49288,
+ 49289,
+ 49290,
+ 49291,
+ 49292,
+ 49293,
+ 49294,
+ 49295,
+ 49296,
+ 49297,
+ 49298,
+ 49299,
+ 49300,
+ 49301,
+ 49302,
+ 49303,
+ 49304,
+ 49305,
+ 49306,
+ 49307,
+ 49308,
+ 49309,
+ 49310,
+ 49311,
+ 49312,
+ 49313,
+ 49314,
+ 49315,
+ 49316,
+ 49317,
+ 49318,
+ 49319,
+ 49320,
+ 49321,
+ 49322,
+ 49323,
+ 49324,
+ 49325,
+ 49326,
+ 49327,
+ 49328,
+ 49329,
+ 49330,
+ 49331,
+ 49332,
+ 49333,
+ 49334,
+ 49335,
+ 49336,
+ 49337,
+ 49338,
+ 49339,
+ 49340,
+ 49341,
+ 49342,
+ 49343,
+ 49344,
+ 49345,
+ 49346,
+ 49347,
+ 49348,
+ 49349,
+ 49350,
+ 49351,
+ 49352,
+ 49353,
+ 49354,
+ 49355,
+ 49356,
+ 49357,
+ 49358,
+ 49359,
+ 49360,
+ 49361,
+ 49362,
+ 49363,
+ 49364,
+ 49365,
+ 49366,
+ 49367,
+ 49368,
+ 49369,
+ 49370,
+ 49371,
+ 49372,
+ 49373,
+ 49374,
+ 49375,
+ 49376,
+ 49377,
+ 49378,
+ 49379,
+ 49380,
+ 49381,
+ 49382,
+ 49383,
+ 49384,
+ 49385,
+ 49386,
+ 49387,
+ 49388,
+ 49389,
+ 49390,
+ 49391,
+ 49392,
+ 49393,
+ 49394,
+ 49395,
+ 49396,
+ 49397,
+ 49398,
+ 49399,
+ 49400,
+ 49401,
+ 49402,
+ 49403,
+ 49404,
+ 49405,
+ 49406,
+ 49407,
+ 49408,
+ 49409,
+ 49410,
+ 49411,
+ 49412,
+ 49413,
+ 49414,
+ 49415,
+ 49416,
+ 49417,
+ 49418,
+ 49419,
+ 49420,
+ 49421,
+ 49422,
+ 49423,
+ 49424,
+ 49425,
+ 49426,
+ 49427,
+ 49428,
+ 49429,
+ 49430,
+ 49431,
+ 49432,
+ 49433,
+ 49434,
+ 49435,
+ 49436,
+ 49437,
+ 49438,
+ 49439,
+ 49440,
+ 49441,
+ 49442,
+ 49443,
+ 49444,
+ 49445,
+ 49446,
+ 49447,
+ 49448,
+ 49449,
+ 49450,
+ 49451,
+ 49452,
+ 49453,
+ 49454,
+ 49455,
+ 49456,
+ 49457,
+ 49458,
+ 49459,
+ 49460,
+ 49461,
+ 49462,
+ 49463,
+ 49464,
+ 49465,
+ 49466,
+ 49467,
+ 49468,
+ 49469,
+ 49470,
+ 49471,
+ 49472,
+ 49473,
+ 49474,
+ 49475,
+ 49476,
+ 49477,
+ 49478,
+ 49479,
+ 49480,
+ 49481,
+ 49482,
+ 49483,
+ 49484,
+ 49485,
+ 49486,
+ 49487,
+ 49488,
+ 49489,
+ 49490,
+ 49491,
+ 49492,
+ 49493,
+ 49494,
+ 49495,
+ 49496,
+ 49497,
+ 49498,
+ 49499,
+ 49500,
+ 49501,
+ 49502,
+ 49503,
+ 49504,
+ 49505,
+ 49506,
+ 49507,
+ 49508,
+ 49509,
+ 49510,
+ 49511,
+ 49512,
+ 49513,
+ 49514,
+ 49515,
+ 49516,
+ 49517,
+ 49518,
+ 49519,
+ 49520,
+ 49521,
+ 49522,
+ 49523,
+ 49524,
+ 49525,
+ 49526,
+ 49527,
+ 49528,
+ 49529,
+ 49530,
+ 49531,
+ 49532,
+ 49533,
+ 49534,
+ 49535,
+ 49536,
+ 49537,
+ 49538,
+ 49539,
+ 49540,
+ 49541,
+ 49542,
+ 49543,
+ 49544,
+ 49545,
+ 49546,
+ 49547,
+ 49548,
+ 49549,
+ 49550,
+ 49551,
+ 49552,
+ 49553,
+ 49554,
+ 49555,
+ 49556,
+ 49557,
+ 49558,
+ 49559,
+ 49560,
+ 49561,
+ 49562,
+ 49563,
+ 49564,
+ 49565,
+ 49566,
+ 49567,
+ 49568,
+ 49569,
+ 49570,
+ 49571,
+ 49572,
+ 49573,
+ 49574,
+ 49575,
+ 49576,
+ 49577,
+ 49578,
+ 49579,
+ 49580,
+ 49581,
+ 49582,
+ 49583,
+ 49584,
+ 49585,
+ 49586,
+ 49587,
+ 49588,
+ 49589,
+ 49590,
+ 49591,
+ 49592,
+ 49593,
+ 49594,
+ 49595,
+ 49596,
+ 49597,
+ 49598,
+ 49599,
+ 49600,
+ 49601,
+ 49602,
+ 49603,
+ 49604,
+ 49605,
+ 49606,
+ 49607,
+ 49608,
+ 49609,
+ 49610,
+ 49611,
+ 49612,
+ 49613,
+ 49614,
+ 49615,
+ 49616,
+ 49617,
+ 49618,
+ 49619,
+ 49620,
+ 49621,
+ 49622,
+ 49623,
+ 49624,
+ 49625,
+ 49626,
+ 49627,
+ 49628,
+ 49629,
+ 49630,
+ 49631,
+ 49632,
+ 49633,
+ 49634,
+ 49635,
+ 49636,
+ 49637,
+ 49638,
+ 49639,
+ 49640,
+ 49641,
+ 49642,
+ 49643,
+ 49644,
+ 49645,
+ 49646,
+ 49647,
+ 49648,
+ 49649,
+ 49650,
+ 49651,
+ 49652,
+ 49653,
+ 49654,
+ 49655,
+ 49656,
+ 49657,
+ 49658,
+ 49659,
+ 49660,
+ 49661,
+ 49662,
+ 49663,
+ 49664,
+ 49665,
+ 49666,
+ 49667,
+ 49668,
+ 49669,
+ 49670,
+ 49671,
+ 49672,
+ 49673,
+ 49674,
+ 49675,
+ 49676,
+ 49677,
+ 49678,
+ 49679,
+ 49680,
+ 49681,
+ 49682,
+ 49683,
+ 49684,
+ 49685,
+ 49686,
+ 49687,
+ 49688,
+ 49689,
+ 49690,
+ 49691,
+ 49692,
+ 49693,
+ 49694,
+ 49695,
+ 49696,
+ 49697,
+ 49698,
+ 49699,
+ 49700,
+ 49701,
+ 49702,
+ 49703,
+ 49704,
+ 49705,
+ 49706,
+ 49707,
+ 49708,
+ 49709,
+ 49710,
+ 49711,
+ 49712,
+ 49713,
+ 49714,
+ 49715,
+ 49716,
+ 49717,
+ 49718,
+ 49719,
+ 49720,
+ 49721,
+ 49722,
+ 49723,
+ 49724,
+ 49725,
+ 49726,
+ 49727,
+ 49728,
+ 49729,
+ 49730,
+ 49731,
+ 49732,
+ 49733,
+ 49734,
+ 49735,
+ 49736,
+ 49737,
+ 49738,
+ 49739,
+ 49740,
+ 49741,
+ 49742,
+ 49743,
+ 49744,
+ 49745,
+ 49746,
+ 49747,
+ 49748,
+ 49749,
+ 49750,
+ 49751,
+ 49752,
+ 49753,
+ 49754,
+ 49755,
+ 49756,
+ 49757,
+ 49758,
+ 49759,
+ 49760,
+ 49761,
+ 49762,
+ 49763,
+ 49764,
+ 49765,
+ 49766,
+ 49767,
+ 49768,
+ 49769,
+ 49770,
+ 49771,
+ 49772,
+ 49773,
+ 49774,
+ 49775,
+ 49776,
+ 49777,
+ 49778,
+ 49779,
+ 49780,
+ 49781,
+ 49782,
+ 49783,
+ 49784,
+ 49785,
+ 49786,
+ 49787,
+ 49788,
+ 49789,
+ 49790,
+ 49791,
+ 49792,
+ 49793,
+ 49794,
+ 49795,
+ 49796,
+ 49797,
+ 49798,
+ 49799,
+ 49800,
+ 49801,
+ 49802,
+ 49803,
+ 49804,
+ 49805,
+ 49806,
+ 49807,
+ 49808,
+ 49809,
+ 49810,
+ 49811,
+ 49812,
+ 49813,
+ 49814,
+ 49815,
+ 49816,
+ 49817,
+ 49818,
+ 49819,
+ 49820,
+ 49821,
+ 49822,
+ 49823,
+ 49824,
+ 49825,
+ 49826,
+ 49827,
+ 49828,
+ 49829,
+ 49830,
+ 49831,
+ 49832,
+ 49833,
+ 49834,
+ 49835,
+ 49836,
+ 49837,
+ 49838,
+ 49839,
+ 49840,
+ 49841,
+ 49842,
+ 49843,
+ 49844,
+ 49845,
+ 49846,
+ 49847,
+ 49848,
+ 49849,
+ 49850,
+ 49851,
+ 49852,
+ 49853,
+ 49854,
+ 49855,
+ 49856,
+ 49857,
+ 49858,
+ 49859,
+ 49860,
+ 49861,
+ 49862,
+ 49863,
+ 49864,
+ 49865,
+ 49866,
+ 49867,
+ 49868,
+ 49869,
+ 49870,
+ 49871,
+ 49872,
+ 49873,
+ 49874,
+ 49875,
+ 49876,
+ 49877,
+ 49878,
+ 49879,
+ 49880,
+ 49881,
+ 49882,
+ 49883,
+ 49884,
+ 49885,
+ 49886,
+ 49887,
+ 49888,
+ 49889,
+ 49890,
+ 49891,
+ 49892,
+ 49893,
+ 49894,
+ 49895,
+ 49896,
+ 49897,
+ 49898,
+ 49899,
+ 49900,
+ 49901,
+ 49902,
+ 49903,
+ 49904,
+ 49905,
+ 49906,
+ 49907,
+ 49908,
+ 49909,
+ 49910,
+ 49911,
+ 49912,
+ 49913,
+ 49914,
+ 49915,
+ 49916,
+ 49917,
+ 49918,
+ 49919,
+ 49920,
+ 49921,
+ 49922,
+ 49923,
+ 49924,
+ 49925,
+ 49926,
+ 49927,
+ 49928,
+ 49929,
+ 49930,
+ 49931,
+ 49932,
+ 49933,
+ 49934,
+ 49935,
+ 49936,
+ 49937,
+ 49938,
+ 49939,
+ 49940,
+ 49941,
+ 49942,
+ 49943,
+ 49944,
+ 49945,
+ 49946,
+ 49947,
+ 49948,
+ 49949,
+ 49950,
+ 49951,
+ 49952,
+ 49953,
+ 49954,
+ 49955,
+ 49956,
+ 49957,
+ 49958,
+ 49959,
+ 49960,
+ 49961,
+ 49962,
+ 49963,
+ 49964,
+ 49965,
+ 49966,
+ 49967,
+ 49968,
+ 49969,
+ 49970,
+ 49971,
+ 49972,
+ 49973,
+ 49974,
+ 49975,
+ 49976,
+ 49977,
+ 49978,
+ 49979,
+ 49980,
+ 49981,
+ 49982,
+ 49983,
+ 49984,
+ 49985,
+ 49986,
+ 49987,
+ 49988,
+ 49989,
+ 49990,
+ 49991,
+ 49992,
+ 49993,
+ 49994,
+ 49995,
+ 49996,
+ 49997,
+ 49998,
+ 49999,
+ 50000,
+ 50001,
+ 50002,
+ 50003,
+ 50004,
+ 50005,
+ 50006,
+ 50007,
+ 50008,
+ 50009,
+ 50010,
+ 50011,
+ 50012,
+ 50013,
+ 50014,
+ 50015,
+ 50016,
+ 50017,
+ 50018,
+ 50019,
+ 50020,
+ 50021,
+ 50022,
+ 50023,
+ 50024,
+ 50025,
+ 50026,
+ 50027,
+ 50028,
+ 50029,
+ 50030,
+ 50031,
+ 50032,
+ 50033,
+ 50034,
+ 50035,
+ 50036,
+ 50037,
+ 50038,
+ 50039,
+ 50040,
+ 50041,
+ 50042,
+ 50043,
+ 50044,
+ 50045,
+ 50046,
+ 50047,
+ 50048,
+ 50049,
+ 50050,
+ 50051,
+ 50052,
+ 50053,
+ 50054,
+ 50055,
+ 50056,
+ 50057,
+ 50058,
+ 50059,
+ 50060,
+ 50061,
+ 50062,
+ 50063,
+ 50064,
+ 50065,
+ 50066,
+ 50067,
+ 50068,
+ 50069,
+ 50070,
+ 50071,
+ 50072,
+ 50073,
+ 50074,
+ 50075,
+ 50076,
+ 50077,
+ 50078,
+ 50079,
+ 50080,
+ 50081,
+ 50082,
+ 50083,
+ 50084,
+ 50085,
+ 50086,
+ 50087,
+ 50088,
+ 50089,
+ 50090,
+ 50091,
+ 50092,
+ 50093,
+ 50094,
+ 50095,
+ 50096,
+ 50097,
+ 50098,
+ 50099,
+ 50100,
+ 50101,
+ 50102,
+ 50103,
+ 50104,
+ 50105,
+ 50106,
+ 50107,
+ 50108,
+ 50109,
+ 50110,
+ 50111,
+ 50112,
+ 50113,
+ 50114,
+ 50115,
+ 50116,
+ 50117,
+ 50118,
+ 50119,
+ 50120,
+ 50121,
+ 50122,
+ 50123,
+ 50124,
+ 50125,
+ 50126,
+ 50127,
+ 50128,
+ 50129,
+ 50130,
+ 50131,
+ 50132,
+ 50133,
+ 50134,
+ 50135,
+ 50136,
+ 50137,
+ 50138,
+ 50139,
+ 50140,
+ 50141,
+ 50142,
+ 50143,
+ 50144,
+ 50145,
+ 50146,
+ 50147,
+ 50148,
+ 50149,
+ 50150,
+ 50151,
+ 50152,
+ 50153,
+ 50154,
+ 50155,
+ 50156,
+ 50157,
+ 50158,
+ 50159,
+ 50160,
+ 50161,
+ 50162,
+ 50163,
+ 50164,
+ 50165,
+ 50166,
+ 50167,
+ 50168,
+ 50169,
+ 50170,
+ 50171,
+ 50172,
+ 50173,
+ 50174,
+ 50175,
+ 50176,
+ 50177,
+ 50178,
+ 50179,
+ 50180,
+ 50181,
+ 50182,
+ 50183,
+ 50184,
+ 50185,
+ 50186,
+ 50187,
+ 50188,
+ 50189,
+ 50190,
+ 50191,
+ 50192,
+ 50193,
+ 50194,
+ 50195,
+ 50196,
+ 50197,
+ 50198,
+ 50199,
+ 50200,
+ 50201,
+ 50202,
+ 50203,
+ 50204,
+ 50205,
+ 50206,
+ 50207,
+ 50208,
+ 50209,
+ 50210,
+ 50211,
+ 50212,
+ 50213,
+ 50214,
+ 50215,
+ 50216,
+ 50217,
+ 50218,
+ 50219,
+ 50220,
+ 50221,
+ 50222,
+ 50223,
+ 50224,
+ 50225,
+ 50226,
+ 50227,
+ 50228,
+ 50229,
+ 50230,
+ 50231,
+ 50232,
+ 50233,
+ 50234,
+ 50235,
+ 50236,
+ 50237,
+ 50238,
+ 50239,
+ 50240,
+ 50241,
+ 50242,
+ 50243,
+ 50244,
+ 50245,
+ 50246,
+ 50247,
+ 50248,
+ 50249,
+ 50250,
+ 50251,
+ 50252,
+ 50253,
+ 50254,
+ 50255,
+ 50256,
+ 50257,
+ 50258,
+ 50259,
+ 50260,
+ 50261,
+ 50262,
+ 50263,
+ 50264,
+ 50265,
+ 50266,
+ 50267,
+ 50268,
+ 50269,
+ 50270,
+ 50271,
+ 50272,
+ 50273,
+ 50274,
+ 50275,
+ 50276,
+ 50277,
+ 50278,
+ 50279,
+ 50280,
+ 50281,
+ 50282,
+ 50283,
+ 50284,
+ 50285,
+ 50286,
+ 50287,
+ 50288,
+ 50289,
+ 50290,
+ 50291,
+ 50292,
+ 50293,
+ 50294,
+ 50295,
+ 50296,
+ 50297,
+ 50298,
+ 50299,
+ 50300,
+ 50301,
+ 50302,
+ 50303,
+ 50304,
+ 50305,
+ 50306,
+ 50307,
+ 50308,
+ 50309,
+ 50310,
+ 50311,
+ 50312,
+ 50313,
+ 50314,
+ 50315,
+ 50316,
+ 50317,
+ 50318,
+ 50319,
+ 50320,
+ 50321,
+ 50322,
+ 50323,
+ 50324,
+ 50325,
+ 50326,
+ 50327,
+ 50328,
+ 50329,
+ 50330,
+ 50331,
+ 50332,
+ 50333,
+ 50334,
+ 50335,
+ 50336,
+ 50337,
+ 50338,
+ 50339,
+ 50340,
+ 50341,
+ 50342,
+ 50343,
+ 50344,
+ 50345,
+ 50346,
+ 50347,
+ 50348,
+ 50349,
+ 50350,
+ 50351,
+ 50352,
+ 50353,
+ 50354,
+ 50355,
+ 50356,
+ 50357,
+ 50358,
+ 50359,
+ 50360,
+ 50361,
+ 50362,
+ 50363,
+ 50364,
+ 50365,
+ 50366,
+ 50367,
+ 50368,
+ 50369,
+ 50370,
+ 50371,
+ 50372,
+ 50373,
+ 50374,
+ 50375,
+ 50376,
+ 50377,
+ 50378,
+ 50379,
+ 50380,
+ 50381,
+ 50382,
+ 50383,
+ 50384,
+ 50385,
+ 50386,
+ 50387,
+ 50388,
+ 50389,
+ 50390,
+ 50391,
+ 50392,
+ 50393,
+ 50394,
+ 50395,
+ 50396,
+ 50397,
+ 50398,
+ 50399,
+ 50400,
+ 50401,
+ 50402,
+ 50403,
+ 50404,
+ 50405,
+ 50406,
+ 50407,
+ 50408,
+ 50409,
+ 50410,
+ 50411,
+ 50412,
+ 50413,
+ 50414,
+ 50415,
+ 50416,
+ 50417,
+ 50418,
+ 50419,
+ 50420,
+ 50421,
+ 50422,
+ 50423,
+ 50424,
+ 50425,
+ 50426,
+ 50427,
+ 50428,
+ 50429,
+ 50430,
+ 50431,
+ 50432,
+ 50433,
+ 50434,
+ 50435,
+ 50436,
+ 50437,
+ 50438,
+ 50439,
+ 50440,
+ 50441,
+ 50442,
+ 50443,
+ 50444,
+ 50445,
+ 50446,
+ 50447,
+ 50448,
+ 50449,
+ 50450,
+ 50451,
+ 50452,
+ 50453,
+ 50454,
+ 50455,
+ 50456,
+ 50457,
+ 50458,
+ 50459,
+ 50460,
+ 50461,
+ 50462,
+ 50463,
+ 50464,
+ 50465,
+ 50466,
+ 50467,
+ 50468,
+ 50469,
+ 50470,
+ 50471,
+ 50472,
+ 50473,
+ 50474,
+ 50475,
+ 50476,
+ 50477,
+ 50478,
+ 50479,
+ 50480,
+ 50481,
+ 50482,
+ 50483,
+ 50484,
+ 50485,
+ 50486,
+ 50487,
+ 50488,
+ 50489,
+ 50490,
+ 50491,
+ 50492,
+ 50493,
+ 50494,
+ 50495,
+ 50496,
+ 50497,
+ 50498,
+ 50499,
+ 50500,
+ 50501,
+ 50502,
+ 50503,
+ 50504,
+ 50505,
+ 50506,
+ 50507,
+ 50508,
+ 50509,
+ 50510,
+ 50511,
+ 50512,
+ 50513,
+ 50514,
+ 50515,
+ 50516,
+ 50517,
+ 50518,
+ 50519,
+ 50520,
+ 50521,
+ 50522,
+ 50523,
+ 50524,
+ 50525,
+ 50526,
+ 50527,
+ 50528,
+ 50529,
+ 50530,
+ 50531,
+ 50532,
+ 50533,
+ 50534,
+ 50535,
+ 50536,
+ 50537,
+ 50538,
+ 50539,
+ 50540,
+ 50541,
+ 50542,
+ 50543,
+ 50544,
+ 50545,
+ 50546,
+ 50547,
+ 50548,
+ 50549,
+ 50550,
+ 50551,
+ 50552,
+ 50553,
+ 50554,
+ 50555,
+ 50556,
+ 50557,
+ 50558,
+ 50559,
+ 50560,
+ 50561,
+ 50562,
+ 50563,
+ 50564,
+ 50565,
+ 50566,
+ 50567,
+ 50568,
+ 50569,
+ 50570,
+ 50571,
+ 50572,
+ 50573,
+ 50574,
+ 50575,
+ 50576,
+ 50577,
+ 50578,
+ 50579,
+ 50580,
+ 50581,
+ 50582,
+ 50583,
+ 50584,
+ 50585,
+ 50586,
+ 50587,
+ 50588,
+ 50589,
+ 50590,
+ 50591,
+ 50592,
+ 50593,
+ 50594,
+ 50595,
+ 50596,
+ 50597,
+ 50598,
+ 50599,
+ 50600,
+ 50601,
+ 50602,
+ 50603,
+ 50604,
+ 50605,
+ 50606,
+ 50607,
+ 50608,
+ 50609,
+ 50610,
+ 50611,
+ 50612,
+ 50613,
+ 50614,
+ 50615,
+ 50616,
+ 50617,
+ 50618,
+ 50619,
+ 50620,
+ 50621,
+ 50622,
+ 50623,
+ 50624,
+ 50625,
+ 50626,
+ 50627,
+ 50628,
+ 50629,
+ 50630,
+ 50631,
+ 50632,
+ 50633,
+ 50634,
+ 50635,
+ 50636,
+ 50637,
+ 50638,
+ 50639,
+ 50640,
+ 50641,
+ 50642,
+ 50643,
+ 50644,
+ 50645,
+ 50646,
+ 50647,
+ 50648,
+ 50649,
+ 50650,
+ 50651,
+ 50652,
+ 50653,
+ 50654,
+ 50655,
+ 50656,
+ 50657,
+ 50658,
+ 50659,
+ 50660,
+ 50661,
+ 50662,
+ 50663,
+ 50664,
+ 50665,
+ 50666,
+ 50667,
+ 50668,
+ 50669,
+ 50670,
+ 50671,
+ 50672,
+ 50673,
+ 50674,
+ 50675,
+ 50676,
+ 50677,
+ 50678,
+ 50679,
+ 50680,
+ 50681,
+ 50682,
+ 50683,
+ 50684,
+ 50685,
+ 50686,
+ 50687,
+ 50688,
+ 50689,
+ 50690,
+ 50691,
+ 50692,
+ 50693,
+ 50694,
+ 50695,
+ 50696,
+ 50697,
+ 50698,
+ 50699,
+ 50700,
+ 50701,
+ 50702,
+ 50703,
+ 50704,
+ 50705,
+ 50706,
+ 50707,
+ 50708,
+ 50709,
+ 50710,
+ 50711,
+ 50712,
+ 50713,
+ 50714,
+ 50715,
+ 50716,
+ 50717,
+ 50718,
+ 50719,
+ 50720,
+ 50721,
+ 50722,
+ 50723,
+ 50724,
+ 50725,
+ 50726,
+ 50727,
+ 50728,
+ 50729,
+ 50730,
+ 50731,
+ 50732,
+ 50733,
+ 50734,
+ 50735,
+ 50736,
+ 50737,
+ 50738,
+ 50739,
+ 50740,
+ 50741,
+ 50742,
+ 50743,
+ 50744,
+ 50745,
+ 50746,
+ 50747,
+ 50748,
+ 50749,
+ 50750,
+ 50751,
+ 50752,
+ 50753,
+ 50754,
+ 50755,
+ 50756,
+ 50757,
+ 50758,
+ 50759,
+ 50760,
+ 50761,
+ 50762,
+ 50763,
+ 50764,
+ 50765,
+ 50766,
+ 50767,
+ 50768,
+ 50769,
+ 50770,
+ 50771,
+ 50772,
+ 50773,
+ 50774,
+ 50775,
+ 50776,
+ 50777,
+ 50778,
+ 50779,
+ 50780,
+ 50781,
+ 50782,
+ 50783,
+ 50784,
+ 50785,
+ 50786,
+ 50787,
+ 50788,
+ 50789,
+ 50790,
+ 50791,
+ 50792,
+ 50793,
+ 50794,
+ 50795,
+ 50796,
+ 50797,
+ 50798,
+ 50799,
+ 50800,
+ 50801,
+ 50802,
+ 50803,
+ 50804,
+ 50805,
+ 50806,
+ 50807,
+ 50808,
+ 50809,
+ 50810,
+ 50811,
+ 50812,
+ 50813,
+ 50814,
+ 50815,
+ 50816,
+ 50817,
+ 50818,
+ 50819,
+ 50820,
+ 50821,
+ 50822,
+ 50823,
+ 50824,
+ 50825,
+ 50826,
+ 50827,
+ 50828,
+ 50829,
+ 50830,
+ 50831,
+ 50832,
+ 50833,
+ 50834,
+ 50835,
+ 50836,
+ 50837,
+ 50838,
+ 50839,
+ 50840,
+ 50841,
+ 50842,
+ 50843,
+ 50844,
+ 50845,
+ 50846,
+ 50847,
+ 50848,
+ 50849,
+ 50850,
+ 50851,
+ 50852,
+ 50853,
+ 50854,
+ 50855,
+ 50856,
+ 50857,
+ 50858,
+ 50859,
+ 50860,
+ 50861,
+ 50862,
+ 50863,
+ 50864,
+ 50865,
+ 50866,
+ 50867,
+ 50868,
+ 50869,
+ 50870,
+ 50871,
+ 50872,
+ 50873,
+ 50874,
+ 50875,
+ 50876,
+ 50877,
+ 50878,
+ 50879,
+ 50880,
+ 50881,
+ 50882,
+ 50883,
+ 50884,
+ 50885,
+ 50886,
+ 50887,
+ 50888,
+ 50889,
+ 50890,
+ 50891,
+ 50892,
+ 50893,
+ 50894,
+ 50895,
+ 50896,
+ 50897,
+ 50898,
+ 50899,
+ 50900,
+ 50901,
+ 50902,
+ 50903,
+ 50904,
+ 50905,
+ 50906,
+ 50907,
+ 50908,
+ 50909,
+ 50910,
+ 50911,
+ 50912,
+ 50913,
+ 50914,
+ 50915,
+ 50916,
+ 50917,
+ 50918,
+ 50919,
+ 50920,
+ 50921,
+ 50922,
+ 50923,
+ 50924,
+ 50925,
+ 50926,
+ 50927,
+ 50928,
+ 50929,
+ 50930,
+ 50931,
+ 50932,
+ 50933,
+ 50934,
+ 50935,
+ 50936,
+ 50937,
+ 50938,
+ 50939,
+ 50940,
+ 50941,
+ 50942,
+ 50943,
+ 50944,
+ 50945,
+ 50946,
+ 50947,
+ 50948,
+ 50949,
+ 50950,
+ 50951,
+ 50952,
+ 50953,
+ 50954,
+ 50955,
+ 50956,
+ 50957,
+ 50958,
+ 50959,
+ 50960,
+ 50961,
+ 50962,
+ 50963,
+ 50964,
+ 50965,
+ 50966,
+ 50967,
+ 50968,
+ 50969,
+ 50970,
+ 50971,
+ 50972,
+ 50973,
+ 50974,
+ 50975,
+ 50976,
+ 50977,
+ 50978,
+ 50979,
+ 50980,
+ 50981,
+ 50982,
+ 50983,
+ 50984,
+ 50985,
+ 50986,
+ 50987,
+ 50988,
+ 50989,
+ 50990,
+ 50991,
+ 50992,
+ 50993,
+ 50994,
+ 50995,
+ 50996,
+ 50997,
+ 50998,
+ 50999,
+ 51000,
+ 51001,
+ 51002,
+ 51003,
+ 51004,
+ 51005,
+ 51006,
+ 51007,
+ 51008,
+ 51009,
+ 51010,
+ 51011,
+ 51012,
+ 51013,
+ 51014,
+ 51015,
+ 51016,
+ 51017,
+ 51018,
+ 51019,
+ 51020,
+ 51021,
+ 51022,
+ 51023,
+ 51024,
+ 51025,
+ 51026,
+ 51027,
+ 51028,
+ 51029,
+ 51030,
+ 51031,
+ 51032,
+ 51033,
+ 51034,
+ 51035,
+ 51036,
+ 51037,
+ 51038,
+ 51039,
+ 51040,
+ 51041,
+ 51042,
+ 51043,
+ 51044,
+ 51045,
+ 51046,
+ 51047,
+ 51048,
+ 51049,
+ 51050,
+ 51051,
+ 51052,
+ 51053,
+ 51054,
+ 51055,
+ 51056,
+ 51057,
+ 51058,
+ 51059,
+ 51060,
+ 51061,
+ 51062,
+ 51063,
+ 51064,
+ 51065,
+ 51066,
+ 51067,
+ 51068,
+ 51069,
+ 51070,
+ 51071,
+ 51072,
+ 51073,
+ 51074,
+ 51075,
+ 51076,
+ 51077,
+ 51078,
+ 51079,
+ 51080,
+ 51081,
+ 51082,
+ 51083,
+ 51084,
+ 51085,
+ 51086,
+ 51087,
+ 51088,
+ 51089,
+ 51090,
+ 51091,
+ 51092,
+ 51093,
+ 51094,
+ 51095,
+ 51096,
+ 51097,
+ 51098,
+ 51099,
+ 51100,
+ 51101,
+ 51102,
+ 51103,
+ 51104,
+ 51105,
+ 51106,
+ 51107,
+ 51108,
+ 51109,
+ 51110,
+ 51111,
+ 51112,
+ 51113,
+ 51114,
+ 51115,
+ 51116,
+ 51117,
+ 51118,
+ 51119,
+ 51120,
+ 51121,
+ 51122,
+ 51123,
+ 51124,
+ 51125,
+ 51126,
+ 51127,
+ 51128,
+ 51129,
+ 51130,
+ 51131,
+ 51132,
+ 51133,
+ 51134,
+ 51135,
+ 51136,
+ 51137,
+ 51138,
+ 51139,
+ 51140,
+ 51141,
+ 51142,
+ 51143,
+ 51144,
+ 51145,
+ 51146,
+ 51147,
+ 51148,
+ 51149,
+ 51150,
+ 51151,
+ 51152,
+ 51153,
+ 51154,
+ 51155,
+ 51156,
+ 51157,
+ 51158,
+ 51159,
+ 51160,
+ 51161,
+ 51162,
+ 51163,
+ 51164,
+ 51165,
+ 51166,
+ 51167,
+ 51168,
+ 51169,
+ 51170,
+ 51171,
+ 51172,
+ 51173,
+ 51174,
+ 51175,
+ 51176,
+ 51177,
+ 51178,
+ 51179,
+ 51180,
+ 51181,
+ 51182,
+ 51183,
+ 51184,
+ 51185,
+ 51186,
+ 51187,
+ 51188,
+ 51189,
+ 51190,
+ 51191,
+ 51192,
+ 51193,
+ 51194,
+ 51195,
+ 51196,
+ 51197,
+ 51198,
+ 51199,
+ 51200,
+ 51201,
+ 51202,
+ 51203,
+ 51204,
+ 51205,
+ 51206,
+ 51207,
+ 51208,
+ 51209,
+ 51210,
+ 51211,
+ 51212,
+ 51213,
+ 51214,
+ 51215,
+ 51216,
+ 51217,
+ 51218,
+ 51219,
+ 51220,
+ 51221,
+ 51222,
+ 51223,
+ 51224,
+ 51225,
+ 51226,
+ 51227,
+ 51228,
+ 51229,
+ 51230,
+ 51231,
+ 51232,
+ 51233,
+ 51234,
+ 51235,
+ 51236,
+ 51237,
+ 51238,
+ 51239,
+ 51240,
+ 51241,
+ 51242,
+ 51243,
+ 51244,
+ 51245,
+ 51246,
+ 51247,
+ 51248,
+ 51249,
+ 51250,
+ 51251,
+ 51252,
+ 51253,
+ 51254,
+ 51255,
+ 51256,
+ 51257,
+ 51258,
+ 51259,
+ 51260,
+ 51261,
+ 51262,
+ 51263,
+ 51264,
+ 51265,
+ 51266,
+ 51267,
+ 51268,
+ 51269,
+ 51270,
+ 51271,
+ 51272,
+ 51273,
+ 51274,
+ 51275,
+ 51276,
+ 51277,
+ 51278,
+ 51279,
+ 51280,
+ 51281,
+ 51282,
+ 51283,
+ 51284,
+ 51285,
+ 51286,
+ 51287,
+ 51288,
+ 51289,
+ 51290,
+ 51291,
+ 51292,
+ 51293,
+ 51294,
+ 51295,
+ 51296,
+ 51297,
+ 51298,
+ 51299,
+ 51300,
+ 51301,
+ 51302,
+ 51303,
+ 51304,
+ 51305,
+ 51306,
+ 51307,
+ 51308,
+ 51309,
+ 51310,
+ 51311,
+ 51312,
+ 51313,
+ 51314,
+ 51315,
+ 51316,
+ 51317,
+ 51318,
+ 51319,
+ 51320,
+ 51321,
+ 51322,
+ 51323,
+ 51324,
+ 51325,
+ 51326,
+ 51327,
+ 51328,
+ 51329,
+ 51330,
+ 51331,
+ 51332,
+ 51333,
+ 51334,
+ 51335,
+ 51336,
+ 51337,
+ 51338,
+ 51339,
+ 51340,
+ 51341,
+ 51342,
+ 51343,
+ 51344,
+ 51345,
+ 51346,
+ 51347,
+ 51348,
+ 51349,
+ 51350,
+ 51351,
+ 51352,
+ 51353,
+ 51354,
+ 51355,
+ 51356,
+ 51357,
+ 51358,
+ 51359,
+ 51360,
+ 51361,
+ 51362,
+ 51363,
+ 51364,
+ 51365,
+ 51366,
+ 51367,
+ 51368,
+ 51369,
+ 51370,
+ 51371,
+ 51372,
+ 51373,
+ 51374,
+ 51375,
+ 51376,
+ 51377,
+ 51378,
+ 51379,
+ 51380,
+ 51381,
+ 51382,
+ 51383,
+ 51384,
+ 51385,
+ 51386,
+ 51387,
+ 51388,
+ 51389,
+ 51390,
+ 51391,
+ 51392,
+ 51393,
+ 51394,
+ 51395,
+ 51396,
+ 51397,
+ 51398,
+ 51399,
+ 51400,
+ 51401,
+ 51402,
+ 51403,
+ 51404,
+ 51405,
+ 51406,
+ 51407,
+ 51408,
+ 51409,
+ 51410,
+ 51411,
+ 51412,
+ 51413,
+ 51414,
+ 51415,
+ 51416,
+ 51417,
+ 51418,
+ 51419,
+ 51420,
+ 51421,
+ 51422,
+ 51423,
+ 51424,
+ 51425,
+ 51426,
+ 51427,
+ 51428,
+ 51429,
+ 51430,
+ 51431,
+ 51432,
+ 51433,
+ 51434,
+ 51435,
+ 51436,
+ 51437,
+ 51438,
+ 51439,
+ 51440,
+ 51441,
+ 51442,
+ 51443,
+ 51444,
+ 51445,
+ 51446,
+ 51447,
+ 51448,
+ 51449,
+ 51450,
+ 51451,
+ 51452,
+ 51453,
+ 51454,
+ 51455,
+ 51456,
+ 51457,
+ 51458,
+ 51459,
+ 51460,
+ 51461,
+ 51462,
+ 51463,
+ 51464,
+ 51465,
+ 51466,
+ 51467,
+ 51468,
+ 51469,
+ 51470,
+ 51471,
+ 51472,
+ 51473,
+ 51474,
+ 51475,
+ 51476,
+ 51477,
+ 51478,
+ 51479,
+ 51480,
+ 51481,
+ 51482,
+ 51483,
+ 51484,
+ 51485,
+ 51486,
+ 51487,
+ 51488,
+ 51489,
+ 51490,
+ 51491,
+ 51492,
+ 51493,
+ 51494,
+ 51495,
+ 51496,
+ 51497,
+ 51498,
+ 51499,
+ 51500,
+ 51501,
+ 51502,
+ 51503,
+ 51504,
+ 51505,
+ 51506,
+ 51507,
+ 51508,
+ 51509,
+ 51510,
+ 51511,
+ 51512,
+ 51513,
+ 51514,
+ 51515,
+ 51516,
+ 51517,
+ 51518,
+ 51519,
+ 51520,
+ 51521,
+ 51522,
+ 51523,
+ 51524,
+ 51525,
+ 51526,
+ 51527,
+ 51528,
+ 51529,
+ 51530,
+ 51531,
+ 51532,
+ 51533,
+ 51534,
+ 51535,
+ 51536,
+ 51537,
+ 51538,
+ 51539,
+ 51540,
+ 51541,
+ 51542,
+ 51543,
+ 51544,
+ 51545,
+ 51546,
+ 51547,
+ 51548,
+ 51549,
+ 51550,
+ 51551,
+ 51552,
+ 51553,
+ 51554,
+ 51555,
+ 51556,
+ 51557,
+ 51558,
+ 51559,
+ 51560,
+ 51561,
+ 51562,
+ 51563,
+ 51564,
+ 51565,
+ 51566,
+ 51567,
+ 51568,
+ 51569,
+ 51570,
+ 51571,
+ 51572,
+ 51573,
+ 51574,
+ 51575,
+ 51576,
+ 51577,
+ 51578,
+ 51579,
+ 51580,
+ 51581,
+ 51582,
+ 51583,
+ 51584,
+ 51585,
+ 51586,
+ 51587,
+ 51588,
+ 51589,
+ 51590,
+ 51591,
+ 51592,
+ 51593,
+ 51594,
+ 51595,
+ 51596,
+ 51597,
+ 51598,
+ 51599,
+ 51600,
+ 51601,
+ 51602,
+ 51603,
+ 51604,
+ 51605,
+ 51606,
+ 51607,
+ 51608,
+ 51609,
+ 51610,
+ 51611,
+ 51612,
+ 51613,
+ 51614,
+ 51615,
+ 51616,
+ 51617,
+ 51618,
+ 51619,
+ 51620,
+ 51621,
+ 51622,
+ 51623,
+ 51624,
+ 51625,
+ 51626,
+ 51627,
+ 51628,
+ 51629,
+ 51630,
+ 51631,
+ 51632,
+ 51633,
+ 51634,
+ 51635,
+ 51636,
+ 51637,
+ 51638,
+ 51639,
+ 51640,
+ 51641,
+ 51642,
+ 51643,
+ 51644,
+ 51645,
+ 51646,
+ 51647,
+ 51648,
+ 51649,
+ 51650,
+ 51651,
+ 51652,
+ 51653,
+ 51654,
+ 51655,
+ 51656,
+ 51657,
+ 51658,
+ 51659,
+ 51660,
+ 51661,
+ 51662,
+ 51663,
+ 51664,
+ 51665,
+ 51666,
+ 51667,
+ 51668,
+ 51669,
+ 51670,
+ 51671,
+ 51672,
+ 51673,
+ 51674,
+ 51675,
+ 51676,
+ 51677,
+ 51678,
+ 51679,
+ 51680,
+ 51681,
+ 51682,
+ 51683,
+ 51684,
+ 51685,
+ 51686,
+ 51687,
+ 51688,
+ 51689,
+ 51690,
+ 51691,
+ 51692,
+ 51693,
+ 51694,
+ 51695,
+ 51696,
+ 51697,
+ 51698,
+ 51699,
+ 51700,
+ 51701,
+ 51702,
+ 51703,
+ 51704,
+ 51705,
+ 51706,
+ 51707,
+ 51708,
+ 51709,
+ 51710,
+ 51711,
+ 51712,
+ 51713,
+ 51714,
+ 51715,
+ 51716,
+ 51717,
+ 51718,
+ 51719,
+ 51720,
+ 51721,
+ 51722,
+ 51723,
+ 51724,
+ 51725,
+ 51726,
+ 51727,
+ 51728,
+ 51729,
+ 51730,
+ 51731,
+ 51732,
+ 51733,
+ 51734,
+ 51735,
+ 51736,
+ 51737,
+ 51738,
+ 51739,
+ 51740,
+ 51741,
+ 51742,
+ 51743,
+ 51744,
+ 51745,
+ 51746,
+ 51747,
+ 51748,
+ 51749,
+ 51750,
+ 51751,
+ 51752,
+ 51753,
+ 51754,
+ 51755,
+ 51756,
+ 51757,
+ 51758,
+ 51759,
+ 51760,
+ 51761,
+ 51762,
+ 51763,
+ 51764,
+ 51765,
+ 51766,
+ 51767,
+ 51768,
+ 51769,
+ 51770,
+ 51771,
+ 51772,
+ 51773,
+ 51774,
+ 51775,
+ 51776,
+ 51777,
+ 51778,
+ 51779,
+ 51780,
+ 51781,
+ 51782,
+ 51783,
+ 51784,
+ 51785,
+ 51786,
+ 51787,
+ 51788,
+ 51789,
+ 51790,
+ 51791,
+ 51792,
+ 51793,
+ 51794,
+ 51795,
+ 51796,
+ 51797,
+ 51798,
+ 51799,
+ 51800,
+ 51801,
+ 51802,
+ 51803,
+ 51804,
+ 51805,
+ 51806,
+ 51807,
+ 51808,
+ 51809,
+ 51810,
+ 51811,
+ 51812,
+ 51813,
+ 51814,
+ 51815,
+ 51816,
+ 51817,
+ 51818,
+ 51819,
+ 51820,
+ 51821,
+ 51822,
+ 51823,
+ 51824,
+ 51825,
+ 51826,
+ 51827,
+ 51828,
+ 51829,
+ 51830,
+ 51831,
+ 51832,
+ 51833,
+ 51834,
+ 51835,
+ 51836,
+ 51837,
+ 51838,
+ 51839,
+ 51840,
+ 51841,
+ 51842,
+ 51843,
+ 51844,
+ 51845,
+ 51846,
+ 51847,
+ 51848,
+ 51849,
+ 51850,
+ 51851,
+ 51852,
+ 51853,
+ 51854,
+ 51855,
+ 51856,
+ 51857,
+ 51858,
+ 51859,
+ 51860,
+ 51861,
+ 51862,
+ 51863,
+ 51864,
+ 51865,
+ 51866,
+ 51867,
+ 51868,
+ 51869,
+ 51870,
+ 51871,
+ 51872,
+ 51873,
+ 51874,
+ 51875,
+ 51876,
+ 51877,
+ 51878,
+ 51879,
+ 51880,
+ 51881,
+ 51882,
+ 51883,
+ 51884,
+ 51885,
+ 51886,
+ 51887,
+ 51888,
+ 51889,
+ 51890,
+ 51891,
+ 51892,
+ 51893,
+ 51894,
+ 51895,
+ 51896,
+ 51897,
+ 51898,
+ 51899,
+ 51900,
+ 51901,
+ 51902,
+ 51903,
+ 51904,
+ 51905,
+ 51906,
+ 51907,
+ 51908,
+ 51909,
+ 51910,
+ 51911,
+ 51912,
+ 51913,
+ 51914,
+ 51915,
+ 51916,
+ 51917,
+ 51918,
+ 51919,
+ 51920,
+ 51921,
+ 51922,
+ 51923,
+ 51924,
+ 51925,
+ 51926,
+ 51927,
+ 51928,
+ 51929,
+ 51930,
+ 51931,
+ 51932,
+ 51933,
+ 51934,
+ 51935,
+ 51936,
+ 51937,
+ 51938,
+ 51939,
+ 51940,
+ 51941,
+ 51942,
+ 51943,
+ 51944,
+ 51945,
+ 51946,
+ 51947,
+ 51948,
+ 51949,
+ 51950,
+ 51951,
+ 51952,
+ 51953,
+ 51954,
+ 51955,
+ 51956,
+ 51957,
+ 51958,
+ 51959,
+ 51960,
+ 51961,
+ 51962,
+ 51963,
+ 51964,
+ 51965,
+ 51966,
+ 51967,
+ 51968,
+ 51969,
+ 51970,
+ 51971,
+ 51972,
+ 51973,
+ 51974,
+ 51975,
+ 51976,
+ 51977,
+ 51978,
+ 51979,
+ 51980,
+ 51981,
+ 51982,
+ 51983,
+ 51984,
+ 51985,
+ 51986,
+ 51987,
+ 51988,
+ 51989,
+ 51990,
+ 51991,
+ 51992,
+ 51993,
+ 51994,
+ 51995,
+ 51996,
+ 51997,
+ 51998,
+ 51999,
+ 52000,
+ 52001,
+ 52002,
+ 52003,
+ 52004,
+ 52005,
+ 52006,
+ 52007,
+ 52008,
+ 52009,
+ 52010,
+ 52011,
+ 52012,
+ 52013,
+ 52014,
+ 52015,
+ 52016,
+ 52017,
+ 52018,
+ 52019,
+ 52020,
+ 52021,
+ 52022,
+ 52023,
+ 52024,
+ 52025,
+ 52026,
+ 52027,
+ 52028,
+ 52029,
+ 52030,
+ 52031,
+ 52032,
+ 52033,
+ 52034,
+ 52035,
+ 52036,
+ 52037,
+ 52038,
+ 52039,
+ 52040,
+ 52041,
+ 52042,
+ 52043,
+ 52044,
+ 52045,
+ 52046,
+ 52047,
+ 52048,
+ 52049,
+ 52050,
+ 52051,
+ 52052,
+ 52053,
+ 52054,
+ 52055,
+ 52056,
+ 52057,
+ 52058,
+ 52059,
+ 52060,
+ 52061,
+ 52062,
+ 52063,
+ 52064,
+ 52065,
+ 52066,
+ 52067,
+ 52068,
+ 52069,
+ 52070,
+ 52071,
+ 52072,
+ 52073,
+ 52074,
+ 52075,
+ 52076,
+ 52077,
+ 52078,
+ 52079,
+ 52080,
+ 52081,
+ 52082,
+ 52083,
+ 52084,
+ 52085,
+ 52086,
+ 52087,
+ 52088,
+ 52089,
+ 52090,
+ 52091,
+ 52092,
+ 52093,
+ 52094,
+ 52095,
+ 52096,
+ 52097,
+ 52098,
+ 52099,
+ 52100,
+ 52101,
+ 52102,
+ 52103,
+ 52104,
+ 52105,
+ 52106,
+ 52107,
+ 52108,
+ 52109,
+ 52110,
+ 52111,
+ 52112,
+ 52113,
+ 52114,
+ 52115,
+ 52116,
+ 52117,
+ 52118,
+ 52119,
+ 52120,
+ 52121,
+ 52122,
+ 52123,
+ 52124,
+ 52125,
+ 52126,
+ 52127,
+ 52128,
+ 52129,
+ 52130,
+ 52131,
+ 52132,
+ 52133,
+ 52134,
+ 52135,
+ 52136,
+ 52137,
+ 52138,
+ 52139,
+ 52140,
+ 52141,
+ 52142,
+ 52143,
+ 52144,
+ 52145,
+ 52146,
+ 52147,
+ 52148,
+ 52149,
+ 52150,
+ 52151,
+ 52152,
+ 52153,
+ 52154,
+ 52155,
+ 52156,
+ 52157,
+ 52158,
+ 52159,
+ 52160,
+ 52161,
+ 52162,
+ 52163,
+ 52164,
+ 52165,
+ 52166,
+ 52167,
+ 52168,
+ 52169,
+ 52170,
+ 52171,
+ 52172,
+ 52173,
+ 52174,
+ 52175,
+ 52176,
+ 52177,
+ 52178,
+ 52179,
+ 52180,
+ 52181,
+ 52182,
+ 52183,
+ 52184,
+ 52185,
+ 52186,
+ 52187,
+ 52188,
+ 52189,
+ 52190,
+ 52191,
+ 52192,
+ 52193,
+ 52194,
+ 52195,
+ 52196,
+ 52197,
+ 52198,
+ 52199,
+ 52200,
+ 52201,
+ 52202,
+ 52203,
+ 52204,
+ 52205,
+ 52206,
+ 52207,
+ 52208,
+ 52209,
+ 52210,
+ 52211,
+ 52212,
+ 52213,
+ 52214,
+ 52215,
+ 52216,
+ 52217,
+ 52218,
+ 52219,
+ 52220,
+ 52221,
+ 52222,
+ 52223,
+ 52224,
+ 52225,
+ 52226,
+ 52227,
+ 52228,
+ 52229,
+ 52230,
+ 52231,
+ 52232,
+ 52233,
+ 52234,
+ 52235,
+ 52236,
+ 52237,
+ 52238,
+ 52239,
+ 52240,
+ 52241,
+ 52242,
+ 52243,
+ 52244,
+ 52245,
+ 52246,
+ 52247,
+ 52248,
+ 52249,
+ 52250,
+ 52251,
+ 52252,
+ 52253,
+ 52254,
+ 52255,
+ 52256,
+ 52257,
+ 52258,
+ 52259,
+ 52260,
+ 52261,
+ 52262,
+ 52263,
+ 52264,
+ 52265,
+ 52266,
+ 52267,
+ 52268,
+ 52269,
+ 52270,
+ 52271,
+ 52272,
+ 52273,
+ 52274,
+ 52275,
+ 52276,
+ 52277,
+ 52278,
+ 52279,
+ 52280,
+ 52281,
+ 52282,
+ 52283,
+ 52284,
+ 52285,
+ 52286,
+ 52287,
+ 52288,
+ 52289,
+ 52290,
+ 52291,
+ 52292,
+ 52293,
+ 52294,
+ 52295,
+ 52296,
+ 52297,
+ 52298,
+ 52299,
+ 52300,
+ 52301,
+ 52302,
+ 52303,
+ 52304,
+ 52305,
+ 52306,
+ 52307,
+ 52308,
+ 52309,
+ 52310,
+ 52311,
+ 52312,
+ 52313,
+ 52314,
+ 52315,
+ 52316,
+ 52317,
+ 52318,
+ 52319,
+ 52320,
+ 52321,
+ 52322,
+ 52323,
+ 52324,
+ 52325,
+ 52326,
+ 52327,
+ 52328,
+ 52329,
+ 52330,
+ 52331,
+ 52332,
+ 52333,
+ 52334,
+ 52335,
+ 52336,
+ 52337,
+ 52338,
+ 52339,
+ 52340,
+ 52341,
+ 52342,
+ 52343,
+ 52344,
+ 52345,
+ 52346,
+ 52347,
+ 52348,
+ 52349,
+ 52350,
+ 52351,
+ 52352,
+ 52353,
+ 52354,
+ 52355,
+ 52356,
+ 52357,
+ 52358,
+ 52359,
+ 52360,
+ 52361,
+ 52362,
+ 52363,
+ 52364,
+ 52365,
+ 52366,
+ 52367,
+ 52368,
+ 52369,
+ 52370,
+ 52371,
+ 52372,
+ 52373,
+ 52374,
+ 52375,
+ 52376,
+ 52377,
+ 52378,
+ 52379,
+ 52380,
+ 52381,
+ 52382,
+ 52383,
+ 52384,
+ 52385,
+ 52386,
+ 52387,
+ 52388,
+ 52389,
+ 52390,
+ 52391,
+ 52392,
+ 52393,
+ 52394,
+ 52395,
+ 52396,
+ 52397,
+ 52398,
+ 52399,
+ 52400,
+ 52401,
+ 52402,
+ 52403,
+ 52404,
+ 52405,
+ 52406,
+ 52407,
+ 52408,
+ 52409,
+ 52410,
+ 52411,
+ 52412,
+ 52413,
+ 52414,
+ 52415,
+ 52416,
+ 52417,
+ 52418,
+ 52419,
+ 52420,
+ 52421,
+ 52422,
+ 52423,
+ 52424,
+ 52425,
+ 52426,
+ 52427,
+ 52428,
+ 52429,
+ 52430,
+ 52431,
+ 52432,
+ 52433,
+ 52434,
+ 52435,
+ 52436,
+ 52437,
+ 52438,
+ 52439,
+ 52440,
+ 52441,
+ 52442,
+ 52443,
+ 52444,
+ 52445,
+ 52446,
+ 52447,
+ 52448,
+ 52449,
+ 52450,
+ 52451,
+ 52452,
+ 52453,
+ 52454,
+ 52455,
+ 52456,
+ 52457,
+ 52458,
+ 52459,
+ 52460,
+ 52461,
+ 52462,
+ 52463,
+ 52464,
+ 52465,
+ 52466,
+ 52467,
+ 52468,
+ 52469,
+ 52470,
+ 52471,
+ 52472,
+ 52473,
+ 52474,
+ 52475,
+ 52476,
+ 52477,
+ 52478,
+ 52479,
+ 52480,
+ 52481,
+ 52482,
+ 52483,
+ 52484,
+ 52485,
+ 52486,
+ 52487,
+ 52488,
+ 52489,
+ 52490,
+ 52491,
+ 52492,
+ 52493,
+ 52494,
+ 52495,
+ 52496,
+ 52497,
+ 52498,
+ 52499,
+ 52500,
+ 52501,
+ 52502,
+ 52503,
+ 52504,
+ 52505,
+ 52506,
+ 52507,
+ 52508,
+ 52509,
+ 52510,
+ 52511,
+ 52512,
+ 52513,
+ 52514,
+ 52515,
+ 52516,
+ 52517,
+ 52518,
+ 52519,
+ 52520,
+ 52521,
+ 52522,
+ 52523,
+ 52524,
+ 52525,
+ 52526,
+ 52527,
+ 52528,
+ 52529,
+ 52530,
+ 52531,
+ 52532,
+ 52533,
+ 52534,
+ 52535,
+ 52536,
+ 52537,
+ 52538,
+ 52539,
+ 52540,
+ 52541,
+ 52542,
+ 52543,
+ 52544,
+ 52545,
+ 52546,
+ 52547,
+ 52548,
+ 52549,
+ 52550,
+ 52551,
+ 52552,
+ 52553,
+ 52554,
+ 52555,
+ 52556,
+ 52557,
+ 52558,
+ 52559,
+ 52560,
+ 52561,
+ 52562,
+ 52563,
+ 52564,
+ 52565,
+ 52566,
+ 52567,
+ 52568,
+ 52569,
+ 52570,
+ 52571,
+ 52572,
+ 52573,
+ 52574,
+ 52575,
+ 52576,
+ 52577,
+ 52578,
+ 52579,
+ 52580,
+ 52581,
+ 52582,
+ 52583,
+ 52584,
+ 52585,
+ 52586,
+ 52587,
+ 52588,
+ 52589,
+ 52590,
+ 52591,
+ 52592,
+ 52593,
+ 52594,
+ 52595,
+ 52596,
+ 52597,
+ 52598,
+ 52599,
+ 52600,
+ 52601,
+ 52602,
+ 52603,
+ 52604,
+ 52605,
+ 52606,
+ 52607,
+ 52608,
+ 52609,
+ 52610,
+ 52611,
+ 52612,
+ 52613,
+ 52614,
+ 52615,
+ 52616,
+ 52617,
+ 52618,
+ 52619,
+ 52620,
+ 52621,
+ 52622,
+ 52623,
+ 52624,
+ 52625,
+ 52626,
+ 52627,
+ 52628,
+ 52629,
+ 52630,
+ 52631,
+ 52632,
+ 52633,
+ 52634,
+ 52635,
+ 52636,
+ 52637,
+ 52638,
+ 52639,
+ 52640,
+ 52641,
+ 52642,
+ 52643,
+ 52644,
+ 52645,
+ 52646,
+ 52647,
+ 52648,
+ 52649,
+ 52650,
+ 52651,
+ 52652,
+ 52653,
+ 52654,
+ 52655,
+ 52656,
+ 52657,
+ 52658,
+ 52659,
+ 52660,
+ 52661,
+ 52662,
+ 52663,
+ 52664,
+ 52665,
+ 52666,
+ 52667,
+ 52668,
+ 52669,
+ 52670,
+ 52671,
+ 52672,
+ 52673,
+ 52674,
+ 52675,
+ 52676,
+ 52677,
+ 52678,
+ 52679,
+ 52680,
+ 52681,
+ 52682,
+ 52683,
+ 52684,
+ 52685,
+ 52686,
+ 52687,
+ 52688,
+ 52689,
+ 52690,
+ 52691,
+ 52692,
+ 52693,
+ 52694,
+ 52695,
+ 52696,
+ 52697,
+ 52698,
+ 52699,
+ 52700,
+ 52701,
+ 52702,
+ 52703,
+ 52704,
+ 52705,
+ 52706,
+ 52707,
+ 52708,
+ 52709,
+ 52710,
+ 52711,
+ 52712,
+ 52713,
+ 52714,
+ 52715,
+ 52716,
+ 52717,
+ 52718,
+ 52719,
+ 52720,
+ 52721,
+ 52722,
+ 52723,
+ 52724,
+ 52725,
+ 52726,
+ 52727,
+ 52728,
+ 52729,
+ 52730,
+ 52731,
+ 52732,
+ 52733,
+ 52734,
+ 52735,
+ 52736,
+ 52737,
+ 52738,
+ 52739,
+ 52740,
+ 52741,
+ 52742,
+ 52743,
+ 52744,
+ 52745,
+ 52746,
+ 52747,
+ 52748,
+ 52749,
+ 52750,
+ 52751,
+ 52752,
+ 52753,
+ 52754,
+ 52755,
+ 52756,
+ 52757,
+ 52758,
+ 52759,
+ 52760,
+ 52761,
+ 52762,
+ 52763,
+ 52764,
+ 52765,
+ 52766,
+ 52767,
+ 52768,
+ 52769,
+ 52770,
+ 52771,
+ 52772,
+ 52773,
+ 52774,
+ 52775,
+ 52776,
+ 52777,
+ 52778,
+ 52779,
+ 52780,
+ 52781,
+ 52782,
+ 52783,
+ 52784,
+ 52785,
+ 52786,
+ 52787,
+ 52788,
+ 52789,
+ 52790,
+ 52791,
+ 52792,
+ 52793,
+ 52794,
+ 52795,
+ 52796,
+ 52797,
+ 52798,
+ 52799,
+ 52800,
+ 52801,
+ 52802,
+ 52803,
+ 52804,
+ 52805,
+ 52806,
+ 52807,
+ 52808,
+ 52809,
+ 52810,
+ 52811,
+ 52812,
+ 52813,
+ 52814,
+ 52815,
+ 52816,
+ 52817,
+ 52818,
+ 52819,
+ 52820,
+ 52821,
+ 52822,
+ 52823,
+ 52824,
+ 52825,
+ 52826,
+ 52827,
+ 52828,
+ 52829,
+ 52830,
+ 52831,
+ 52832,
+ 52833,
+ 52834,
+ 52835,
+ 52836,
+ 52837,
+ 52838,
+ 52839,
+ 52840,
+ 52841,
+ 52842,
+ 52843,
+ 52844,
+ 52845,
+ 52846,
+ 52847,
+ 52848,
+ 52849,
+ 52850,
+ 52851,
+ 52852,
+ 52853,
+ 52854,
+ 52855,
+ 52856,
+ 52857,
+ 52858,
+ 52859,
+ 52860,
+ 52861,
+ 52862,
+ 52863,
+ 52864,
+ 52865,
+ 52866,
+ 52867,
+ 52868,
+ 52869,
+ 52870,
+ 52871,
+ 52872,
+ 52873,
+ 52874,
+ 52875,
+ 52876,
+ 52877,
+ 52878,
+ 52879,
+ 52880,
+ 52881,
+ 52882,
+ 52883,
+ 52884,
+ 52885,
+ 52886,
+ 52887,
+ 52888,
+ 52889,
+ 52890,
+ 52891,
+ 52892,
+ 52893,
+ 52894,
+ 52895,
+ 52896,
+ 52897,
+ 52898,
+ 52899,
+ 52900,
+ 52901,
+ 52902,
+ 52903,
+ 52904,
+ 52905,
+ 52906,
+ 52907,
+ 52908,
+ 52909,
+ 52910,
+ 52911,
+ 52912,
+ 52913,
+ 52914,
+ 52915,
+ 52916,
+ 52917,
+ 52918,
+ 52919,
+ 52920,
+ 52921,
+ 52922,
+ 52923,
+ 52924,
+ 52925,
+ 52926,
+ 52927,
+ 52928,
+ 52929,
+ 52930,
+ 52931,
+ 52932,
+ 52933,
+ 52934,
+ 52935,
+ 52936,
+ 52937,
+ 52938,
+ 52939,
+ 52940,
+ 52941,
+ 52942,
+ 52943,
+ 52944,
+ 52945,
+ 52946,
+ 52947,
+ 52948,
+ 52949,
+ 52950,
+ 52951,
+ 52952,
+ 52953,
+ 52954,
+ 52955,
+ 52956,
+ 52957,
+ 52958,
+ 52959,
+ 52960,
+ 52961,
+ 52962,
+ 52963,
+ 52964,
+ 52965,
+ 52966,
+ 52967,
+ 52968,
+ 52969,
+ 52970,
+ 52971,
+ 52972,
+ 52973,
+ 52974,
+ 52975,
+ 52976,
+ 52977,
+ 52978,
+ 52979,
+ 52980,
+ 52981,
+ 52982,
+ 52983,
+ 52984,
+ 52985,
+ 52986,
+ 52987,
+ 52988,
+ 52989,
+ 52990,
+ 52991,
+ 52992,
+ 52993,
+ 52994,
+ 52995,
+ 52996,
+ 52997,
+ 52998,
+ 52999,
+ 53000,
+ 53001,
+ 53002,
+ 53003,
+ 53004,
+ 53005,
+ 53006,
+ 53007,
+ 53008,
+ 53009,
+ 53010,
+ 53011,
+ 53012,
+ 53013,
+ 53014,
+ 53015,
+ 53016,
+ 53017,
+ 53018,
+ 53019,
+ 53020,
+ 53021,
+ 53022,
+ 53023,
+ 53024,
+ 53025,
+ 53026,
+ 53027,
+ 53028,
+ 53029,
+ 53030,
+ 53031,
+ 53032,
+ 53033,
+ 53034,
+ 53035,
+ 53036,
+ 53037,
+ 53038,
+ 53039,
+ 53040,
+ 53041,
+ 53042,
+ 53043,
+ 53044,
+ 53045,
+ 53046,
+ 53047,
+ 53048,
+ 53049,
+ 53050,
+ 53051,
+ 53052,
+ 53053,
+ 53054,
+ 53055,
+ 53056,
+ 53057,
+ 53058,
+ 53059,
+ 53060,
+ 53061,
+ 53062,
+ 53063,
+ 53064,
+ 53065,
+ 53066,
+ 53067,
+ 53068,
+ 53069,
+ 53070,
+ 53071,
+ 53072,
+ 53073,
+ 53074,
+ 53075,
+ 53076,
+ 53077,
+ 53078,
+ 53079,
+ 53080,
+ 53081,
+ 53082,
+ 53083,
+ 53084,
+ 53085,
+ 53086,
+ 53087,
+ 53088,
+ 53089,
+ 53090,
+ 53091,
+ 53092,
+ 53093,
+ 53094,
+ 53095,
+ 53096,
+ 53097,
+ 53098,
+ 53099,
+ 53100,
+ 53101,
+ 53102,
+ 53103,
+ 53104,
+ 53105,
+ 53106,
+ 53107,
+ 53108,
+ 53109,
+ 53110,
+ 53111,
+ 53112,
+ 53113,
+ 53114,
+ 53115,
+ 53116,
+ 53117,
+ 53118,
+ 53119,
+ 53120,
+ 53121,
+ 53122,
+ 53123,
+ 53124,
+ 53125,
+ 53126,
+ 53127,
+ 53128,
+ 53129,
+ 53130,
+ 53131,
+ 53132,
+ 53133,
+ 53134,
+ 53135,
+ 53136,
+ 53137,
+ 53138,
+ 53139,
+ 53140,
+ 53141,
+ 53142,
+ 53143,
+ 53144,
+ 53145,
+ 53146,
+ 53147,
+ 53148,
+ 53149,
+ 53150,
+ 53151,
+ 53152,
+ 53153,
+ 53154,
+ 53155,
+ 53156,
+ 53157,
+ 53158,
+ 53159,
+ 53160,
+ 53161,
+ 53162,
+ 53163,
+ 53164,
+ 53165,
+ 53166,
+ 53167,
+ 53168,
+ 53169,
+ 53170,
+ 53171,
+ 53172,
+ 53173,
+ 53174,
+ 53175,
+ 53176,
+ 53177,
+ 53178,
+ 53179,
+ 53180,
+ 53181,
+ 53182,
+ 53183,
+ 53184,
+ 53185,
+ 53186,
+ 53187,
+ 53188,
+ 53189,
+ 53190,
+ 53191,
+ 53192,
+ 53193,
+ 53194,
+ 53195,
+ 53196,
+ 53197,
+ 53198,
+ 53199,
+ 53200,
+ 53201,
+ 53202,
+ 53203,
+ 53204,
+ 53205,
+ 53206,
+ 53207,
+ 53208,
+ 53209,
+ 53210,
+ 53211,
+ 53212,
+ 53213,
+ 53214,
+ 53215,
+ 53216,
+ 53217,
+ 53218,
+ 53219,
+ 53220,
+ 53221,
+ 53222,
+ 53223,
+ 53224,
+ 53225,
+ 53226,
+ 53227,
+ 53228,
+ 53229,
+ 53230,
+ 53231,
+ 53232,
+ 53233,
+ 53234,
+ 53235,
+ 53236,
+ 53237,
+ 53238,
+ 53239,
+ 53240,
+ 53241,
+ 53242,
+ 53243,
+ 53244,
+ 53245,
+ 53246,
+ 53247,
+ 53248,
+ 53249,
+ 53250,
+ 53251,
+ 53252,
+ 53253,
+ 53254,
+ 53255,
+ 53256,
+ 53257,
+ 53258,
+ 53259,
+ 53260,
+ 53261,
+ 53262,
+ 53263,
+ 53264,
+ 53265,
+ 53266,
+ 53267,
+ 53268,
+ 53269,
+ 53270,
+ 53271,
+ 53272,
+ 53273,
+ 53274,
+ 53275,
+ 53276,
+ 53277,
+ 53278,
+ 53279,
+ 53280,
+ 53281,
+ 53282,
+ 53283,
+ 53284,
+ 53285,
+ 53286,
+ 53287,
+ 53288,
+ 53289,
+ 53290,
+ 53291,
+ 53292,
+ 53293,
+ 53294,
+ 53295,
+ 53296,
+ 53297,
+ 53298,
+ 53299,
+ 53300,
+ 53301,
+ 53302,
+ 53303,
+ 53304,
+ 53305,
+ 53306,
+ 53307,
+ 53308,
+ 53309,
+ 53310,
+ 53311,
+ 53312,
+ 53313,
+ 53314,
+ 53315,
+ 53316,
+ 53317,
+ 53318,
+ 53319,
+ 53320,
+ 53321,
+ 53322,
+ 53323,
+ 53324,
+ 53325,
+ 53326,
+ 53327,
+ 53328,
+ 53329,
+ 53330,
+ 53331,
+ 53332,
+ 53333,
+ 53334,
+ 53335,
+ 53336,
+ 53337,
+ 53338,
+ 53339,
+ 53340,
+ 53341,
+ 53342,
+ 53343,
+ 53344,
+ 53345,
+ 53346,
+ 53347,
+ 53348,
+ 53349,
+ 53350,
+ 53351,
+ 53352,
+ 53353,
+ 53354,
+ 53355,
+ 53356,
+ 53357,
+ 53358,
+ 53359,
+ 53360,
+ 53361,
+ 53362,
+ 53363,
+ 53364,
+ 53365,
+ 53366,
+ 53367,
+ 53368,
+ 53369,
+ 53370,
+ 53371,
+ 53372,
+ 53373,
+ 53374,
+ 53375,
+ 53376,
+ 53377,
+ 53378,
+ 53379,
+ 53380,
+ 53381,
+ 53382,
+ 53383,
+ 53384,
+ 53385,
+ 53386,
+ 53387,
+ 53388,
+ 53389,
+ 53390,
+ 53391,
+ 53392,
+ 53393,
+ 53394,
+ 53395,
+ 53396,
+ 53397,
+ 53398,
+ 53399,
+ 53400,
+ 53401,
+ 53402,
+ 53403,
+ 53404,
+ 53405,
+ 53406,
+ 53407,
+ 53408,
+ 53409,
+ 53410,
+ 53411,
+ 53412,
+ 53413,
+ 53414,
+ 53415,
+ 53416,
+ 53417,
+ 53418,
+ 53419,
+ 53420,
+ 53421,
+ 53422,
+ 53423,
+ 53424,
+ 53425,
+ 53426,
+ 53427,
+ 53428,
+ 53429,
+ 53430,
+ 53431,
+ 53432,
+ 53433,
+ 53434,
+ 53435,
+ 53436,
+ 53437,
+ 53438,
+ 53439,
+ 53440,
+ 53441,
+ 53442,
+ 53443,
+ 53444,
+ 53445,
+ 53446,
+ 53447,
+ 53448,
+ 53449,
+ 53450,
+ 53451,
+ 53452,
+ 53453,
+ 53454,
+ 53455,
+ 53456,
+ 53457,
+ 53458,
+ 53459,
+ 53460,
+ 53461,
+ 53462,
+ 53463,
+ 53464,
+ 53465,
+ 53466,
+ 53467,
+ 53468,
+ 53469,
+ 53470,
+ 53471,
+ 53472,
+ 53473,
+ 53474,
+ 53475,
+ 53476,
+ 53477,
+ 53478,
+ 53479,
+ 53480,
+ 53481,
+ 53482,
+ 53483,
+ 53484,
+ 53485,
+ 53486,
+ 53487,
+ 53488,
+ 53489,
+ 53490,
+ 53491,
+ 53492,
+ 53493,
+ 53494,
+ 53495,
+ 53496,
+ 53497,
+ 53498,
+ 53499,
+ 53500,
+ 53501,
+ 53502,
+ 53503,
+ 53504,
+ 53505,
+ 53506,
+ 53507,
+ 53508,
+ 53509,
+ 53510,
+ 53511,
+ 53512,
+ 53513,
+ 53514,
+ 53515,
+ 53516,
+ 53517,
+ 53518,
+ 53519,
+ 53520,
+ 53521,
+ 53522,
+ 53523,
+ 53524,
+ 53525,
+ 53526,
+ 53527,
+ 53528,
+ 53529,
+ 53530,
+ 53531,
+ 53532,
+ 53533,
+ 53534,
+ 53535,
+ 53536,
+ 53537,
+ 53538,
+ 53539,
+ 53540,
+ 53541,
+ 53542,
+ 53543,
+ 53544,
+ 53545,
+ 53546,
+ 53547,
+ 53548,
+ 53549,
+ 53550,
+ 53551,
+ 53552,
+ 53553,
+ 53554,
+ 53555,
+ 53556,
+ 53557,
+ 53558,
+ 53559,
+ 53560,
+ 53561,
+ 53562,
+ 53563,
+ 53564,
+ 53565,
+ 53566,
+ 53567,
+ 53568,
+ 53569,
+ 53570,
+ 53571,
+ 53572,
+ 53573,
+ 53574,
+ 53575,
+ 53576,
+ 53577,
+ 53578,
+ 53579,
+ 53580,
+ 53581,
+ 53582,
+ 53583,
+ 53584,
+ 53585,
+ 53586,
+ 53587,
+ 53588,
+ 53589,
+ 53590,
+ 53591,
+ 53592,
+ 53593,
+ 53594,
+ 53595,
+ 53596,
+ 53597,
+ 53598,
+ 53599,
+ 53600,
+ 53601,
+ 53602,
+ 53603,
+ 53604,
+ 53605,
+ 53606,
+ 53607,
+ 53608,
+ 53609,
+ 53610,
+ 53611,
+ 53612,
+ 53613,
+ 53614,
+ 53615,
+ 53616,
+ 53617,
+ 53618,
+ 53619,
+ 53620,
+ 53621,
+ 53622,
+ 53623,
+ 53624,
+ 53625,
+ 53626,
+ 53627,
+ 53628,
+ 53629,
+ 53630,
+ 53631,
+ 53632,
+ 53633,
+ 53634,
+ 53635,
+ 53636,
+ 53637,
+ 53638,
+ 53639,
+ 53640,
+ 53641,
+ 53642,
+ 53643,
+ 53644,
+ 53645,
+ 53646,
+ 53647,
+ 53648,
+ 53649,
+ 53650,
+ 53651,
+ 53652,
+ 53653,
+ 53654,
+ 53655,
+ 53656,
+ 53657,
+ 53658,
+ 53659,
+ 53660,
+ 53661,
+ 53662,
+ 53663,
+ 53664,
+ 53665,
+ 53666,
+ 53667,
+ 53668,
+ 53669,
+ 53670,
+ 53671,
+ 53672,
+ 53673,
+ 53674,
+ 53675,
+ 53676,
+ 53677,
+ 53678,
+ 53679,
+ 53680,
+ 53681,
+ 53682,
+ 53683,
+ 53684,
+ 53685,
+ 53686,
+ 53687,
+ 53688,
+ 53689,
+ 53690,
+ 53691,
+ 53692,
+ 53693,
+ 53694,
+ 53695,
+ 53696,
+ 53697,
+ 53698,
+ 53699,
+ 53700,
+ 53701,
+ 53702,
+ 53703,
+ 53704,
+ 53705,
+ 53706,
+ 53707,
+ 53708,
+ 53709,
+ 53710,
+ 53711,
+ 53712,
+ 53713,
+ 53714,
+ 53715,
+ 53716,
+ 53717,
+ 53718,
+ 53719,
+ 53720,
+ 53721,
+ 53722,
+ 53723,
+ 53724,
+ 53725,
+ 53726,
+ 53727,
+ 53728,
+ 53729,
+ 53730,
+ 53731,
+ 53732,
+ 53733,
+ 53734,
+ 53735,
+ 53736,
+ 53737,
+ 53738,
+ 53739,
+ 53740,
+ 53741,
+ 53742,
+ 53743,
+ 53744,
+ 53745,
+ 53746,
+ 53747,
+ 53748,
+ 53749,
+ 53750,
+ 53751,
+ 53752,
+ 53753,
+ 53754,
+ 53755,
+ 53756,
+ 53757,
+ 53758,
+ 53759,
+ 53760,
+ 53761,
+ 53762,
+ 53763,
+ 53764,
+ 53765,
+ 53766,
+ 53767,
+ 53768,
+ 53769,
+ 53770,
+ 53771,
+ 53772,
+ 53773,
+ 53774,
+ 53775,
+ 53776,
+ 53777,
+ 53778,
+ 53779,
+ 53780,
+ 53781,
+ 53782,
+ 53783,
+ 53784,
+ 53785,
+ 53786,
+ 53787,
+ 53788,
+ 53789,
+ 53790,
+ 53791,
+ 53792,
+ 53793,
+ 53794,
+ 53795,
+ 53796,
+ 53797,
+ 53798,
+ 53799,
+ 53800,
+ 53801,
+ 53802,
+ 53803,
+ 53804,
+ 53805,
+ 53806,
+ 53807,
+ 53808,
+ 53809,
+ 53810,
+ 53811,
+ 53812,
+ 53813,
+ 53814,
+ 53815,
+ 53816,
+ 53817,
+ 53818,
+ 53819,
+ 53820,
+ 53821,
+ 53822,
+ 53823,
+ 53824,
+ 53825,
+ 53826,
+ 53827,
+ 53828,
+ 53829,
+ 53830,
+ 53831,
+ 53832,
+ 53833,
+ 53834,
+ 53835,
+ 53836,
+ 53837,
+ 53838,
+ 53839,
+ 53840,
+ 53841,
+ 53842,
+ 53843,
+ 53844,
+ 53845,
+ 53846,
+ 53847,
+ 53848,
+ 53849,
+ 53850,
+ 53851,
+ 53852,
+ 53853,
+ 53854,
+ 53855,
+ 53856,
+ 53857,
+ 53858,
+ 53859,
+ 53860,
+ 53861,
+ 53862,
+ 53863,
+ 53864,
+ 53865,
+ 53866,
+ 53867,
+ 53868,
+ 53869,
+ 53870,
+ 53871,
+ 53872,
+ 53873,
+ 53874,
+ 53875,
+ 53876,
+ 53877,
+ 53878,
+ 53879,
+ 53880,
+ 53881,
+ 53882,
+ 53883,
+ 53884,
+ 53885,
+ 53886,
+ 53887,
+ 53888,
+ 53889,
+ 53890,
+ 53891,
+ 53892,
+ 53893,
+ 53894,
+ 53895,
+ 53896,
+ 53897,
+ 53898,
+ 53899,
+ 53900,
+ 53901,
+ 53902,
+ 53903,
+ 53904,
+ 53905,
+ 53906,
+ 53907,
+ 53908,
+ 53909,
+ 53910,
+ 53911,
+ 53912,
+ 53913,
+ 53914,
+ 53915,
+ 53916,
+ 53917,
+ 53918,
+ 53919,
+ 53920,
+ 53921,
+ 53922,
+ 53923,
+ 53924,
+ 53925,
+ 53926,
+ 53927,
+ 53928,
+ 53929,
+ 53930,
+ 53931,
+ 53932,
+ 53933,
+ 53934,
+ 53935,
+ 53936,
+ 53937,
+ 53938,
+ 53939,
+ 53940,
+ 53941,
+ 53942,
+ 53943,
+ 53944,
+ 53945,
+ 53946,
+ 53947,
+ 53948,
+ 53949,
+ 53950,
+ 53951,
+ 53952,
+ 53953,
+ 53954,
+ 53955,
+ 53956,
+ 53957,
+ 53958,
+ 53959,
+ 53960,
+ 53961,
+ 53962,
+ 53963,
+ 53964,
+ 53965,
+ 53966,
+ 53967,
+ 53968,
+ 53969,
+ 53970,
+ 53971,
+ 53972,
+ 53973,
+ 53974,
+ 53975,
+ 53976,
+ 53977,
+ 53978,
+ 53979,
+ 53980,
+ 53981,
+ 53982,
+ 53983,
+ 53984,
+ 53985,
+ 53986,
+ 53987,
+ 53988,
+ 53989,
+ 53990,
+ 53991,
+ 53992,
+ 53993,
+ 53994,
+ 53995,
+ 53996,
+ 53997,
+ 53998,
+ 53999,
+ 54000,
+ 54001,
+ 54002,
+ 54003,
+ 54004,
+ 54005,
+ 54006,
+ 54007,
+ 54008,
+ 54009,
+ 54010,
+ 54011,
+ 54012,
+ 54013,
+ 54014,
+ 54015,
+ 54016,
+ 54017,
+ 54018,
+ 54019,
+ 54020,
+ 54021,
+ 54022,
+ 54023,
+ 54024,
+ 54025,
+ 54026,
+ 54027,
+ 54028,
+ 54029,
+ 54030,
+ 54031,
+ 54032,
+ 54033,
+ 54034,
+ 54035,
+ 54036,
+ 54037,
+ 54038,
+ 54039,
+ 54040,
+ 54041,
+ 54042,
+ 54043,
+ 54044,
+ 54045,
+ 54046,
+ 54047,
+ 54048,
+ 54049,
+ 54050,
+ 54051,
+ 54052,
+ 54053,
+ 54054,
+ 54055,
+ 54056,
+ 54057,
+ 54058,
+ 54059,
+ 54060,
+ 54061,
+ 54062,
+ 54063,
+ 54064,
+ 54065,
+ 54066,
+ 54067,
+ 54068,
+ 54069,
+ 54070,
+ 54071,
+ 54072,
+ 54073,
+ 54074,
+ 54075,
+ 54076,
+ 54077,
+ 54078,
+ 54079,
+ 54080,
+ 54081,
+ 54082,
+ 54083,
+ 54084,
+ 54085,
+ 54086,
+ 54087,
+ 54088,
+ 54089,
+ 54090,
+ 54091,
+ 54092,
+ 54093,
+ 54094,
+ 54095,
+ 54096,
+ 54097,
+ 54098,
+ 54099,
+ 54100,
+ 54101,
+ 54102,
+ 54103,
+ 54104,
+ 54105,
+ 54106,
+ 54107,
+ 54108,
+ 54109,
+ 54110,
+ 54111,
+ 54112,
+ 54113,
+ 54114,
+ 54115,
+ 54116,
+ 54117,
+ 54118,
+ 54119,
+ 54120,
+ 54121,
+ 54122,
+ 54123,
+ 54124,
+ 54125,
+ 54126,
+ 54127,
+ 54128,
+ 54129,
+ 54130,
+ 54131,
+ 54132,
+ 54133,
+ 54134,
+ 54135,
+ 54136,
+ 54137,
+ 54138,
+ 54139,
+ 54140,
+ 54141,
+ 54142,
+ 54143,
+ 54144,
+ 54145,
+ 54146,
+ 54147,
+ 54148,
+ 54149,
+ 54150,
+ 54151,
+ 54152,
+ 54153,
+ 54154,
+ 54155,
+ 54156,
+ 54157,
+ 54158,
+ 54159,
+ 54160,
+ 54161,
+ 54162,
+ 54163,
+ 54164,
+ 54165,
+ 54166,
+ 54167,
+ 54168,
+ 54169,
+ 54170,
+ 54171,
+ 54172,
+ 54173,
+ 54174,
+ 54175,
+ 54176,
+ 54177,
+ 54178,
+ 54179,
+ 54180,
+ 54181,
+ 54182,
+ 54183,
+ 54184,
+ 54185,
+ 54186,
+ 54187,
+ 54188,
+ 54189,
+ 54190,
+ 54191,
+ 54192,
+ 54193,
+ 54194,
+ 54195,
+ 54196,
+ 54197,
+ 54198,
+ 54199,
+ 54200,
+ 54201,
+ 54202,
+ 54203,
+ 54204,
+ 54205,
+ 54206,
+ 54207,
+ 54208,
+ 54209,
+ 54210,
+ 54211,
+ 54212,
+ 54213,
+ 54214,
+ 54215,
+ 54216,
+ 54217,
+ 54218,
+ 54219,
+ 54220,
+ 54221,
+ 54222,
+ 54223,
+ 54224,
+ 54225,
+ 54226,
+ 54227,
+ 54228,
+ 54229,
+ 54230,
+ 54231,
+ 54232,
+ 54233,
+ 54234,
+ 54235,
+ 54236,
+ 54237,
+ 54238,
+ 54239,
+ 54240,
+ 54241,
+ 54242,
+ 54243,
+ 54244,
+ 54245,
+ 54246,
+ 54247,
+ 54248,
+ 54249,
+ 54250,
+ 54251,
+ 54252,
+ 54253,
+ 54254,
+ 54255,
+ 54256,
+ 54257,
+ 54258,
+ 54259,
+ 54260,
+ 54261,
+ 54262,
+ 54263,
+ 54264,
+ 54265,
+ 54266,
+ 54267,
+ 54268,
+ 54269,
+ 54270,
+ 54271,
+ 54272,
+ 54273,
+ 54274,
+ 54275,
+ 54276,
+ 54277,
+ 54278,
+ 54279,
+ 54280,
+ 54281,
+ 54282,
+ 54283,
+ 54284,
+ 54285,
+ 54286,
+ 54287,
+ 54288,
+ 54289,
+ 54290,
+ 54291,
+ 54292,
+ 54293,
+ 54294,
+ 54295,
+ 54296,
+ 54297,
+ 54298,
+ 54299,
+ 54300,
+ 54301,
+ 54302,
+ 54303,
+ 54304,
+ 54305,
+ 54306,
+ 54307,
+ 54308,
+ 54309,
+ 54310,
+ 54311,
+ 54312,
+ 54313,
+ 54314,
+ 54315,
+ 54316,
+ 54317,
+ 54318,
+ 54319,
+ 54320,
+ 54321,
+ 54322,
+ 54323,
+ 54324,
+ 54325,
+ 54326,
+ 54327,
+ 54328,
+ 54329,
+ 54330,
+ 54331,
+ 54332,
+ 54333,
+ 54334,
+ 54335,
+ 54336,
+ 54337,
+ 54338,
+ 54339,
+ 54340,
+ 54341,
+ 54342,
+ 54343,
+ 54344,
+ 54345,
+ 54346,
+ 54347,
+ 54348,
+ 54349,
+ 54350,
+ 54351,
+ 54352,
+ 54353,
+ 54354,
+ 54355,
+ 54356,
+ 54357,
+ 54358,
+ 54359,
+ 54360,
+ 54361,
+ 54362,
+ 54363,
+ 54364,
+ 54365,
+ 54366,
+ 54367,
+ 54368,
+ 54369,
+ 54370,
+ 54371,
+ 54372,
+ 54373,
+ 54374,
+ 54375,
+ 54376,
+ 54377,
+ 54378,
+ 54379,
+ 54380,
+ 54381,
+ 54382,
+ 54383,
+ 54384,
+ 54385,
+ 54386,
+ 54387,
+ 54388,
+ 54389,
+ 54390,
+ 54391,
+ 54392,
+ 54393,
+ 54394,
+ 54395,
+ 54396,
+ 54397,
+ 54398,
+ 54399,
+ 54400,
+ 54401,
+ 54402,
+ 54403,
+ 54404,
+ 54405,
+ 54406,
+ 54407,
+ 54408,
+ 54409,
+ 54410,
+ 54411,
+ 54412,
+ 54413,
+ 54414,
+ 54415,
+ 54416,
+ 54417,
+ 54418,
+ 54419,
+ 54420,
+ 54421,
+ 54422,
+ 54423,
+ 54424,
+ 54425,
+ 54426,
+ 54427,
+ 54428,
+ 54429,
+ 54430,
+ 54431,
+ 54432,
+ 54433,
+ 54434,
+ 54435,
+ 54436,
+ 54437,
+ 54438,
+ 54439,
+ 54440,
+ 54441,
+ 54442,
+ 54443,
+ 54444,
+ 54445,
+ 54446,
+ 54447,
+ 54448,
+ 54449,
+ 54450,
+ 54451,
+ 54452,
+ 54453,
+ 54454,
+ 54455,
+ 54456,
+ 54457,
+ 54458,
+ 54459,
+ 54460,
+ 54461,
+ 54462,
+ 54463,
+ 54464,
+ 54465,
+ 54466,
+ 54467,
+ 54468,
+ 54469,
+ 54470,
+ 54471,
+ 54472,
+ 54473,
+ 54474,
+ 54475,
+ 54476,
+ 54477,
+ 54478,
+ 54479,
+ 54480,
+ 54481,
+ 54482,
+ 54483,
+ 54484,
+ 54485,
+ 54486,
+ 54487,
+ 54488,
+ 54489,
+ 54490,
+ 54491,
+ 54492,
+ 54493,
+ 54494,
+ 54495,
+ 54496,
+ 54497,
+ 54498,
+ 54499,
+ 54500,
+ 54501,
+ 54502,
+ 54503,
+ 54504,
+ 54505,
+ 54506,
+ 54507,
+ 54508,
+ 54509,
+ 54510,
+ 54511,
+ 54512,
+ 54513,
+ 54514,
+ 54515,
+ 54516,
+ 54517,
+ 54518,
+ 54519,
+ 54520,
+ 54521,
+ 54522,
+ 54523,
+ 54524,
+ 54525,
+ 54526,
+ 54527,
+ 54528,
+ 54529,
+ 54530,
+ 54531,
+ 54532,
+ 54533,
+ 54534,
+ 54535,
+ 54536,
+ 54537,
+ 54538,
+ 54539,
+ 54540,
+ 54541,
+ 54542,
+ 54543,
+ 54544,
+ 54545,
+ 54546,
+ 54547,
+ 54548,
+ 54549,
+ 54550,
+ 54551,
+ 54552,
+ 54553,
+ 54554,
+ 54555,
+ 54556,
+ 54557,
+ 54558,
+ 54559,
+ 54560,
+ 54561,
+ 54562,
+ 54563,
+ 54564,
+ 54565,
+ 54566,
+ 54567,
+ 54568,
+ 54569,
+ 54570,
+ 54571,
+ 54572,
+ 54573,
+ 54574,
+ 54575,
+ 54576,
+ 54577,
+ 54578,
+ 54579,
+ 54580,
+ 54581,
+ 54582,
+ 54583,
+ 54584,
+ 54585,
+ 54586,
+ 54587,
+ 54588,
+ 54589,
+ 54590,
+ 54591,
+ 54592,
+ 54593,
+ 54594,
+ 54595,
+ 54596,
+ 54597,
+ 54598,
+ 54599,
+ 54600,
+ 54601,
+ 54602,
+ 54603,
+ 54604,
+ 54605,
+ 54606,
+ 54607,
+ 54608,
+ 54609,
+ 54610,
+ 54611,
+ 54612,
+ 54613,
+ 54614,
+ 54615,
+ 54616,
+ 54617,
+ 54618,
+ 54619,
+ 54620,
+ 54621,
+ 54622,
+ 54623,
+ 54624,
+ 54625,
+ 54626,
+ 54627,
+ 54628,
+ 54629,
+ 54630,
+ 54631,
+ 54632,
+ 54633,
+ 54634,
+ 54635,
+ 54636,
+ 54637,
+ 54638,
+ 54639,
+ 54640,
+ 54641,
+ 54642,
+ 54643,
+ 54644,
+ 54645,
+ 54646,
+ 54647,
+ 54648,
+ 54649,
+ 54650,
+ 54651,
+ 54652,
+ 54653,
+ 54654,
+ 54655,
+ 54656,
+ 54657,
+ 54658,
+ 54659,
+ 54660,
+ 54661,
+ 54662,
+ 54663,
+ 54664,
+ 54665,
+ 54666,
+ 54667,
+ 54668,
+ 54669,
+ 54670,
+ 54671,
+ 54672,
+ 54673,
+ 54674,
+ 54675,
+ 54676,
+ 54677,
+ 54678,
+ 54679,
+ 54680,
+ 54681,
+ 54682,
+ 54683,
+ 54684,
+ 54685,
+ 54686,
+ 54687,
+ 54688,
+ 54689,
+ 54690,
+ 54691,
+ 54692,
+ 54693,
+ 54694,
+ 54695,
+ 54696,
+ 54697,
+ 54698,
+ 54699,
+ 54700,
+ 54701,
+ 54702,
+ 54703,
+ 54704,
+ 54705,
+ 54706,
+ 54707,
+ 54708,
+ 54709,
+ 54710,
+ 54711,
+ 54712,
+ 54713,
+ 54714,
+ 54715,
+ 54716,
+ 54717,
+ 54718,
+ 54719,
+ 54720,
+ 54721,
+ 54722,
+ 54723,
+ 54724,
+ 54725,
+ 54726,
+ 54727,
+ 54728,
+ 54729,
+ 54730,
+ 54731,
+ 54732,
+ 54733,
+ 54734,
+ 54735,
+ 54736,
+ 54737,
+ 54738,
+ 54739,
+ 54740,
+ 54741,
+ 54742,
+ 54743,
+ 54744,
+ 54745,
+ 54746,
+ 54747,
+ 54748,
+ 54749,
+ 54750,
+ 54751,
+ 54752,
+ 54753,
+ 54754,
+ 54755,
+ 54756,
+ 54757,
+ 54758,
+ 54759,
+ 54760,
+ 54761,
+ 54762,
+ 54763,
+ 54764,
+ 54765,
+ 54766,
+ 54767,
+ 54768,
+ 54769,
+ 54770,
+ 54771,
+ 54772,
+ 54773,
+ 54774,
+ 54775,
+ 54776,
+ 54777,
+ 54778,
+ 54779,
+ 54780,
+ 54781,
+ 54782,
+ 54783,
+ 54784,
+ 54785,
+ 54786,
+ 54787,
+ 54788,
+ 54789,
+ 54790,
+ 54791,
+ 54792,
+ 54793,
+ 54794,
+ 54795,
+ 54796,
+ 54797,
+ 54798,
+ 54799,
+ 54800,
+ 54801,
+ 54802,
+ 54803,
+ 54804,
+ 54805,
+ 54806,
+ 54807,
+ 54808,
+ 54809,
+ 54810,
+ 54811,
+ 54812,
+ 54813,
+ 54814,
+ 54815,
+ 54816,
+ 54817,
+ 54818,
+ 54819,
+ 54820,
+ 54821,
+ 54822,
+ 54823,
+ 54824,
+ 54825,
+ 54826,
+ 54827,
+ 54828,
+ 54829,
+ 54830,
+ 54831,
+ 54832,
+ 54833,
+ 54834,
+ 54835,
+ 54836,
+ 54837,
+ 54838,
+ 54839,
+ 54840,
+ 54841,
+ 54842,
+ 54843,
+ 54844,
+ 54845,
+ 54846,
+ 54847,
+ 54848,
+ 54849,
+ 54850,
+ 54851,
+ 54852,
+ 54853,
+ 54854,
+ 54855,
+ 54856,
+ 54857,
+ 54858,
+ 54859,
+ 54860,
+ 54861,
+ 54862,
+ 54863,
+ 54864,
+ 54865,
+ 54866,
+ 54867,
+ 54868,
+ 54869,
+ 54870,
+ 54871,
+ 54872,
+ 54873,
+ 54874,
+ 54875,
+ 54876,
+ 54877,
+ 54878,
+ 54879,
+ 54880,
+ 54881,
+ 54882,
+ 54883,
+ 54884,
+ 54885,
+ 54886,
+ 54887,
+ 54888,
+ 54889,
+ 54890,
+ 54891,
+ 54892,
+ 54893,
+ 54894,
+ 54895,
+ 54896,
+ 54897,
+ 54898,
+ 54899,
+ 54900,
+ 54901,
+ 54902,
+ 54903,
+ 54904,
+ 54905,
+ 54906,
+ 54907,
+ 54908,
+ 54909,
+ 54910,
+ 54911,
+ 54912,
+ 54913,
+ 54914,
+ 54915,
+ 54916,
+ 54917,
+ 54918,
+ 54919,
+ 54920,
+ 54921,
+ 54922,
+ 54923,
+ 54924,
+ 54925,
+ 54926,
+ 54927,
+ 54928,
+ 54929,
+ 54930,
+ 54931,
+ 54932,
+ 54933,
+ 54934,
+ 54935,
+ 54936,
+ 54937,
+ 54938,
+ 54939,
+ 54940,
+ 54941,
+ 54942,
+ 54943,
+ 54944,
+ 54945,
+ 54946,
+ 54947,
+ 54948,
+ 54949,
+ 54950,
+ 54951,
+ 54952,
+ 54953,
+ 54954,
+ 54955,
+ 54956,
+ 54957,
+ 54958,
+ 54959,
+ 54960,
+ 54961,
+ 54962,
+ 54963,
+ 54964,
+ 54965,
+ 54966,
+ 54967,
+ 54968,
+ 54969,
+ 54970,
+ 54971,
+ 54972,
+ 54973,
+ 54974,
+ 54975,
+ 54976,
+ 54977,
+ 54978,
+ 54979,
+ 54980,
+ 54981,
+ 54982,
+ 54983,
+ 54984,
+ 54985,
+ 54986,
+ 54987,
+ 54988,
+ 54989,
+ 54990,
+ 54991,
+ 54992,
+ 54993,
+ 54994,
+ 54995,
+ 54996,
+ 54997,
+ 54998,
+ 54999,
+ 55000,
+ 55001,
+ 55002,
+ 55003,
+ 55004,
+ 55005,
+ 55006,
+ 55007,
+ 55008,
+ 55009,
+ 55010,
+ 55011,
+ 55012,
+ 55013,
+ 55014,
+ 55015,
+ 55016,
+ 55017,
+ 55018,
+ 55019,
+ 55020,
+ 55021,
+ 55022,
+ 55023,
+ 55024,
+ 55025,
+ 55026,
+ 55027,
+ 55028,
+ 55029,
+ 55030,
+ 55031,
+ 55032,
+ 55033,
+ 55034,
+ 55035,
+ 55036,
+ 55037,
+ 55038,
+ 55039,
+ 55040,
+ 55041,
+ 55042,
+ 55043,
+ 55044,
+ 55045,
+ 55046,
+ 55047,
+ 55048,
+ 55049,
+ 55050,
+ 55051,
+ 55052,
+ 55053,
+ 55054,
+ 55055,
+ 55056,
+ 55057,
+ 55058,
+ 55059,
+ 55060,
+ 55061,
+ 55062,
+ 55063,
+ 55064,
+ 55065,
+ 55066,
+ 55067,
+ 55068,
+ 55069,
+ 55070,
+ 55071,
+ 55072,
+ 55073,
+ 55074,
+ 55075,
+ 55076,
+ 55077,
+ 55078,
+ 55079,
+ 55080,
+ 55081,
+ 55082,
+ 55083,
+ 55084,
+ 55085,
+ 55086,
+ 55087,
+ 55088,
+ 55089,
+ 55090,
+ 55091,
+ 55092,
+ 55093,
+ 55094,
+ 55095,
+ 55096,
+ 55097,
+ 55098,
+ 55099,
+ 55100,
+ 55101,
+ 55102,
+ 55103,
+ 55104,
+ 55105,
+ 55106,
+ 55107,
+ 55108,
+ 55109,
+ 55110,
+ 55111,
+ 55112,
+ 55113,
+ 55114,
+ 55115,
+ 55116,
+ 55117,
+ 55118,
+ 55119,
+ 55120,
+ 55121,
+ 55122,
+ 55123,
+ 55124,
+ 55125,
+ 55126,
+ 55127,
+ 55128,
+ 55129,
+ 55130,
+ 55131,
+ 55132,
+ 55133,
+ 55134,
+ 55135,
+ 55136,
+ 55137,
+ 55138,
+ 55139,
+ 55140,
+ 55141,
+ 55142,
+ 55143,
+ 55144,
+ 55145,
+ 55146,
+ 55147,
+ 55148,
+ 55149,
+ 55150,
+ 55151,
+ 55152,
+ 55153,
+ 55154,
+ 55155,
+ 55156,
+ 55157,
+ 55158,
+ 55159,
+ 55160,
+ 55161,
+ 55162,
+ 55163,
+ 55164,
+ 55165,
+ 55166,
+ 55167,
+ 55168,
+ 55169,
+ 55170,
+ 55171,
+ 55172,
+ 55173,
+ 55174,
+ 55175,
+ 55176,
+ 55177,
+ 55178,
+ 55179,
+ 55180,
+ 55181,
+ 55182,
+ 55183,
+ 55184,
+ 55185,
+ 55186,
+ 55187,
+ 55188,
+ 55189,
+ 55190,
+ 55191,
+ 55192,
+ 55193,
+ 55194,
+ 55195,
+ 55196,
+ 55197,
+ 55198,
+ 55199,
+ 55200,
+ 55201,
+ 55202,
+ 55203,
+ 55216,
+ 55217,
+ 55218,
+ 55219,
+ 55220,
+ 55221,
+ 55222,
+ 55223,
+ 55224,
+ 55225,
+ 55226,
+ 55227,
+ 55228,
+ 55229,
+ 55230,
+ 55231,
+ 55232,
+ 55233,
+ 55234,
+ 55235,
+ 55236,
+ 55237,
+ 55238,
+ 55243,
+ 55244,
+ 55245,
+ 55246,
+ 55247,
+ 55248,
+ 55249,
+ 55250,
+ 55251,
+ 55252,
+ 55253,
+ 55254,
+ 55255,
+ 55256,
+ 55257,
+ 55258,
+ 55259,
+ 55260,
+ 55261,
+ 55262,
+ 55263,
+ 55264,
+ 55265,
+ 55266,
+ 55267,
+ 55268,
+ 55269,
+ 55270,
+ 55271,
+ 55272,
+ 55273,
+ 55274,
+ 55275,
+ 55276,
+ 55277,
+ 55278,
+ 55279,
+ 55280,
+ 55281,
+ 55282,
+ 55283,
+ 55284,
+ 55285,
+ 55286,
+ 55287,
+ 55288,
+ 55289,
+ 55290,
+ 55291,
+ 63744,
+ 63745,
+ 63746,
+ 63747,
+ 63748,
+ 63749,
+ 63750,
+ 63751,
+ 63752,
+ 63753,
+ 63754,
+ 63755,
+ 63756,
+ 63757,
+ 63758,
+ 63759,
+ 63760,
+ 63761,
+ 63762,
+ 63763,
+ 63764,
+ 63765,
+ 63766,
+ 63767,
+ 63768,
+ 63769,
+ 63770,
+ 63771,
+ 63772,
+ 63773,
+ 63774,
+ 63775,
+ 63776,
+ 63777,
+ 63778,
+ 63779,
+ 63780,
+ 63781,
+ 63782,
+ 63783,
+ 63784,
+ 63785,
+ 63786,
+ 63787,
+ 63788,
+ 63789,
+ 63790,
+ 63791,
+ 63792,
+ 63793,
+ 63794,
+ 63795,
+ 63796,
+ 63797,
+ 63798,
+ 63799,
+ 63800,
+ 63801,
+ 63802,
+ 63803,
+ 63804,
+ 63805,
+ 63806,
+ 63807,
+ 63808,
+ 63809,
+ 63810,
+ 63811,
+ 63812,
+ 63813,
+ 63814,
+ 63815,
+ 63816,
+ 63817,
+ 63818,
+ 63819,
+ 63820,
+ 63821,
+ 63822,
+ 63823,
+ 63824,
+ 63825,
+ 63826,
+ 63827,
+ 63828,
+ 63829,
+ 63830,
+ 63831,
+ 63832,
+ 63833,
+ 63834,
+ 63835,
+ 63836,
+ 63837,
+ 63838,
+ 63839,
+ 63840,
+ 63841,
+ 63842,
+ 63843,
+ 63844,
+ 63845,
+ 63846,
+ 63847,
+ 63848,
+ 63849,
+ 63850,
+ 63851,
+ 63852,
+ 63853,
+ 63854,
+ 63855,
+ 63856,
+ 63857,
+ 63858,
+ 63859,
+ 63860,
+ 63861,
+ 63862,
+ 63863,
+ 63864,
+ 63865,
+ 63866,
+ 63867,
+ 63868,
+ 63869,
+ 63870,
+ 63871,
+ 63872,
+ 63873,
+ 63874,
+ 63875,
+ 63876,
+ 63877,
+ 63878,
+ 63879,
+ 63880,
+ 63881,
+ 63882,
+ 63883,
+ 63884,
+ 63885,
+ 63886,
+ 63887,
+ 63888,
+ 63889,
+ 63890,
+ 63891,
+ 63892,
+ 63893,
+ 63894,
+ 63895,
+ 63896,
+ 63897,
+ 63898,
+ 63899,
+ 63900,
+ 63901,
+ 63902,
+ 63903,
+ 63904,
+ 63905,
+ 63906,
+ 63907,
+ 63908,
+ 63909,
+ 63910,
+ 63911,
+ 63912,
+ 63913,
+ 63914,
+ 63915,
+ 63916,
+ 63917,
+ 63918,
+ 63919,
+ 63920,
+ 63921,
+ 63922,
+ 63923,
+ 63924,
+ 63925,
+ 63926,
+ 63927,
+ 63928,
+ 63929,
+ 63930,
+ 63931,
+ 63932,
+ 63933,
+ 63934,
+ 63935,
+ 63936,
+ 63937,
+ 63938,
+ 63939,
+ 63940,
+ 63941,
+ 63942,
+ 63943,
+ 63944,
+ 63945,
+ 63946,
+ 63947,
+ 63948,
+ 63949,
+ 63950,
+ 63951,
+ 63952,
+ 63953,
+ 63954,
+ 63955,
+ 63956,
+ 63957,
+ 63958,
+ 63959,
+ 63960,
+ 63961,
+ 63962,
+ 63963,
+ 63964,
+ 63965,
+ 63966,
+ 63967,
+ 63968,
+ 63969,
+ 63970,
+ 63971,
+ 63972,
+ 63973,
+ 63974,
+ 63975,
+ 63976,
+ 63977,
+ 63978,
+ 63979,
+ 63980,
+ 63981,
+ 63982,
+ 63983,
+ 63984,
+ 63985,
+ 63986,
+ 63987,
+ 63988,
+ 63989,
+ 63990,
+ 63991,
+ 63992,
+ 63993,
+ 63994,
+ 63995,
+ 63996,
+ 63997,
+ 63998,
+ 63999,
+ 64000,
+ 64001,
+ 64002,
+ 64003,
+ 64004,
+ 64005,
+ 64006,
+ 64007,
+ 64008,
+ 64009,
+ 64010,
+ 64011,
+ 64012,
+ 64013,
+ 64014,
+ 64015,
+ 64016,
+ 64017,
+ 64018,
+ 64019,
+ 64020,
+ 64021,
+ 64022,
+ 64023,
+ 64024,
+ 64025,
+ 64026,
+ 64027,
+ 64028,
+ 64029,
+ 64030,
+ 64031,
+ 64032,
+ 64033,
+ 64034,
+ 64035,
+ 64036,
+ 64037,
+ 64038,
+ 64039,
+ 64040,
+ 64041,
+ 64042,
+ 64043,
+ 64044,
+ 64045,
+ 64046,
+ 64047,
+ 64048,
+ 64049,
+ 64050,
+ 64051,
+ 64052,
+ 64053,
+ 64054,
+ 64055,
+ 64056,
+ 64057,
+ 64058,
+ 64059,
+ 64060,
+ 64061,
+ 64062,
+ 64063,
+ 64064,
+ 64065,
+ 64066,
+ 64067,
+ 64068,
+ 64069,
+ 64070,
+ 64071,
+ 64072,
+ 64073,
+ 64074,
+ 64075,
+ 64076,
+ 64077,
+ 64078,
+ 64079,
+ 64080,
+ 64081,
+ 64082,
+ 64083,
+ 64084,
+ 64085,
+ 64086,
+ 64087,
+ 64088,
+ 64089,
+ 64090,
+ 64091,
+ 64092,
+ 64093,
+ 64094,
+ 64095,
+ 64096,
+ 64097,
+ 64098,
+ 64099,
+ 64100,
+ 64101,
+ 64102,
+ 64103,
+ 64104,
+ 64105,
+ 64106,
+ 64107,
+ 64108,
+ 64109,
+ 64112,
+ 64113,
+ 64114,
+ 64115,
+ 64116,
+ 64117,
+ 64118,
+ 64119,
+ 64120,
+ 64121,
+ 64122,
+ 64123,
+ 64124,
+ 64125,
+ 64126,
+ 64127,
+ 64128,
+ 64129,
+ 64130,
+ 64131,
+ 64132,
+ 64133,
+ 64134,
+ 64135,
+ 64136,
+ 64137,
+ 64138,
+ 64139,
+ 64140,
+ 64141,
+ 64142,
+ 64143,
+ 64144,
+ 64145,
+ 64146,
+ 64147,
+ 64148,
+ 64149,
+ 64150,
+ 64151,
+ 64152,
+ 64153,
+ 64154,
+ 64155,
+ 64156,
+ 64157,
+ 64158,
+ 64159,
+ 64160,
+ 64161,
+ 64162,
+ 64163,
+ 64164,
+ 64165,
+ 64166,
+ 64167,
+ 64168,
+ 64169,
+ 64170,
+ 64171,
+ 64172,
+ 64173,
+ 64174,
+ 64175,
+ 64176,
+ 64177,
+ 64178,
+ 64179,
+ 64180,
+ 64181,
+ 64182,
+ 64183,
+ 64184,
+ 64185,
+ 64186,
+ 64187,
+ 64188,
+ 64189,
+ 64190,
+ 64191,
+ 64192,
+ 64193,
+ 64194,
+ 64195,
+ 64196,
+ 64197,
+ 64198,
+ 64199,
+ 64200,
+ 64201,
+ 64202,
+ 64203,
+ 64204,
+ 64205,
+ 64206,
+ 64207,
+ 64208,
+ 64209,
+ 64210,
+ 64211,
+ 64212,
+ 64213,
+ 64214,
+ 64215,
+ 64216,
+ 64217,
+ 64256,
+ 64257,
+ 64258,
+ 64259,
+ 64260,
+ 64261,
+ 64262,
+ 64275,
+ 64276,
+ 64277,
+ 64278,
+ 64279,
+ 64285,
+ 64287,
+ 64288,
+ 64289,
+ 64290,
+ 64291,
+ 64292,
+ 64293,
+ 64294,
+ 64295,
+ 64296,
+ 64298,
+ 64299,
+ 64300,
+ 64301,
+ 64302,
+ 64303,
+ 64304,
+ 64305,
+ 64306,
+ 64307,
+ 64308,
+ 64309,
+ 64310,
+ 64312,
+ 64313,
+ 64314,
+ 64315,
+ 64316,
+ 64318,
+ 64320,
+ 64321,
+ 64323,
+ 64324,
+ 64326,
+ 64327,
+ 64328,
+ 64329,
+ 64330,
+ 64331,
+ 64332,
+ 64333,
+ 64334,
+ 64335,
+ 64336,
+ 64337,
+ 64338,
+ 64339,
+ 64340,
+ 64341,
+ 64342,
+ 64343,
+ 64344,
+ 64345,
+ 64346,
+ 64347,
+ 64348,
+ 64349,
+ 64350,
+ 64351,
+ 64352,
+ 64353,
+ 64354,
+ 64355,
+ 64356,
+ 64357,
+ 64358,
+ 64359,
+ 64360,
+ 64361,
+ 64362,
+ 64363,
+ 64364,
+ 64365,
+ 64366,
+ 64367,
+ 64368,
+ 64369,
+ 64370,
+ 64371,
+ 64372,
+ 64373,
+ 64374,
+ 64375,
+ 64376,
+ 64377,
+ 64378,
+ 64379,
+ 64380,
+ 64381,
+ 64382,
+ 64383,
+ 64384,
+ 64385,
+ 64386,
+ 64387,
+ 64388,
+ 64389,
+ 64390,
+ 64391,
+ 64392,
+ 64393,
+ 64394,
+ 64395,
+ 64396,
+ 64397,
+ 64398,
+ 64399,
+ 64400,
+ 64401,
+ 64402,
+ 64403,
+ 64404,
+ 64405,
+ 64406,
+ 64407,
+ 64408,
+ 64409,
+ 64410,
+ 64411,
+ 64412,
+ 64413,
+ 64414,
+ 64415,
+ 64416,
+ 64417,
+ 64418,
+ 64419,
+ 64420,
+ 64421,
+ 64422,
+ 64423,
+ 64424,
+ 64425,
+ 64426,
+ 64427,
+ 64428,
+ 64429,
+ 64430,
+ 64431,
+ 64432,
+ 64433,
+ 64467,
+ 64468,
+ 64469,
+ 64470,
+ 64471,
+ 64472,
+ 64473,
+ 64474,
+ 64475,
+ 64476,
+ 64477,
+ 64478,
+ 64479,
+ 64480,
+ 64481,
+ 64482,
+ 64483,
+ 64484,
+ 64485,
+ 64486,
+ 64487,
+ 64488,
+ 64489,
+ 64490,
+ 64491,
+ 64492,
+ 64493,
+ 64494,
+ 64495,
+ 64496,
+ 64497,
+ 64498,
+ 64499,
+ 64500,
+ 64501,
+ 64502,
+ 64503,
+ 64504,
+ 64505,
+ 64506,
+ 64507,
+ 64508,
+ 64509,
+ 64510,
+ 64511,
+ 64512,
+ 64513,
+ 64514,
+ 64515,
+ 64516,
+ 64517,
+ 64518,
+ 64519,
+ 64520,
+ 64521,
+ 64522,
+ 64523,
+ 64524,
+ 64525,
+ 64526,
+ 64527,
+ 64528,
+ 64529,
+ 64530,
+ 64531,
+ 64532,
+ 64533,
+ 64534,
+ 64535,
+ 64536,
+ 64537,
+ 64538,
+ 64539,
+ 64540,
+ 64541,
+ 64542,
+ 64543,
+ 64544,
+ 64545,
+ 64546,
+ 64547,
+ 64548,
+ 64549,
+ 64550,
+ 64551,
+ 64552,
+ 64553,
+ 64554,
+ 64555,
+ 64556,
+ 64557,
+ 64558,
+ 64559,
+ 64560,
+ 64561,
+ 64562,
+ 64563,
+ 64564,
+ 64565,
+ 64566,
+ 64567,
+ 64568,
+ 64569,
+ 64570,
+ 64571,
+ 64572,
+ 64573,
+ 64574,
+ 64575,
+ 64576,
+ 64577,
+ 64578,
+ 64579,
+ 64580,
+ 64581,
+ 64582,
+ 64583,
+ 64584,
+ 64585,
+ 64586,
+ 64587,
+ 64588,
+ 64589,
+ 64590,
+ 64591,
+ 64592,
+ 64593,
+ 64594,
+ 64595,
+ 64596,
+ 64597,
+ 64598,
+ 64599,
+ 64600,
+ 64601,
+ 64602,
+ 64603,
+ 64604,
+ 64605,
+ 64606,
+ 64607,
+ 64608,
+ 64609,
+ 64610,
+ 64611,
+ 64612,
+ 64613,
+ 64614,
+ 64615,
+ 64616,
+ 64617,
+ 64618,
+ 64619,
+ 64620,
+ 64621,
+ 64622,
+ 64623,
+ 64624,
+ 64625,
+ 64626,
+ 64627,
+ 64628,
+ 64629,
+ 64630,
+ 64631,
+ 64632,
+ 64633,
+ 64634,
+ 64635,
+ 64636,
+ 64637,
+ 64638,
+ 64639,
+ 64640,
+ 64641,
+ 64642,
+ 64643,
+ 64644,
+ 64645,
+ 64646,
+ 64647,
+ 64648,
+ 64649,
+ 64650,
+ 64651,
+ 64652,
+ 64653,
+ 64654,
+ 64655,
+ 64656,
+ 64657,
+ 64658,
+ 64659,
+ 64660,
+ 64661,
+ 64662,
+ 64663,
+ 64664,
+ 64665,
+ 64666,
+ 64667,
+ 64668,
+ 64669,
+ 64670,
+ 64671,
+ 64672,
+ 64673,
+ 64674,
+ 64675,
+ 64676,
+ 64677,
+ 64678,
+ 64679,
+ 64680,
+ 64681,
+ 64682,
+ 64683,
+ 64684,
+ 64685,
+ 64686,
+ 64687,
+ 64688,
+ 64689,
+ 64690,
+ 64691,
+ 64692,
+ 64693,
+ 64694,
+ 64695,
+ 64696,
+ 64697,
+ 64698,
+ 64699,
+ 64700,
+ 64701,
+ 64702,
+ 64703,
+ 64704,
+ 64705,
+ 64706,
+ 64707,
+ 64708,
+ 64709,
+ 64710,
+ 64711,
+ 64712,
+ 64713,
+ 64714,
+ 64715,
+ 64716,
+ 64717,
+ 64718,
+ 64719,
+ 64720,
+ 64721,
+ 64722,
+ 64723,
+ 64724,
+ 64725,
+ 64726,
+ 64727,
+ 64728,
+ 64729,
+ 64730,
+ 64731,
+ 64732,
+ 64733,
+ 64734,
+ 64735,
+ 64736,
+ 64737,
+ 64738,
+ 64739,
+ 64740,
+ 64741,
+ 64742,
+ 64743,
+ 64744,
+ 64745,
+ 64746,
+ 64747,
+ 64748,
+ 64749,
+ 64750,
+ 64751,
+ 64752,
+ 64753,
+ 64754,
+ 64755,
+ 64756,
+ 64757,
+ 64758,
+ 64759,
+ 64760,
+ 64761,
+ 64762,
+ 64763,
+ 64764,
+ 64765,
+ 64766,
+ 64767,
+ 64768,
+ 64769,
+ 64770,
+ 64771,
+ 64772,
+ 64773,
+ 64774,
+ 64775,
+ 64776,
+ 64777,
+ 64778,
+ 64779,
+ 64780,
+ 64781,
+ 64782,
+ 64783,
+ 64784,
+ 64785,
+ 64786,
+ 64787,
+ 64788,
+ 64789,
+ 64790,
+ 64791,
+ 64792,
+ 64793,
+ 64794,
+ 64795,
+ 64796,
+ 64797,
+ 64798,
+ 64799,
+ 64800,
+ 64801,
+ 64802,
+ 64803,
+ 64804,
+ 64805,
+ 64806,
+ 64807,
+ 64808,
+ 64809,
+ 64810,
+ 64811,
+ 64812,
+ 64813,
+ 64814,
+ 64815,
+ 64816,
+ 64817,
+ 64818,
+ 64819,
+ 64820,
+ 64821,
+ 64822,
+ 64823,
+ 64824,
+ 64825,
+ 64826,
+ 64827,
+ 64828,
+ 64829,
+ 64848,
+ 64849,
+ 64850,
+ 64851,
+ 64852,
+ 64853,
+ 64854,
+ 64855,
+ 64856,
+ 64857,
+ 64858,
+ 64859,
+ 64860,
+ 64861,
+ 64862,
+ 64863,
+ 64864,
+ 64865,
+ 64866,
+ 64867,
+ 64868,
+ 64869,
+ 64870,
+ 64871,
+ 64872,
+ 64873,
+ 64874,
+ 64875,
+ 64876,
+ 64877,
+ 64878,
+ 64879,
+ 64880,
+ 64881,
+ 64882,
+ 64883,
+ 64884,
+ 64885,
+ 64886,
+ 64887,
+ 64888,
+ 64889,
+ 64890,
+ 64891,
+ 64892,
+ 64893,
+ 64894,
+ 64895,
+ 64896,
+ 64897,
+ 64898,
+ 64899,
+ 64900,
+ 64901,
+ 64902,
+ 64903,
+ 64904,
+ 64905,
+ 64906,
+ 64907,
+ 64908,
+ 64909,
+ 64910,
+ 64911,
+ 64914,
+ 64915,
+ 64916,
+ 64917,
+ 64918,
+ 64919,
+ 64920,
+ 64921,
+ 64922,
+ 64923,
+ 64924,
+ 64925,
+ 64926,
+ 64927,
+ 64928,
+ 64929,
+ 64930,
+ 64931,
+ 64932,
+ 64933,
+ 64934,
+ 64935,
+ 64936,
+ 64937,
+ 64938,
+ 64939,
+ 64940,
+ 64941,
+ 64942,
+ 64943,
+ 64944,
+ 64945,
+ 64946,
+ 64947,
+ 64948,
+ 64949,
+ 64950,
+ 64951,
+ 64952,
+ 64953,
+ 64954,
+ 64955,
+ 64956,
+ 64957,
+ 64958,
+ 64959,
+ 64960,
+ 64961,
+ 64962,
+ 64963,
+ 64964,
+ 64965,
+ 64966,
+ 64967,
+ 65008,
+ 65009,
+ 65010,
+ 65011,
+ 65012,
+ 65013,
+ 65014,
+ 65015,
+ 65016,
+ 65017,
+ 65018,
+ 65019,
+ 65136,
+ 65137,
+ 65138,
+ 65139,
+ 65140,
+ 65142,
+ 65143,
+ 65144,
+ 65145,
+ 65146,
+ 65147,
+ 65148,
+ 65149,
+ 65150,
+ 65151,
+ 65152,
+ 65153,
+ 65154,
+ 65155,
+ 65156,
+ 65157,
+ 65158,
+ 65159,
+ 65160,
+ 65161,
+ 65162,
+ 65163,
+ 65164,
+ 65165,
+ 65166,
+ 65167,
+ 65168,
+ 65169,
+ 65170,
+ 65171,
+ 65172,
+ 65173,
+ 65174,
+ 65175,
+ 65176,
+ 65177,
+ 65178,
+ 65179,
+ 65180,
+ 65181,
+ 65182,
+ 65183,
+ 65184,
+ 65185,
+ 65186,
+ 65187,
+ 65188,
+ 65189,
+ 65190,
+ 65191,
+ 65192,
+ 65193,
+ 65194,
+ 65195,
+ 65196,
+ 65197,
+ 65198,
+ 65199,
+ 65200,
+ 65201,
+ 65202,
+ 65203,
+ 65204,
+ 65205,
+ 65206,
+ 65207,
+ 65208,
+ 65209,
+ 65210,
+ 65211,
+ 65212,
+ 65213,
+ 65214,
+ 65215,
+ 65216,
+ 65217,
+ 65218,
+ 65219,
+ 65220,
+ 65221,
+ 65222,
+ 65223,
+ 65224,
+ 65225,
+ 65226,
+ 65227,
+ 65228,
+ 65229,
+ 65230,
+ 65231,
+ 65232,
+ 65233,
+ 65234,
+ 65235,
+ 65236,
+ 65237,
+ 65238,
+ 65239,
+ 65240,
+ 65241,
+ 65242,
+ 65243,
+ 65244,
+ 65245,
+ 65246,
+ 65247,
+ 65248,
+ 65249,
+ 65250,
+ 65251,
+ 65252,
+ 65253,
+ 65254,
+ 65255,
+ 65256,
+ 65257,
+ 65258,
+ 65259,
+ 65260,
+ 65261,
+ 65262,
+ 65263,
+ 65264,
+ 65265,
+ 65266,
+ 65267,
+ 65268,
+ 65269,
+ 65270,
+ 65271,
+ 65272,
+ 65273,
+ 65274,
+ 65275,
+ 65276,
+ 65313,
+ 65314,
+ 65315,
+ 65316,
+ 65317,
+ 65318,
+ 65319,
+ 65320,
+ 65321,
+ 65322,
+ 65323,
+ 65324,
+ 65325,
+ 65326,
+ 65327,
+ 65328,
+ 65329,
+ 65330,
+ 65331,
+ 65332,
+ 65333,
+ 65334,
+ 65335,
+ 65336,
+ 65337,
+ 65338,
+ 65345,
+ 65346,
+ 65347,
+ 65348,
+ 65349,
+ 65350,
+ 65351,
+ 65352,
+ 65353,
+ 65354,
+ 65355,
+ 65356,
+ 65357,
+ 65358,
+ 65359,
+ 65360,
+ 65361,
+ 65362,
+ 65363,
+ 65364,
+ 65365,
+ 65366,
+ 65367,
+ 65368,
+ 65369,
+ 65370,
+ 65382,
+ 65383,
+ 65384,
+ 65385,
+ 65386,
+ 65387,
+ 65388,
+ 65389,
+ 65390,
+ 65391,
+ 65392,
+ 65393,
+ 65394,
+ 65395,
+ 65396,
+ 65397,
+ 65398,
+ 65399,
+ 65400,
+ 65401,
+ 65402,
+ 65403,
+ 65404,
+ 65405,
+ 65406,
+ 65407,
+ 65408,
+ 65409,
+ 65410,
+ 65411,
+ 65412,
+ 65413,
+ 65414,
+ 65415,
+ 65416,
+ 65417,
+ 65418,
+ 65419,
+ 65420,
+ 65421,
+ 65422,
+ 65423,
+ 65424,
+ 65425,
+ 65426,
+ 65427,
+ 65428,
+ 65429,
+ 65430,
+ 65431,
+ 65432,
+ 65433,
+ 65434,
+ 65435,
+ 65436,
+ 65437,
+ 65438,
+ 65439,
+ 65440,
+ 65441,
+ 65442,
+ 65443,
+ 65444,
+ 65445,
+ 65446,
+ 65447,
+ 65448,
+ 65449,
+ 65450,
+ 65451,
+ 65452,
+ 65453,
+ 65454,
+ 65455,
+ 65456,
+ 65457,
+ 65458,
+ 65459,
+ 65460,
+ 65461,
+ 65462,
+ 65463,
+ 65464,
+ 65465,
+ 65466,
+ 65467,
+ 65468,
+ 65469,
+ 65470,
+ 65474,
+ 65475,
+ 65476,
+ 65477,
+ 65478,
+ 65479,
+ 65482,
+ 65483,
+ 65484,
+ 65485,
+ 65486,
+ 65487,
+ 65490,
+ 65491,
+ 65492,
+ 65493,
+ 65494,
+ 65495,
+ 65498,
+ 65499,
+ 65500
+];
+
+},{}],4:[function(require,module,exports){
+// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
+//
+// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
+//
+// Originally from narwhal.js (http://narwhaljs.org)
+// Copyright (c) 2009 Thomas Robinson <280north.com>
+//
+// 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 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.
+
+// when used in node, this will actually load the util module we depend on
+// versus loading the builtin util module as happens otherwise
+// this is a bug in node module loading as far as I am concerned
+var util = require('util/');
+
+var pSlice = Array.prototype.slice;
+var hasOwn = Object.prototype.hasOwnProperty;
+
+// 1. The assert module provides functions that throw
+// AssertionError's when particular conditions are not met. The
+// assert module must conform to the following interface.
+
+var assert = module.exports = ok;
+
+// 2. The AssertionError is defined in assert.
+// new assert.AssertionError({ message: message,
+// actual: actual,
+// expected: expected })
+
+assert.AssertionError = function AssertionError(options) {
+ this.name = 'AssertionError';
+ this.actual = options.actual;
+ this.expected = options.expected;
+ this.operator = options.operator;
+ if (options.message) {
+ this.message = options.message;
+ this.generatedMessage = false;
+ } else {
+ this.message = getMessage(this);
+ this.generatedMessage = true;
+ }
+ var stackStartFunction = options.stackStartFunction || fail;
+
+ if (Error.captureStackTrace) {
+ Error.captureStackTrace(this, stackStartFunction);
+ }
+ else {
+ // non v8 browsers so we can have a stacktrace
+ var err = new Error();
+ if (err.stack) {
+ var out = err.stack;
+
+ // try to strip useless frames
+ var fn_name = stackStartFunction.name;
+ var idx = out.indexOf('\n' + fn_name);
+ if (idx >= 0) {
+ // once we have located the function frame
+ // we need to strip out everything before it (and its line)
+ var next_line = out.indexOf('\n', idx + 1);
+ out = out.substring(next_line + 1);
+ }
+
+ this.stack = out;
+ }
+ }
+};
+
+// assert.AssertionError instanceof Error
+util.inherits(assert.AssertionError, Error);
+
+function replacer(key, value) {
+ if (util.isUndefined(value)) {
+ return '' + value;
+ }
+ if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
+ return value.toString();
+ }
+ if (util.isFunction(value) || util.isRegExp(value)) {
+ return value.toString();
+ }
+ return value;
+}
+
+function truncate(s, n) {
+ if (util.isString(s)) {
+ return s.length < n ? s : s.slice(0, n);
+ } else {
+ return s;
+ }
+}
+
+function getMessage(self) {
+ return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
+ self.operator + ' ' +
+ truncate(JSON.stringify(self.expected, replacer), 128);
+}
+
+// At present only the three keys mentioned above are used and
+// understood by the spec. Implementations or sub modules can pass
+// other keys to the AssertionError's constructor - they will be
+// ignored.
+
+// 3. All of the following functions must throw an AssertionError
+// when a corresponding condition is not met, with a message that
+// may be undefined if not provided. All assertion methods provide
+// both the actual and expected values to the assertion error for
+// display purposes.
+
+function fail(actual, expected, message, operator, stackStartFunction) {
+ throw new assert.AssertionError({
+ message: message,
+ actual: actual,
+ expected: expected,
+ operator: operator,
+ stackStartFunction: stackStartFunction
+ });
+}
+
+// EXTENSION! allows for well behaved errors defined elsewhere.
+assert.fail = fail;
+
+// 4. Pure assertion tests whether a value is truthy, as determined
+// by !!guard.
+// assert.ok(guard, message_opt);
+// This statement is equivalent to assert.equal(true, !!guard,
+// message_opt);. To test strictly for the value true, use
+// assert.strictEqual(true, guard, message_opt);.
+
+function ok(value, message) {
+ if (!value) fail(value, true, message, '==', assert.ok);
+}
+assert.ok = ok;
+
+// 5. The equality assertion tests shallow, coercive equality with
+// ==.
+// assert.equal(actual, expected, message_opt);
+
+assert.equal = function equal(actual, expected, message) {
+ if (actual != expected) fail(actual, expected, message, '==', assert.equal);
+};
+
+// 6. The non-equality assertion tests for whether two objects are not equal
+// with != assert.notEqual(actual, expected, message_opt);
+
+assert.notEqual = function notEqual(actual, expected, message) {
+ if (actual == expected) {
+ fail(actual, expected, message, '!=', assert.notEqual);
+ }
+};
+
+// 7. The equivalence assertion tests a deep equality relation.
+// assert.deepEqual(actual, expected, message_opt);
+
+assert.deepEqual = function deepEqual(actual, expected, message) {
+ if (!_deepEqual(actual, expected)) {
+ fail(actual, expected, message, 'deepEqual', assert.deepEqual);
+ }
+};
+
+function _deepEqual(actual, expected) {
+ // 7.1. All identical values are equivalent, as determined by ===.
+ if (actual === expected) {
+ return true;
+
+ } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
+ if (actual.length != expected.length) return false;
+
+ for (var i = 0; i < actual.length; i++) {
+ if (actual[i] !== expected[i]) return false;
+ }
+
+ return true;
+
+ // 7.2. If the expected value is a Date object, the actual value is
+ // equivalent if it is also a Date object that refers to the same time.
+ } else if (util.isDate(actual) && util.isDate(expected)) {
+ return actual.getTime() === expected.getTime();
+
+ // 7.3 If the expected value is a RegExp object, the actual value is
+ // equivalent if it is also a RegExp object with the same source and
+ // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
+ } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
+ return actual.source === expected.source &&
+ actual.global === expected.global &&
+ actual.multiline === expected.multiline &&
+ actual.lastIndex === expected.lastIndex &&
+ actual.ignoreCase === expected.ignoreCase;
+
+ // 7.4. Other pairs that do not both pass typeof value == 'object',
+ // equivalence is determined by ==.
+ } else if (!util.isObject(actual) && !util.isObject(expected)) {
+ return actual == expected;
+
+ // 7.5 For all other Object pairs, including Array objects, equivalence is
+ // determined by having the same number of owned properties (as verified
+ // with Object.prototype.hasOwnProperty.call), the same set of keys
+ // (although not necessarily the same order), equivalent values for every
+ // corresponding key, and an identical 'prototype' property. Note: this
+ // accounts for both named and indexed properties on Arrays.
+ } else {
+ return objEquiv(actual, expected);
+ }
+}
+
+function isArguments(object) {
+ return Object.prototype.toString.call(object) == '[object Arguments]';
+}
+
+function objEquiv(a, b) {
+ if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
+ return false;
+ // an identical 'prototype' property.
+ if (a.prototype !== b.prototype) return false;
+ //~~~I've managed to break Object.keys through screwy arguments passing.
+ // Converting to array solves the problem.
+ if (isArguments(a)) {
+ if (!isArguments(b)) {
+ return false;
+ }
+ a = pSlice.call(a);
+ b = pSlice.call(b);
+ return _deepEqual(a, b);
+ }
+ try {
+ var ka = objectKeys(a),
+ kb = objectKeys(b),
+ key, i;
+ } catch (e) {//happens when one is a string literal and the other isn't
+ return false;
+ }
+ // having the same number of owned properties (keys incorporates
+ // hasOwnProperty)
+ if (ka.length != kb.length)
+ return false;
+ //the same set of keys (although not necessarily the same order),
+ ka.sort();
+ kb.sort();
+ //~~~cheap key test
+ for (i = ka.length - 1; i >= 0; i--) {
+ if (ka[i] != kb[i])
+ return false;
+ }
+ //equivalent values for every corresponding key, and
+ //~~~possibly expensive deep test
+ for (i = ka.length - 1; i >= 0; i--) {
+ key = ka[i];
+ if (!_deepEqual(a[key], b[key])) return false;
+ }
+ return true;
+}
+
+// 8. The non-equivalence assertion tests for any deep inequality.
+// assert.notDeepEqual(actual, expected, message_opt);
+
+assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
+ if (_deepEqual(actual, expected)) {
+ fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
+ }
+};
+
+// 9. The strict equality assertion tests strict equality, as determined by ===.
+// assert.strictEqual(actual, expected, message_opt);
+
+assert.strictEqual = function strictEqual(actual, expected, message) {
+ if (actual !== expected) {
+ fail(actual, expected, message, '===', assert.strictEqual);
+ }
+};
+
+// 10. The strict non-equality assertion tests for strict inequality, as
+// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
+
+assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
+ if (actual === expected) {
+ fail(actual, expected, message, '!==', assert.notStrictEqual);
+ }
+};
+
+function expectedException(actual, expected) {
+ if (!actual || !expected) {
+ return false;
+ }
+
+ if (Object.prototype.toString.call(expected) == '[object RegExp]') {
+ return expected.test(actual);
+ } else if (actual instanceof expected) {
+ return true;
+ } else if (expected.call({}, actual) === true) {
+ return true;
+ }
+
+ return false;
+}
+
+function _throws(shouldThrow, block, expected, message) {
+ var actual;
+
+ if (util.isString(expected)) {
+ message = expected;
+ expected = null;
+ }
+
+ try {
+ block();
+ } catch (e) {
+ actual = e;
+ }
+
+ message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
+ (message ? ' ' + message : '.');
+
+ if (shouldThrow && !actual) {
+ fail(actual, expected, 'Missing expected exception' + message);
+ }
+
+ if (!shouldThrow && expectedException(actual, expected)) {
+ fail(actual, expected, 'Got unwanted exception' + message);
+ }
+
+ if ((shouldThrow && actual && expected &&
+ !expectedException(actual, expected)) || (!shouldThrow && actual)) {
+ throw actual;
+ }
+}
+
+// 11. Expected to throw an error:
+// assert.throws(block, Error_opt, message_opt);
+
+assert.throws = function(block, /*optional*/error, /*optional*/message) {
+ _throws.apply(this, [true].concat(pSlice.call(arguments)));
+};
+
+// EXTENSION! This is annoying to write outside this module.
+assert.doesNotThrow = function(block, /*optional*/message) {
+ _throws.apply(this, [false].concat(pSlice.call(arguments)));
+};
+
+assert.ifError = function(err) { if (err) {throw err;}};
+
+var objectKeys = Object.keys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ if (hasOwn.call(obj, key)) keys.push(key);
+ }
+ return keys;
+};
+
+},{"util/":6}],5:[function(require,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(require,module,exports){
+(function (process,global){
+// 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 = require('./support/isBuffer');
+
+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 = require('inherits');
+
+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);
+}
+
+}).call(this,require("/Users/antonkovalyov/src/jshint/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"./support/isBuffer":5,"/Users/antonkovalyov/src/jshint/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":9,"inherits":8}],7:[function(require,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 {
+ throw TypeError('Uncaught, unspecified "error" event.');
+ }
+ return false;
+ }
+ }
+
+ 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:
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ handler.apply(this, args);
+ }
+ } else if (isObject(handler)) {
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+
+ 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) {
+ var m;
+ 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);
+ 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 {
+ // 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.listenerCount = function(emitter, type) {
+ var ret;
+ if (!emitter._events || !emitter._events[type])
+ ret = 0;
+ else if (isFunction(emitter._events[type]))
+ ret = 1;
+ else
+ ret = emitter._events[type].length;
+ return ret;
+};
+
+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;
+}
+
+},{}],8:[function(require,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
+ }
+}
+
+},{}],9:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+
+process.nextTick = (function () {
+ var canSetImmediate = typeof window !== 'undefined'
+ && window.setImmediate;
+ var canPost = typeof window !== 'undefined'
+ && window.postMessage && window.addEventListener
+ ;
+
+ if (canSetImmediate) {
+ return function (f) { return window.setImmediate(f) };
+ }
+
+ if (canPost) {
+ var queue = [];
+ window.addEventListener('message', function (ev) {
+ var source = ev.source;
+ if ((source === window || source === null) && ev.data === 'process-tick') {
+ ev.stopPropagation();
+ if (queue.length > 0) {
+ var fn = queue.shift();
+ fn();
+ }
+ }
+ }, true);
+
+ return function nextTick(fn) {
+ queue.push(fn);
+ window.postMessage('process-tick', '*');
+ };
+ }
+
+ return function nextTick(fn) {
+ setTimeout(fn, 0);
+ };
+})();
+
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+}
+
+// TODO(shtylman)
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+
+},{}],10:[function(require,module,exports){
+module.exports=require(5)
+},{}],11:[function(require,module,exports){
+module.exports=require(6)
+},{"./support/isBuffer":10,"/Users/antonkovalyov/src/jshint/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":9,"inherits":8}],12:[function(require,module,exports){
+(function (global){
+/*global window, global*/
+var util = require("util")
+var assert = require("assert")
+
+var slice = Array.prototype.slice
+var console
+var times = {}
+
+if (typeof global !== "undefined" && global.console) {
+ console = global.console
+} else if (typeof window !== "undefined" && window.console) {
+ console = window.console
+} else {
+ console = window.console = {}
+}
+
+var functions = [
+ [log, "log"]
+ , [info, "info"]
+ , [warn, "warn"]
+ , [error, "error"]
+ , [time, "time"]
+ , [timeEnd, "timeEnd"]
+ , [trace, "trace"]
+ , [dir, "dir"]
+ , [assert, "assert"]
+]
+
+for (var i = 0; i < functions.length; i++) {
+ var tuple = functions[i]
+ var f = tuple[0]
+ var name = tuple[1]
+
+ if (!console[name]) {
+ console[name] = f
+ }
+}
+
+module.exports = console
+
+function log() {}
+
+function info() {
+ console.log.apply(console, arguments)
+}
+
+function warn() {
+ console.log.apply(console, arguments)
+}
+
+function error() {
+ console.warn.apply(console, arguments)
+}
+
+function time(label) {
+ times[label] = Date.now()
+}
+
+function timeEnd(label) {
+ var time = times[label]
+ if (!time) {
+ throw new Error("No such label: " + label)
+ }
+
+ var duration = Date.now() - time
+ console.log(label + ": " + duration + "ms")
+}
+
+function trace() {
+ var err = new Error()
+ err.name = "Trace"
+ err.message = util.format.apply(null, arguments)
+ console.error(err.stack)
+}
+
+function dir(object) {
+ console.log(util.inspect(object) + "\n")
+}
+
+function assert(expression) {
+ if (!expression) {
+ var arr = slice.call(arguments, 1)
+ assert.ok(false, util.format.apply(null, arr))
+ }
+}
+
+}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"assert":4,"util":11}],13:[function(require,module,exports){
+// Underscore.js 1.4.4
+// http://underscorejs.org
+// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `global` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Establish the object that gets returned to break out of a loop iteration.
+ var breaker = {};
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ concat = ArrayProto.concat,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeForEach = ArrayProto.forEach,
+ nativeMap = ArrayProto.map,
+ nativeReduce = ArrayProto.reduce,
+ nativeReduceRight = ArrayProto.reduceRight,
+ nativeFilter = ArrayProto.filter,
+ nativeEvery = ArrayProto.every,
+ nativeSome = ArrayProto.some,
+ nativeIndexOf = ArrayProto.indexOf,
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind;
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object via a string identifier,
+ // for Closure Compiler "advanced" mode.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.4.4';
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles objects with the built-in `forEach`, arrays, and raw objects.
+ // Delegates to **ECMAScript 5**'s native `forEach` if available.
+ var each = _.each = _.forEach = function(obj, iterator, context) {
+ if (obj == null) return;
+ if (nativeForEach && obj.forEach === nativeForEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length === +obj.length) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (iterator.call(context, obj[i], i, obj) === breaker) return;
+ }
+ } else {
+ for (var key in obj) {
+ if (_.has(obj, key)) {
+ if (iterator.call(context, obj[key], key, obj) === breaker) return;
+ }
+ }
+ }
+ };
+
+ // Return the results of applying the iterator to each element.
+ // Delegates to **ECMAScript 5**'s native `map` if available.
+ _.map = _.collect = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+ each(obj, function(value, index, list) {
+ results[results.length] = iterator.call(context, value, index, list);
+ });
+ return results;
+ };
+
+ var reduceError = 'Reduce of empty array with no initial value';
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
+ _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduce && obj.reduce === nativeReduce) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+ }
+ each(obj, function(value, index, list) {
+ if (!initial) {
+ memo = value;
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, value, index, list);
+ }
+ });
+ if (!initial) throw new TypeError(reduceError);
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as `foldr`.
+ // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+ _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ }
+ var length = obj.length;
+ if (length !== +length) {
+ var keys = _.keys(obj);
+ length = keys.length;
+ }
+ each(obj, function(value, index, list) {
+ index = keys ? keys[--length] : --length;
+ if (!initial) {
+ memo = obj[index];
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, obj[index], index, list);
+ }
+ });
+ if (!initial) throw new TypeError(reduceError);
+ return memo;
+ };
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, iterator, context) {
+ var result;
+ any(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test.
+ // Delegates to **ECMAScript 5**'s native `filter` if available.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+ each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ return _.filter(obj, function(value, index, list) {
+ return !iterator.call(context, value, index, list);
+ }, context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Delegates to **ECMAScript 5**'s native `every` if available.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = true;
+ if (obj == null) return result;
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+ each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Delegates to **ECMAScript 5**'s native `some` if available.
+ // Aliased as `any`.
+ var any = _.some = _.any = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = false;
+ if (obj == null) return result;
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+ each(obj, function(value, index, list) {
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if the array or object contains a given value (using `===`).
+ // Aliased as `include`.
+ _.contains = _.include = function(obj, target) {
+ if (obj == null) return false;
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ return any(obj, function(value) {
+ return value === target;
+ });
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ return (isFunc ? method : value[method]).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs, first) {
+ if (_.isEmpty(attrs)) return first ? null : [];
+ return _[first ? 'find' : 'filter'](obj, function(value) {
+ for (var key in attrs) {
+ if (attrs[key] !== value[key]) return false;
+ }
+ return true;
+ });
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.where(obj, attrs, true);
+ };
+
+ // Return the maximum element or (element-based computation).
+ // Can't optimize arrays of integers longer than 65,535 elements.
+ // See: https://bugs.webkit.org/show_bug.cgi?id=80797
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+ return Math.max.apply(Math, obj);
+ }
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
+ var result = {computed : -Infinity, value: -Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+ return Math.min.apply(Math, obj);
+ }
+ if (!iterator && _.isEmpty(obj)) return Infinity;
+ var result = {computed : Infinity, value: Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Shuffle an array.
+ _.shuffle = function(obj) {
+ var rand;
+ var index = 0;
+ var shuffled = [];
+ each(obj, function(value) {
+ rand = _.random(index++);
+ shuffled[index - 1] = shuffled[rand];
+ shuffled[rand] = value;
+ });
+ return shuffled;
+ };
+
+ // An internal function to generate lookup iterators.
+ var lookupIterator = function(value) {
+ return _.isFunction(value) ? value : function(obj){ return obj[value]; };
+ };
+
+ // Sort the object's values by a criterion produced by an iterator.
+ _.sortBy = function(obj, value, context) {
+ var iterator = lookupIterator(value);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ index : index,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index < right.index ? -1 : 1;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(obj, value, context, behavior) {
+ var result = {};
+ var iterator = lookupIterator(value || _.identity);
+ each(obj, function(value, index) {
+ var key = iterator.call(context, value, index, obj);
+ behavior(result, key, value);
+ });
+ return result;
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = function(obj, value, context) {
+ return group(obj, value, context, function(result, key, value) {
+ (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
+ });
+ };
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = function(obj, value, context) {
+ return group(obj, value, context, function(result, key) {
+ if (!_.has(result, key)) result[key] = 0;
+ result[key]++;
+ });
+ };
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator, context) {
+ iterator = iterator == null ? _.identity : lookupIterator(iterator);
+ var value = iterator.call(context, obj);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >>> 1;
+ iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ // Safely convert anything iterable into a real, live array.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (obj.length === +obj.length) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N. The **guard** check allows it to work with
+ // `_.map`.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array. The **guard** check allows it to work with `_.map`.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if ((n != null) && !guard) {
+ return slice.call(array, Math.max(array.length - n, 0));
+ } else {
+ return array[array.length - 1];
+ }
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array. The **guard**
+ // check allows it to work with `_.map`.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, (n == null) || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, output) {
+ each(input, function(value) {
+ if (_.isArray(value)) {
+ shallow ? push.apply(output, value) : flatten(value, shallow, output);
+ } else {
+ output.push(value);
+ }
+ });
+ return output;
+ };
+
+ // Return a completely flattened version of an array.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, []);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iterator, context) {
+ if (_.isFunction(isSorted)) {
+ context = iterator;
+ iterator = isSorted;
+ isSorted = false;
+ }
+ var initial = iterator ? _.map(array, iterator, context) : array;
+ var results = [];
+ var seen = [];
+ each(initial, function(value, index) {
+ if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
+ seen.push(value);
+ results.push(array[index]);
+ }
+ });
+ return results;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(concat.apply(ArrayProto, arguments));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var rest = slice.call(arguments, 1);
+ return _.filter(_.uniq(array), function(item) {
+ return _.every(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
+ return _.filter(array, function(value){ return !_.contains(rest, value); });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ var args = slice.call(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i = 0; i < length; i++) {
+ results[i] = _.pluck(args, "" + i);
+ }
+ return results;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ if (list == null) return {};
+ var result = {};
+ for (var i = 0, l = list.length; i < l; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+ // we need this function. Return the position of the first occurrence of an
+ // item in an array, or -1 if the item is not included in the array.
+ // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = function(array, item, isSorted) {
+ if (array == null) return -1;
+ var i = 0, l = array.length;
+ if (isSorted) {
+ if (typeof isSorted == 'number') {
+ i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
+ } else {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ }
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
+ for (; i < l; i++) if (array[i] === item) return i;
+ return -1;
+ };
+
+ // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+ _.lastIndexOf = function(array, item, from) {
+ if (array == null) return -1;
+ var hasIndex = from != null;
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
+ return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
+ }
+ var i = (hasIndex ? from : array.length);
+ while (i--) if (array[i] === item) return i;
+ return -1;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (arguments.length <= 1) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = arguments[2] || 1;
+
+ var len = Math.max(Math.ceil((stop - start) / step), 0);
+ var idx = 0;
+ var range = new Array(len);
+
+ while(idx < len) {
+ range[idx++] = start;
+ start += step;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ var args = slice.call(arguments, 2);
+ return function() {
+ return func.apply(context, args.concat(slice.call(arguments)));
+ };
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context.
+ _.partial = function(func) {
+ var args = slice.call(arguments, 1);
+ return function() {
+ return func.apply(this, args.concat(slice.call(arguments)));
+ };
+ };
+
+ // Bind all of an object's methods to that object. Useful for ensuring that
+ // all callbacks defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var funcs = slice.call(arguments, 1);
+ if (funcs.length === 0) funcs = _.functions(obj);
+ each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memo = {};
+ hasher || (hasher = _.identity);
+ return function() {
+ var key = hasher.apply(this, arguments);
+ return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+ };
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){ return func.apply(null, args); }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+ };
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time.
+ _.throttle = function(func, wait) {
+ var context, args, timeout, result;
+ var previous = 0;
+ var later = function() {
+ previous = new Date;
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function() {
+ var now = new Date;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, result;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) result = func.apply(context, args);
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) result = func.apply(context, args);
+ return result;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = function(func) {
+ var ran = false, memo;
+ return function() {
+ if (ran) return memo;
+ ran = true;
+ memo = func.apply(this, arguments);
+ func = null;
+ return memo;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func];
+ push.apply(args, arguments);
+ return wrapper.apply(this, args);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var funcs = arguments;
+ return function() {
+ var args = arguments;
+ for (var i = funcs.length - 1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+
+ // Returns a function that will only be executed after being called N times.
+ _.after = function(times, func) {
+ if (times <= 0) return func();
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Object Functions
+ // ----------------
+
+ // Retrieve the names of an object's properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = nativeKeys || function(obj) {
+ if (obj !== Object(obj)) throw new TypeError('Invalid object');
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var values = [];
+ for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
+ return values;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var pairs = [];
+ for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ if (source) {
+ for (var prop in source) {
+ obj[prop] = source[prop];
+ }
+ }
+ });
+ return obj;
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(obj) {
+ var copy = {};
+ var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+ each(keys, function(key) {
+ if (key in obj) copy[key] = obj[key];
+ });
+ return copy;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj) {
+ var copy = {};
+ var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+ for (var key in obj) {
+ if (!_.contains(keys, key)) copy[key] = obj[key];
+ }
+ return copy;
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ if (source) {
+ for (var prop in source) {
+ if (obj[prop] == null) obj[prop] = source[prop];
+ }
+ }
+ });
+ return obj;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
+ if (a === b) return a !== 0 || 1 / a == 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className != toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, dates, and booleans are compared by value.
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return a == String(b);
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
+ // other numeric values.
+ return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a == +b;
+ // RegExps are compared by their source patterns and flags.
+ case '[object RegExp]':
+ return a.source == b.source &&
+ a.global == b.global &&
+ a.multiline == b.multiline &&
+ a.ignoreCase == b.ignoreCase;
+ }
+ if (typeof a != 'object' || typeof b != 'object') return false;
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] == a) return bStack[length] == b;
+ }
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+ var size = 0, result = true;
+ // Recursively compare objects and arrays.
+ if (className == '[object Array]') {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ size = a.length;
+ result = size == b.length;
+ if (result) {
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (size--) {
+ if (!(result = eq(a[size], b[size], aStack, bStack))) break;
+ }
+ }
+ } else {
+ // Objects with different constructors are not equivalent, but `Object`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
+ _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
+ return false;
+ }
+ // Deep compare objects.
+ for (var key in a) {
+ if (_.has(a, key)) {
+ // Count the expected number of properties.
+ size++;
+ // Deep compare each member.
+ if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
+ }
+ }
+ // Ensure that both objects contain the same number of properties.
+ if (result) {
+ for (key in b) {
+ if (_.has(b, key) && !(size--)) break;
+ }
+ result = !size;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return result;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b, [], []);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+ for (var key in obj) if (_.has(obj, key)) return false;
+ return true;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) == '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ return obj === Object(obj);
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
+ each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) == '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return !!(obj && _.has(obj, 'callee'));
+ };
+ }
+
+ // Optimize `isFunction` if appropriate.
+ if (typeof (/./) !== 'function') {
+ _.isFunction = function(obj) {
+ return typeof obj === 'function';
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj != +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iterators.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iterator, context) {
+ var accum = Array(n);
+ for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // List of HTML entities for escaping.
+ var entityMap = {
+ escape: {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/'
+ }
+ };
+ entityMap.unescape = _.invert(entityMap.escape);
+
+ // Regexes containing the keys and values listed immediately above.
+ var entityRegexes = {
+ escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
+ unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
+ };
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ _.each(['escape', 'unescape'], function(method) {
+ _[method] = function(string) {
+ if (string == null) return '';
+ return ('' + string).replace(entityRegexes[method], function(match) {
+ return entityMap[method][match];
+ });
+ };
+ });
+
+ // If the value of the named property is a function then invoke it;
+ // otherwise, return it.
+ _.result = function(object, property) {
+ if (object == null) return null;
+ var value = object[property];
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ each(_.functions(obj), function(name){
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result.call(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\t': 't',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ _.template = function(text, data, settings) {
+ var render;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = new RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset)
+ .replace(escaper, function(match) { return '\\' + escapes[match]; });
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ }
+ if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ }
+ if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+ index = offset + match.length;
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + "return __p;\n";
+
+ try {
+ render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ if (data) return render(data, _);
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled function source as a convenience for precompilation.
+ template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function, which will delegate to the wrapper.
+ _.chain = function(obj) {
+ return _(obj).chain();
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(obj) {
+ return this._chain ? _(obj).chain() : obj;
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
+ return result.call(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result.call(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ _.extend(_.prototype, {
+
+ // Start chaining a wrapped Underscore object.
+ chain: function() {
+ this._chain = true;
+ return this;
+ },
+
+ // Extracts the result from a wrapped and chained object.
+ value: function() {
+ return this._wrapped;
+ }
+
+ });
+
+}).call(this);
+
+},{}],"jshint":[function(require,module,exports){
+module.exports=require('fNbQ4d');
+},{}],"fNbQ4d":[function(require,module,exports){
+/*!
+ * JSHint, by JSHint Community.
+ *
+ * This file (and this file only) is licensed under the same slightly modified
+ * MIT license that JSLint is. It stops evil-doers everywhere:
+ *
+ * Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
+ *
+ * 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 shall be used for Good, not Evil.
+ *
+ * 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.
+ *
+ */
+
+/*jshint quotmark:double */
+/*global console:true */
+/*exported console */
+
+var _ = require("underscore");
+var events = require("events");
+var vars = require("./vars.js");
+var messages = require("./messages.js");
+var Lexer = require("./lex.js").Lexer;
+var reg = require("./reg.js");
+var state = require("./state.js").state;
+var style = require("./style.js");
+
+// We need this module here because environments such as IE and Rhino
+// don't necessarilly expose the 'console' API and browserify uses
+// it to log things. It's a sad state of affair, really.
+var console = require("console-browserify");
+
+// We build the application inside a function so that we produce only a singleton
+// variable. That function will be invoked immediately, and its return value is
+// the JSHINT function itself.
+
+var JSHINT = (function () {
+ "use strict";
+
+ var anonname, // The guessed name for anonymous functions.
+ api, // Extension API
+
+ // These are operators that should not be used with the ! operator.
+ bang = {
+ "<" : true,
+ "<=" : true,
+ "==" : true,
+ "===": true,
+ "!==": true,
+ "!=" : true,
+ ">" : true,
+ ">=" : true,
+ "+" : true,
+ "-" : true,
+ "*" : true,
+ "/" : true,
+ "%" : true
+ },
+
+ // These are the JSHint boolean options.
+ boolOptions = {
+ asi : true, // if automatic semicolon insertion should be tolerated
+ bitwise : true, // if bitwise operators should not be allowed
+ boss : true, // if advanced usage of assignments should be allowed
+ browser : true, // if the standard browser globals should be predefined
+ camelcase : true, // if identifiers should be required in camel case
+ couch : true, // if CouchDB globals should be predefined
+ curly : true, // if curly braces around all blocks should be required
+ debug : true, // if debugger statements should be allowed
+ devel : true, // if logging globals should be predefined (console, alert, etc.)
+ dojo : true, // if Dojo Toolkit globals should be predefined
+ eqeqeq : true, // if === should be required
+ eqnull : true, // if == null comparisons should be tolerated
+ notypeof : true, // if should report typos in typeof comparisons
+ es3 : true, // if ES3 syntax should be allowed
+ es5 : true, // if ES5 syntax should be allowed (is now set per default)
+ esnext : true, // if es.next specific syntax should be allowed
+ moz : true, // if mozilla specific syntax should be allowed
+ evil : true, // if eval should be allowed
+ expr : true, // if ExpressionStatement should be allowed as Programs
+ forin : true, // if for in statements must filter
+ funcscope : true, // if only function scope should be used for scope tests
+ globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
+ immed : true, // if immediate invocations must be wrapped in parens
+ iterator : true, // if the `__iterator__` property should be allowed
+ jasmine : true, // Jasmine functions should be predefined
+ jquery : true, // if jQuery globals should be predefined
+ lastsemic : true, // if semicolons may be ommitted for the trailing
+ // statements inside of a one-line blocks.
+ laxbreak : true, // if line breaks should not be checked
+ laxcomma : true, // if line breaks should not be checked around commas
+ loopfunc : true, // if functions should be allowed to be defined within
+ // loops
+ mootools : true, // if MooTools globals should be predefined
+ multistr : true, // allow multiline strings
+ freeze : true, // if modifying native object prototypes should be disallowed
+ newcap : true, // if constructor names must be capitalized
+ noarg : true, // if arguments.caller and arguments.callee should be
+ // disallowed
+ node : true, // if the Node.js environment globals should be
+ // predefined
+ noempty : true, // if empty blocks should be disallowed
+ nonbsp : true, // if non-breaking spaces should be disallowed
+ nonew : true, // if using `new` for side-effects should be disallowed
+ nonstandard : true, // if non-standard (but widely adopted) globals should
+ // be predefined
+ phantom : true, // if PhantomJS symbols should be allowed
+ plusplus : true, // if increment/decrement should not be allowed
+ proto : true, // if the `__proto__` property should be allowed
+ prototypejs : true, // if Prototype and Scriptaculous globals should be
+ // predefined
+ qunit : true, // if the QUnit environment globals should be predefined
+ rhino : true, // if the Rhino environment globals should be predefined
+ shelljs : true, // if ShellJS globals should be predefined
+ typed : true, // if typed array globals should be predefined
+ undef : true, // if variables should be declared before used
+ scripturl : true, // if script-targeted URLs should be tolerated
+ strict : true, // require the "use strict"; pragma
+ sub : true, // if all forms of subscript notation are tolerated
+ supernew : true, // if `new function () { ... };` and `new Object;`
+ // should be tolerated
+ validthis : true, // if 'this' inside a non-constructor function is valid.
+ // This is a function scoped option only.
+ withstmt : true, // if with statements should be allowed
+ worker : true, // if Web Worker script symbols should be allowed
+ wsh : true, // if the Windows Scripting Host environment globals
+ // should be predefined
+ yui : true, // YUI variables should be predefined
+ mocha : true, // Mocha functions should be predefined
+ noyield : true, // allow generators without a yield
+
+ // Obsolete options
+ onecase : true, // if one case switch statements should be allowed
+ regexp : true, // if the . should not be allowed in regexp literals
+ regexdash : true // if unescaped first/last dash (-) inside brackets
+ // should be tolerated
+ },
+
+ // These are the JSHint options that can take any value
+ // (we use this object to detect invalid options)
+ valOptions = {
+ maxlen : false,
+ indent : false,
+ maxerr : false,
+ predef : false, // predef is deprecated and being replaced by globals
+ globals : false,
+ quotmark : false, // 'single'|'double'|true
+ scope : false,
+ maxstatements: false, // {int} max statements per function
+ maxdepth : false, // {int} max nested block depth per function
+ maxparams : false, // {int} max params per function
+ maxcomplexity: false, // {int} max cyclomatic complexity per function
+ shadow : false, // if variable shadowing should be tolerated
+ // "inner" - check for variables defined in the same scope only
+ // "outer" - check for variables defined in outer scopes as well
+ // false - same as inner
+ // true - allow variable shadowing
+ unused : true, // warn if variables are unused. Available options:
+ // false - don't check for unused variables
+ // true - "vars" + check last function param
+ // "vars" - skip checking unused function params
+ // "strict" - "vars" + check all function params
+ latedef : false, // warn if the variable is used before its definition
+ // false - don't emit any warnings
+ // true - warn if any variable is used before its definition
+ // "nofunc" - warn for any variable but function declarations
+ ignore : false // start/end ignoring lines of code, bypassing the lexer
+ // start - start ignoring lines, including the current line
+ // end - stop ignoring lines, starting on the next line
+ // line - ignore warnings / errors for just a single line
+ // (this option does not bypass the lexer)
+ },
+
+ // These are JSHint boolean options which are shared with JSLint
+ // where the definition in JSHint is opposite JSLint
+ invertedOptions = {
+ bitwise : true,
+ forin : true,
+ newcap : true,
+ plusplus: true,
+ regexp : true,
+ undef : true,
+
+ // Inverted and renamed, use JSHint name here
+ eqeqeq : true,
+ strict : true
+ },
+
+ // These are JSHint boolean options which are shared with JSLint
+ // where the name has been changed but the effect is unchanged
+ renamedOptions = {
+ eqeq : "eqeqeq",
+ windows: "wsh",
+ sloppy : "strict"
+ },
+
+ removedOptions = {
+ nomen: true,
+ onevar: true,
+ passfail: true,
+ white: true,
+ gcl: true,
+ smarttabs: true,
+ trailing: true
+ },
+
+ declared, // Globals that were declared using /*global ... */ syntax.
+ exported, // Variables that are used outside of the current file.
+
+ functionicity = [
+ "closure", "exception", "global", "label",
+ "outer", "unused", "var"
+ ],
+
+ funct, // The current function
+ functions, // All of the functions
+
+ global, // The global scope
+ implied, // Implied globals
+ inblock,
+ indent,
+ lookahead,
+ lex,
+ member,
+ membersOnly,
+ noreach,
+ predefined, // Global variables defined by option
+
+ scope, // The current scope
+ stack,
+ unuseds,
+ urls,
+
+ extraModules = [],
+ emitter = new events.EventEmitter();
+
+ function checkOption(name, t) {
+ name = name.trim();
+
+ if (/^[+-]W\d{3}$/g.test(name)) {
+ return true;
+ }
+
+ if (valOptions[name] === undefined && boolOptions[name] === undefined) {
+ if (t.type !== "jslint" && !removedOptions[name]) {
+ error("E001", t, name);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function isString(obj) {
+ return Object.prototype.toString.call(obj) === "[object String]";
+ }
+
+ function isIdentifier(tkn, value) {
+ if (!tkn)
+ return false;
+
+ if (!tkn.identifier || tkn.value !== value)
+ return false;
+
+ return true;
+ }
+
+ function isReserved(token) {
+ if (!token.reserved) {
+ return false;
+ }
+ var meta = token.meta;
+
+ if (meta && meta.isFutureReservedWord && state.option.inES5()) {
+ // ES3 FutureReservedWord in an ES5 environment.
+ if (!meta.es5) {
+ return false;
+ }
+
+ // Some ES5 FutureReservedWord identifiers are active only
+ // within a strict mode environment.
+ if (meta.strictOnly) {
+ if (!state.option.strict && !state.directive["use strict"]) {
+ return false;
+ }
+ }
+
+ if (token.isProperty) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function supplant(str, data) {
+ return str.replace(/\{([^{}]*)\}/g, function (a, b) {
+ var r = data[b];
+ return typeof r === "string" || typeof r === "number" ? r : a;
+ });
+ }
+
+ function combine(dest, src) {
+ Object.keys(src).forEach(function (name) {
+ if (JSHINT.blacklist.hasOwnProperty(name)) return;
+ dest[name] = src[name];
+ });
+ }
+
+ function assume() {
+ if (state.option.es5) {
+ warning("I003");
+ }
+
+ if (state.option.esnext) {
+ combine(predefined, vars.newEcmaIdentifiers);
+ }
+
+ if (state.option.couch) {
+ combine(predefined, vars.couch);
+ }
+
+ if (state.option.qunit) {
+ combine(predefined, vars.qunit);
+ }
+
+ if (state.option.rhino) {
+ combine(predefined, vars.rhino);
+ }
+
+ if (state.option.shelljs) {
+ combine(predefined, vars.shelljs);
+ combine(predefined, vars.node);
+ }
+ if (state.option.typed) {
+ combine(predefined, vars.typed);
+ }
+
+ if (state.option.phantom) {
+ combine(predefined, vars.phantom);
+ }
+
+ if (state.option.prototypejs) {
+ combine(predefined, vars.prototypejs);
+ }
+
+ if (state.option.node) {
+ combine(predefined, vars.node);
+ combine(predefined, vars.typed);
+ }
+
+ if (state.option.devel) {
+ combine(predefined, vars.devel);
+ }
+
+ if (state.option.dojo) {
+ combine(predefined, vars.dojo);
+ }
+
+ if (state.option.browser) {
+ combine(predefined, vars.browser);
+ combine(predefined, vars.typed);
+ }
+
+ if (state.option.nonstandard) {
+ combine(predefined, vars.nonstandard);
+ }
+
+ if (state.option.jasmine) {
+ combine(predefined, vars.jasmine);
+ }
+
+ if (state.option.jquery) {
+ combine(predefined, vars.jquery);
+ }
+
+ if (state.option.mootools) {
+ combine(predefined, vars.mootools);
+ }
+
+ if (state.option.worker) {
+ combine(predefined, vars.worker);
+ }
+
+ if (state.option.wsh) {
+ combine(predefined, vars.wsh);
+ }
+
+ if (state.option.globalstrict && state.option.strict !== false) {
+ state.option.strict = true;
+ }
+
+ if (state.option.yui) {
+ combine(predefined, vars.yui);
+ }
+
+ if (state.option.mocha) {
+ combine(predefined, vars.mocha);
+ }
+
+ // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
+
+ state.option.inMoz = function (strict) {
+ if (strict) {
+ return state.option.moz && !state.option.esnext;
+ }
+ return state.option.moz;
+ };
+
+ state.option.inESNext = function (strict) {
+ if (strict) {
+ return !state.option.moz && state.option.esnext;
+ }
+ return state.option.moz || state.option.esnext;
+ };
+
+ state.option.inES5 = function (/* strict */) {
+ return !state.option.es3;
+ };
+
+ state.option.inES3 = function (strict) {
+ if (strict) {
+ return !state.option.moz && !state.option.esnext && state.option.es3;
+ }
+ return state.option.es3;
+ };
+ }
+
+ // Produce an error warning.
+ function quit(code, line, chr) {
+ var percentage = Math.floor((line / state.lines.length) * 100);
+ var message = messages.errors[code].desc;
+
+ throw {
+ name: "JSHintError",
+ line: line,
+ character: chr,
+ message: message + " (" + percentage + "% scanned).",
+ raw: message,
+ code: code
+ };
+ }
+
+ function isundef(scope, code, token, a) {
+ return JSHINT.undefs.push([scope, code, token, a]);
+ }
+
+ function removeIgnoredMessages() {
+ var ignored = state.ignoredLines;
+
+ if (_.isEmpty(ignored)) return;
+ JSHINT.errors = _.reject(JSHINT.errors, function (err) { return ignored[err.line] });
+ }
+
+ function warning(code, t, a, b, c, d) {
+ var ch, l, w, msg;
+
+ if (/^W\d{3}$/.test(code)) {
+ if (state.ignored[code])
+ return;
+
+ msg = messages.warnings[code];
+ } else if (/E\d{3}/.test(code)) {
+ msg = messages.errors[code];
+ } else if (/I\d{3}/.test(code)) {
+ msg = messages.info[code];
+ }
+
+ t = t || state.tokens.next;
+ if (t.id === "(end)") { // `~
+ t = state.tokens.curr;
+ }
+
+ l = t.line || 0;
+ ch = t.from || 0;
+
+ w = {
+ id: "(error)",
+ raw: msg.desc,
+ code: msg.code,
+ evidence: state.lines[l - 1] || "",
+ line: l,
+ character: ch,
+ scope: JSHINT.scope,
+ a: a,
+ b: b,
+ c: c,
+ d: d
+ };
+
+ w.reason = supplant(msg.desc, w);
+ JSHINT.errors.push(w);
+
+ removeIgnoredMessages();
+
+ if (JSHINT.errors.length >= state.option.maxerr)
+ quit("E043", l, ch);
+
+ return w;
+ }
+
+ function warningAt(m, l, ch, a, b, c, d) {
+ return warning(m, {
+ line: l,
+ from: ch
+ }, a, b, c, d);
+ }
+
+ function error(m, t, a, b, c, d) {
+ warning(m, t, a, b, c, d);
+ }
+
+ function errorAt(m, l, ch, a, b, c, d) {
+ return error(m, {
+ line: l,
+ from: ch
+ }, a, b, c, d);
+ }
+
+ // Tracking of "internal" scripts, like eval containing a static string
+ function addInternalSrc(elem, src) {
+ var i;
+ i = {
+ id: "(internal)",
+ elem: elem,
+ value: src
+ };
+ JSHINT.internals.push(i);
+ return i;
+ }
+
+ // name: string
+ // opts: { type: string, token: token, islet: bool }
+ function addlabel(name, opts) {
+ opts = opts || {};
+
+ var type = opts.type;
+ var token = opts.token;
+ var islet = opts.islet;
+
+ // Define label in the current function in the current scope.
+ if (type === "exception") {
+ if (_.has(funct["(context)"], name)) {
+ if (funct[name] !== true && !state.option.node) {
+ warning("W002", state.tokens.next, name);
+ }
+ }
+ }
+
+ if (_.has(funct, name) && !funct["(global)"]) {
+ if (funct[name] === true) {
+ if (state.option.latedef) {
+ if ((state.option.latedef === true && _.contains([funct[name], type], "unction")) ||
+ !_.contains([funct[name], type], "unction")) {
+ warning("W003", state.tokens.next, name);
+ }
+ }
+ } else {
+ if ((!state.option.shadow || _.contains([ "inner", "outer" ], state.option.shadow)) &&
+ type !== "exception" || funct["(blockscope)"].getlabel(name)) {
+ warning("W004", state.tokens.next, name);
+ }
+ }
+ }
+
+ if (funct["(context)"] && _.has(funct["(context)"], name) && type !== "function") {
+ if (state.option.shadow === "outer") {
+ warning("W123", state.tokens.next, name);
+ }
+ }
+
+ // if the identifier is from a let, adds it only to the current blockscope
+ if (islet) {
+ funct["(blockscope)"].current.add(name, type, state.tokens.curr);
+ } else {
+ funct["(blockscope)"].shadow(name);
+ funct[name] = type;
+
+ if (token) {
+ funct["(tokens)"][name] = token;
+ }
+
+ setprop(funct, name, { unused: opts.unused || false });
+
+ if (funct["(global)"]) {
+ global[name] = funct;
+ if (_.has(implied, name)) {
+ if (state.option.latedef) {
+ if ((state.option.latedef === true && _.contains([funct[name], type], "unction")) ||
+ !_.contains([funct[name], type], "unction")) {
+ warning("W003", state.tokens.next, name);
+ }
+ }
+
+ delete implied[name];
+ }
+ } else {
+ scope[name] = funct;
+ }
+ }
+ }
+
+ function doOption() {
+ var nt = state.tokens.next;
+ var body = nt.body.split(",").map(function (s) { return s.trim(); });
+ var predef = {};
+
+ if (nt.type === "globals") {
+ body.forEach(function (g) {
+ g = g.split(":");
+ var key = (g[0] || "").trim();
+ var val = (g[1] || "").trim();
+
+ if (key.charAt(0) === "-") {
+ key = key.slice(1);
+ val = false;
+
+ JSHINT.blacklist[key] = key;
+ delete predefined[key];
+ } else {
+ predef[key] = (val === "true");
+ }
+ });
+
+ combine(predefined, predef);
+
+ for (var key in predef) {
+ if (_.has(predef, key)) {
+ declared[key] = nt;
+ }
+ }
+ }
+
+ if (nt.type === "exported") {
+ body.forEach(function (e) {
+ exported[e] = true;
+ });
+ }
+
+ if (nt.type === "members") {
+ membersOnly = membersOnly || {};
+
+ body.forEach(function (m) {
+ var ch1 = m.charAt(0);
+ var ch2 = m.charAt(m.length - 1);
+
+ if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
+ m = m
+ .substr(1, m.length - 2)
+ .replace("\\\"", "\"");
+ }
+
+ membersOnly[m] = false;
+ });
+ }
+
+ var numvals = [
+ "maxstatements",
+ "maxparams",
+ "maxdepth",
+ "maxcomplexity",
+ "maxerr",
+ "maxlen",
+ "indent"
+ ];
+
+ if (nt.type === "jshint" || nt.type === "jslint") {
+ body.forEach(function (g) {
+ g = g.split(":");
+ var key = (g[0] || "").trim();
+ var val = (g[1] || "").trim();
+
+ if (!checkOption(key, nt)) {
+ return;
+ }
+
+ if (numvals.indexOf(key) >= 0) {
+ // GH988 - numeric options can be disabled by setting them to `false`
+ if (val !== "false") {
+ val = +val;
+
+ if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
+ error("E032", nt, g[1].trim());
+ return;
+ }
+
+ state.option[key] = val;
+ } else {
+ state.option[key] = key === "indent" ? 4 : false;
+ }
+
+ return;
+ }
+
+ if (key === "validthis") {
+ // `validthis` is valid only within a function scope.
+
+ if (funct["(global)"])
+ return void error("E009");
+
+ if (val !== "true" && val !== "false")
+ return void error("E002", nt);
+
+ state.option.validthis = (val === "true");
+ return;
+ }
+
+ if (key === "quotmark") {
+ switch (val) {
+ case "true":
+ case "false":
+ state.option.quotmark = (val === "true");
+ break;
+ case "double":
+ case "single":
+ state.option.quotmark = val;
+ break;
+ default:
+ error("E002", nt);
+ }
+ return;
+ }
+
+ if (key === "shadow") {
+ switch (val) {
+ case "true":
+ state.option.shadow = true;
+ break;
+ case "outer":
+ state.option.shadow = "outer";
+ break;
+ case "false":
+ case "inner":
+ state.option.shadow = "inner";
+ break;
+ default:
+ error("E002", nt);
+ }
+ return;
+ }
+
+ if (key === "unused") {
+ switch (val) {
+ case "true":
+ state.option.unused = true;
+ break;
+ case "false":
+ state.option.unused = false;
+ break;
+ case "vars":
+ case "strict":
+ state.option.unused = val;
+ break;
+ default:
+ error("E002", nt);
+ }
+ return;
+ }
+
+ if (key === "latedef") {
+ switch (val) {
+ case "true":
+ state.option.latedef = true;
+ break;
+ case "false":
+ state.option.latedef = false;
+ break;
+ case "nofunc":
+ state.option.latedef = "nofunc";
+ break;
+ default:
+ error("E002", nt);
+ }
+ return;
+ }
+
+ if (key === "ignore") {
+ switch (val) {
+ case "start":
+ state.ignoreLinterErrors = true;
+ break;
+ case "end":
+ state.ignoreLinterErrors = false;
+ break;
+ case "line":
+ state.ignoredLines[nt.line] = true;
+ removeIgnoredMessages();
+ break;
+ default:
+ error("E002", nt);
+ }
+ return;
+ }
+
+ var match = /^([+-])(W\d{3})$/g.exec(key);
+ if (match) {
+ // ignore for -W..., unignore for +W...
+ state.ignored[match[2]] = (match[1] === "-");
+ return;
+ }
+
+ var tn;
+ if (val === "true" || val === "false") {
+ if (nt.type === "jslint") {
+ tn = renamedOptions[key] || key;
+ state.option[tn] = (val === "true");
+
+ if (invertedOptions[tn] !== undefined) {
+ state.option[tn] = !state.option[tn];
+ }
+ } else {
+ state.option[key] = (val === "true");
+ }
+
+ if (key === "newcap") {
+ state.option["(explicitNewcap)"] = true;
+ }
+ return;
+ }
+
+ error("E002", nt);
+ });
+
+ assume();
+ }
+ }
+
+ // We need a peek function. If it has an argument, it peeks that much farther
+ // ahead. It is used to distinguish
+ // for ( var i in ...
+ // from
+ // for ( var i = ...
+
+ function peek(p) {
+ var i = p || 0, j = 0, t;
+
+ while (j <= i) {
+ t = lookahead[j];
+ if (!t) {
+ t = lookahead[j] = lex.token();
+ }
+ j += 1;
+ }
+ return t;
+ }
+
+ // Produce the next token. It looks for programming errors.
+
+ function advance(id, t) {
+ switch (state.tokens.curr.id) {
+ case "(number)":
+ if (state.tokens.next.id === ".") {
+ warning("W005", state.tokens.curr);
+ }
+ break;
+ case "-":
+ if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
+ warning("W006");
+ }
+ break;
+ case "+":
+ if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
+ warning("W007");
+ }
+ break;
+ }
+
+ if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
+ anonname = state.tokens.curr.value;
+ }
+
+ if (id && state.tokens.next.id !== id) {
+ if (t) {
+ if (state.tokens.next.id === "(end)") {
+ error("E019", t, t.id);
+ } else {
+ error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
+ }
+ } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
+ warning("W116", state.tokens.next, id, state.tokens.next.value);
+ }
+ }
+
+ state.tokens.prev = state.tokens.curr;
+ state.tokens.curr = state.tokens.next;
+ for (;;) {
+ state.tokens.next = lookahead.shift() || lex.token();
+
+ if (!state.tokens.next) { // No more tokens left, give up
+ quit("E041", state.tokens.curr.line);
+ }
+
+ if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
+ return;
+ }
+
+ if (state.tokens.next.check) {
+ state.tokens.next.check();
+ }
+
+ if (state.tokens.next.isSpecial) {
+ doOption();
+ } else {
+ if (state.tokens.next.id !== "(endline)") {
+ break;
+ }
+ }
+ }
+ }
+
+ function isInfix(token) {
+ return token.infix || (!token.identifier && !!token.led);
+ }
+
+ function isEndOfExpr() {
+ var curr = state.tokens.curr;
+ var next = state.tokens.next;
+ if (next.id === ";" || next.id === "}" || next.id === ":") {
+ return true;
+ }
+ if (isInfix(next) === isInfix(curr) || (curr.id === "yield" && state.option.inMoz(true))) {
+ return curr.line !== next.line;
+ }
+ return false;
+ }
+
+ // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
+ // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
+ // like .nud except that it is only used on the first token of a statement.
+ // Having .fud makes it much easier to define statement-oriented languages like
+ // JavaScript. I retained Pratt's nomenclature.
+
+ // .nud Null denotation
+ // .fud First null denotation
+ // .led Left denotation
+ // lbp Left binding power
+ // rbp Right binding power
+
+ // They are elements of the parsing method called Top Down Operator Precedence.
+
+ function expression(rbp, initial) {
+ var left, isArray = false, isObject = false, isLetExpr = false;
+
+ // if current expression is a let expression
+ if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.next, "let expressions");
+ }
+ isLetExpr = true;
+ // create a new block scope we use only for the current expression
+ funct["(blockscope)"].stack();
+ advance("let");
+ advance("(");
+ state.syntax["let"].fud.call(state.syntax["let"].fud, false);
+ advance(")");
+ }
+
+ if (state.tokens.next.id === "(end)")
+ error("E006", state.tokens.curr);
+
+ var isDangerous =
+ state.option.asi &&
+ state.tokens.prev.line < state.tokens.curr.line &&
+ _.contains(["]", ")"], state.tokens.prev.id) &&
+ _.contains(["[", "("], state.tokens.curr.id);
+
+ if (isDangerous)
+ warning("W014", state.tokens.curr, state.tokens.curr.id);
+
+ advance();
+
+ if (initial) {
+ anonname = "anonymous";
+ funct["(verb)"] = state.tokens.curr.value;
+ }
+
+ if (initial === true && state.tokens.curr.fud) {
+ left = state.tokens.curr.fud();
+ } else {
+ if (state.tokens.curr.nud) {
+ left = state.tokens.curr.nud();
+ } else {
+ error("E030", state.tokens.curr, state.tokens.curr.id);
+ }
+
+ while (rbp < state.tokens.next.lbp && !isEndOfExpr()) {
+ isArray = state.tokens.curr.value === "Array";
+ isObject = state.tokens.curr.value === "Object";
+
+ // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
+ // Line breaks in IfStatement heads exist to satisfy the checkJSHint
+ // "Line too long." error.
+ if (left && (left.value || (left.first && left.first.value))) {
+ // If the left.value is not "new", or the left.first.value is a "."
+ // then safely assume that this is not "new Array()" and possibly
+ // not "new Object()"...
+ if (left.value !== "new" ||
+ (left.first && left.first.value && left.first.value === ".")) {
+ isArray = false;
+ // ...In the case of Object, if the left.value and state.tokens.curr.value
+ // are not equal, then safely assume that this not "new Object()"
+ if (left.value !== state.tokens.curr.value) {
+ isObject = false;
+ }
+ }
+ }
+
+ advance();
+
+ if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+ warning("W009", state.tokens.curr);
+ }
+
+ if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+ warning("W010", state.tokens.curr);
+ }
+
+ if (left && state.tokens.curr.led) {
+ left = state.tokens.curr.led(left);
+ } else {
+ error("E033", state.tokens.curr, state.tokens.curr.id);
+ }
+ }
+ }
+ if (isLetExpr) {
+ funct["(blockscope)"].unstack();
+ }
+ return left;
+ }
+
+
+ // Functions for conformance of style.
+
+ function nobreaknonadjacent(left, right) {
+ left = left || state.tokens.curr;
+ right = right || state.tokens.next;
+ if (!state.option.laxbreak && left.line !== right.line) {
+ warning("W014", right, right.value);
+ }
+ }
+
+ function nolinebreak(t) {
+ t = t || state.tokens.curr;
+ if (t.line !== state.tokens.next.line) {
+ warning("E022", t, t.value);
+ }
+ }
+
+ function nobreakcomma(left, right) {
+ if (left.line !== right.line) {
+ if (!state.option.laxcomma) {
+ if (comma.first) {
+ warning("I001");
+ comma.first = false;
+ }
+ warning("W014", left, right.value);
+ }
+ }
+ }
+
+ function comma(opts) {
+ opts = opts || {};
+
+ if (!opts.peek) {
+ nobreakcomma(state.tokens.curr, state.tokens.next);
+ advance(",");
+ } else {
+ nobreakcomma(state.tokens.prev, state.tokens.curr);
+ }
+
+ if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {
+ // Keywords that cannot follow a comma operator.
+ switch (state.tokens.next.value) {
+ case "break":
+ case "case":
+ case "catch":
+ case "continue":
+ case "default":
+ case "do":
+ case "else":
+ case "finally":
+ case "for":
+ case "if":
+ case "in":
+ case "instanceof":
+ case "return":
+ case "switch":
+ case "throw":
+ case "try":
+ case "var":
+ case "let":
+ case "while":
+ case "with":
+ error("E024", state.tokens.next, state.tokens.next.value);
+ return false;
+ }
+ }
+
+ if (state.tokens.next.type === "(punctuator)") {
+ switch (state.tokens.next.value) {
+ case "}":
+ case "]":
+ case ",":
+ if (opts.allowTrailing) {
+ return true;
+ }
+
+ /* falls through */
+ case ")":
+ error("E024", state.tokens.next, state.tokens.next.value);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Functional constructors for making the symbols that will be inherited by
+ // tokens.
+
+ function symbol(s, p) {
+ var x = state.syntax[s];
+ if (!x || typeof x !== "object") {
+ state.syntax[s] = x = {
+ id: s,
+ lbp: p,
+ value: s
+ };
+ }
+ return x;
+ }
+
+ function delim(s) {
+ return symbol(s, 0);
+ }
+
+ function stmt(s, f) {
+ var x = delim(s);
+ x.identifier = x.reserved = true;
+ x.fud = f;
+ return x;
+ }
+
+ function blockstmt(s, f) {
+ var x = stmt(s, f);
+ x.block = true;
+ return x;
+ }
+
+ function reserveName(x) {
+ var c = x.id.charAt(0);
+ if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
+ x.identifier = x.reserved = true;
+ }
+ return x;
+ }
+
+ function prefix(s, f) {
+ var x = symbol(s, 150);
+ reserveName(x);
+
+ x.nud = (typeof f === "function") ? f : function () {
+ this.right = expression(150);
+ this.arity = "unary";
+
+ if (this.id === "++" || this.id === "--") {
+ if (state.option.plusplus) {
+ warning("W016", this, this.id);
+ } else if (this.right && (!this.right.identifier || isReserved(this.right)) &&
+ this.right.id !== "." && this.right.id !== "[") {
+ warning("W017", this);
+ }
+ }
+
+ return this;
+ };
+
+ return x;
+ }
+
+ function type(s, f) {
+ var x = delim(s);
+ x.type = s;
+ x.nud = f;
+ return x;
+ }
+
+ function reserve(name, func) {
+ var x = type(name, func);
+ x.identifier = true;
+ x.reserved = true;
+ return x;
+ }
+
+ function FutureReservedWord(name, meta) {
+ var x = type(name, (meta && meta.nud) || function () {
+ return this;
+ });
+
+ meta = meta || {};
+ meta.isFutureReservedWord = true;
+
+ x.value = name;
+ x.identifier = true;
+ x.reserved = true;
+ x.meta = meta;
+
+ return x;
+ }
+
+ function reservevar(s, v) {
+ return reserve(s, function () {
+ if (typeof v === "function") {
+ v(this);
+ }
+ return this;
+ });
+ }
+
+ function infix(s, f, p, w) {
+ var x = symbol(s, p);
+ reserveName(x);
+ x.infix = true;
+ x.led = function (left) {
+ if (!w) {
+ nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+ }
+ if (s === "in" && left.id === "!") {
+ warning("W018", left, "!");
+ }
+ if (typeof f === "function") {
+ return f(left, this);
+ } else {
+ this.left = left;
+ this.right = expression(p);
+ return this;
+ }
+ };
+ return x;
+ }
+
+
+ function application(s) {
+ var x = symbol(s, 42);
+
+ x.led = function (left) {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "arrow function syntax (=>)");
+ }
+
+ nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+
+ this.left = left;
+ this.right = doFunction(undefined, undefined, false, left);
+ return this;
+ };
+ return x;
+ }
+
+ function relation(s, f) {
+ var x = symbol(s, 100);
+
+ x.led = function (left) {
+ nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+ var right = expression(100);
+
+ if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
+ warning("W019", this);
+ } else if (f) {
+ f.apply(this, [left, right]);
+ }
+
+ if (!left || !right) {
+ quit("E041", state.tokens.curr.line);
+ }
+
+ if (left.id === "!") {
+ warning("W018", left, "!");
+ }
+
+ if (right.id === "!") {
+ warning("W018", right, "!");
+ }
+
+ this.left = left;
+ this.right = right;
+ return this;
+ };
+ return x;
+ }
+
+ function isPoorRelation(node) {
+ return node &&
+ ((node.type === "(number)" && +node.value === 0) ||
+ (node.type === "(string)" && node.value === "") ||
+ (node.type === "null" && !state.option.eqnull) ||
+ node.type === "true" ||
+ node.type === "false" ||
+ node.type === "undefined");
+ }
+
+ // Checks whether the 'typeof' operator is used with the correct
+ // value. For docs on 'typeof' see:
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
+
+ function isTypoTypeof(left, right) {
+ if (state.option.notypeof)
+ return false;
+
+ if (!left || !right)
+ return false;
+
+ var values = [
+ "undefined", "object", "boolean", "number",
+ "string", "function", "xml", "object", "unknown"
+ ];
+
+ if (right.type === "(identifier)" && right.value === "typeof" && left.type === "(string)")
+ return !_.contains(values, left.value);
+
+ return false;
+ }
+
+ function findNativePrototype(left) {
+ var natives = [
+ "Array", "ArrayBuffer", "Boolean", "Collator", "DataView", "Date",
+ "DateTimeFormat", "Error", "EvalError", "Float32Array", "Float64Array",
+ "Function", "Infinity", "Intl", "Int16Array", "Int32Array", "Int8Array",
+ "Iterator", "Number", "NumberFormat", "Object", "RangeError",
+ "ReferenceError", "RegExp", "StopIteration", "String", "SyntaxError",
+ "TypeError", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray",
+ "URIError"
+ ];
+
+ function walkPrototype(obj) {
+ if (typeof obj !== "object") return;
+ return obj.right === "prototype" ? obj : walkPrototype(obj.left);
+ }
+
+ function walkNative(obj) {
+ while (!obj.identifier && typeof obj.left === "object")
+ obj = obj.left;
+
+ if (obj.identifier && natives.indexOf(obj.value) >= 0)
+ return obj.value;
+ }
+
+ var prototype = walkPrototype(left);
+ if (prototype) return walkNative(prototype);
+ }
+
+ function assignop(s, f, p) {
+ var x = infix(s, typeof f === "function" ? f : function (left, that) {
+ that.left = left;
+
+ if (left) {
+ if (state.option.freeze) {
+ var nativeObject = findNativePrototype(left);
+ if (nativeObject)
+ warning("W121", left, nativeObject);
+ }
+
+ if (predefined[left.value] === false &&
+ scope[left.value]["(global)"] === true) {
+ warning("W020", left);
+ } else if (left["function"]) {
+ warning("W021", left, left.value);
+ }
+
+ if (funct[left.value] === "const") {
+ error("E013", left, left.value);
+ }
+
+ if (left.id === ".") {
+ if (!left.left) {
+ warning("E031", that);
+ } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
+ warning("E031", that);
+ }
+
+ that.right = expression(10);
+ return that;
+ } else if (left.id === "[") {
+ if (state.tokens.curr.left.first) {
+ state.tokens.curr.left.first.forEach(function (t) {
+ if (t && funct[t.value] === "const") {
+ error("E013", t, t.value);
+ }
+ });
+ } else if (!left.left) {
+ warning("E031", that);
+ } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
+ warning("E031", that);
+ }
+ that.right = expression(10);
+ return that;
+ } else if (left.identifier && !isReserved(left)) {
+ if (funct[left.value] === "exception") {
+ warning("W022", left);
+ }
+ that.right = expression(10);
+ return that;
+ }
+
+ if (left === state.syntax["function"]) {
+ warning("W023", state.tokens.curr);
+ }
+ }
+
+ error("E031", that);
+ }, p);
+
+ x.exps = true;
+ x.assign = true;
+ return x;
+ }
+
+
+ function bitwise(s, f, p) {
+ var x = symbol(s, p);
+ reserveName(x);
+ x.led = (typeof f === "function") ? f : function (left) {
+ if (state.option.bitwise) {
+ warning("W016", this, this.id);
+ }
+ this.left = left;
+ this.right = expression(p);
+ return this;
+ };
+ return x;
+ }
+
+
+ function bitwiseassignop(s) {
+ return assignop(s, function (left, that) {
+ if (state.option.bitwise) {
+ warning("W016", that, that.id);
+ }
+
+ if (left) {
+ if (left.id === "." || left.id === "[" ||
+ (left.identifier && !isReserved(left))) {
+ expression(10);
+ return that;
+ }
+ if (left === state.syntax["function"]) {
+ warning("W023", state.tokens.curr);
+ }
+ return that;
+ }
+ error("E031", that);
+ }, 20);
+ }
+
+
+ function suffix(s) {
+ var x = symbol(s, 150);
+
+ x.led = function (left) {
+ if (state.option.plusplus) {
+ warning("W016", this, this.id);
+ } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
+ warning("W017", this);
+ }
+
+ this.left = left;
+ return this;
+ };
+ return x;
+ }
+
+ // fnparam means that this identifier is being defined as a function
+ // argument (see identifier())
+ // prop means that this identifier is that of an object property
+
+ function optionalidentifier(fnparam, prop) {
+ if (!state.tokens.next.identifier) {
+ return;
+ }
+
+ advance();
+
+ var curr = state.tokens.curr;
+ var val = state.tokens.curr.value;
+
+ if (!isReserved(curr)) {
+ return val;
+ }
+
+ if (prop) {
+ if (state.option.inES5()) {
+ return val;
+ }
+ }
+
+ if (fnparam && val === "undefined") {
+ return val;
+ }
+
+ warning("W024", state.tokens.curr, state.tokens.curr.id);
+ return val;
+ }
+
+ // fnparam means that this identifier is being defined as a function
+ // argument
+ // prop means that this identifier is that of an object property
+ function identifier(fnparam, prop) {
+ var i = optionalidentifier(fnparam, prop);
+ if (i) {
+ return i;
+ }
+ if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
+ warning("W025");
+ } else {
+ error("E030", state.tokens.next, state.tokens.next.value);
+ }
+ }
+
+
+ function reachable(s) {
+ var i = 0, t;
+ if (state.tokens.next.id !== ";" || noreach) {
+ return;
+ }
+ for (;;) {
+ do {
+ t = peek(i);
+ i += 1;
+ } while (t.id != "(end)" && t.id === "(comment)");
+
+ if (t.reach) {
+ return;
+ }
+ if (t.id !== "(endline)") {
+ if (t.id === "function") {
+ if (state.option.latedef === true) {
+ warning("W026", t);
+ }
+ break;
+ }
+
+ warning("W027", t, t.value, s);
+ break;
+ }
+ }
+ }
+
+ function parseFinalSemicolon() {
+ if (state.tokens.next.id !== ";") {
+ if (!state.option.asi) {
+ // If this is the last statement in a block that ends on
+ // the same line *and* option lastsemic is on, ignore the warning.
+ // Otherwise, complain about missing semicolon.
+ if (!state.option.lastsemic || state.tokens.next.id !== "}" ||
+ state.tokens.next.line !== state.tokens.curr.line) {
+ warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
+ }
+ }
+ } else {
+ advance(";");
+ }
+ }
+
+ function statement() {
+ var values;
+ var i = indent, r, s = scope, t = state.tokens.next;
+
+ if (t.id === ";") {
+ advance(";");
+ return;
+ }
+
+ // Is this a labelled statement?
+ var res = isReserved(t);
+
+ // We're being more tolerant here: if someone uses
+ // a FutureReservedWord as a label, we warn but proceed
+ // anyway.
+
+ if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
+ warning("W024", t, t.id);
+ res = false;
+ }
+
+ // detect a module import declaration
+ if (t.value === "module" && t.type === "(identifier)") {
+ if (peek().type === "(identifier)") {
+ if (!state.option.inESNext()) {
+ warning("W119", state.tokens.curr, "module");
+ }
+
+ advance("module");
+ var name = identifier();
+ addlabel(name, { type: "unused", token: state.tokens.curr });
+ advance("from");
+ advance("(string)");
+ parseFinalSemicolon();
+ return;
+ }
+ }
+
+ // detect a destructuring assignment
+ if (_.has(["[", "{"], t.value)) {
+ if (lookupBlockType().isDestAssign) {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "destructuring expression");
+ }
+ values = destructuringExpression();
+ values.forEach(function (tok) {
+ isundef(funct, "W117", tok.token, tok.id);
+ });
+ advance("=");
+ destructuringExpressionMatch(values, expression(10, true));
+ advance(";");
+ return;
+ }
+ }
+ if (t.identifier && !res && peek().id === ":") {
+ advance();
+ advance(":");
+ scope = Object.create(s);
+ addlabel(t.value, { type: "label" });
+
+ if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
+ warning("W028", state.tokens.next, t.value, state.tokens.next.value);
+ }
+
+ state.tokens.next.label = t.value;
+ t = state.tokens.next;
+ }
+
+ // Is it a lonely block?
+
+ if (t.id === "{") {
+ // Is it a switch case block?
+ //
+ // switch (foo) {
+ // case bar: { <= here.
+ // ...
+ // }
+ // }
+ var iscase = (funct["(verb)"] === "case" && state.tokens.curr.value === ":");
+ block(true, true, false, false, iscase);
+ return;
+ }
+
+ // Parse the statement.
+
+ r = expression(0, true);
+
+ if (r && (!r.identifier || r.value !== "function") && (r.type !== "(punctuator)")) {
+ if (!state.directive["use strict"] &&
+ state.option.globalstrict &&
+ state.option.strict) {
+ warning("E007");
+ }
+ }
+
+ // Look for the final semicolon.
+
+ if (!t.block) {
+ if (!state.option.expr && (!r || !r.exps)) {
+ warning("W030", state.tokens.curr);
+ } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
+ warning("W031", t);
+ }
+ parseFinalSemicolon();
+ }
+
+
+ // Restore the indentation.
+
+ indent = i;
+ scope = s;
+ return r;
+ }
+
+
+ function statements(startLine) {
+ var a = [], p;
+
+ while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
+ if (state.tokens.next.id === ";") {
+ p = peek();
+
+ if (!p || (p.id !== "(" && p.id !== "[")) {
+ warning("W032");
+ }
+
+ advance(";");
+ } else {
+ a.push(statement(startLine === state.tokens.next.line));
+ }
+ }
+ return a;
+ }
+
+
+ /*
+ * read all directives
+ * recognizes a simple form of asi, but always
+ * warns, if it is used
+ */
+ function directives() {
+ var i, p, pn;
+
+ for (;;) {
+ if (state.tokens.next.id === "(string)") {
+ p = peek(0);
+ if (p.id === "(endline)") {
+ i = 1;
+ do {
+ pn = peek(i);
+ i = i + 1;
+ } while (pn.id === "(endline)");
+
+ if (pn.id !== ";") {
+ if (pn.id !== "(string)" && pn.id !== "(number)" &&
+ pn.id !== "(regexp)" && pn.identifier !== true &&
+ pn.id !== "}") {
+ break;
+ }
+ warning("W033", state.tokens.next);
+ } else {
+ p = pn;
+ }
+ } else if (p.id === "}") {
+ // Directive with no other statements, warn about missing semicolon
+ warning("W033", p);
+ } else if (p.id !== ";") {
+ break;
+ }
+
+ advance();
+ if (state.directive[state.tokens.curr.value]) {
+ warning("W034", state.tokens.curr, state.tokens.curr.value);
+ }
+
+ if (state.tokens.curr.value === "use strict") {
+ if (!state.option["(explicitNewcap)"])
+ state.option.newcap = true;
+ state.option.undef = true;
+ }
+
+ // there's no directive negation, so always set to true
+ state.directive[state.tokens.curr.value] = true;
+
+ if (p.id === ";") {
+ advance(";");
+ }
+ continue;
+ }
+ break;
+ }
+ }
+
+
+ /*
+ * Parses a single block. A block is a sequence of statements wrapped in
+ * braces.
+ *
+ * ordinary - true for everything but function bodies and try blocks.
+ * stmt - true if block can be a single statement (e.g. in if/for/while).
+ * isfunc - true if block is a function body
+ * isfatarrow - true if its a body of a fat arrow function
+ * iscase - true if block is a switch case block
+ */
+ function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
+ var a,
+ b = inblock,
+ old_indent = indent,
+ m,
+ s = scope,
+ t,
+ line,
+ d;
+
+ inblock = ordinary;
+
+ if (!ordinary || !state.option.funcscope)
+ scope = Object.create(scope);
+
+ t = state.tokens.next;
+
+ var metrics = funct["(metrics)"];
+ metrics.nestedBlockDepth += 1;
+ metrics.verifyMaxNestedBlockDepthPerFunction();
+
+ if (state.tokens.next.id === "{") {
+ advance("{");
+
+ // create a new block scope
+ funct["(blockscope)"].stack();
+
+ line = state.tokens.curr.line;
+ if (state.tokens.next.id !== "}") {
+ indent += state.option.indent;
+ while (!ordinary && state.tokens.next.from > indent) {
+ indent += state.option.indent;
+ }
+
+ if (isfunc) {
+ m = {};
+ for (d in state.directive) {
+ if (_.has(state.directive, d)) {
+ m[d] = state.directive[d];
+ }
+ }
+ directives();
+
+ if (state.option.strict && funct["(context)"]["(global)"]) {
+ if (!m["use strict"] && !state.directive["use strict"]) {
+ warning("E007");
+ }
+ }
+ }
+
+ a = statements(line);
+
+ metrics.statementCount += a.length;
+
+ if (isfunc) {
+ state.directive = m;
+ }
+
+ indent -= state.option.indent;
+ }
+
+ advance("}", t);
+
+ funct["(blockscope)"].unstack();
+
+ indent = old_indent;
+ } else if (!ordinary) {
+ if (isfunc) {
+ m = {};
+ if (stmt && !isfatarrow && !state.option.inMoz(true)) {
+ error("W118", state.tokens.curr, "function closure expressions");
+ }
+
+ if (!stmt) {
+ for (d in state.directive) {
+ if (_.has(state.directive, d)) {
+ m[d] = state.directive[d];
+ }
+ }
+ }
+ expression(10);
+
+ if (state.option.strict && funct["(context)"]["(global)"]) {
+ if (!m["use strict"] && !state.directive["use strict"]) {
+ warning("E007");
+ }
+ }
+ } else {
+ error("E021", state.tokens.next, "{", state.tokens.next.value);
+ }
+ } else {
+
+ // check to avoid let declaration not within a block
+ funct["(nolet)"] = true;
+
+ if (!stmt || state.option.curly) {
+ warning("W116", state.tokens.next, "{", state.tokens.next.value);
+ }
+
+ noreach = true;
+ indent += state.option.indent;
+ // test indentation only if statement is in new line
+ a = [statement()];
+ indent -= state.option.indent;
+ noreach = false;
+
+ delete funct["(nolet)"];
+ }
+
+ // Don't clear and let it propagate out if it is "break", "return" or similar in switch case
+ switch (funct["(verb)"]) {
+ case "break":
+ case "continue":
+ case "return":
+ case "throw":
+ if (iscase) {
+ break;
+ }
+
+ /* falls through */
+ default:
+ funct["(verb)"] = null;
+ }
+
+ if (!ordinary || !state.option.funcscope) scope = s;
+ inblock = b;
+ if (ordinary && state.option.noempty && (!a || a.length === 0)) {
+ warning("W035");
+ }
+ metrics.nestedBlockDepth -= 1;
+ return a;
+ }
+
+
+ function countMember(m) {
+ if (membersOnly && typeof membersOnly[m] !== "boolean") {
+ warning("W036", state.tokens.curr, m);
+ }
+ if (typeof member[m] === "number") {
+ member[m] += 1;
+ } else {
+ member[m] = 1;
+ }
+ }
+
+
+ function note_implied(tkn) {
+ var name = tkn.value;
+ var desc = Object.getOwnPropertyDescriptor(implied, name);
+
+ if (!desc)
+ implied[name] = [tkn.line];
+ else
+ desc.value.push(tkn.line);
+ }
+
+
+ // Build the syntax table by declaring the syntactic elements of the language.
+
+ type("(number)", function () {
+ return this;
+ });
+
+ type("(string)", function () {
+ return this;
+ });
+
+ type("(template)", function () {
+ return this;
+ });
+
+ state.syntax["(identifier)"] = {
+ type: "(identifier)",
+ lbp: 0,
+ identifier: true,
+
+ nud: function () {
+ var v = this.value;
+ var s = scope[v];
+ var f;
+ var block;
+
+ if (typeof s === "function") {
+ // Protection against accidental inheritance.
+ s = undefined;
+ } else if (!funct["(blockscope)"].current.has(v) && typeof s === "boolean") {
+ f = funct;
+ funct = functions[0];
+ addlabel(v, { type: "var" });
+ s = funct;
+ funct = f;
+ }
+
+ block = funct["(blockscope)"].getlabel(v);
+
+ // The name is in scope and defined in the current function.
+ if (funct === s || block) {
+ // Change 'unused' to 'var', and reject labels.
+ // the name is in a block scope.
+ switch (block ? block[v]["(type)"] : funct[v]) {
+ case "unused":
+ if (block) block[v]["(type)"] = "var";
+ else funct[v] = "var";
+ break;
+ case "unction":
+ if (block) block[v]["(type)"] = "function";
+ else funct[v] = "function";
+ this["function"] = true;
+ break;
+ case "const":
+ setprop(funct, v, { unused: false });
+ break;
+ case "function":
+ this["function"] = true;
+ break;
+ case "label":
+ warning("W037", state.tokens.curr, v);
+ break;
+ }
+ } else if (funct["(global)"]) {
+ // The name is not defined in the function. If we are in the global
+ // scope, then we have an undefined variable.
+ //
+ // Operators typeof and delete do not raise runtime errors even if
+ // the base object of a reference is null so no need to display warning
+ // if we're inside of typeof or delete.
+
+ if (typeof predefined[v] !== "boolean") {
+ // Attempting to subscript a null reference will throw an
+ // error, even within the typeof and delete operators
+ if (!(anonname === "typeof" || anonname === "delete") ||
+ (state.tokens.next && (state.tokens.next.value === "." ||
+ state.tokens.next.value === "["))) {
+
+ // if we're in a list comprehension, variables are declared
+ // locally and used before being defined. So we check
+ // the presence of the given variable in the comp array
+ // before declaring it undefined.
+
+ if (!funct["(comparray)"].check(v)) {
+ isundef(funct, "W117", state.tokens.curr, v);
+ }
+ }
+ }
+
+ note_implied(state.tokens.curr);
+ } else {
+ // If the name is already defined in the current
+ // function, but not as outer, then there is a scope error.
+
+ switch (funct[v]) {
+ case "closure":
+ case "function":
+ case "var":
+ case "unused":
+ warning("W038", state.tokens.curr, v);
+ break;
+ case "label":
+ warning("W037", state.tokens.curr, v);
+ break;
+ case "outer":
+ case "global":
+ break;
+ default:
+ // If the name is defined in an outer function, make an outer entry,
+ // and if it was unused, make it var.
+ if (s === true) {
+ funct[v] = true;
+ } else if (s === null) {
+ warning("W039", state.tokens.curr, v);
+ note_implied(state.tokens.curr);
+ } else if (typeof s !== "object") {
+ // Operators typeof and delete do not raise runtime errors even
+ // if the base object of a reference is null so no need to
+ //
+ // display warning if we're inside of typeof or delete.
+ // Attempting to subscript a null reference will throw an
+ // error, even within the typeof and delete operators
+ if (!(anonname === "typeof" || anonname === "delete") ||
+ (state.tokens.next &&
+ (state.tokens.next.value === "." || state.tokens.next.value === "["))) {
+
+ isundef(funct, "W117", state.tokens.curr, v);
+ }
+ funct[v] = true;
+ note_implied(state.tokens.curr);
+ } else {
+ switch (s[v]) {
+ case "function":
+ case "unction":
+ this["function"] = true;
+ s[v] = "closure";
+ funct[v] = s["(global)"] ? "global" : "outer";
+ break;
+ case "var":
+ case "unused":
+ s[v] = "closure";
+ funct[v] = s["(global)"] ? "global" : "outer";
+ break;
+ case "const":
+ setprop(s, v, { unused: false });
+ break;
+ case "closure":
+ funct[v] = s["(global)"] ? "global" : "outer";
+ break;
+ case "label":
+ warning("W037", state.tokens.curr, v);
+ }
+ }
+ }
+ }
+ return this;
+ },
+
+ led: function () {
+ error("E033", state.tokens.next, state.tokens.next.value);
+ }
+ };
+
+ type("(regexp)", function () {
+ return this;
+ });
+
+ // ECMAScript parser
+
+ delim("(endline)");
+ delim("(begin)");
+ delim("(end)").reach = true;
+ delim("(error)").reach = true;
+ delim("}").reach = true;
+ delim(")");
+ delim("]");
+ delim("\"").reach = true;
+ delim("'").reach = true;
+ delim(";");
+ delim(":").reach = true;
+ delim("#");
+
+ reserve("else");
+ reserve("case").reach = true;
+ reserve("catch");
+ reserve("default").reach = true;
+ reserve("finally");
+ reservevar("arguments", function (x) {
+ if (state.directive["use strict"] && funct["(global)"]) {
+ warning("E008", x);
+ }
+ });
+ reservevar("eval");
+ reservevar("false");
+ reservevar("Infinity");
+ reservevar("null");
+ reservevar("this", function (x) {
+ if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
+ funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
+ warning("W040", x);
+ }
+ });
+ reservevar("true");
+ reservevar("undefined");
+
+ assignop("=", "assign", 20);
+ assignop("+=", "assignadd", 20);
+ assignop("-=", "assignsub", 20);
+ assignop("*=", "assignmult", 20);
+ assignop("/=", "assigndiv", 20).nud = function () {
+ error("E014");
+ };
+ assignop("%=", "assignmod", 20);
+
+ bitwiseassignop("&=", "assignbitand", 20);
+ bitwiseassignop("|=", "assignbitor", 20);
+ bitwiseassignop("^=", "assignbitxor", 20);
+ bitwiseassignop("<<=", "assignshiftleft", 20);
+ bitwiseassignop(">>=", "assignshiftright", 20);
+ bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
+ infix(",", function (left, that) {
+ var expr;
+ that.exprs = [left];
+ if (!comma({peek: true})) {
+ return that;
+ }
+ while (true) {
+ if (!(expr = expression(10))) {
+ break;
+ }
+ that.exprs.push(expr);
+ if (state.tokens.next.value !== "," || !comma()) {
+ break;
+ }
+ }
+ return that;
+ }, 10, true);
+
+ infix("?", function (left, that) {
+ increaseComplexityCount();
+ that.left = left;
+ that.right = expression(10);
+ advance(":");
+ that["else"] = expression(10);
+ return that;
+ }, 30);
+
+ var orPrecendence = 40;
+ infix("||", function (left, that) {
+ increaseComplexityCount();
+ that.left = left;
+ that.right = expression(orPrecendence);
+ return that;
+ }, orPrecendence);
+ infix("&&", "and", 50);
+ bitwise("|", "bitor", 70);
+ bitwise("^", "bitxor", 80);
+ bitwise("&", "bitand", 90);
+ relation("==", function (left, right) {
+ var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
+
+ switch (true) {
+ case !eqnull && state.option.eqeqeq:
+ this.from = this.character;
+ warning("W116", this, "===", "==");
+ break;
+ case isPoorRelation(left):
+ warning("W041", this, "===", left.value);
+ break;
+ case isPoorRelation(right):
+ warning("W041", this, "===", right.value);
+ break;
+ case isTypoTypeof(right, left):
+ warning("W122", this, right.value);
+ break;
+ case isTypoTypeof(left, right):
+ warning("W122", this, left.value);
+ break;
+ }
+
+ return this;
+ });
+ relation("===", function (left, right) {
+ if (isTypoTypeof(right, left)) {
+ warning("W122", this, right.value);
+ } else if (isTypoTypeof(left, right)) {
+ warning("W122", this, left.value);
+ }
+ return this;
+ });
+ relation("!=", function (left, right) {
+ var eqnull = state.option.eqnull &&
+ (left.value === "null" || right.value === "null");
+
+ if (!eqnull && state.option.eqeqeq) {
+ this.from = this.character;
+ warning("W116", this, "!==", "!=");
+ } else if (isPoorRelation(left)) {
+ warning("W041", this, "!==", left.value);
+ } else if (isPoorRelation(right)) {
+ warning("W041", this, "!==", right.value);
+ } else if (isTypoTypeof(right, left)) {
+ warning("W122", this, right.value);
+ } else if (isTypoTypeof(left, right)) {
+ warning("W122", this, left.value);
+ }
+ return this;
+ });
+ relation("!==", function (left, right) {
+ if (isTypoTypeof(right, left)) {
+ warning("W122", this, right.value);
+ } else if (isTypoTypeof(left, right)) {
+ warning("W122", this, left.value);
+ }
+ return this;
+ });
+ relation("<");
+ relation(">");
+ relation("<=");
+ relation(">=");
+ bitwise("<<", "shiftleft", 120);
+ bitwise(">>", "shiftright", 120);
+ bitwise(">>>", "shiftrightunsigned", 120);
+ infix("in", "in", 120);
+ infix("instanceof", "instanceof", 120);
+ infix("+", function (left, that) {
+ var right = expression(130);
+ if (left && right && left.id === "(string)" && right.id === "(string)") {
+ left.value += right.value;
+ left.character = right.character;
+ if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
+ warning("W050", left);
+ }
+ return left;
+ }
+ that.left = left;
+ that.right = right;
+ return that;
+ }, 130);
+ prefix("+", "num");
+ prefix("+++", function () {
+ warning("W007");
+ this.right = expression(150);
+ this.arity = "unary";
+ return this;
+ });
+ infix("+++", function (left) {
+ warning("W007");
+ this.left = left;
+ this.right = expression(130);
+ return this;
+ }, 130);
+ infix("-", "sub", 130);
+ prefix("-", "neg");
+ prefix("---", function () {
+ warning("W006");
+ this.right = expression(150);
+ this.arity = "unary";
+ return this;
+ });
+ infix("---", function (left) {
+ warning("W006");
+ this.left = left;
+ this.right = expression(130);
+ return this;
+ }, 130);
+ infix("*", "mult", 140);
+ infix("/", "div", 140);
+ infix("%", "mod", 140);
+
+ suffix("++", "postinc");
+ prefix("++", "preinc");
+ state.syntax["++"].exps = true;
+
+ suffix("--", "postdec");
+ prefix("--", "predec");
+ state.syntax["--"].exps = true;
+ prefix("delete", function () {
+ var p = expression(10);
+ if (!p || (p.id !== "." && p.id !== "[")) {
+ warning("W051");
+ }
+ this.first = p;
+ return this;
+ }).exps = true;
+
+ prefix("~", function () {
+ if (state.option.bitwise) {
+ warning("W052", this, "~");
+ }
+ expression(150);
+ return this;
+ });
+
+ prefix("...", function () {
+ if (!state.option.inESNext()) {
+ warning("W104", this, "spread/rest operator");
+ }
+ if (!state.tokens.next.identifier) {
+ error("E030", state.tokens.next, state.tokens.next.value);
+ }
+ expression(150);
+ return this;
+ });
+
+ prefix("!", function () {
+ this.right = expression(150);
+ this.arity = "unary";
+
+ if (!this.right) { // '!' followed by nothing? Give up.
+ quit("E041", this.line || 0);
+ }
+
+ if (bang[this.right.id] === true) {
+ warning("W018", this, "!");
+ }
+ return this;
+ });
+
+ prefix("typeof", "typeof");
+ prefix("new", function () {
+ var c = expression(155), i;
+ if (c && c.id !== "function") {
+ if (c.identifier) {
+ c["new"] = true;
+ switch (c.value) {
+ case "Number":
+ case "String":
+ case "Boolean":
+ case "Math":
+ case "JSON":
+ warning("W053", state.tokens.prev, c.value);
+ break;
+ case "Function":
+ if (!state.option.evil) {
+ warning("W054");
+ }
+ break;
+ case "Date":
+ case "RegExp":
+ case "this":
+ break;
+ default:
+ if (c.id !== "function") {
+ i = c.value.substr(0, 1);
+ if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) {
+ warning("W055", state.tokens.curr);
+ }
+ }
+ }
+ } else {
+ if (c.id !== "." && c.id !== "[" && c.id !== "(") {
+ warning("W056", state.tokens.curr);
+ }
+ }
+ } else {
+ if (!state.option.supernew)
+ warning("W057", this);
+ }
+ if (state.tokens.next.id !== "(" && !state.option.supernew) {
+ warning("W058", state.tokens.curr, state.tokens.curr.value);
+ }
+ this.first = c;
+ return this;
+ });
+ state.syntax["new"].exps = true;
+
+ prefix("void").exps = true;
+
+ infix(".", function (left, that) {
+ var m = identifier(false, true);
+
+ if (typeof m === "string") {
+ countMember(m);
+ }
+
+ that.left = left;
+ that.right = m;
+
+ if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
+ warning("W001");
+ }
+
+ if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
+ if (state.option.noarg)
+ warning("W059", left, m);
+ else if (state.directive["use strict"])
+ error("E008");
+ } else if (!state.option.evil && left && left.value === "document" &&
+ (m === "write" || m === "writeln")) {
+ warning("W060", left);
+ }
+
+ if (!state.option.evil && (m === "eval" || m === "execScript")) {
+ warning("W061");
+ }
+
+ return that;
+ }, 160, true);
+
+ infix("(", function (left, that) {
+ if (state.option.immed && left && !left.immed && left.id === "function") {
+ warning("W062");
+ }
+
+ var n = 0;
+ var p = [];
+
+ if (left) {
+ if (left.type === "(identifier)") {
+ if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
+ if ("Number String Boolean Date Object Error".indexOf(left.value) === -1) {
+ if (left.value === "Math") {
+ warning("W063", left);
+ } else if (state.option.newcap) {
+ warning("W064", left);
+ }
+ }
+ }
+ }
+ }
+
+ if (state.tokens.next.id !== ")") {
+ for (;;) {
+ p[p.length] = expression(10);
+ n += 1;
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ }
+
+ advance(")");
+
+ if (typeof left === "object") {
+ if (state.option.inES3() && left.value === "parseInt" && n === 1) {
+ warning("W065", state.tokens.curr);
+ }
+ if (!state.option.evil) {
+ if (left.value === "eval" || left.value === "Function" ||
+ left.value === "execScript") {
+ warning("W061", left);
+
+ if (p[0] && [0].id === "(string)") {
+ addInternalSrc(left, p[0].value);
+ }
+ } else if (p[0] && p[0].id === "(string)" &&
+ (left.value === "setTimeout" ||
+ left.value === "setInterval")) {
+ warning("W066", left);
+ addInternalSrc(left, p[0].value);
+
+ // window.setTimeout/setInterval
+ } else if (p[0] && p[0].id === "(string)" &&
+ left.value === "." &&
+ left.left.value === "window" &&
+ (left.right === "setTimeout" ||
+ left.right === "setInterval")) {
+ warning("W066", left);
+ addInternalSrc(left, p[0].value);
+ }
+ }
+ if (!left.identifier && left.id !== "." && left.id !== "[" &&
+ left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
+ left.id !== "?") {
+ warning("W067", left);
+ }
+ }
+
+ that.left = left;
+ return that;
+ }, 155, true).exps = true;
+
+ prefix("(", function () {
+ var bracket, brackets = [];
+ var pn, pn1, i = 0;
+ var ret;
+ var parens = 1;
+
+ do {
+ pn = peek(i);
+
+ if (pn.value === "(") {
+ parens += 1;
+ } else if (pn.value === ")") {
+ parens -= 1;
+ }
+
+ i += 1;
+ pn1 = peek(i);
+ } while (!(parens === 0 && pn.value === ")") &&
+ pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");
+
+ if (state.tokens.next.id === "function") {
+ state.tokens.next.immed = true;
+ }
+
+ var exprs = [];
+
+ if (state.tokens.next.id !== ")") {
+ for (;;) {
+ if (pn1.value === "=>" && _.contains(["{", "["], state.tokens.next.value)) {
+ bracket = state.tokens.next;
+ bracket.left = destructuringExpression();
+ brackets.push(bracket);
+ for (var t in bracket.left) {
+ exprs.push(bracket.left[t].token);
+ }
+ } else {
+ exprs.push(expression(10));
+ }
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ }
+
+ advance(")", this);
+ if (state.option.immed && exprs[0] && exprs[0].id === "function") {
+ if (state.tokens.next.id !== "(" &&
+ (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
+ warning("W068", this);
+ }
+ }
+
+ if (state.tokens.next.value === "=>") {
+ return exprs;
+ }
+ if (!exprs.length) {
+ return;
+ }
+ if (exprs.length > 1) {
+ ret = Object.create(state.syntax[","]);
+ ret.exprs = exprs;
+ } else {
+ ret = exprs[0];
+ }
+ if (ret) {
+ ret.paren = true;
+ }
+ return ret;
+ });
+
+ application("=>");
+
+ infix("[", function (left, that) {
+ var e = expression(10), s;
+ if (e && e.type === "(string)") {
+ if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
+ warning("W061", that);
+ }
+
+ countMember(e.value);
+ if (!state.option.sub && reg.identifier.test(e.value)) {
+ s = state.syntax[e.value];
+ if (!s || !isReserved(s)) {
+ warning("W069", state.tokens.prev, e.value);
+ }
+ }
+ }
+ advance("]", that);
+
+ if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
+ warning("W001");
+ }
+
+ that.left = left;
+ that.right = e;
+ return that;
+ }, 160, true);
+
+ function comprehensiveArrayExpression() {
+ var res = {};
+ res.exps = true;
+ funct["(comparray)"].stack();
+
+ // Handle reversed for expressions, used in spidermonkey
+ var reversed = false;
+ if (state.tokens.next.value !== "for") {
+ reversed = true;
+ if (!state.option.inMoz(true)) {
+ warning("W116", state.tokens.next, "for", state.tokens.next.value);
+ }
+ funct["(comparray)"].setState("use");
+ res.right = expression(10);
+ }
+
+ advance("for");
+ if (state.tokens.next.value === "each") {
+ advance("each");
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.curr, "for each");
+ }
+ }
+ advance("(");
+ funct["(comparray)"].setState("define");
+ res.left = expression(130);
+ if (_.contains(["in", "of"], state.tokens.next.value)) {
+ advance();
+ } else {
+ error("E045", state.tokens.curr);
+ }
+ funct["(comparray)"].setState("generate");
+ expression(10);
+
+ advance(")");
+ if (state.tokens.next.value === "if") {
+ advance("if");
+ advance("(");
+ funct["(comparray)"].setState("filter");
+ res.filter = expression(10);
+ advance(")");
+ }
+
+ if (!reversed) {
+ funct["(comparray)"].setState("use");
+ res.right = expression(10);
+ }
+
+ advance("]");
+ funct["(comparray)"].unstack();
+ return res;
+ }
+
+ prefix("[", function () {
+ var blocktype = lookupBlockType(true);
+ if (blocktype.isCompArray) {
+ if (!state.option.inESNext()) {
+ warning("W119", state.tokens.curr, "array comprehension");
+ }
+ return comprehensiveArrayExpression();
+ } else if (blocktype.isDestAssign && !state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "destructuring assignment");
+ }
+ var b = state.tokens.curr.line !== state.tokens.next.line;
+ this.first = [];
+ if (b) {
+ indent += state.option.indent;
+ if (state.tokens.next.from === indent + state.option.indent) {
+ indent += state.option.indent;
+ }
+ }
+ while (state.tokens.next.id !== "(end)") {
+ while (state.tokens.next.id === ",") {
+ if (!state.option.inES5())
+ warning("W070");
+ advance(",");
+ }
+
+ if (state.tokens.next.id === "]") {
+ break;
+ }
+
+ this.first.push(expression(10));
+ if (state.tokens.next.id === ",") {
+ comma({ allowTrailing: true });
+ if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
+ warning("W070", state.tokens.curr);
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (b) {
+ indent -= state.option.indent;
+ }
+ advance("]", this);
+ return this;
+ }, 160);
+
+
+ function property_name() {
+ var id = optionalidentifier(false, true);
+
+ if (!id) {
+ if (state.tokens.next.id === "(string)") {
+ id = state.tokens.next.value;
+ advance();
+ } else if (state.tokens.next.id === "(number)") {
+ id = state.tokens.next.value.toString();
+ advance();
+ }
+ }
+
+ if (id === "hasOwnProperty") {
+ warning("W001");
+ }
+
+ return id;
+ }
+
+ function functionparams(parsed) {
+ var curr, next;
+ var params = [];
+ var ident;
+ var tokens = [];
+ var t;
+ var pastDefault = false;
+
+ if (parsed) {
+ if (Array.isArray(parsed)) {
+ for (var i in parsed) {
+ curr = parsed[i];
+ if (curr.value === "...") {
+ if (!state.option.inESNext()) {
+ warning("W104", curr, "spread/rest operator");
+ }
+ continue;
+ } else if (curr.value !== ",") {
+ params.push(curr.value);
+ addlabel(curr.value, { type: "unused", token: curr });
+ }
+ }
+ return params;
+ } else {
+ if (parsed.identifier === true) {
+ addlabel(parsed.value, { type: "unused", token: parsed });
+ return [parsed];
+ }
+ }
+ }
+
+ next = state.tokens.next;
+
+ advance("(");
+
+ if (state.tokens.next.id === ")") {
+ advance(")");
+ return;
+ }
+
+ for (;;) {
+ if (_.contains(["{", "["], state.tokens.next.id)) {
+ tokens = destructuringExpression();
+ for (t in tokens) {
+ t = tokens[t];
+ if (t.id) {
+ params.push(t.id);
+ addlabel(t.id, { type: "unused", token: t.token });
+ }
+ }
+ } else if (state.tokens.next.value === "...") {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.next, "spread/rest operator");
+ }
+ advance("...");
+ ident = identifier(true);
+ params.push(ident);
+ addlabel(ident, { type: "unused", token: state.tokens.curr });
+ } else {
+ ident = identifier(true);
+ params.push(ident);
+ addlabel(ident, { type: "unused", token: state.tokens.curr });
+ }
+
+ // it is a syntax error to have a regular argument after a default argument
+ if (pastDefault) {
+ if (state.tokens.next.id !== "=") {
+ error("E051", state.tokens.current);
+ }
+ }
+ if (state.tokens.next.id === "=") {
+ if (!state.option.inESNext()) {
+ warning("W119", state.tokens.next, "default parameters");
+ }
+ advance("=");
+ pastDefault = true;
+ expression(10);
+ }
+ if (state.tokens.next.id === ",") {
+ comma();
+ } else {
+ advance(")", next);
+ return params;
+ }
+ }
+ }
+
+ function setprop(funct, name, values) {
+ if (!funct["(properties)"][name]) {
+ funct["(properties)"][name] = { unused: false };
+ }
+
+ _.extend(funct["(properties)"][name], values);
+ }
+
+ function getprop(funct, name, prop) {
+ if (!funct["(properties)"][name])
+ return null;
+
+ return funct["(properties)"][name][prop] || null;
+ }
+
+ function functor(name, token, scope, overwrites) {
+ var funct = {
+ "(name)" : name,
+ "(breakage)" : 0,
+ "(loopage)" : 0,
+ "(scope)" : scope,
+ "(tokens)" : {},
+ "(properties)": {},
+
+ "(catch)" : false,
+ "(global)" : false,
+
+ "(line)" : null,
+ "(character)" : null,
+ "(metrics)" : null,
+ "(statement)" : null,
+ "(context)" : null,
+ "(blockscope)": null,
+ "(comparray)" : null,
+ "(generator)" : null,
+ "(params)" : null
+ };
+
+ if (token) {
+ _.extend(funct, {
+ "(line)" : token.line,
+ "(character)": token.character,
+ "(metrics)" : createMetrics(token)
+ });
+ }
+
+ _.extend(funct, overwrites);
+
+ if (funct["(context)"]) {
+ funct["(blockscope)"] = funct["(context)"]["(blockscope)"];
+ funct["(comparray)"] = funct["(context)"]["(comparray)"];
+ }
+
+ return funct;
+ }
+
+ function doFunction(name, statement, generator, fatarrowparams) {
+ var f;
+ var oldOption = state.option;
+ var oldIgnored = state.ignored;
+ var oldScope = scope;
+
+ state.option = Object.create(state.option);
+ state.ignored = Object.create(state.ignored);
+ scope = Object.create(scope);
+
+ funct = functor(name || "\"" + anonname + "\"", state.tokens.next, scope, {
+ "(statement)": statement,
+ "(context)": funct,
+ "(generator)": generator ? true : null
+ });
+
+ f = funct;
+ state.tokens.curr.funct = funct;
+
+ functions.push(funct);
+
+ if (name) {
+ addlabel(name, { type: "function" });
+ }
+
+ funct["(params)"] = functionparams(fatarrowparams);
+ funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
+
+ // So we parse fat-arrow functions after we encounter =>. So basically
+ // doFunction is called with the left side of => as its last argument.
+ // This means that the parser, at that point, had already added its
+ // arguments to the undefs array and here we undo that.
+
+ JSHINT.undefs = _.filter(JSHINT.undefs, function (item) {
+ return !_.contains(_.union(fatarrowparams), item[2]);
+ });
+
+ block(false, true, true, fatarrowparams ? true : false);
+
+ if (!state.option.noyield && generator && funct["(generator)"] !== "yielded") {
+ warning("W124", state.tokens.curr);
+ }
+
+ funct["(metrics)"].verifyMaxStatementsPerFunction();
+ funct["(metrics)"].verifyMaxComplexityPerFunction();
+ funct["(unusedOption)"] = state.option.unused;
+
+ scope = oldScope;
+ state.option = oldOption;
+ state.ignored = oldIgnored;
+ funct["(last)"] = state.tokens.curr.line;
+ funct["(lastcharacter)"] = state.tokens.curr.character;
+
+ _.map(Object.keys(funct), function (key) {
+ if (key[0] === "(") return;
+ funct["(blockscope)"].unshadow(key);
+ });
+
+ funct = funct["(context)"];
+
+ return f;
+ }
+
+ function createMetrics(functionStartToken) {
+ return {
+ statementCount: 0,
+ nestedBlockDepth: -1,
+ ComplexityCount: 1,
+
+ verifyMaxStatementsPerFunction: function () {
+ if (state.option.maxstatements &&
+ this.statementCount > state.option.maxstatements) {
+ warning("W071", functionStartToken, this.statementCount);
+ }
+ },
+
+ verifyMaxParametersPerFunction: function (params) {
+ params = params || [];
+
+ if (state.option.maxparams && params.length > state.option.maxparams) {
+ warning("W072", functionStartToken, params.length);
+ }
+ },
+
+ verifyMaxNestedBlockDepthPerFunction: function () {
+ if (state.option.maxdepth &&
+ this.nestedBlockDepth > 0 &&
+ this.nestedBlockDepth === state.option.maxdepth + 1) {
+ warning("W073", null, this.nestedBlockDepth);
+ }
+ },
+
+ verifyMaxComplexityPerFunction: function () {
+ var max = state.option.maxcomplexity;
+ var cc = this.ComplexityCount;
+ if (max && cc > max) {
+ warning("W074", functionStartToken, cc);
+ }
+ }
+ };
+ }
+
+ function increaseComplexityCount() {
+ funct["(metrics)"].ComplexityCount += 1;
+ }
+
+ // Parse assignments that were found instead of conditionals.
+ // For example: if (a = 1) { ... }
+
+ function checkCondAssignment(expr) {
+ var id, paren;
+ if (expr) {
+ id = expr.id;
+ paren = expr.paren;
+ if (id === "," && (expr = expr.exprs[expr.exprs.length - 1])) {
+ id = expr.id;
+ paren = paren || expr.paren;
+ }
+ }
+ switch (id) {
+ case "=":
+ case "+=":
+ case "-=":
+ case "*=":
+ case "%=":
+ case "&=":
+ case "|=":
+ case "^=":
+ case "/=":
+ if (!paren && !state.option.boss) {
+ warning("W084");
+ }
+ }
+ }
+
+
+ (function (x) {
+ x.nud = function (isclassdef) {
+ var b, f, i, p, t, g;
+ var props = {}; // All properties, including accessors
+ var tag = "";
+
+ function saveProperty(name, tkn) {
+ if (props[name] && _.has(props, name))
+ warning("W075", state.tokens.next, i);
+ else
+ props[name] = {};
+
+ props[name].basic = true;
+ props[name].basictkn = tkn;
+ }
+
+ function saveSetter(name, tkn) {
+ if (props[name] && _.has(props, name)) {
+ if (props[name].basic || props[name].setter)
+ warning("W075", state.tokens.next, i);
+ } else {
+ props[name] = {};
+ }
+
+ props[name].setter = true;
+ props[name].setterToken = tkn;
+ }
+
+ function saveGetter(name) {
+ if (props[name] && _.has(props, name)) {
+ if (props[name].basic || props[name].getter)
+ warning("W075", state.tokens.next, i);
+ } else {
+ props[name] = {};
+ }
+
+ props[name].getter = true;
+ props[name].getterToken = state.tokens.curr;
+ }
+
+ b = state.tokens.curr.line !== state.tokens.next.line;
+ if (b) {
+ indent += state.option.indent;
+ if (state.tokens.next.from === indent + state.option.indent) {
+ indent += state.option.indent;
+ }
+ }
+
+ for (;;) {
+ if (state.tokens.next.id === "}") {
+ break;
+ }
+
+ if (isclassdef && state.tokens.next.value === "static") {
+ advance("static");
+ tag = "static ";
+ }
+
+ if (state.tokens.next.value === "get" && peek().id !== ":") {
+ advance("get");
+
+ if (!state.option.inES5(!isclassdef)) {
+ error("E034");
+ }
+
+ i = property_name();
+
+ // ES6 allows for get() {...} and set() {...} method
+ // definition shorthand syntax, so we don't produce an error
+ // if the esnext option is enabled.
+ if (!i && !state.option.inESNext()) {
+ error("E035");
+ }
+
+ // It is a Syntax Error if PropName of MethodDefinition is
+ // "constructor" and SpecialMethod of MethodDefinition is true.
+ if (isclassdef && i === "constructor") {
+ error("E049", state.tokens.next, "class getter method", i);
+ }
+
+ // We don't want to save this getter unless it's an actual getter
+ // and not an ES6 concise method
+ if (i) {
+ saveGetter(tag + i);
+ }
+
+ t = state.tokens.next;
+ f = doFunction();
+ p = f["(params)"];
+
+ // Don't warn about getter/setter pairs if this is an ES6 concise method
+ if (i && p) {
+ warning("W076", t, p[0], i);
+ }
+ } else if (state.tokens.next.value === "set" && peek().id !== ":") {
+ advance("set");
+
+ if (!state.option.inES5(!isclassdef)) {
+ error("E034");
+ }
+
+ i = property_name();
+
+ // ES6 allows for get() {...} and set() {...} method
+ // definition shorthand syntax, so we don't produce an error
+ // if the esnext option is enabled.
+ if (!i && !state.option.inESNext()) {
+ error("E035");
+ }
+
+ // It is a Syntax Error if PropName of MethodDefinition is
+ // "constructor" and SpecialMethod of MethodDefinition is true.
+ if (isclassdef && i === "constructor") {
+ error("E049", state.tokens.next, "class setter method", i);
+ }
+
+ // We don't want to save this getter unless it's an actual getter
+ // and not an ES6 concise method
+ if (i) {
+ saveSetter(tag + i, state.tokens.next);
+ }
+
+ t = state.tokens.next;
+ f = doFunction();
+ p = f["(params)"];
+
+ // Don't warn about getter/setter pairs if this is an ES6 concise method
+ if (i && (!p || p.length !== 1)) {
+ warning("W077", t, i);
+ }
+ } else {
+ g = false;
+ if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.next, "generator functions");
+ }
+ advance("*");
+ g = true;
+ }
+ i = property_name();
+ saveProperty(tag + i, state.tokens.next);
+
+ if (typeof i !== "string") {
+ break;
+ }
+
+ if (state.tokens.next.value === "(") {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "concise methods");
+ }
+ doFunction(i, undefined, g);
+ } else if (!isclassdef) {
+ advance(":");
+ expression(10);
+ }
+ }
+ // It is a Syntax Error if PropName of MethodDefinition is "prototype".
+ if (isclassdef && i === "prototype") {
+ error("E049", state.tokens.next, "class method", i);
+ }
+
+ countMember(i);
+ if (isclassdef) {
+ tag = "";
+ continue;
+ }
+ if (state.tokens.next.id === ",") {
+ comma({ allowTrailing: true, property: true });
+ if (state.tokens.next.id === ",") {
+ warning("W070", state.tokens.curr);
+ } else if (state.tokens.next.id === "}" && !state.option.inES5(true)) {
+ warning("W070", state.tokens.curr);
+ }
+ } else {
+ break;
+ }
+ }
+ if (b) {
+ indent -= state.option.indent;
+ }
+ advance("}", this);
+
+ // Check for lonely setters if in the ES5 mode.
+ if (state.option.inES5()) {
+ for (var name in props) {
+ if (_.has(props, name) && props[name].setter && !props[name].getter) {
+ warning("W078", props[name].setterToken);
+ }
+ }
+ }
+ return this;
+ };
+ x.fud = function () {
+ error("E036", state.tokens.curr);
+ };
+ }(delim("{")));
+
+ function destructuringExpression() {
+ var id, ids;
+ var identifiers = [];
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "destructuring expression");
+ }
+ var nextInnerDE = function () {
+ var ident;
+ if (_.contains(["[", "{"], state.tokens.next.value)) {
+ ids = destructuringExpression();
+ for (var id in ids) {
+ id = ids[id];
+ identifiers.push({ id: id.id, token: id.token });
+ }
+ } else if (state.tokens.next.value === ",") {
+ identifiers.push({ id: null, token: state.tokens.curr });
+ } else if (state.tokens.next.value === "(") {
+ advance("(");
+ nextInnerDE();
+ advance(")");
+ } else {
+ ident = identifier();
+ if (ident)
+ identifiers.push({ id: ident, token: state.tokens.curr });
+ }
+ };
+ if (state.tokens.next.value === "[") {
+ advance("[");
+ nextInnerDE();
+ while (state.tokens.next.value !== "]") {
+ advance(",");
+ nextInnerDE();
+ }
+ advance("]");
+ } else if (state.tokens.next.value === "{") {
+ advance("{");
+ id = identifier();
+ if (state.tokens.next.value === ":") {
+ advance(":");
+ nextInnerDE();
+ } else {
+ identifiers.push({ id: id, token: state.tokens.curr });
+ }
+ while (state.tokens.next.value !== "}") {
+ advance(",");
+ id = identifier();
+ if (state.tokens.next.value === ":") {
+ advance(":");
+ nextInnerDE();
+ } else {
+ identifiers.push({ id: id, token: state.tokens.curr });
+ }
+ }
+ advance("}");
+ }
+ return identifiers;
+ }
+
+ function destructuringExpressionMatch(tokens, value) {
+ var first = value.first;
+
+ if (!first)
+ return;
+
+ _.zip(tokens, Array.isArray(first) ? first : [ first ]).forEach(function (val) {
+ var token = val[0];
+ var value = val[1];
+
+ if (token && value)
+ token.first = value;
+ else if (token && token.first && !value)
+ warning("W080", token.first, token.first.value);
+ });
+ }
+
+ var conststatement = stmt("const", function (prefix) {
+ var tokens;
+ var value;
+ var lone; // State variable to know if it is a lone identifier, or a destructuring statement.
+
+ if (!state.option.inESNext())
+ warning("W104", state.tokens.curr, "const");
+
+ this.first = [];
+ for (;;) {
+ var names = [];
+ if (_.contains(["{", "["], state.tokens.next.value)) {
+ tokens = destructuringExpression();
+ lone = false;
+ } else {
+ tokens = [ { id: identifier(), token: state.tokens.curr } ];
+ lone = true;
+ }
+ for (var t in tokens) {
+ if (tokens.hasOwnProperty(t)) {
+ t = tokens[t];
+ if (funct[t.id] === "const") {
+ warning("E011", null, t.id);
+ }
+ if (funct["(global)"] && predefined[t.id] === false) {
+ warning("W079", t.token, t.id);
+ }
+ if (t.id) {
+ addlabel(t.id, { token: t.token, type: "const", unused: true });
+ names.push(t.token);
+ }
+ }
+ }
+ if (prefix) {
+ break;
+ }
+
+ this.first = this.first.concat(names);
+
+ if (state.tokens.next.id !== "=") {
+ warning("E012", state.tokens.curr, state.tokens.curr.value);
+ }
+
+ if (state.tokens.next.id === "=") {
+ advance("=");
+ if (state.tokens.next.id === "undefined") {
+ warning("W080", state.tokens.prev, state.tokens.prev.value);
+ }
+ if (peek(0).id === "=" && state.tokens.next.identifier) {
+ warning("W120", state.tokens.next, state.tokens.next.value);
+ }
+ value = expression(10);
+ if (lone) {
+ tokens[0].first = value;
+ } else {
+ destructuringExpressionMatch(names, value);
+ }
+ }
+
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ return this;
+ });
+
+ conststatement.exps = true;
+ var varstatement = stmt("var", function (prefix) {
+ // JavaScript does not have block scope. It only has function scope. So,
+ // declaring a variable in a block can have unexpected consequences.
+ var tokens, lone, value;
+
+ this.first = [];
+ for (;;) {
+ var names = [];
+ if (_.contains(["{", "["], state.tokens.next.value)) {
+ tokens = destructuringExpression();
+ lone = false;
+ } else {
+ tokens = [ { id: identifier(), token: state.tokens.curr } ];
+ lone = true;
+ }
+ for (var t in tokens) {
+ if (tokens.hasOwnProperty(t)) {
+ t = tokens[t];
+ if (state.option.inESNext() && funct[t.id] === "const") {
+ warning("E011", null, t.id);
+ }
+ if (funct["(global)"] && predefined[t.id] === false) {
+ warning("W079", t.token, t.id);
+ }
+ if (t.id) {
+ addlabel(t.id, { type: "unused", token: t.token });
+ names.push(t.token);
+ }
+ }
+ }
+ if (prefix) {
+ break;
+ }
+
+ this.first = this.first.concat(names);
+
+ if (state.tokens.next.id === "=") {
+ advance("=");
+ if (state.tokens.next.id === "undefined") {
+ warning("W080", state.tokens.prev, state.tokens.prev.value);
+ }
+ if (peek(0).id === "=" && state.tokens.next.identifier) {
+ warning("W120", state.tokens.next, state.tokens.next.value);
+ }
+ value = expression(10);
+ if (lone) {
+ tokens[0].first = value;
+ } else {
+ destructuringExpressionMatch(names, value);
+ }
+ }
+
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ return this;
+ });
+ varstatement.exps = true;
+
+ var letstatement = stmt("let", function (prefix) {
+ var tokens, lone, value, letblock;
+
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "let");
+ }
+
+ if (state.tokens.next.value === "(") {
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.next, "let block");
+ }
+ advance("(");
+ funct["(blockscope)"].stack();
+ letblock = true;
+ } else if (funct["(nolet)"]) {
+ error("E048", state.tokens.curr);
+ }
+
+ this.first = [];
+ for (;;) {
+ var names = [];
+ if (_.contains(["{", "["], state.tokens.next.value)) {
+ tokens = destructuringExpression();
+ lone = false;
+ } else {
+ tokens = [ { id: identifier(), token: state.tokens.curr.value } ];
+ lone = true;
+ }
+ for (var t in tokens) {
+ if (tokens.hasOwnProperty(t)) {
+ t = tokens[t];
+ if (state.option.inESNext() && funct[t.id] === "const") {
+ warning("E011", null, t.id);
+ }
+ if (funct["(global)"] && predefined[t.id] === false) {
+ warning("W079", t.token, t.id);
+ }
+ if (t.id && !funct["(nolet)"]) {
+ addlabel(t.id, { type: "unused", token: t.token, islet: true });
+ names.push(t.token);
+ }
+ }
+ }
+ if (prefix) {
+ break;
+ }
+
+ this.first = this.first.concat(names);
+
+ if (state.tokens.next.id === "=") {
+ advance("=");
+ if (state.tokens.next.id === "undefined") {
+ warning("W080", state.tokens.prev, state.tokens.prev.value);
+ }
+ if (peek(0).id === "=" && state.tokens.next.identifier) {
+ warning("W120", state.tokens.next, state.tokens.next.value);
+ }
+ value = expression(10);
+ if (lone) {
+ tokens[0].first = value;
+ } else {
+ destructuringExpressionMatch(names, value);
+ }
+ }
+
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ if (letblock) {
+ advance(")");
+ block(true, true);
+ this.block = true;
+ funct["(blockscope)"].unstack();
+ }
+
+ return this;
+ });
+ letstatement.exps = true;
+
+ blockstmt("class", function () {
+ return classdef.call(this, true);
+ });
+
+ function classdef(stmt) {
+ /*jshint validthis:true */
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "class");
+ }
+ if (stmt) {
+ // BindingIdentifier
+ this.name = identifier();
+ addlabel(this.name, { type: "unused", token: state.tokens.curr });
+ } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
+ // BindingIdentifier(opt)
+ this.name = identifier();
+ }
+ classtail(this);
+ return this;
+ }
+
+ function classtail(c) {
+ var strictness = state.directive["use strict"];
+
+ // ClassHeritage(opt)
+ if (state.tokens.next.value === "extends") {
+ advance("extends");
+ c.heritage = expression(10);
+ }
+
+ // A ClassBody is always strict code.
+ state.directive["use strict"] = true;
+ advance("{");
+ // ClassBody(opt)
+ c.body = state.syntax["{"].nud(true);
+ state.directive["use strict"] = strictness;
+ }
+
+ blockstmt("function", function () {
+ var generator = false;
+ if (state.tokens.next.value === "*") {
+ advance("*");
+ if (state.option.inESNext(true)) {
+ generator = true;
+ } else {
+ warning("W119", state.tokens.curr, "function*");
+ }
+ }
+ if (inblock) {
+ warning("W082", state.tokens.curr);
+
+ }
+ var i = identifier();
+ if (funct[i] === "const") {
+ warning("E011", null, i);
+ }
+ addlabel(i, { type: "unction", token: state.tokens.curr });
+
+ doFunction(i, { statement: true }, generator);
+ if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {
+ error("E039");
+ }
+ return this;
+ });
+
+ prefix("function", function () {
+ var generator = false;
+ if (state.tokens.next.value === "*") {
+ if (!state.option.inESNext()) {
+ warning("W119", state.tokens.curr, "function*");
+ }
+ advance("*");
+ generator = true;
+ }
+ var i = optionalidentifier();
+ doFunction(i, undefined, generator);
+ if (!state.option.loopfunc && funct["(loopage)"]) {
+ warning("W083");
+ }
+ return this;
+ });
+
+ blockstmt("if", function () {
+ var t = state.tokens.next;
+ increaseComplexityCount();
+ state.condition = true;
+ advance("(");
+ checkCondAssignment(expression(0));
+ advance(")", t);
+ state.condition = false;
+ block(true, true);
+ if (state.tokens.next.id === "else") {
+ advance("else");
+ if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
+ statement(true);
+ } else {
+ block(true, true);
+ }
+ }
+ return this;
+ });
+
+ blockstmt("try", function () {
+ var b;
+
+ function doCatch() {
+ var oldScope = scope;
+ var e;
+
+ advance("catch");
+ advance("(");
+
+ scope = Object.create(oldScope);
+
+ e = state.tokens.next.value;
+ if (state.tokens.next.type !== "(identifier)") {
+ e = null;
+ warning("E030", state.tokens.next, e);
+ }
+
+ advance();
+
+ funct = functor("(catch)", state.tokens.next, scope, {
+ "(context)" : funct,
+ "(breakage)" : funct["(breakage)"],
+ "(loopage)" : funct["(loopage)"],
+ "(statement)": false,
+ "(catch)" : true
+ });
+
+ if (e) {
+ addlabel(e, { type: "exception" });
+ }
+
+ if (state.tokens.next.value === "if") {
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.curr, "catch filter");
+ }
+ advance("if");
+ expression(0);
+ }
+
+ advance(")");
+
+ state.tokens.curr.funct = funct;
+ functions.push(funct);
+
+ block(false);
+
+ scope = oldScope;
+
+ funct["(last)"] = state.tokens.curr.line;
+ funct["(lastcharacter)"] = state.tokens.curr.character;
+ funct = funct["(context)"];
+ }
+
+ block(true);
+
+ while (state.tokens.next.id === "catch") {
+ increaseComplexityCount();
+ if (b && (!state.option.inMoz(true))) {
+ warning("W118", state.tokens.next, "multiple catch blocks");
+ }
+ doCatch();
+ b = true;
+ }
+
+ if (state.tokens.next.id === "finally") {
+ advance("finally");
+ block(true);
+ return;
+ }
+
+ if (!b) {
+ error("E021", state.tokens.next, "catch", state.tokens.next.value);
+ }
+
+ return this;
+ });
+
+ blockstmt("while", function () {
+ var t = state.tokens.next;
+ funct["(breakage)"] += 1;
+ funct["(loopage)"] += 1;
+ increaseComplexityCount();
+ advance("(");
+ checkCondAssignment(expression(0));
+ advance(")", t);
+ block(true, true);
+ funct["(breakage)"] -= 1;
+ funct["(loopage)"] -= 1;
+ return this;
+ }).labelled = true;
+
+ blockstmt("with", function () {
+ var t = state.tokens.next;
+ if (state.directive["use strict"]) {
+ error("E010", state.tokens.curr);
+ } else if (!state.option.withstmt) {
+ warning("W085", state.tokens.curr);
+ }
+
+ advance("(");
+ expression(0);
+ advance(")", t);
+ block(true, true);
+
+ return this;
+ });
+
+ blockstmt("switch", function () {
+ var t = state.tokens.next;
+ var g = false;
+ var noindent = false;
+
+ funct["(breakage)"] += 1;
+ advance("(");
+ checkCondAssignment(expression(0));
+ advance(")", t);
+ t = state.tokens.next;
+ advance("{");
+
+ if (state.tokens.next.from === indent)
+ noindent = true;
+
+ if (!noindent)
+ indent += state.option.indent;
+
+ this.cases = [];
+
+ for (;;) {
+ switch (state.tokens.next.id) {
+ case "case":
+ switch (funct["(verb)"]) {
+ case "yield":
+ case "break":
+ case "case":
+ case "continue":
+ case "return":
+ case "switch":
+ case "throw":
+ break;
+ default:
+ // You can tell JSHint that you don't use break intentionally by
+ // adding a comment /* falls through */ on a line just before
+ // the next `case`.
+ if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
+ warning("W086", state.tokens.curr, "case");
+ }
+ }
+
+ advance("case");
+ this.cases.push(expression(0));
+ increaseComplexityCount();
+ g = true;
+ advance(":");
+ funct["(verb)"] = "case";
+ break;
+ case "default":
+ switch (funct["(verb)"]) {
+ case "yield":
+ case "break":
+ case "continue":
+ case "return":
+ case "throw":
+ break;
+ default:
+ // Do not display a warning if 'default' is the first statement or if
+ // there is a special /* falls through */ comment.
+ if (this.cases.length) {
+ if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
+ warning("W086", state.tokens.curr, "default");
+ }
+ }
+ }
+
+ advance("default");
+ g = true;
+ advance(":");
+ break;
+ case "}":
+ if (!noindent)
+ indent -= state.option.indent;
+
+ advance("}", t);
+ funct["(breakage)"] -= 1;
+ funct["(verb)"] = undefined;
+ return;
+ case "(end)":
+ error("E023", state.tokens.next, "}");
+ return;
+ default:
+ indent += state.option.indent;
+ if (g) {
+ switch (state.tokens.curr.id) {
+ case ",":
+ error("E040");
+ return;
+ case ":":
+ g = false;
+ statements();
+ break;
+ default:
+ error("E025", state.tokens.curr);
+ return;
+ }
+ } else {
+ if (state.tokens.curr.id === ":") {
+ advance(":");
+ error("E024", state.tokens.curr, ":");
+ statements();
+ } else {
+ error("E021", state.tokens.next, "case", state.tokens.next.value);
+ return;
+ }
+ }
+ indent -= state.option.indent;
+ }
+ }
+ }).labelled = true;
+
+ stmt("debugger", function () {
+ if (!state.option.debug) {
+ warning("W087", this);
+ }
+ return this;
+ }).exps = true;
+
+ (function () {
+ var x = stmt("do", function () {
+ funct["(breakage)"] += 1;
+ funct["(loopage)"] += 1;
+ increaseComplexityCount();
+
+ this.first = block(true, true);
+ advance("while");
+ var t = state.tokens.next;
+ advance("(");
+ checkCondAssignment(expression(0));
+ advance(")", t);
+ funct["(breakage)"] -= 1;
+ funct["(loopage)"] -= 1;
+ return this;
+ });
+ x.labelled = true;
+ x.exps = true;
+ }());
+
+ blockstmt("for", function () {
+ var s, t = state.tokens.next;
+ var letscope = false;
+ var foreachtok = null;
+
+ if (t.value === "each") {
+ foreachtok = t;
+ advance("each");
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.curr, "for each");
+ }
+ }
+
+ funct["(breakage)"] += 1;
+ funct["(loopage)"] += 1;
+ increaseComplexityCount();
+ advance("(");
+
+ // what kind of for(…) statement it is? for(…of…)? for(…in…)? for(…;…;…)?
+ var nextop; // contains the token of the "in" or "of" operator
+ var i = 0;
+ var inof = ["in", "of"];
+ do {
+ nextop = peek(i);
+ ++i;
+ } while (!_.contains(inof, nextop.value) && nextop.value !== ";" &&
+ nextop.type !== "(end)");
+
+ // if we're in a for (… in|of …) statement
+ if (_.contains(inof, nextop.value)) {
+ if (!state.option.inESNext() && nextop.value === "of") {
+ error("W104", nextop, "for of");
+ }
+
+ if (state.tokens.next.id === "var") {
+ advance("var");
+ state.syntax["var"].fud.call(state.syntax["var"].fud, true);
+ } else if (state.tokens.next.id === "let") {
+ advance("let");
+ // create a new block scope
+ letscope = true;
+ funct["(blockscope)"].stack();
+ state.syntax["let"].fud.call(state.syntax["let"].fud, true);
+ } else if (!state.tokens.next.identifier) {
+ error("E030", state.tokens.next, state.tokens.next.type);
+ advance();
+ } else {
+ switch (funct[state.tokens.next.value]) {
+ case "unused":
+ funct[state.tokens.next.value] = "var";
+ break;
+ case "var":
+ break;
+ default:
+ if (!funct["(blockscope)"].getlabel(state.tokens.next.value))
+ warning("W088", state.tokens.next, state.tokens.next.value);
+ }
+ advance();
+ }
+ advance(nextop.value);
+ expression(20);
+ advance(")", t);
+ s = block(true, true);
+ if (state.option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
+ s[0].value !== "if")) {
+ warning("W089", this);
+ }
+ funct["(breakage)"] -= 1;
+ funct["(loopage)"] -= 1;
+ } else {
+ if (foreachtok) {
+ error("E045", foreachtok);
+ }
+ if (state.tokens.next.id !== ";") {
+ if (state.tokens.next.id === "var") {
+ advance("var");
+ state.syntax["var"].fud.call(state.syntax["var"].fud);
+ } else if (state.tokens.next.id === "let") {
+ advance("let");
+ // create a new block scope
+ letscope = true;
+ funct["(blockscope)"].stack();
+ state.syntax["let"].fud.call(state.syntax["let"].fud);
+ } else {
+ for (;;) {
+ expression(0, "for");
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ }
+ }
+ nolinebreak(state.tokens.curr);
+ advance(";");
+ if (state.tokens.next.id !== ";") {
+ checkCondAssignment(expression(0));
+ }
+ nolinebreak(state.tokens.curr);
+ advance(";");
+ if (state.tokens.next.id === ";") {
+ error("E021", state.tokens.next, ")", ";");
+ }
+ if (state.tokens.next.id !== ")") {
+ for (;;) {
+ expression(0, "for");
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ }
+ advance(")", t);
+ block(true, true);
+ funct["(breakage)"] -= 1;
+ funct["(loopage)"] -= 1;
+
+ }
+ // unstack loop blockscope
+ if (letscope) {
+ funct["(blockscope)"].unstack();
+ }
+ return this;
+ }).labelled = true;
+
+
+ stmt("break", function () {
+ var v = state.tokens.next.value;
+
+ if (funct["(breakage)"] === 0)
+ warning("W052", state.tokens.next, this.value);
+
+ if (!state.option.asi)
+ nolinebreak(this);
+
+ if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+ if (state.tokens.curr.line === state.tokens.next.line) {
+ if (funct[v] !== "label") {
+ warning("W090", state.tokens.next, v);
+ } else if (scope[v] !== funct) {
+ warning("W091", state.tokens.next, v);
+ }
+ this.first = state.tokens.next;
+ advance();
+ }
+ }
+ reachable("break");
+ return this;
+ }).exps = true;
+
+
+ stmt("continue", function () {
+ var v = state.tokens.next.value;
+
+ if (funct["(breakage)"] === 0)
+ warning("W052", state.tokens.next, this.value);
+
+ if (!state.option.asi)
+ nolinebreak(this);
+
+ if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+ if (state.tokens.curr.line === state.tokens.next.line) {
+ if (funct[v] !== "label") {
+ warning("W090", state.tokens.next, v);
+ } else if (scope[v] !== funct) {
+ warning("W091", state.tokens.next, v);
+ }
+ this.first = state.tokens.next;
+ advance();
+ }
+ } else if (!funct["(loopage)"]) {
+ warning("W052", state.tokens.next, this.value);
+ }
+ reachable("continue");
+ return this;
+ }).exps = true;
+
+
+ stmt("return", function () {
+ if (this.line === state.tokens.next.line) {
+ if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+ this.first = expression(0);
+
+ if (this.first &&
+ this.first.type === "(punctuator)" && this.first.value === "=" &&
+ !this.first.paren && !state.option.boss) {
+ warningAt("W093", this.first.line, this.first.character);
+ }
+ }
+ } else {
+ if (state.tokens.next.type === "(punctuator)" &&
+ ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) {
+ nolinebreak(this); // always warn (Line breaking error)
+ }
+ }
+ reachable("return");
+ return this;
+ }).exps = true;
+
+ (function (x) {
+ x.exps = true;
+ x.lbp = 25;
+ }(prefix("yield", function () {
+ var prev = state.tokens.prev;
+ if (state.option.inESNext(true) && !funct["(generator)"]) {
+ // If it's a yield within a catch clause inside a generator then that's ok
+ if (!("(catch)" === funct["(name)"] && funct["(context)"]["(generator)"])) {
+ error("E046", state.tokens.curr, "yield");
+ }
+ } else if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "yield");
+ }
+ funct["(generator)"] = "yielded";
+ if (this.line === state.tokens.next.line || !state.option.inMoz(true)) {
+ if (state.tokens.next.id !== ";" && !state.tokens.next.reach && state.tokens.next.nud) {
+ nobreaknonadjacent(state.tokens.curr, state.tokens.next);
+ this.first = expression(10);
+
+ if (this.first.type === "(punctuator)" && this.first.value === "=" &&
+ !this.first.paren && !state.option.boss) {
+ warningAt("W093", this.first.line, this.first.character);
+ }
+ }
+
+ if (state.option.inMoz(true) && state.tokens.next.id !== ")" &&
+ (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === "yield")) {
+ error("E050", this);
+ }
+ } else if (!state.option.asi) {
+ nolinebreak(this); // always warn (Line breaking error)
+ }
+ return this;
+ })));
+
+
+ stmt("throw", function () {
+ nolinebreak(this);
+ this.first = expression(20);
+ reachable("throw");
+ return this;
+ }).exps = true;
+
+ stmt("import", function () {
+ if (!state.option.inESNext()) {
+ warning("W119", state.tokens.curr, "import");
+ }
+
+ if (state.tokens.next.type === "(string)") {
+ advance("(string)");
+ return this;
+ }
+ if (state.tokens.next.identifier) {
+ this.name = identifier();
+ addlabel(this.name, { type: "unused", token: state.tokens.curr });
+ } else {
+ advance("{");
+ for (;;) {
+ if (state.tokens.next.value === "}") {
+ advance("}");
+ break;
+ }
+ var importName;
+ if (state.tokens.next.type === "default") {
+ importName = "default";
+ advance("default");
+ } else {
+ importName = identifier();
+ }
+ if (state.tokens.next.value === "as") {
+ advance("as");
+ importName = identifier();
+ }
+ addlabel(importName, { type: "unused", token: state.tokens.curr });
+
+ if (state.tokens.next.value === ",") {
+ advance(",");
+ } else if (state.tokens.next.value === "}") {
+ advance("}");
+ break;
+ } else {
+ error("E024", state.tokens.next, state.tokens.next.value);
+ break;
+ }
+ }
+ }
+
+ advance("from");
+ advance("(string)");
+ return this;
+ }).exps = true;
+
+ stmt("export", function () {
+ if (!state.option.inESNext()) {
+ warning("W119", state.tokens.curr, "export");
+ }
+
+ if (state.tokens.next.type === "default") {
+ advance("default");
+ if (state.tokens.next.id === "function" || state.tokens.next.id === "class") {
+ this.block = true;
+ }
+ this.exportee = expression(10);
+
+ return this;
+ }
+
+ if (state.tokens.next.value === "{") {
+ advance("{");
+ for (;;) {
+ exported[identifier()] = true;
+
+ if (state.tokens.next.value === ",") {
+ advance(",");
+ } else if (state.tokens.next.value === "}") {
+ advance("}");
+ break;
+ } else {
+ error("E024", state.tokens.next, state.tokens.next.value);
+ break;
+ }
+ }
+ return this;
+ }
+
+ if (state.tokens.next.id === "var") {
+ advance("var");
+ exported[state.tokens.next.value] = true;
+ state.syntax["var"].fud.call(state.syntax["var"].fud);
+ } else if (state.tokens.next.id === "let") {
+ advance("let");
+ exported[state.tokens.next.value] = true;
+ state.syntax["let"].fud.call(state.syntax["let"].fud);
+ } else if (state.tokens.next.id === "const") {
+ advance("const");
+ exported[state.tokens.next.value] = true;
+ state.syntax["const"].fud.call(state.syntax["const"].fud);
+ } else if (state.tokens.next.id === "function") {
+ this.block = true;
+ advance("function");
+ exported[state.tokens.next.value] = true;
+ state.syntax["function"].fud();
+ } else if (state.tokens.next.id === "class") {
+ this.block = true;
+ advance("class");
+ exported[state.tokens.next.value] = true;
+ state.syntax["class"].fud();
+ } else {
+ error("E024", state.tokens.next, state.tokens.next.value);
+ }
+
+ return this;
+ }).exps = true;
+
+ // Future Reserved Words
+
+ FutureReservedWord("abstract");
+ FutureReservedWord("boolean");
+ FutureReservedWord("byte");
+ FutureReservedWord("char");
+ FutureReservedWord("class", { es5: true, nud: classdef });
+ FutureReservedWord("double");
+ FutureReservedWord("enum", { es5: true });
+ FutureReservedWord("export", { es5: true });
+ FutureReservedWord("extends", { es5: true });
+ FutureReservedWord("final");
+ FutureReservedWord("float");
+ FutureReservedWord("goto");
+ FutureReservedWord("implements", { es5: true, strictOnly: true });
+ FutureReservedWord("import", { es5: true });
+ FutureReservedWord("int");
+ FutureReservedWord("interface", { es5: true, strictOnly: true });
+ FutureReservedWord("long");
+ FutureReservedWord("native");
+ FutureReservedWord("package", { es5: true, strictOnly: true });
+ FutureReservedWord("private", { es5: true, strictOnly: true });
+ FutureReservedWord("protected", { es5: true, strictOnly: true });
+ FutureReservedWord("public", { es5: true, strictOnly: true });
+ FutureReservedWord("short");
+ FutureReservedWord("static", { es5: true, strictOnly: true });
+ FutureReservedWord("super", { es5: true });
+ FutureReservedWord("synchronized");
+ FutureReservedWord("transient");
+ FutureReservedWord("volatile");
+
+ // this function is used to determine wether a squarebracket or a curlybracket
+ // expression is a comprehension array, destructuring assignment or a json value.
+
+ var lookupBlockType = function () {
+ var pn, pn1;
+ var i = -1;
+ var bracketStack = 0;
+ var ret = {};
+ if (_.contains(["[", "{"], state.tokens.curr.value))
+ bracketStack += 1;
+ do {
+ pn = (i === -1) ? state.tokens.next : peek(i);
+ pn1 = peek(i + 1);
+ i = i + 1;
+ if (_.contains(["[", "{"], pn.value)) {
+ bracketStack += 1;
+ } else if (_.contains(["]", "}"], pn.value)) {
+ bracketStack -= 1;
+ }
+ if (pn.identifier && pn.value === "for" && bracketStack === 1) {
+ ret.isCompArray = true;
+ ret.notJson = true;
+ break;
+ }
+ if (_.contains(["}", "]"], pn.value) && pn1.value === "=" && bracketStack === 0) {
+ ret.isDestAssign = true;
+ ret.notJson = true;
+ break;
+ }
+ if (pn.value === ";") {
+ ret.isBlock = true;
+ ret.notJson = true;
+ }
+ } while (bracketStack > 0 && pn.id !== "(end)" && i < 15);
+ return ret;
+ };
+
+ // Check whether this function has been reached for a destructuring assign with undeclared values
+ function destructuringAssignOrJsonValue() {
+ // lookup for the assignment (esnext only)
+ // if it has semicolons, it is a block, so go parse it as a block
+ // or it's not a block, but there are assignments, check for undeclared variables
+
+ var block = lookupBlockType();
+ if (block.notJson) {
+ if (!state.option.inESNext() && block.isDestAssign) {
+ warning("W104", state.tokens.curr, "destructuring assignment");
+ }
+ statements();
+ // otherwise parse json value
+ } else {
+ state.option.laxbreak = true;
+ state.jsonMode = true;
+ jsonValue();
+ }
+ }
+
+ // array comprehension parsing function
+ // parses and defines the three states of the list comprehension in order
+ // to avoid defining global variables, but keeping them to the list comprehension scope
+ // only. The order of the states are as follows:
+ // * "use" which will be the returned iterative part of the list comprehension
+ // * "define" which will define the variables local to the list comprehension
+ // * "filter" which will help filter out values
+
+ var arrayComprehension = function () {
+ var CompArray = function () {
+ this.mode = "use";
+ this.variables = [];
+ };
+ var _carrays = [];
+ var _current;
+ function declare(v) {
+ var l = _current.variables.filter(function (elt) {
+ // if it has, change its undef state
+ if (elt.value === v) {
+ elt.undef = false;
+ return v;
+ }
+ }).length;
+ return l !== 0;
+ }
+ function use(v) {
+ var l = _current.variables.filter(function (elt) {
+ // and if it has been defined
+ if (elt.value === v && !elt.undef) {
+ if (elt.unused === true) {
+ elt.unused = false;
+ }
+ return v;
+ }
+ }).length;
+ // otherwise we warn about it
+ return (l === 0);
+ }
+ return {stack: function () {
+ _current = new CompArray();
+ _carrays.push(_current);
+ },
+ unstack: function () {
+ _current.variables.filter(function (v) {
+ if (v.unused)
+ warning("W098", v.token, v.value);
+ if (v.undef)
+ isundef(v.funct, "W117", v.token, v.value);
+ });
+ _carrays.splice(-1, 1);
+ _current = _carrays[_carrays.length - 1];
+ },
+ setState: function (s) {
+ if (_.contains(["use", "define", "generate", "filter"], s))
+ _current.mode = s;
+ },
+ check: function (v) {
+ if (!_current) {
+ return;
+ }
+ // When we are in "use" state of the list comp, we enqueue that var
+ if (_current && _current.mode === "use") {
+ if (use(v)) {
+ _current.variables.push({
+ funct: funct,
+ token: state.tokens.curr,
+ value: v,
+ undef: true,
+ unused: false
+ });
+ }
+ return true;
+ // When we are in "define" state of the list comp,
+ } else if (_current && _current.mode === "define") {
+ // check if the variable has been used previously
+ if (!declare(v)) {
+ _current.variables.push({
+ funct: funct,
+ token: state.tokens.curr,
+ value: v,
+ undef: false,
+ unused: true
+ });
+ }
+ return true;
+ // When we are in the "generate" state of the list comp,
+ } else if (_current && _current.mode === "generate") {
+ isundef(funct, "W117", state.tokens.curr, v);
+ return true;
+ // When we are in "filter" state,
+ } else if (_current && _current.mode === "filter") {
+ // we check whether current variable has been declared
+ if (use(v)) {
+ // if not we warn about it
+ isundef(funct, "W117", state.tokens.curr, v);
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+ };
+
+
+ // Parse JSON
+
+ function jsonValue() {
+ function jsonObject() {
+ var o = {}, t = state.tokens.next;
+ advance("{");
+ if (state.tokens.next.id !== "}") {
+ for (;;) {
+ if (state.tokens.next.id === "(end)") {
+ error("E026", state.tokens.next, t.line);
+ } else if (state.tokens.next.id === "}") {
+ warning("W094", state.tokens.curr);
+ break;
+ } else if (state.tokens.next.id === ",") {
+ error("E028", state.tokens.next);
+ } else if (state.tokens.next.id !== "(string)") {
+ warning("W095", state.tokens.next, state.tokens.next.value);
+ }
+ if (o[state.tokens.next.value] === true) {
+ warning("W075", state.tokens.next, state.tokens.next.value);
+ } else if ((state.tokens.next.value === "__proto__" &&
+ !state.option.proto) || (state.tokens.next.value === "__iterator__" &&
+ !state.option.iterator)) {
+ warning("W096", state.tokens.next, state.tokens.next.value);
+ } else {
+ o[state.tokens.next.value] = true;
+ }
+ advance();
+ advance(":");
+ jsonValue();
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ advance(",");
+ }
+ }
+ advance("}");
+ }
+
+ function jsonArray() {
+ var t = state.tokens.next;
+ advance("[");
+ if (state.tokens.next.id !== "]") {
+ for (;;) {
+ if (state.tokens.next.id === "(end)") {
+ error("E027", state.tokens.next, t.line);
+ } else if (state.tokens.next.id === "]") {
+ warning("W094", state.tokens.curr);
+ break;
+ } else if (state.tokens.next.id === ",") {
+ error("E028", state.tokens.next);
+ }
+ jsonValue();
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ advance(",");
+ }
+ }
+ advance("]");
+ }
+
+ switch (state.tokens.next.id) {
+ case "{":
+ jsonObject();
+ break;
+ case "[":
+ jsonArray();
+ break;
+ case "true":
+ case "false":
+ case "null":
+ case "(number)":
+ case "(string)":
+ advance();
+ break;
+ case "-":
+ advance("-");
+ advance("(number)");
+ break;
+ default:
+ error("E003", state.tokens.next);
+ }
+ }
+
+ var blockScope = function () {
+ var _current = {};
+ var _variables = [_current];
+
+ function _checkBlockLabels() {
+ for (var t in _current) {
+ if (_current[t]["(type)"] === "unused") {
+ if (state.option.unused) {
+ var tkn = _current[t]["(token)"];
+ var line = tkn.line;
+ var chr = tkn.character;
+ warningAt("W098", line, chr, t);
+ }
+ }
+ }
+ }
+
+ return {
+ stack: function () {
+ _current = {};
+ _variables.push(_current);
+ },
+
+ unstack: function () {
+ _checkBlockLabels();
+ _variables.splice(_variables.length - 1, 1);
+ _current = _.last(_variables);
+ },
+
+ getlabel: function (l) {
+ for (var i = _variables.length - 1 ; i >= 0; --i) {
+ if (_.has(_variables[i], l) && !_variables[i][l]["(shadowed)"]) {
+ return _variables[i];
+ }
+ }
+ },
+
+ shadow: function (name) {
+ for (var i = _variables.length - 1; i >= 0; i--) {
+ if (_.has(_variables[i], name)) {
+ _variables[i][name]["(shadowed)"] = true;
+ }
+ }
+ },
+
+ unshadow: function (name) {
+ for (var i = _variables.length - 1; i >= 0; i--) {
+ if (_.has(_variables[i], name)) {
+ _variables[i][name]["(shadowed)"] = false;
+ }
+ }
+ },
+
+ current: {
+ has: function (t) {
+ return _.has(_current, t);
+ },
+
+ add: function (t, type, tok) {
+ _current[t] = { "(type)" : type, "(token)": tok, "(shadowed)": false };
+ }
+ }
+ };
+ };
+
+ // The actual JSHINT function itself.
+ var itself = function (s, o, g) {
+ var i, k, x;
+ var optionKeys;
+ var newOptionObj = {};
+ var newIgnoredObj = {};
+
+ o = _.clone(o);
+ state.reset();
+
+ if (o && o.scope) {
+ JSHINT.scope = o.scope;
+ } else {
+ JSHINT.errors = [];
+ JSHINT.undefs = [];
+ JSHINT.internals = [];
+ JSHINT.blacklist = {};
+ JSHINT.scope = "(main)";
+ }
+
+ predefined = Object.create(null);
+ combine(predefined, vars.ecmaIdentifiers);
+ combine(predefined, vars.reservedVars);
+
+ combine(predefined, g || {});
+
+ declared = Object.create(null);
+ exported = Object.create(null);
+
+ function each(obj, cb) {
+ if (!obj)
+ return;
+
+ if (!Array.isArray(obj) && typeof obj === "object")
+ obj = Object.keys(obj);
+
+ obj.forEach(cb);
+ }
+
+ if (o) {
+ each(o.predef || null, function (item) {
+ var slice, prop;
+
+ if (item[0] === "-") {
+ slice = item.slice(1);
+ JSHINT.blacklist[slice] = slice;
+ } else {
+ prop = Object.getOwnPropertyDescriptor(o.predef, item);
+ predefined[item] = prop ? prop.value : false;
+ }
+ });
+
+ each(o.exported || null, function (item) {
+ exported[item] = true;
+ });
+
+ delete o.predef;
+ delete o.exported;
+
+ optionKeys = Object.keys(o);
+ for (x = 0; x < optionKeys.length; x++) {
+ if (/^-W\d{3}$/g.test(optionKeys[x])) {
+ newIgnoredObj[optionKeys[x].slice(1)] = true;
+ } else {
+ newOptionObj[optionKeys[x]] = o[optionKeys[x]];
+
+ if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
+ newOptionObj["(explicitNewcap)"] = true;
+ }
+ }
+ }
+
+ state.option = newOptionObj;
+ state.ignored = newIgnoredObj;
+
+ state.option.indent = state.option.indent || 4;
+ state.option.maxerr = state.option.maxerr || 50;
+
+ indent = 1;
+ global = Object.create(predefined);
+ scope = global;
+
+ funct = functor("(global)", null, scope, {
+ "(global)" : true,
+ "(blockscope)": blockScope(),
+ "(comparray)" : arrayComprehension(),
+ "(metrics)" : createMetrics(state.tokens.next)
+ });
+
+ functions = [funct];
+ urls = [];
+ stack = null;
+ member = {};
+ membersOnly = null;
+ implied = {};
+ inblock = false;
+ lookahead = [];
+ unuseds = [];
+
+ if (!isString(s) && !Array.isArray(s)) {
+ errorAt("E004", 0);
+ return false;
+ }
+
+ api = {
+ get isJSON() {
+ return state.jsonMode;
+ },
+
+ getOption: function (name) {
+ return state.option[name] || null;
+ },
+
+ getCache: function (name) {
+ return state.cache[name];
+ },
+
+ setCache: function (name, value) {
+ state.cache[name] = value;
+ },
+
+ warn: function (code, data) {
+ warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));
+ },
+
+ on: function (names, listener) {
+ names.split(" ").forEach(function (name) {
+ emitter.on(name, listener);
+ }.bind(this));
+ }
+ };
+
+ emitter.removeAllListeners();
+ (extraModules || []).forEach(function (func) {
+ func(api);
+ });
+
+ state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
+
+ lex = new Lexer(s);
+
+ lex.on("warning", function (ev) {
+ warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
+ });
+
+ lex.on("error", function (ev) {
+ errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
+ });
+
+ lex.on("fatal", function (ev) {
+ quit("E041", ev.line, ev.from);
+ });
+
+ lex.on("Identifier", function (ev) {
+ emitter.emit("Identifier", ev);
+ });
+
+ lex.on("String", function (ev) {
+ emitter.emit("String", ev);
+ });
+
+ lex.on("Number", function (ev) {
+ emitter.emit("Number", ev);
+ });
+
+ lex.start();
+
+ // Check options
+ for (var name in o) {
+ if (_.has(o, name)) {
+ checkOption(name, state.tokens.curr);
+ }
+ }
+
+ assume();
+
+ // combine the passed globals after we've assumed all our options
+ combine(predefined, g || {});
+
+ //reset values
+ comma.first = true;
+
+ try {
+ advance();
+ switch (state.tokens.next.id) {
+ case "{":
+ case "[":
+ destructuringAssignOrJsonValue();
+ break;
+ default:
+ directives();
+
+ if (state.directive["use strict"]) {
+ if (!state.option.globalstrict && !(state.option.node || state.option.phantom)) {
+ warning("W097", state.tokens.prev);
+ }
+ }
+
+ statements();
+ }
+ advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined);
+ funct["(blockscope)"].unstack();
+
+ var markDefined = function (name, context) {
+ do {
+ if (typeof context[name] === "string") {
+ // JSHINT marks unused variables as 'unused' and
+ // unused function declaration as 'unction'. This
+ // code changes such instances back 'var' and
+ // 'closure' so that the code in JSHINT.data()
+ // doesn't think they're unused.
+
+ if (context[name] === "unused")
+ context[name] = "var";
+ else if (context[name] === "unction")
+ context[name] = "closure";
+
+ return true;
+ }
+
+ context = context["(context)"];
+ } while (context);
+
+ return false;
+ };
+
+ var clearImplied = function (name, line) {
+ if (!implied[name])
+ return;
+
+ var newImplied = [];
+ for (var i = 0; i < implied[name].length; i += 1) {
+ if (implied[name][i] !== line)
+ newImplied.push(implied[name][i]);
+ }
+
+ if (newImplied.length === 0)
+ delete implied[name];
+ else
+ implied[name] = newImplied;
+ };
+
+ var warnUnused = function (name, tkn, type, unused_opt) {
+ var line = tkn.line;
+ var chr = tkn.character;
+
+ if (unused_opt === undefined) {
+ unused_opt = state.option.unused;
+ }
+
+ if (unused_opt === true) {
+ unused_opt = "last-param";
+ }
+
+ var warnable_types = {
+ "vars": ["var"],
+ "last-param": ["var", "param"],
+ "strict": ["var", "param", "last-param"]
+ };
+
+ if (unused_opt) {
+ if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
+ warningAt("W098", line, chr, name);
+ }
+ }
+
+ unuseds.push({
+ name: name,
+ line: line,
+ character: chr
+ });
+ };
+
+ var checkUnused = function (func, key) {
+ var type = func[key];
+ var tkn = func["(tokens)"][key];
+
+ if (key.charAt(0) === "(")
+ return;
+
+ if (type !== "unused" && type !== "unction" && type !== "const")
+ return;
+
+ // Params are checked separately from other variables.
+ if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
+ return;
+
+ // Variable is in global scope and defined as exported.
+ if (func["(global)"] && _.has(exported, key))
+ return;
+
+ // Is this constant unused?
+ if (type === "const" && !getprop(func, key, "unused"))
+ return;
+
+ warnUnused(key, tkn, "var");
+ };
+
+ // Check queued 'x is not defined' instances to see if they're still undefined.
+ for (i = 0; i < JSHINT.undefs.length; i += 1) {
+ k = JSHINT.undefs[i].slice(0);
+
+ if (markDefined(k[2].value, k[0])) {
+ clearImplied(k[2].value, k[2].line);
+ } else if (state.option.undef) {
+ warning.apply(warning, k.slice(1));
+ }
+ }
+
+ functions.forEach(function (func) {
+ if (func["(unusedOption)"] === false) {
+ return;
+ }
+
+ for (var key in func) {
+ if (_.has(func, key)) {
+ checkUnused(func, key);
+ }
+ }
+
+ if (!func["(params)"])
+ return;
+
+ var params = func["(params)"].slice();
+ var param = params.pop();
+ var type, unused_opt;
+
+ while (param) {
+ type = func[param];
+ unused_opt = func["(unusedOption)"] || state.option.unused;
+ unused_opt = unused_opt === true ? "last-param" : unused_opt;
+
+ // 'undefined' is a special case for (function (window, undefined) { ... })();
+ // patterns.
+
+ if (param === "undefined")
+ return;
+
+ if (type === "unused" || type === "unction") {
+ warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]);
+ } else if (unused_opt === "last-param") {
+ return;
+ }
+
+ param = params.pop();
+ }
+ });
+
+ for (var key in declared) {
+ if (_.has(declared, key) && !_.has(global, key) && !_.has(exported, key)) {
+ warnUnused(key, declared[key], "var");
+ }
+ }
+
+ } catch (err) {
+ if (err && err.name === "JSHintError") {
+ var nt = state.tokens.next || {};
+ JSHINT.errors.push({
+ scope : "(main)",
+ raw : err.raw,
+ code : err.code,
+ reason : err.message,
+ line : err.line || nt.line,
+ character : err.character || nt.from
+ }, null);
+ } else {
+ throw err;
+ }
+ }
+
+ // Loop over the listed "internals", and check them as well.
+
+ if (JSHINT.scope === "(main)") {
+ o = o || {};
+
+ for (i = 0; i < JSHINT.internals.length; i += 1) {
+ k = JSHINT.internals[i];
+ o.scope = k.elem;
+ itself(k.value, o, g);
+ }
+ }
+
+ return JSHINT.errors.length === 0;
+ };
+
+ // Modules.
+ itself.addModule = function (func) {
+ extraModules.push(func);
+ };
+
+ itself.addModule(style.register);
+
+ // Data summary.
+ itself.data = function () {
+ var data = {
+ functions: [],
+ options: state.option
+ };
+
+ var implieds = [];
+ var members = [];
+ var fu, f, i, j, n, globals;
+
+ if (itself.errors.length) {
+ data.errors = itself.errors;
+ }
+
+ if (state.jsonMode) {
+ data.json = true;
+ }
+
+ for (n in implied) {
+ if (_.has(implied, n)) {
+ implieds.push({
+ name: n,
+ line: implied[n]
+ });
+ }
+ }
+
+ if (implieds.length > 0) {
+ data.implieds = implieds;
+ }
+
+ if (urls.length > 0) {
+ data.urls = urls;
+ }
+
+ globals = Object.keys(scope);
+ if (globals.length > 0) {
+ data.globals = globals;
+ }
+
+ for (i = 1; i < functions.length; i += 1) {
+ f = functions[i];
+ fu = {};
+
+ for (j = 0; j < functionicity.length; j += 1) {
+ fu[functionicity[j]] = [];
+ }
+
+ for (j = 0; j < functionicity.length; j += 1) {
+ if (fu[functionicity[j]].length === 0) {
+ delete fu[functionicity[j]];
+ }
+ }
+
+ fu.name = f["(name)"];
+ fu.param = f["(params)"];
+ fu.line = f["(line)"];
+ fu.character = f["(character)"];
+ fu.last = f["(last)"];
+ fu.lastcharacter = f["(lastcharacter)"];
+
+ fu.metrics = {
+ complexity: f["(metrics)"].ComplexityCount,
+ parameters: (f["(params)"] || []).length,
+ statements: f["(metrics)"].statementCount
+ };
+
+ data.functions.push(fu);
+ }
+
+ if (unuseds.length > 0) {
+ data.unused = unuseds;
+ }
+
+ members = [];
+ for (n in member) {
+ if (typeof member[n] === "number") {
+ data.member = member;
+ break;
+ }
+ }
+
+ return data;
+ };
+
+ itself.jshint = itself;
+
+ return itself;
+}());
+
+// Make JSHINT a Node module, if possible.
+if (typeof exports === "object" && exports) {
+ exports.JSHINT = JSHINT;
+}
+
+},{"./lex.js":16,"./messages.js":17,"./reg.js":18,"./state.js":19,"./style.js":20,"./vars.js":21,"console-browserify":12,"events":7,"underscore":13}],16:[function(require,module,exports){
+/*
+ * Lexical analysis and token construction.
+ */
+
+"use strict";
+
+var _ = require("underscore");
+var events = require("events");
+var reg = require("./reg.js");
+var state = require("./state.js").state;
+
+var unicodeData = require("../data/ascii-identifier-data.js");
+var asciiIdentifierStartTable = unicodeData.asciiIdentifierStartTable;
+var asciiIdentifierPartTable = unicodeData.asciiIdentifierPartTable;
+var nonAsciiIdentifierStartTable = require("../data/non-ascii-identifier-start.js");
+var nonAsciiIdentifierPartTable = require("../data/non-ascii-identifier-part-only.js");
+
+// Some of these token types are from JavaScript Parser API
+// while others are specific to JSHint parser.
+// JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
+
+var Token = {
+ Identifier: 1,
+ Punctuator: 2,
+ NumericLiteral: 3,
+ StringLiteral: 4,
+ Comment: 5,
+ Keyword: 6,
+ NullLiteral: 7,
+ BooleanLiteral: 8,
+ RegExp: 9,
+ TemplateLiteral: 10
+};
+
+// Object that handles postponed lexing verifications that checks the parsed
+// environment state.
+
+function asyncTrigger() {
+ var _checks = [];
+
+ return {
+ push: function (fn) {
+ _checks.push(fn);
+ },
+
+ check: function () {
+ for (var check = 0; check < _checks.length; ++check) {
+ _checks[check]();
+ }
+
+ _checks.splice(0, _checks.length);
+ }
+ };
+}
+
+/*
+ * Lexer for JSHint.
+ *
+ * This object does a char-by-char scan of the provided source code
+ * and produces a sequence of tokens.
+ *
+ * var lex = new Lexer("var i = 0;");
+ * lex.start();
+ * lex.token(); // returns the next token
+ *
+ * You have to use the token() method to move the lexer forward
+ * but you don't have to use its return value to get tokens. In addition
+ * to token() method returning the next token, the Lexer object also
+ * emits events.
+ *
+ * lex.on("Identifier", function (data) {
+ * if (data.name.indexOf("_") >= 0) {
+ * // Produce a warning.
+ * }
+ * });
+ *
+ * Note that the token() method returns tokens in a JSLint-compatible
+ * format while the event emitter uses a slightly modified version of
+ * Mozilla's JavaScript Parser API. Eventually, we will move away from
+ * JSLint format.
+ */
+function Lexer(source) {
+ var lines = source;
+
+ if (typeof lines === "string") {
+ lines = lines
+ .replace(/\r\n/g, "\n")
+ .replace(/\r/g, "\n")
+ .split("\n");
+ }
+
+ // If the first line is a shebang (#!), make it a blank and move on.
+ // Shebangs are used by Node scripts.
+
+ if (lines[0] && lines[0].substr(0, 2) === "#!") {
+ if (lines[0].indexOf("node") !== -1) {
+ state.option.node = true;
+ }
+ lines[0] = "";
+ }
+
+ this.emitter = new events.EventEmitter();
+ this.source = source;
+ this.setLines(lines);
+ this.prereg = true;
+
+ this.line = 0;
+ this.char = 1;
+ this.from = 1;
+ this.input = "";
+ this.inComment = false;
+
+ for (var i = 0; i < state.option.indent; i += 1) {
+ state.tab += " ";
+ }
+}
+
+Lexer.prototype = {
+ _lines: [],
+
+ getLines: function () {
+ this._lines = state.lines;
+ return this._lines;
+ },
+
+ setLines: function (val) {
+ this._lines = val;
+ state.lines = this._lines;
+ },
+
+ /*
+ * Return the next i character without actually moving the
+ * char pointer.
+ */
+ peek: function (i) {
+ return this.input.charAt(i || 0);
+ },
+
+ /*
+ * Move the char pointer forward i times.
+ */
+ skip: function (i) {
+ i = i || 1;
+ this.char += i;
+ this.input = this.input.slice(i);
+ },
+
+ /*
+ * Subscribe to a token event. The API for this method is similar
+ * Underscore.js i.e. you can subscribe to multiple events with
+ * one call:
+ *
+ * lex.on("Identifier Number", function (data) {
+ * // ...
+ * });
+ */
+ on: function (names, listener) {
+ names.split(" ").forEach(function (name) {
+ this.emitter.on(name, listener);
+ }.bind(this));
+ },
+
+ /*
+ * Trigger a token event. All arguments will be passed to each
+ * listener.
+ */
+ trigger: function () {
+ this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
+ },
+
+ /*
+ * Postpone a token event. the checking condition is set as
+ * last parameter, and the trigger function is called in a
+ * stored callback. To be later called using the check() function
+ * by the parser. This avoids parser's peek() to give the lexer
+ * a false context.
+ */
+ triggerAsync: function (type, args, checks, fn) {
+ checks.push(function () {
+ if (fn()) {
+ this.trigger(type, args);
+ }
+ }.bind(this));
+ },
+
+ /*
+ * Extract a punctuator out of the next sequence of characters
+ * or return 'null' if its not possible.
+ *
+ * This method's implementation was heavily influenced by the
+ * scanPunctuator function in the Esprima parser's source code.
+ */
+ scanPunctuator: function () {
+ var ch1 = this.peek();
+ var ch2, ch3, ch4;
+
+ switch (ch1) {
+ // Most common single-character punctuators
+ case ".":
+ if ((/^[0-9]$/).test(this.peek(1))) {
+ return null;
+ }
+ if (this.peek(1) === "." && this.peek(2) === ".") {
+ return {
+ type: Token.Punctuator,
+ value: "..."
+ };
+ }
+ /* falls through */
+ case "(":
+ case ")":
+ case ";":
+ case ",":
+ case "{":
+ case "}":
+ case "[":
+ case "]":
+ case ":":
+ case "~":
+ case "?":
+ return {
+ type: Token.Punctuator,
+ value: ch1
+ };
+
+ // A pound sign (for Node shebangs)
+ case "#":
+ return {
+ type: Token.Punctuator,
+ value: ch1
+ };
+
+ // We're at the end of input
+ case "":
+ return null;
+ }
+
+ // Peek more characters
+
+ ch2 = this.peek(1);
+ ch3 = this.peek(2);
+ ch4 = this.peek(3);
+
+ // 4-character punctuator: >>>=
+
+ if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: ">>>="
+ };
+ }
+
+ // 3-character punctuators: === !== >>> <<= >>=
+
+ if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: "==="
+ };
+ }
+
+ if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: "!=="
+ };
+ }
+
+ if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
+ return {
+ type: Token.Punctuator,
+ value: ">>>"
+ };
+ }
+
+ if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: "<<="
+ };
+ }
+
+ if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: ">>="
+ };
+ }
+
+ // Fat arrow punctuator
+ if (ch1 === "=" && ch2 === ">") {
+ return {
+ type: Token.Punctuator,
+ value: ch1 + ch2
+ };
+ }
+
+ // 2-character punctuators: <= >= == != ++ -- << >> && ||
+ // += -= *= %= &= |= ^= (but not /=, see below)
+ if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
+ return {
+ type: Token.Punctuator,
+ value: ch1 + ch2
+ };
+ }
+
+ if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
+ if (ch2 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: ch1 + ch2
+ };
+ }
+
+ return {
+ type: Token.Punctuator,
+ value: ch1
+ };
+ }
+
+ // Special case: /=. We need to make sure that this is an
+ // operator and not a regular expression.
+
+ if (ch1 === "/") {
+ if (ch2 === "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input)) {
+ // /= is not a part of a regular expression, return it as a
+ // punctuator.
+ return {
+ type: Token.Punctuator,
+ value: "/="
+ };
+ }
+
+ return {
+ type: Token.Punctuator,
+ value: "/"
+ };
+ }
+
+ return null;
+ },
+
+ /*
+ * Extract a comment out of the next sequence of characters and/or
+ * lines or return 'null' if its not possible. Since comments can
+ * span across multiple lines this method has to move the char
+ * pointer.
+ *
+ * In addition to normal JavaScript comments (// and /*) this method
+ * also recognizes JSHint- and JSLint-specific comments such as
+ * /*jshint, /*jslint, /*globals and so on.
+ */
+ scanComments: function () {
+ var ch1 = this.peek();
+ var ch2 = this.peek(1);
+ var rest = this.input.substr(2);
+ var startLine = this.line;
+ var startChar = this.char;
+
+ // Create a comment token object and make sure it
+ // has all the data JSHint needs to work with special
+ // comments.
+
+ function commentToken(label, body, opt) {
+ var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
+ var isSpecial = false;
+ var value = label + body;
+ var commentType = "plain";
+ opt = opt || {};
+
+ if (opt.isMultiline) {
+ value += "*/";
+ }
+
+ special.forEach(function (str) {
+ if (isSpecial) {
+ return;
+ }
+
+ // Don't recognize any special comments other than jshint for single-line
+ // comments. This introduced many problems with legit comments.
+ if (label === "//" && str !== "jshint") {
+ return;
+ }
+
+ if (body.substr(0, str.length) === str) {
+ isSpecial = true;
+ label = label + str;
+ body = body.substr(str.length);
+ }
+
+ if (!isSpecial && body.charAt(0) === " " && body.substr(1, str.length) === str) {
+ isSpecial = true;
+ label = label + " " + str;
+ body = body.substr(str.length + 1);
+ }
+
+ if (!isSpecial) {
+ return;
+ }
+
+ switch (str) {
+ case "member":
+ commentType = "members";
+ break;
+ case "global":
+ commentType = "globals";
+ break;
+ default:
+ commentType = str;
+ }
+ });
+
+ return {
+ type: Token.Comment,
+ commentType: commentType,
+ value: value,
+ body: body,
+ isSpecial: isSpecial,
+ isMultiline: opt.isMultiline || false,
+ isMalformed: opt.isMalformed || false
+ };
+ }
+
+ // End of unbegun comment. Raise an error and skip that input.
+ if (ch1 === "*" && ch2 === "/") {
+ this.trigger("error", {
+ code: "E018",
+ line: startLine,
+ character: startChar
+ });
+
+ this.skip(2);
+ return null;
+ }
+
+ // Comments must start either with // or /*
+ if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
+ return null;
+ }
+
+ // One-line comment
+ if (ch2 === "/") {
+ this.skip(this.input.length); // Skip to the EOL.
+ return commentToken("//", rest);
+ }
+
+ var body = "";
+
+ /* Multi-line comment */
+ if (ch2 === "*") {
+ this.inComment = true;
+ this.skip(2);
+
+ while (this.peek() !== "*" || this.peek(1) !== "/") {
+ if (this.peek() === "") { // End of Line
+ body += "\n";
+
+ // If we hit EOF and our comment is still unclosed,
+ // trigger an error and end the comment implicitly.
+ if (!this.nextLine()) {
+ this.trigger("error", {
+ code: "E017",
+ line: startLine,
+ character: startChar
+ });
+
+ this.inComment = false;
+ return commentToken("/*", body, {
+ isMultiline: true,
+ isMalformed: true
+ });
+ }
+ } else {
+ body += this.peek();
+ this.skip();
+ }
+ }
+
+ this.skip(2);
+ this.inComment = false;
+ return commentToken("/*", body, { isMultiline: true });
+ }
+ },
+
+ /*
+ * Extract a keyword out of the next sequence of characters or
+ * return 'null' if its not possible.
+ */
+ scanKeyword: function () {
+ var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
+ var keywords = [
+ "if", "in", "do", "var", "for", "new",
+ "try", "let", "this", "else", "case",
+ "void", "with", "enum", "while", "break",
+ "catch", "throw", "const", "yield", "class",
+ "super", "return", "typeof", "delete",
+ "switch", "export", "import", "default",
+ "finally", "extends", "function", "continue",
+ "debugger", "instanceof"
+ ];
+
+ if (result && keywords.indexOf(result[0]) >= 0) {
+ return {
+ type: Token.Keyword,
+ value: result[0]
+ };
+ }
+
+ return null;
+ },
+
+ /*
+ * Extract a JavaScript identifier out of the next sequence of
+ * characters or return 'null' if its not possible. In addition,
+ * to Identifier this method can also produce BooleanLiteral
+ * (true/false) and NullLiteral (null).
+ */
+ scanIdentifier: function () {
+ var id = "";
+ var index = 0;
+ var type, char;
+
+ function isNonAsciiIdentifierStart(code) {
+ return nonAsciiIdentifierStartTable.indexOf(code) > -1;
+ }
+
+ function isNonAsciiIdentifierPart(code) {
+ return isNonAsciiIdentifierStart(code) || nonAsciiIdentifierPartTable.indexOf(code) > -1;
+ }
+
+ function isHexDigit(str) {
+ return (/^[0-9a-fA-F]$/).test(str);
+ }
+
+ var readUnicodeEscapeSequence = function () {
+ /*jshint validthis:true */
+ index += 1;
+
+ if (this.peek(index) !== "u") {
+ return null;
+ }
+
+ var ch1 = this.peek(index + 1);
+ var ch2 = this.peek(index + 2);
+ var ch3 = this.peek(index + 3);
+ var ch4 = this.peek(index + 4);
+ var code;
+
+ if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
+ code = parseInt(ch1 + ch2 + ch3 + ch4, 16);
+
+ if (asciiIdentifierPartTable[code] || isNonAsciiIdentifierPart(code)) {
+ index += 5;
+ return "\\u" + ch1 + ch2 + ch3 + ch4;
+ }
+
+ return null;
+ }
+
+ return null;
+ }.bind(this);
+
+ var getIdentifierStart = function () {
+ /*jshint validthis:true */
+ var chr = this.peek(index);
+ var code = chr.charCodeAt(0);
+
+ if (code === 92) {
+ return readUnicodeEscapeSequence();
+ }
+
+ if (code < 128) {
+ if (asciiIdentifierStartTable[code]) {
+ index += 1;
+ return chr;
+ }
+
+ return null;
+ }
+
+ if (isNonAsciiIdentifierStart(code)) {
+ index += 1;
+ return chr;
+ }
+
+ return null;
+ }.bind(this);
+
+ var getIdentifierPart = function () {
+ /*jshint validthis:true */
+ var chr = this.peek(index);
+ var code = chr.charCodeAt(0);
+
+ if (code === 92) {
+ return readUnicodeEscapeSequence();
+ }
+
+ if (code < 128) {
+ if (asciiIdentifierPartTable[code]) {
+ index += 1;
+ return chr;
+ }
+
+ return null;
+ }
+
+ if (isNonAsciiIdentifierPart(code)) {
+ index += 1;
+ return chr;
+ }
+
+ return null;
+ }.bind(this);
+
+ char = getIdentifierStart();
+ if (char === null) {
+ return null;
+ }
+
+ id = char;
+ for (;;) {
+ char = getIdentifierPart();
+
+ if (char === null) {
+ break;
+ }
+
+ id += char;
+ }
+
+ switch (id) {
+ case "true":
+ case "false":
+ type = Token.BooleanLiteral;
+ break;
+ case "null":
+ type = Token.NullLiteral;
+ break;
+ default:
+ type = Token.Identifier;
+ }
+
+ return {
+ type: type,
+ value: id
+ };
+ },
+
+ /*
+ * Extract a numeric literal out of the next sequence of
+ * characters or return 'null' if its not possible. This method
+ * supports all numeric literals described in section 7.8.3
+ * of the EcmaScript 5 specification.
+ *
+ * This method's implementation was heavily influenced by the
+ * scanNumericLiteral function in the Esprima parser's source code.
+ */
+ scanNumericLiteral: function () {
+ var index = 0;
+ var value = "";
+ var length = this.input.length;
+ var char = this.peek(index);
+ var bad;
+
+ function isDecimalDigit(str) {
+ return (/^[0-9]$/).test(str);
+ }
+
+ function isOctalDigit(str) {
+ return (/^[0-7]$/).test(str);
+ }
+
+ function isHexDigit(str) {
+ return (/^[0-9a-fA-F]$/).test(str);
+ }
+
+ function isIdentifierStart(ch) {
+ return (ch === "$") || (ch === "_") || (ch === "\\") ||
+ (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
+ }
+
+ // Numbers must start either with a decimal digit or a point.
+
+ if (char !== "." && !isDecimalDigit(char)) {
+ return null;
+ }
+
+ if (char !== ".") {
+ value = this.peek(index);
+ index += 1;
+ char = this.peek(index);
+
+ if (value === "0") {
+ // Base-16 numbers.
+ if (char === "x" || char === "X") {
+ index += 1;
+ value += char;
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!isHexDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+
+ if (value.length <= 2) { // 0x
+ return {
+ type: Token.NumericLiteral,
+ value: value,
+ isMalformed: true
+ };
+ }
+
+ if (index < length) {
+ char = this.peek(index);
+ if (isIdentifierStart(char)) {
+ return null;
+ }
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: value,
+ base: 16,
+ isMalformed: false
+ };
+ }
+
+ // Base-8 numbers.
+ if (isOctalDigit(char)) {
+ index += 1;
+ value += char;
+ bad = false;
+
+ while (index < length) {
+ char = this.peek(index);
+
+ // Numbers like '019' (note the 9) are not valid octals
+ // but we still parse them and mark as malformed.
+
+ if (isDecimalDigit(char)) {
+ bad = true;
+ } else if (!isOctalDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+
+ if (index < length) {
+ char = this.peek(index);
+ if (isIdentifierStart(char)) {
+ return null;
+ }
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: value,
+ base: 8,
+ isMalformed: false
+ };
+ }
+
+ // Decimal numbers that start with '0' such as '09' are illegal
+ // but we still parse them and return as malformed.
+
+ if (isDecimalDigit(char)) {
+ index += 1;
+ value += char;
+ }
+ }
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!isDecimalDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+ }
+
+ // Decimal digits.
+
+ if (char === ".") {
+ value += char;
+ index += 1;
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!isDecimalDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+ }
+
+ // Exponent part.
+
+ if (char === "e" || char === "E") {
+ value += char;
+ index += 1;
+ char = this.peek(index);
+
+ if (char === "+" || char === "-") {
+ value += this.peek(index);
+ index += 1;
+ }
+
+ char = this.peek(index);
+ if (isDecimalDigit(char)) {
+ value += char;
+ index += 1;
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!isDecimalDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ if (index < length) {
+ char = this.peek(index);
+ if (isIdentifierStart(char)) {
+ return null;
+ }
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: value,
+ base: 10,
+ isMalformed: !isFinite(value)
+ };
+ },
+
+ /*
+ * Extract a template literal out of the next sequence of characters
+ * and/or lines or return 'null' if its not possible. Since template
+ * literals can span across multiple lines, this method has to move
+ * the char pointer.
+ */
+ scanTemplateLiteral: function () {
+ // String must start with a backtick.
+ if (!state.option.esnext || this.peek() !== "`") {
+ return null;
+ }
+
+ var startLine = this.line;
+ var startChar = this.char;
+ var jump = 1;
+ var value = "";
+
+ // For now, do not perform any linting of the content of the template
+ // string. Just skip until the next backtick is found.
+ this.skip();
+
+ while (this.peek() !== "`") {
+ while (this.peek() === "") {
+ // End of line --- For template literals in ES6, no backslash is
+ // required to precede newlines.
+ if (!this.nextLine()) {
+ this.trigger("error", {
+ code: "E052",
+ line: startLine,
+ character: startChar
+ });
+
+ return {
+ type: Token.TemplateLiteral,
+ value: value,
+ isUnclosed: true
+ };
+ }
+ value += "\n";
+ }
+
+ // TODO: do more interesting linting here, similar to string literal
+ // linting.
+ var char = this.peek();
+ this.skip(jump);
+ value += char;
+ }
+
+ this.skip();
+ return {
+ type: Token.TemplateLiteral,
+ value: value,
+ isUnclosed: false
+ };
+ },
+
+ /*
+ * Extract a string out of the next sequence of characters and/or
+ * lines or return 'null' if its not possible. Since strings can
+ * span across multiple lines this method has to move the char
+ * pointer.
+ *
+ * This method recognizes pseudo-multiline JavaScript strings:
+ *
+ * var str = "hello\
+ * world";
+ */
+ scanStringLiteral: function (checks) {
+ /*jshint loopfunc:true */
+ var quote = this.peek();
+
+ // String must start with a quote.
+ if (quote !== "\"" && quote !== "'") {
+ return null;
+ }
+
+ // In JSON strings must always use double quotes.
+ this.triggerAsync("warning", {
+ code: "W108",
+ line: this.line,
+ character: this.char // +1?
+ }, checks, function () { return state.jsonMode && quote !== "\""; });
+
+ var value = "";
+ var startLine = this.line;
+ var startChar = this.char;
+ var allowNewLine = false;
+
+ this.skip();
+
+ while (this.peek() !== quote) {
+ while (this.peek() === "") { // End Of Line
+
+ // If an EOL is not preceded by a backslash, show a warning
+ // and proceed like it was a legit multi-line string where
+ // author simply forgot to escape the newline symbol.
+ //
+ // Another approach is to implicitly close a string on EOL
+ // but it generates too many false positives.
+
+ if (!allowNewLine) {
+ this.trigger("warning", {
+ code: "W112",
+ line: this.line,
+ character: this.char
+ });
+ } else {
+ allowNewLine = false;
+
+ // Otherwise show a warning if multistr option was not set.
+ // For JSON, show warning no matter what.
+
+ this.triggerAsync("warning", {
+ code: "W043",
+ line: this.line,
+ character: this.char
+ }, checks, function () { return !state.option.multistr; });
+
+ this.triggerAsync("warning", {
+ code: "W042",
+ line: this.line,
+ character: this.char
+ }, checks, function () { return state.jsonMode && state.option.multistr; });
+ }
+
+ // If we get an EOF inside of an unclosed string, show an
+ // error and implicitly close it at the EOF point.
+
+ if (!this.nextLine()) {
+ this.trigger("error", {
+ code: "E029",
+ line: startLine,
+ character: startChar
+ });
+
+ return {
+ type: Token.StringLiteral,
+ value: value,
+ isUnclosed: true,
+ quote: quote
+ };
+ }
+ }
+
+ allowNewLine = false;
+ var char = this.peek();
+ var jump = 1; // A length of a jump, after we're done
+ // parsing this character.
+
+ if (char < " ") {
+ // Warn about a control character in a string.
+ this.trigger("warning", {
+ code: "W113",
+ line: this.line,
+ character: this.char,
+ data: [ "" ]
+ });
+ }
+
+ // Special treatment for some escaped characters.
+
+ if (char === "\\") {
+ this.skip();
+ char = this.peek();
+
+ switch (char) {
+ case "'":
+ this.triggerAsync("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.char,
+ data: [ "\\'" ]
+ }, checks, function () {return state.jsonMode; });
+ break;
+ case "b":
+ char = "\\b";
+ break;
+ case "f":
+ char = "\\f";
+ break;
+ case "n":
+ char = "\\n";
+ break;
+ case "r":
+ char = "\\r";
+ break;
+ case "t":
+ char = "\\t";
+ break;
+ case "0":
+ char = "\\0";
+
+ // Octal literals fail in strict mode.
+ // Check if the number is between 00 and 07.
+ var n = parseInt(this.peek(1), 10);
+ this.triggerAsync("warning", {
+ code: "W115",
+ line: this.line,
+ character: this.char
+ }, checks,
+ function () { return n >= 0 && n <= 7 && state.directive["use strict"]; });
+ break;
+ case "u":
+ char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));
+ jump = 5;
+ break;
+ case "v":
+ this.triggerAsync("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.char,
+ data: [ "\\v" ]
+ }, checks, function () { return state.jsonMode; });
+
+ char = "\v";
+ break;
+ case "x":
+ var x = parseInt(this.input.substr(1, 2), 16);
+
+ this.triggerAsync("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.char,
+ data: [ "\\x-" ]
+ }, checks, function () { return state.jsonMode; });
+
+ char = String.fromCharCode(x);
+ jump = 3;
+ break;
+ case "\\":
+ char = "\\\\";
+ break;
+ case "\"":
+ char = "\\\"";
+ break;
+ case "/":
+ break;
+ case "":
+ allowNewLine = true;
+ char = "";
+ break;
+ case "!":
+ if (value.slice(value.length - 2) === "<") {
+ break;
+ }
+
+ /*falls through */
+ default:
+ // Weird escaping.
+ this.trigger("warning", {
+ code: "W044",
+ line: this.line,
+ character: this.char
+ });
+ }
+ }
+
+ value += char;
+ this.skip(jump);
+ }
+
+ this.skip();
+ return {
+ type: Token.StringLiteral,
+ value: value,
+ isUnclosed: false,
+ quote: quote
+ };
+ },
+
+ /*
+ * Extract a regular expression out of the next sequence of
+ * characters and/or lines or return 'null' if its not possible.
+ *
+ * This method is platform dependent: it accepts almost any
+ * regular expression values but then tries to compile and run
+ * them using system's RegExp object. This means that there are
+ * rare edge cases where one JavaScript engine complains about
+ * your regular expression while others don't.
+ */
+ scanRegExp: function () {
+ var index = 0;
+ var length = this.input.length;
+ var char = this.peek();
+ var value = char;
+ var body = "";
+ var flags = [];
+ var malformed = false;
+ var isCharSet = false;
+ var terminated;
+
+ var scanUnexpectedChars = function () {
+ // Unexpected control character
+ if (char < " ") {
+ malformed = true;
+ this.trigger("warning", {
+ code: "W048",
+ line: this.line,
+ character: this.char
+ });
+ }
+
+ // Unexpected escaped character
+ if (char === "<") {
+ malformed = true;
+ this.trigger("warning", {
+ code: "W049",
+ line: this.line,
+ character: this.char,
+ data: [ char ]
+ });
+ }
+ }.bind(this);
+
+ // Regular expressions must start with '/'
+ if (!this.prereg || char !== "/") {
+ return null;
+ }
+
+ index += 1;
+ terminated = false;
+
+ // Try to get everything in between slashes. A couple of
+ // cases aside (see scanUnexpectedChars) we don't really
+ // care whether the resulting expression is valid or not.
+ // We will check that later using the RegExp object.
+
+ while (index < length) {
+ char = this.peek(index);
+ value += char;
+ body += char;
+
+ if (isCharSet) {
+ if (char === "]") {
+ if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
+ isCharSet = false;
+ }
+ }
+
+ if (char === "\\") {
+ index += 1;
+ char = this.peek(index);
+ body += char;
+ value += char;
+
+ scanUnexpectedChars();
+ }
+
+ index += 1;
+ continue;
+ }
+
+ if (char === "\\") {
+ index += 1;
+ char = this.peek(index);
+ body += char;
+ value += char;
+
+ scanUnexpectedChars();
+
+ if (char === "/") {
+ index += 1;
+ continue;
+ }
+
+ if (char === "[") {
+ index += 1;
+ continue;
+ }
+ }
+
+ if (char === "[") {
+ isCharSet = true;
+ index += 1;
+ continue;
+ }
+
+ if (char === "/") {
+ body = body.substr(0, body.length - 1);
+ terminated = true;
+ index += 1;
+ break;
+ }
+
+ index += 1;
+ }
+
+ // A regular expression that was never closed is an
+ // error from which we cannot recover.
+
+ if (!terminated) {
+ this.trigger("error", {
+ code: "E015",
+ line: this.line,
+ character: this.from
+ });
+
+ return void this.trigger("fatal", {
+ line: this.line,
+ from: this.from
+ });
+ }
+
+ // Parse flags (if any).
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!/[gim]/.test(char)) {
+ break;
+ }
+ flags.push(char);
+ value += char;
+ index += 1;
+ }
+
+ // Check regular expression for correctness.
+
+ try {
+ new RegExp(body, flags.join(""));
+ } catch (err) {
+ malformed = true;
+ this.trigger("error", {
+ code: "E016",
+ line: this.line,
+ character: this.char,
+ data: [ err.message ] // Platform dependent!
+ });
+ }
+
+ return {
+ type: Token.RegExp,
+ value: value,
+ flags: flags,
+ isMalformed: malformed
+ };
+ },
+
+ /*
+ * Scan for any occurence of non-breaking spaces. Non-breaking spaces
+ * can be mistakenly typed on OS X with option-space. Non UTF-8 web
+ * pages with non-breaking pages produce syntax errors.
+ */
+ scanNonBreakingSpaces: function () {
+ return state.option.nonbsp ?
+ this.input.search(/(\u00A0)/) : -1;
+ },
+
+ /*
+ * Scan for characters that get silently deleted by one or more browsers.
+ */
+ scanUnsafeChars: function () {
+ return this.input.search(reg.unsafeChars);
+ },
+
+ /*
+ * Produce the next raw token or return 'null' if no tokens can be matched.
+ * This method skips over all space characters.
+ */
+ next: function (checks) {
+ this.from = this.char;
+
+ // Move to the next non-space character.
+ var start;
+ if (/\s/.test(this.peek())) {
+ start = this.char;
+
+ while (/\s/.test(this.peek())) {
+ this.from += 1;
+ this.skip();
+ }
+ }
+
+ // Methods that work with multi-line structures and move the
+ // character pointer.
+
+ var match = this.scanComments() ||
+ this.scanStringLiteral(checks) ||
+ this.scanTemplateLiteral();
+
+ if (match) {
+ return match;
+ }
+
+ // Methods that don't move the character pointer.
+
+ match =
+ this.scanRegExp() ||
+ this.scanPunctuator() ||
+ this.scanKeyword() ||
+ this.scanIdentifier() ||
+ this.scanNumericLiteral();
+
+ if (match) {
+ this.skip(match.value.length);
+ return match;
+ }
+
+ // No token could be matched, give up.
+
+ return null;
+ },
+
+ /*
+ * Switch to the next line and reset all char pointers. Once
+ * switched, this method also checks for other minor warnings.
+ */
+ nextLine: function () {
+ var char;
+
+ if (this.line >= this.getLines().length) {
+ return false;
+ }
+
+ this.input = this.getLines()[this.line];
+ this.line += 1;
+ this.char = 1;
+ this.from = 1;
+
+ var inputTrimmed = this.input.trim();
+
+ var startsWith = function () {
+ return _.some(arguments, function (prefix) {
+ return inputTrimmed.indexOf(prefix) === 0;
+ });
+ };
+
+ var endsWith = function () {
+ return _.some(arguments, function (suffix) {
+ return inputTrimmed.indexOf(suffix, inputTrimmed.length - suffix.length) !== -1;
+ });
+ };
+
+ // If we are ignoring linter errors, replace the input with empty string
+ // if it doesn't already at least start or end a multi-line comment
+ if (state.ignoreLinterErrors === true) {
+ if (!startsWith("/*", "//") && !endsWith("*/")) {
+ this.input = "";
+ }
+ }
+
+ char = this.scanNonBreakingSpaces();
+ if (char >= 0) {
+ this.trigger("warning", { code: "W125", line: this.line, character: char + 1 });
+ }
+
+ this.input = this.input.replace(/\t/g, state.tab);
+ char = this.scanUnsafeChars();
+
+ if (char >= 0) {
+ this.trigger("warning", { code: "W100", line: this.line, character: char });
+ }
+
+ // If there is a limit on line length, warn when lines get too
+ // long.
+
+ if (state.option.maxlen && state.option.maxlen < this.input.length) {
+ var inComment = this.inComment ||
+ startsWith.call(inputTrimmed, "//") ||
+ startsWith.call(inputTrimmed, "/*");
+
+ var shouldTriggerError = !inComment || !reg.maxlenException.test(inputTrimmed);
+
+ if (shouldTriggerError) {
+ this.trigger("warning", { code: "W101", line: this.line, character: this.input.length });
+ }
+ }
+
+ return true;
+ },
+
+ /*
+ * This is simply a synonym for nextLine() method with a friendlier
+ * public name.
+ */
+ start: function () {
+ this.nextLine();
+ },
+
+ /*
+ * Produce the next token. This function is called by advance() to get
+ * the next token. It retuns a token in a JSLint-compatible format.
+ */
+ token: function () {
+ /*jshint loopfunc:true */
+ var checks = asyncTrigger();
+ var token;
+
+
+ function isReserved(token, isProperty) {
+ if (!token.reserved) {
+ return false;
+ }
+ var meta = token.meta;
+
+ if (meta && meta.isFutureReservedWord && state.option.inES5()) {
+ // ES3 FutureReservedWord in an ES5 environment.
+ if (!meta.es5) {
+ return false;
+ }
+
+ // Some ES5 FutureReservedWord identifiers are active only
+ // within a strict mode environment.
+ if (meta.strictOnly) {
+ if (!state.option.strict && !state.directive["use strict"]) {
+ return false;
+ }
+ }
+
+ if (isProperty) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // Produce a token object.
+ var create = function (type, value, isProperty) {
+ /*jshint validthis:true */
+ var obj;
+
+ if (type !== "(endline)" && type !== "(end)") {
+ this.prereg = false;
+ }
+
+ if (type === "(punctuator)") {
+ switch (value) {
+ case ".":
+ case ")":
+ case "~":
+ case "#":
+ case "]":
+ this.prereg = false;
+ break;
+ default:
+ this.prereg = true;
+ }
+
+ obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
+ }
+
+ if (type === "(identifier)") {
+ if (value === "return" || value === "case" || value === "typeof") {
+ this.prereg = true;
+ }
+
+ if (_.has(state.syntax, value)) {
+ obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
+
+ // If this can't be a reserved keyword, reset the object.
+ if (!isReserved(obj, isProperty && type === "(identifier)")) {
+ obj = null;
+ }
+ }
+ }
+
+ if (!obj) {
+ obj = Object.create(state.syntax[type]);
+ }
+
+ obj.identifier = (type === "(identifier)");
+ obj.type = obj.type || type;
+ obj.value = value;
+ obj.line = this.line;
+ obj.character = this.char;
+ obj.from = this.from;
+
+ if (isProperty && obj.identifier) {
+ obj.isProperty = isProperty;
+ }
+
+ obj.check = checks.check;
+
+ return obj;
+ }.bind(this);
+
+ for (;;) {
+ if (!this.input.length) {
+ return create(this.nextLine() ? "(endline)" : "(end)", "");
+ }
+
+ token = this.next(checks);
+
+ if (!token) {
+ if (this.input.length) {
+ // Unexpected character.
+ this.trigger("error", {
+ code: "E024",
+ line: this.line,
+ character: this.char,
+ data: [ this.peek() ]
+ });
+
+ this.input = "";
+ }
+
+ continue;
+ }
+
+ switch (token.type) {
+ case Token.StringLiteral:
+ this.triggerAsync("String", {
+ line: this.line,
+ char: this.char,
+ from: this.from,
+ value: token.value,
+ quote: token.quote
+ }, checks, function () { return true; });
+
+ return create("(string)", token.value);
+
+ case Token.TemplateLiteral:
+ this.trigger("Template", {
+ line: this.line,
+ char: this.char,
+ from: this.from,
+ value: token.value
+ });
+ return create("(template)", token.value);
+
+ case Token.Identifier:
+ this.trigger("Identifier", {
+ line: this.line,
+ char: this.char,
+ from: this.form,
+ name: token.value,
+ isProperty: state.tokens.curr.id === "."
+ });
+
+ /* falls through */
+ case Token.Keyword:
+ case Token.NullLiteral:
+ case Token.BooleanLiteral:
+ return create("(identifier)", token.value, state.tokens.curr.id === ".");
+
+ case Token.NumericLiteral:
+ if (token.isMalformed) {
+ this.trigger("warning", {
+ code: "W045",
+ line: this.line,
+ character: this.char,
+ data: [ token.value ]
+ });
+ }
+
+ this.triggerAsync("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.char,
+ data: [ "0x-" ]
+ }, checks, function () { return token.base === 16 && state.jsonMode; });
+
+ this.triggerAsync("warning", {
+ code: "W115",
+ line: this.line,
+ character: this.char
+ }, checks, function () {
+ return state.directive["use strict"] && token.base === 8;
+ });
+
+ this.trigger("Number", {
+ line: this.line,
+ char: this.char,
+ from: this.from,
+ value: token.value,
+ base: token.base,
+ isMalformed: token.malformed
+ });
+
+ return create("(number)", token.value);
+
+ case Token.RegExp:
+ return create("(regexp)", token.value);
+
+ case Token.Comment:
+ state.tokens.curr.comment = true;
+
+ if (token.isSpecial) {
+ return {
+ id: '(comment)',
+ value: token.value,
+ body: token.body,
+ type: token.commentType,
+ isSpecial: token.isSpecial,
+ line: this.line,
+ character: this.char,
+ from: this.from
+ };
+ }
+
+ break;
+
+ case "":
+ break;
+
+ default:
+ return create("(punctuator)", token.value);
+ }
+ }
+ }
+};
+
+exports.Lexer = Lexer;
+
+},{"../data/ascii-identifier-data.js":1,"../data/non-ascii-identifier-part-only.js":2,"../data/non-ascii-identifier-start.js":3,"./reg.js":18,"./state.js":19,"events":7,"underscore":13}],17:[function(require,module,exports){
+"use strict";
+
+var _ = require("underscore");
+
+var errors = {
+ // JSHint options
+ E001: "Bad option: '{a}'.",
+ E002: "Bad option value.",
+
+ // JSHint input
+ E003: "Expected a JSON value.",
+ E004: "Input is neither a string nor an array of strings.",
+ E005: "Input is empty.",
+ E006: "Unexpected early end of program.",
+
+ // Strict mode
+ E007: "Missing \"use strict\" statement.",
+ E008: "Strict violation.",
+ E009: "Option 'validthis' can't be used in a global scope.",
+ E010: "'with' is not allowed in strict mode.",
+
+ // Constants
+ E011: "const '{a}' has already been declared.",
+ E012: "const '{a}' is initialized to 'undefined'.",
+ E013: "Attempting to override '{a}' which is a constant.",
+
+ // Regular expressions
+ E014: "A regular expression literal can be confused with '/='.",
+ E015: "Unclosed regular expression.",
+ E016: "Invalid regular expression.",
+
+ // Tokens
+ E017: "Unclosed comment.",
+ E018: "Unbegun comment.",
+ E019: "Unmatched '{a}'.",
+ E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
+ E021: "Expected '{a}' and instead saw '{b}'.",
+ E022: "Line breaking error '{a}'.",
+ E023: "Missing '{a}'.",
+ E024: "Unexpected '{a}'.",
+ E025: "Missing ':' on a case clause.",
+ E026: "Missing '}' to match '{' from line {a}.",
+ E027: "Missing ']' to match '[' from line {a}.",
+ E028: "Illegal comma.",
+ E029: "Unclosed string.",
+
+ // Everything else
+ E030: "Expected an identifier and instead saw '{a}'.",
+ E031: "Bad assignment.", // FIXME: Rephrase
+ E032: "Expected a small integer or 'false' and instead saw '{a}'.",
+ E033: "Expected an operator and instead saw '{a}'.",
+ E034: "get/set are ES5 features.",
+ E035: "Missing property name.",
+ E036: "Expected to see a statement and instead saw a block.",
+ E037: null,
+ E038: null,
+ E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
+ E040: "Each value should have its own case label.",
+ E041: "Unrecoverable syntax error.",
+ E042: "Stopping.",
+ E043: "Too many errors.",
+ E044: null,
+ E045: "Invalid for each loop.",
+ E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
+ E047: null, // Vacant
+ E048: "Let declaration not directly within block.",
+ E049: "A {a} cannot be named '{b}'.",
+ E050: "Mozilla requires the yield expression to be parenthesized here.",
+ E051: "Regular parameters cannot come after default parameters.",
+ E052: "Unclosed template literal."
+};
+
+var warnings = {
+ W001: "'hasOwnProperty' is a really bad name.",
+ W002: "Value of '{a}' may be overwritten in IE 8 and earlier.",
+ W003: "'{a}' was used before it was defined.",
+ W004: "'{a}' is already defined.",
+ W005: "A dot following a number can be confused with a decimal point.",
+ W006: "Confusing minuses.",
+ W007: "Confusing plusses.",
+ W008: "A leading decimal point can be confused with a dot: '{a}'.",
+ W009: "The array literal notation [] is preferable.",
+ W010: "The object literal notation {} is preferable.",
+ W011: null,
+ W012: null,
+ W013: null,
+ W014: "Bad line breaking before '{a}'.",
+ W015: null,
+ W016: "Unexpected use of '{a}'.",
+ W017: "Bad operand.",
+ W018: "Confusing use of '{a}'.",
+ W019: "Use the isNaN function to compare with NaN.",
+ W020: "Read only.",
+ W021: "'{a}' is a function.",
+ W022: "Do not assign to the exception parameter.",
+ W023: "Expected an identifier in an assignment and instead saw a function invocation.",
+ W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
+ W025: "Missing name in function declaration.",
+ W026: "Inner functions should be listed at the top of the outer function.",
+ W027: "Unreachable '{a}' after '{b}'.",
+ W028: "Label '{a}' on {b} statement.",
+ W030: "Expected an assignment or function call and instead saw an expression.",
+ W031: "Do not use 'new' for side effects.",
+ W032: "Unnecessary semicolon.",
+ W033: "Missing semicolon.",
+ W034: "Unnecessary directive \"{a}\".",
+ W035: "Empty block.",
+ W036: "Unexpected /*member '{a}'.",
+ W037: "'{a}' is a statement label.",
+ W038: "'{a}' used out of scope.",
+ W039: "'{a}' is not allowed.",
+ W040: "Possible strict violation.",
+ W041: "Use '{a}' to compare with '{b}'.",
+ W042: "Avoid EOL escaping.",
+ W043: "Bad escaping of EOL. Use option multistr if needed.",
+ W044: "Bad or unnecessary escaping.",
+ W045: "Bad number '{a}'.",
+ W046: "Don't use extra leading zeros '{a}'.",
+ W047: "A trailing decimal point can be confused with a dot: '{a}'.",
+ W048: "Unexpected control character in regular expression.",
+ W049: "Unexpected escaped character '{a}' in regular expression.",
+ W050: "JavaScript URL.",
+ W051: "Variables should not be deleted.",
+ W052: "Unexpected '{a}'.",
+ W053: "Do not use {a} as a constructor.",
+ W054: "The Function constructor is a form of eval.",
+ W055: "A constructor name should start with an uppercase letter.",
+ W056: "Bad constructor.",
+ W057: "Weird construction. Is 'new' necessary?",
+ W058: "Missing '()' invoking a constructor.",
+ W059: "Avoid arguments.{a}.",
+ W060: "document.write can be a form of eval.",
+ W061: "eval can be harmful.",
+ W062: "Wrap an immediate function invocation in parens " +
+ "to assist the reader in understanding that the expression " +
+ "is the result of a function, and not the function itself.",
+ W063: "Math is not a function.",
+ W064: "Missing 'new' prefix when invoking a constructor.",
+ W065: "Missing radix parameter.",
+ W066: "Implied eval. Consider passing a function instead of a string.",
+ W067: "Bad invocation.",
+ W068: "Wrapping non-IIFE function literals in parens is unnecessary.",
+ W069: "['{a}'] is better written in dot notation.",
+ W070: "Extra comma. (it breaks older versions of IE)",
+ W071: "This function has too many statements. ({a})",
+ W072: "This function has too many parameters. ({a})",
+ W073: "Blocks are nested too deeply. ({a})",
+ W074: "This function's cyclomatic complexity is too high. ({a})",
+ W075: "Duplicate key '{a}'.",
+ W076: "Unexpected parameter '{a}' in get {b} function.",
+ W077: "Expected a single parameter in set {a} function.",
+ W078: "Setter is defined without getter.",
+ W079: "Redefinition of '{a}'.",
+ W080: "It's not necessary to initialize '{a}' to 'undefined'.",
+ W081: null,
+ W082: "Function declarations should not be placed in blocks. " +
+ "Use a function expression or move the statement to the top of " +
+ "the outer function.",
+ W083: "Don't make functions within a loop.",
+ W084: "Expected a conditional expression and instead saw an assignment.",
+ W085: "Don't use 'with'.",
+ W086: "Expected a 'break' statement before '{a}'.",
+ W087: "Forgotten 'debugger' statement?",
+ W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
+ W089: "The body of a for in should be wrapped in an if statement to filter " +
+ "unwanted properties from the prototype.",
+ W090: "'{a}' is not a statement label.",
+ W091: "'{a}' is out of scope.",
+ W093: "Did you mean to return a conditional instead of an assignment?",
+ W094: "Unexpected comma.",
+ W095: "Expected a string and instead saw {a}.",
+ W096: "The '{a}' key may produce unexpected results.",
+ W097: "Use the function form of \"use strict\".",
+ W098: "'{a}' is defined but never used.",
+ W099: null,
+ W100: "This character may get silently deleted by one or more browsers.",
+ W101: "Line is too long.",
+ W102: null,
+ W103: "The '{a}' property is deprecated.",
+ W104: "'{a}' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).",
+ W105: "Unexpected {a} in '{b}'.",
+ W106: "Identifier '{a}' is not in camel case.",
+ W107: "Script URL.",
+ W108: "Strings must use doublequote.",
+ W109: "Strings must use singlequote.",
+ W110: "Mixed double and single quotes.",
+ W112: "Unclosed string.",
+ W113: "Control character in string: {a}.",
+ W114: "Avoid {a}.",
+ W115: "Octal literals are not allowed in strict mode.",
+ W116: "Expected '{a}' and instead saw '{b}'.",
+ W117: "'{a}' is not defined.",
+ W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
+ W119: "'{a}' is only available in ES6 (use esnext option).",
+ W120: "You might be leaking a variable ({a}) here.",
+ W121: "Extending prototype of native object: '{a}'.",
+ W122: "Invalid typeof value '{a}'",
+ W123: "'{a}' is already defined in outer scope.",
+ W124: "A generator function shall contain a yield statement.",
+ W125: "This line contains non-breaking spaces: http://jshint.com/doc/options/#nonbsp"
+};
+
+var info = {
+ I001: "Comma warnings can be turned off with 'laxcomma'.",
+ I002: null,
+ I003: "ES5 option is now set per default"
+};
+
+exports.errors = {};
+exports.warnings = {};
+exports.info = {};
+
+_.each(errors, function (desc, code) {
+ exports.errors[code] = { code: code, desc: desc };
+});
+
+_.each(warnings, function (desc, code) {
+ exports.warnings[code] = { code: code, desc: desc };
+});
+
+_.each(info, function (desc, code) {
+ exports.info[code] = { code: code, desc: desc };
+});
+
+},{"underscore":13}],18:[function(require,module,exports){
+/*
+ * Regular expressions. Some of these are stupidly long.
+ */
+
+/*jshint maxlen:1000 */
+
+"use string";
+
+// Unsafe comment or string (ax)
+exports.unsafeString =
+ /@cc|<\/?|script|\]\s*\]|<\s*!|</i;
+
+// Unsafe characters that are silently deleted by one or more browsers (cx)
+exports.unsafeChars =
+ /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+
+// Characters in strings that need escaping (nx and nxg)
+exports.needEsc =
+ /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+
+exports.needEscGlobal =
+ /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
+
+// Star slash (lx)
+exports.starSlash = /\*\//;
+
+// Identifier (ix)
+exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
+
+// JavaScript URL (jx)
+exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i;
+
+// Catches /* falls through */ comments (ft)
+exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
+
+// very conservative rule (eg: only one space between the start of the comment and the first character)
+// to relax the maxlen option
+exports.maxlenException = /^(?:(?:\/\/|\/\*|\*) ?)?[^ ]+$/;
+
+},{}],19:[function(require,module,exports){
+"use strict";
+
+var state = {
+ syntax: {},
+
+ reset: function () {
+ this.tokens = {
+ prev: null,
+ next: null,
+ curr: null
+ };
+
+ this.option = {};
+ this.ignored = {};
+ this.directive = {};
+ this.jsonMode = false;
+ this.jsonWarnings = [];
+ this.lines = [];
+ this.tab = "";
+ this.cache = {}; // Node.JS doesn't have Map. Sniff.
+ this.ignoredLines = {};
+
+ // Blank out non-multi-line-commented lines when ignoring linter errors
+ this.ignoreLinterErrors = false;
+ }
+};
+
+exports.state = state;
+
+},{}],20:[function(require,module,exports){
+"use strict";
+
+exports.register = function (linter) {
+ // Check for properties named __proto__. This special property was
+ // deprecated and then re-introduced for ES6.
+
+ linter.on("Identifier", function style_scanProto(data) {
+ if (linter.getOption("proto")) {
+ return;
+ }
+
+ if (data.name === "__proto__") {
+ linter.warn("W103", {
+ line: data.line,
+ char: data.char,
+ data: [ data.name ]
+ });
+ }
+ });
+
+ // Check for properties named __iterator__. This is a special property
+ // available only in browsers with JavaScript 1.7 implementation.
+
+ linter.on("Identifier", function style_scanIterator(data) {
+ if (linter.getOption("iterator")) {
+ return;
+ }
+
+ if (data.name === "__iterator__") {
+ linter.warn("W104", {
+ line: data.line,
+ char: data.char,
+ data: [ data.name ]
+ });
+ }
+ });
+
+ // Check that all identifiers are using camelCase notation.
+ // Exceptions: names like MY_VAR and _myVar.
+
+ linter.on("Identifier", function style_scanCamelCase(data) {
+ if (!linter.getOption("camelcase")) {
+ return;
+ }
+
+ if (data.name.replace(/^_+|_+$/g, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
+ linter.warn("W106", {
+ line: data.line,
+ char: data.from,
+ data: [ data.name ]
+ });
+ }
+ });
+
+ // Enforce consistency in style of quoting.
+
+ linter.on("String", function style_scanQuotes(data) {
+ var quotmark = linter.getOption("quotmark");
+ var code;
+
+ if (!quotmark) {
+ return;
+ }
+
+ // If quotmark is set to 'single' warn about all double-quotes.
+
+ if (quotmark === "single" && data.quote !== "'") {
+ code = "W109";
+ }
+
+ // If quotmark is set to 'double' warn about all single-quotes.
+
+ if (quotmark === "double" && data.quote !== "\"") {
+ code = "W108";
+ }
+
+ // If quotmark is set to true, remember the first quotation style
+ // and then warn about all others.
+
+ if (quotmark === true) {
+ if (!linter.getCache("quotmark")) {
+ linter.setCache("quotmark", data.quote);
+ }
+
+ if (linter.getCache("quotmark") !== data.quote) {
+ code = "W110";
+ }
+ }
+
+ if (code) {
+ linter.warn(code, {
+ line: data.line,
+ char: data.char,
+ });
+ }
+ });
+
+ linter.on("Number", function style_scanNumbers(data) {
+ if (data.value.charAt(0) === ".") {
+ // Warn about a leading decimal point.
+ linter.warn("W008", {
+ line: data.line,
+ char: data.char,
+ data: [ data.value ]
+ });
+ }
+
+ if (data.value.substr(data.value.length - 1) === ".") {
+ // Warn about a trailing decimal point.
+ linter.warn("W047", {
+ line: data.line,
+ char: data.char,
+ data: [ data.value ]
+ });
+ }
+
+ if (/^00+/.test(data.value)) {
+ // Multiple leading zeroes.
+ linter.warn("W046", {
+ line: data.line,
+ char: data.char,
+ data: [ data.value ]
+ });
+ }
+ });
+
+ // Warn about script URLs.
+
+ linter.on("String", function style_scanJavaScriptURLs(data) {
+ var re = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i;
+
+ if (linter.getOption("scripturl")) {
+ return;
+ }
+
+ if (re.test(data.value)) {
+ linter.warn("W107", {
+ line: data.line,
+ char: data.char
+ });
+ }
+ });
+};
+
+},{}],21:[function(require,module,exports){
+// jshint -W001
+
+"use strict";
+
+// Identifiers provided by the ECMAScript standard.
+
+exports.reservedVars = {
+ arguments : false,
+ NaN : false
+};
+
+exports.ecmaIdentifiers = {
+ Array : false,
+ Boolean : false,
+ Date : false,
+ decodeURI : false,
+ decodeURIComponent : false,
+ encodeURI : false,
+ encodeURIComponent : false,
+ Error : false,
+ "eval" : false,
+ EvalError : false,
+ Function : false,
+ hasOwnProperty : false,
+ isFinite : false,
+ isNaN : false,
+ JSON : false,
+ Math : false,
+ Number : false,
+ Object : false,
+ parseInt : false,
+ parseFloat : false,
+ RangeError : false,
+ ReferenceError : false,
+ RegExp : false,
+ String : false,
+ SyntaxError : false,
+ TypeError : false,
+ URIError : false,
+};
+
+exports.newEcmaIdentifiers = {
+ Set : false,
+ Map : false,
+ WeakMap : false,
+ WeakSet : false,
+ Proxy : false,
+ Promise : false
+};
+
+// Global variables commonly provided by a web browser environment.
+
+exports.browser = {
+ Audio : false,
+ Blob : false,
+ addEventListener : false,
+ applicationCache : false,
+ atob : false,
+ blur : false,
+ btoa : false,
+ CanvasGradient : false,
+ CanvasPattern : false,
+ CanvasRenderingContext2D: false,
+ clearInterval : false,
+ clearTimeout : false,
+ close : false,
+ closed : false,
+ CustomEvent : false,
+ DOMParser : false,
+ defaultStatus : false,
+ document : false,
+ Element : false,
+ ElementTimeControl : false,
+ event : false,
+ FileReader : false,
+ FormData : false,
+ focus : false,
+ frames : false,
+ getComputedStyle : false,
+ HTMLElement : false,
+ HTMLAnchorElement : false,
+ HTMLBaseElement : false,
+ HTMLBlockquoteElement: false,
+ HTMLBodyElement : false,
+ HTMLBRElement : false,
+ HTMLButtonElement : false,
+ HTMLCanvasElement : false,
+ HTMLDirectoryElement : false,
+ HTMLDivElement : false,
+ HTMLDListElement : false,
+ HTMLFieldSetElement : false,
+ HTMLFontElement : false,
+ HTMLFormElement : false,
+ HTMLFrameElement : false,
+ HTMLFrameSetElement : false,
+ HTMLHeadElement : false,
+ HTMLHeadingElement : false,
+ HTMLHRElement : false,
+ HTMLHtmlElement : false,
+ HTMLIFrameElement : false,
+ HTMLImageElement : false,
+ HTMLInputElement : false,
+ HTMLIsIndexElement : false,
+ HTMLLabelElement : false,
+ HTMLLayerElement : false,
+ HTMLLegendElement : false,
+ HTMLLIElement : false,
+ HTMLLinkElement : false,
+ HTMLMapElement : false,
+ HTMLMenuElement : false,
+ HTMLMetaElement : false,
+ HTMLModElement : false,
+ HTMLObjectElement : false,
+ HTMLOListElement : false,
+ HTMLOptGroupElement : false,
+ HTMLOptionElement : false,
+ HTMLParagraphElement : false,
+ HTMLParamElement : false,
+ HTMLPreElement : false,
+ HTMLQuoteElement : false,
+ HTMLScriptElement : false,
+ HTMLSelectElement : false,
+ HTMLStyleElement : false,
+ HTMLTableCaptionElement: false,
+ HTMLTableCellElement : false,
+ HTMLTableColElement : false,
+ HTMLTableElement : false,
+ HTMLTableRowElement : false,
+ HTMLTableSectionElement: false,
+ HTMLTextAreaElement : false,
+ HTMLTitleElement : false,
+ HTMLUListElement : false,
+ HTMLVideoElement : false,
+ history : false,
+ Image : false,
+ length : false,
+ localStorage : false,
+ location : false,
+ matchMedia : false,
+ MessageChannel : false,
+ MessageEvent : false,
+ MessagePort : false,
+ MouseEvent : false,
+ moveBy : false,
+ moveTo : false,
+ MutationObserver : false,
+ name : false,
+ Node : false,
+ NodeFilter : false,
+ NodeList : false,
+ navigator : false,
+ onbeforeunload : true,
+ onblur : true,
+ onerror : true,
+ onfocus : true,
+ onload : true,
+ onresize : true,
+ onunload : true,
+ open : false,
+ openDatabase : false,
+ opener : false,
+ Option : false,
+ parent : false,
+ print : false,
+ removeEventListener : false,
+ resizeBy : false,
+ resizeTo : false,
+ screen : false,
+ scroll : false,
+ scrollBy : false,
+ scrollTo : false,
+ sessionStorage : false,
+ setInterval : false,
+ setTimeout : false,
+ SharedWorker : false,
+ status : false,
+ SVGAElement : false,
+ SVGAltGlyphDefElement: false,
+ SVGAltGlyphElement : false,
+ SVGAltGlyphItemElement: false,
+ SVGAngle : false,
+ SVGAnimateColorElement: false,
+ SVGAnimateElement : false,
+ SVGAnimateMotionElement: false,
+ SVGAnimateTransformElement: false,
+ SVGAnimatedAngle : false,
+ SVGAnimatedBoolean : false,
+ SVGAnimatedEnumeration: false,
+ SVGAnimatedInteger : false,
+ SVGAnimatedLength : false,
+ SVGAnimatedLengthList: false,
+ SVGAnimatedNumber : false,
+ SVGAnimatedNumberList: false,
+ SVGAnimatedPathData : false,
+ SVGAnimatedPoints : false,
+ SVGAnimatedPreserveAspectRatio: false,
+ SVGAnimatedRect : false,
+ SVGAnimatedString : false,
+ SVGAnimatedTransformList: false,
+ SVGAnimationElement : false,
+ SVGCSSRule : false,
+ SVGCircleElement : false,
+ SVGClipPathElement : false,
+ SVGColor : false,
+ SVGColorProfileElement: false,
+ SVGColorProfileRule : false,
+ SVGComponentTransferFunctionElement: false,
+ SVGCursorElement : false,
+ SVGDefsElement : false,
+ SVGDescElement : false,
+ SVGDocument : false,
+ SVGElement : false,
+ SVGElementInstance : false,
+ SVGElementInstanceList: false,
+ SVGEllipseElement : false,
+ SVGExternalResourcesRequired: false,
+ SVGFEBlendElement : false,
+ SVGFEColorMatrixElement: false,
+ SVGFEComponentTransferElement: false,
+ SVGFECompositeElement: false,
+ SVGFEConvolveMatrixElement: false,
+ SVGFEDiffuseLightingElement: false,
+ SVGFEDisplacementMapElement: false,
+ SVGFEDistantLightElement: false,
+ SVGFEFloodElement : false,
+ SVGFEFuncAElement : false,
+ SVGFEFuncBElement : false,
+ SVGFEFuncGElement : false,
+ SVGFEFuncRElement : false,
+ SVGFEGaussianBlurElement: false,
+ SVGFEImageElement : false,
+ SVGFEMergeElement : false,
+ SVGFEMergeNodeElement: false,
+ SVGFEMorphologyElement: false,
+ SVGFEOffsetElement : false,
+ SVGFEPointLightElement: false,
+ SVGFESpecularLightingElement: false,
+ SVGFESpotLightElement: false,
+ SVGFETileElement : false,
+ SVGFETurbulenceElement: false,
+ SVGFilterElement : false,
+ SVGFilterPrimitiveStandardAttributes: false,
+ SVGFitToViewBox : false,
+ SVGFontElement : false,
+ SVGFontFaceElement : false,
+ SVGFontFaceFormatElement: false,
+ SVGFontFaceNameElement: false,
+ SVGFontFaceSrcElement: false,
+ SVGFontFaceUriElement: false,
+ SVGForeignObjectElement: false,
+ SVGGElement : false,
+ SVGGlyphElement : false,
+ SVGGlyphRefElement : false,
+ SVGGradientElement : false,
+ SVGHKernElement : false,
+ SVGICCColor : false,
+ SVGImageElement : false,
+ SVGLangSpace : false,
+ SVGLength : false,
+ SVGLengthList : false,
+ SVGLineElement : false,
+ SVGLinearGradientElement: false,
+ SVGLocatable : false,
+ SVGMPathElement : false,
+ SVGMarkerElement : false,
+ SVGMaskElement : false,
+ SVGMatrix : false,
+ SVGMetadataElement : false,
+ SVGMissingGlyphElement: false,
+ SVGNumber : false,
+ SVGNumberList : false,
+ SVGPaint : false,
+ SVGPathElement : false,
+ SVGPathSeg : false,
+ SVGPathSegArcAbs : false,
+ SVGPathSegArcRel : false,
+ SVGPathSegClosePath : false,
+ SVGPathSegCurvetoCubicAbs: false,
+ SVGPathSegCurvetoCubicRel: false,
+ SVGPathSegCurvetoCubicSmoothAbs: false,
+ SVGPathSegCurvetoCubicSmoothRel: false,
+ SVGPathSegCurvetoQuadraticAbs: false,
+ SVGPathSegCurvetoQuadraticRel: false,
+ SVGPathSegCurvetoQuadraticSmoothAbs: false,
+ SVGPathSegCurvetoQuadraticSmoothRel: false,
+ SVGPathSegLinetoAbs : false,
+ SVGPathSegLinetoHorizontalAbs: false,
+ SVGPathSegLinetoHorizontalRel: false,
+ SVGPathSegLinetoRel : false,
+ SVGPathSegLinetoVerticalAbs: false,
+ SVGPathSegLinetoVerticalRel: false,
+ SVGPathSegList : false,
+ SVGPathSegMovetoAbs : false,
+ SVGPathSegMovetoRel : false,
+ SVGPatternElement : false,
+ SVGPoint : false,
+ SVGPointList : false,
+ SVGPolygonElement : false,
+ SVGPolylineElement : false,
+ SVGPreserveAspectRatio: false,
+ SVGRadialGradientElement: false,
+ SVGRect : false,
+ SVGRectElement : false,
+ SVGRenderingIntent : false,
+ SVGSVGElement : false,
+ SVGScriptElement : false,
+ SVGSetElement : false,
+ SVGStopElement : false,
+ SVGStringList : false,
+ SVGStylable : false,
+ SVGStyleElement : false,
+ SVGSwitchElement : false,
+ SVGSymbolElement : false,
+ SVGTRefElement : false,
+ SVGTSpanElement : false,
+ SVGTests : false,
+ SVGTextContentElement: false,
+ SVGTextElement : false,
+ SVGTextPathElement : false,
+ SVGTextPositioningElement: false,
+ SVGTitleElement : false,
+ SVGTransform : false,
+ SVGTransformList : false,
+ SVGTransformable : false,
+ SVGURIReference : false,
+ SVGUnitTypes : false,
+ SVGUseElement : false,
+ SVGVKernElement : false,
+ SVGViewElement : false,
+ SVGViewSpec : false,
+ SVGZoomAndPan : false,
+ TimeEvent : false,
+ top : false,
+ URL : false,
+ WebSocket : false,
+ window : false,
+ Worker : false,
+ XMLHttpRequest : false,
+ XMLSerializer : false,
+ XPathEvaluator : false,
+ XPathException : false,
+ XPathExpression : false,
+ XPathNamespace : false,
+ XPathNSResolver : false,
+ XPathResult : false
+};
+
+exports.devel = {
+ alert : false,
+ confirm: false,
+ console: false,
+ Debug : false,
+ opera : false,
+ prompt : false
+};
+
+exports.worker = {
+ importScripts: true,
+ postMessage : true,
+ self : true
+};
+
+// Widely adopted global names that are not part of ECMAScript standard
+exports.nonstandard = {
+ escape : false,
+ unescape: false
+};
+
+// Globals provided by popular JavaScript environments.
+
+exports.couch = {
+ "require" : false,
+ respond : false,
+ getRow : false,
+ emit : false,
+ send : false,
+ start : false,
+ sum : false,
+ log : false,
+ exports : false,
+ module : false,
+ provides : false
+};
+
+exports.node = {
+ __filename : false,
+ __dirname : false,
+ GLOBAL : false,
+ global : false,
+ module : false,
+ require : false,
+
+ // These globals are writeable because Node allows the following
+ // usage pattern: var Buffer = require("buffer").Buffer;
+
+ Buffer : true,
+ console : true,
+ exports : true,
+ process : true,
+ setTimeout : true,
+ clearTimeout : true,
+ setInterval : true,
+ clearInterval : true,
+ setImmediate : true, // v0.9.1+
+ clearImmediate: true // v0.9.1+
+};
+
+exports.phantom = {
+ phantom : true,
+ require : true,
+ WebPage : true,
+ console : true, // in examples, but undocumented
+ exports : true // v1.7+
+};
+
+exports.qunit = {
+ asyncTest : false,
+ deepEqual : false,
+ equal : false,
+ expect : false,
+ module : false,
+ notDeepEqual : false,
+ notEqual : false,
+ notPropEqual : false,
+ notStrictEqual : false,
+ ok : false,
+ propEqual : false,
+ QUnit : false,
+ raises : false,
+ start : false,
+ stop : false,
+ strictEqual : false,
+ test : false,
+ "throws" : false
+};
+
+exports.rhino = {
+ defineClass : false,
+ deserialize : false,
+ gc : false,
+ help : false,
+ importClass : false,
+ importPackage: false,
+ "java" : false,
+ load : false,
+ loadClass : false,
+ Packages : false,
+ print : false,
+ quit : false,
+ readFile : false,
+ readUrl : false,
+ runCommand : false,
+ seal : false,
+ serialize : false,
+ spawn : false,
+ sync : false,
+ toint32 : false,
+ version : false
+};
+
+exports.shelljs = {
+ target : false,
+ echo : false,
+ exit : false,
+ cd : false,
+ pwd : false,
+ ls : false,
+ find : false,
+ cp : false,
+ rm : false,
+ mv : false,
+ mkdir : false,
+ test : false,
+ cat : false,
+ sed : false,
+ grep : false,
+ which : false,
+ dirs : false,
+ pushd : false,
+ popd : false,
+ env : false,
+ exec : false,
+ chmod : false,
+ config : false,
+ error : false,
+ tempdir : false
+};
+
+exports.typed = {
+ ArrayBuffer : false,
+ ArrayBufferView : false,
+ DataView : false,
+ Float32Array : false,
+ Float64Array : false,
+ Int16Array : false,
+ Int32Array : false,
+ Int8Array : false,
+ Uint16Array : false,
+ Uint32Array : false,
+ Uint8Array : false,
+ Uint8ClampedArray : false
+};
+
+exports.wsh = {
+ ActiveXObject : true,
+ Enumerator : true,
+ GetObject : true,
+ ScriptEngine : true,
+ ScriptEngineBuildVersion : true,
+ ScriptEngineMajorVersion : true,
+ ScriptEngineMinorVersion : true,
+ VBArray : true,
+ WSH : true,
+ WScript : true,
+ XDomainRequest : true
+};
+
+// Globals provided by popular JavaScript libraries.
+
+exports.dojo = {
+ dojo : false,
+ dijit : false,
+ dojox : false,
+ define : false,
+ "require": false
+};
+
+exports.jquery = {
+ "$" : false,
+ jQuery : false
+};
+
+exports.mootools = {
+ "$" : false,
+ "$$" : false,
+ Asset : false,
+ Browser : false,
+ Chain : false,
+ Class : false,
+ Color : false,
+ Cookie : false,
+ Core : false,
+ Document : false,
+ DomReady : false,
+ DOMEvent : false,
+ DOMReady : false,
+ Drag : false,
+ Element : false,
+ Elements : false,
+ Event : false,
+ Events : false,
+ Fx : false,
+ Group : false,
+ Hash : false,
+ HtmlTable : false,
+ IFrame : false,
+ IframeShim : false,
+ InputValidator: false,
+ instanceOf : false,
+ Keyboard : false,
+ Locale : false,
+ Mask : false,
+ MooTools : false,
+ Native : false,
+ Options : false,
+ OverText : false,
+ Request : false,
+ Scroller : false,
+ Slick : false,
+ Slider : false,
+ Sortables : false,
+ Spinner : false,
+ Swiff : false,
+ Tips : false,
+ Type : false,
+ typeOf : false,
+ URI : false,
+ Window : false
+};
+
+exports.prototypejs = {
+ "$" : false,
+ "$$" : false,
+ "$A" : false,
+ "$F" : false,
+ "$H" : false,
+ "$R" : false,
+ "$break" : false,
+ "$continue" : false,
+ "$w" : false,
+ Abstract : false,
+ Ajax : false,
+ Class : false,
+ Enumerable : false,
+ Element : false,
+ Event : false,
+ Field : false,
+ Form : false,
+ Hash : false,
+ Insertion : false,
+ ObjectRange : false,
+ PeriodicalExecuter: false,
+ Position : false,
+ Prototype : false,
+ Selector : false,
+ Template : false,
+ Toggle : false,
+ Try : false,
+ Autocompleter : false,
+ Builder : false,
+ Control : false,
+ Draggable : false,
+ Draggables : false,
+ Droppables : false,
+ Effect : false,
+ Sortable : false,
+ SortableObserver : false,
+ Sound : false,
+ Scriptaculous : false
+};
+
+exports.yui = {
+ YUI : false,
+ Y : false,
+ YUI_config: false
+};
+
+exports.mocha = {
+ // BDD
+ describe : false,
+ it : false,
+ before : false,
+ after : false,
+ beforeEach : false,
+ afterEach : false,
+ // TDD
+ suite : false,
+ test : false,
+ setup : false,
+ teardown : false
+};
+
+exports.jasmine = {
+ jasmine : false,
+ describe : false,
+ it : false,
+ xit : false,
+ beforeEach : false,
+ afterEach : false,
+ setFixtures : false,
+ loadFixtures: false,
+ spyOn : false,
+ expect : false,
+ // Jasmine 1.3
+ runs : false,
+ waitsFor : false,
+ waits : false
+};
+
+},{}]},{},["fNbQ4d"])
+JSHINT = require('jshint').JSHINT;
+if (typeof exports === 'object' && exports) exports.JSHINT = JSHINT;
+}());;// This is CodeMirror (http://codemirror.net), a code editor
+// implemented in JavaScript on top of the browser's DOM.
+//
+// You can find some technical background for some of the code below
+// at http://marijnhaverbeke.nl/blog/#cm-internals .
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ module.exports = mod();
+ else if (typeof define == "function" && define.amd) // AMD
+ return define([], mod);
+ else // Plain browser env
+ this.CodeMirror = mod();
+})(function() {
+ "use strict";
+
+ // BROWSER SNIFFING
+
+ // Kludges for bugs and behavior differences that can't be feature
+ // detected are enabled based on userAgent etc sniffing.
+
+ var gecko = /gecko\/\d/i.test(navigator.userAgent);
+ // ie_uptoN means Internet Explorer version N or lower
+ var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
+ var ie_upto7 = ie_upto10 && (document.documentMode == null || document.documentMode < 8);
+ var ie_upto8 = ie_upto10 && (document.documentMode == null || document.documentMode < 9);
+ var ie_upto9 = ie_upto10 && (document.documentMode == null || document.documentMode < 10);
+ var ie_11up = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent);
+ var ie = ie_upto10 || ie_11up;
+ var webkit = /WebKit\//.test(navigator.userAgent);
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
+ var chrome = /Chrome\//.test(navigator.userAgent);
+ var presto = /Opera\//.test(navigator.userAgent);
+ var safari = /Apple Computer/.test(navigator.vendor);
+ var khtml = /KHTML\//.test(navigator.userAgent);
+ var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
+ var phantom = /PhantomJS/.test(navigator.userAgent);
+
+ var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
+ var mac = ios || /Mac/.test(navigator.platform);
+ var windows = /win/i.test(navigator.platform);
+
+ var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
+ if (presto_version) presto_version = Number(presto_version[1]);
+ if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
+ // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
+ var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
+ var captureRightClick = gecko || (ie && !ie_upto8);
+
+ // Optimize some code when these features are not used.
+ var sawReadOnlySpans = false, sawCollapsedSpans = false;
+
+ // EDITOR CONSTRUCTOR
+
+ // A CodeMirror instance represents an editor. This is the object
+ // that user code is usually dealing with.
+
+ function CodeMirror(place, options) {
+ if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
+
+ this.options = options = options || {};
+ // Determine effective options based on given values and defaults.
+ for (var opt in defaults) if (!options.hasOwnProperty(opt))
+ options[opt] = defaults[opt];
+ setGuttersForLineNumbers(options);
+
+ var doc = options.value;
+ if (typeof doc == "string") doc = new Doc(doc, options.mode);
+ this.doc = doc;
+
+ var display = this.display = new Display(place, doc);
+ display.wrapper.CodeMirror = this;
+ updateGutters(this);
+ themeChanged(this);
+ if (options.lineWrapping)
+ this.display.wrapper.className += " CodeMirror-wrap";
+ if (options.autofocus && !mobile) focusInput(this);
+
+ this.state = {
+ keyMaps: [], // stores maps added by addKeyMap
+ overlays: [], // highlighting overlays, as added by addOverlay
+ modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
+ overwrite: false, focused: false,
+ suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
+ pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in readInput
+ draggingText: false,
+ highlight: new Delayed() // stores highlight worker timeout
+ };
+
+ // Override magic textarea content restore that IE sometimes does
+ // on our hidden textarea on reload
+ if (ie_upto10) setTimeout(bind(resetInput, this, true), 20);
+
+ registerEventHandlers(this);
+
+ var cm = this;
+ runInOp(this, function() {
+ cm.curOp.forceUpdate = true;
+ attachDoc(cm, doc);
+
+ if ((options.autofocus && !mobile) || activeElt() == display.input)
+ setTimeout(bind(onFocus, cm), 20);
+ else
+ onBlur(cm);
+
+ for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
+ optionHandlers[opt](cm, options[opt], Init);
+ for (var i = 0; i < initHooks.length; ++i) initHooks[i](cm);
+ });
+ }
+
+ // DISPLAY CONSTRUCTOR
+
+ // The display handles the DOM integration, both for input reading
+ // and content drawing. It holds references to DOM nodes and
+ // display-related state.
+
+ function Display(place, doc) {
+ var d = this;
+
+ // The semihidden textarea that is focused when the editor is
+ // focused, and receives input.
+ var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
+ // The textarea is kept positioned near the cursor to prevent the
+ // fact that it'll be scrolled into view on input from scrolling
+ // our fake cursor out of view. On webkit, when wrap=off, paste is
+ // very slow. So make the area wide instead.
+ if (webkit) input.style.width = "1000px";
+ else input.setAttribute("wrap", "off");
+ // If border: 0; -- iOS fails to open keyboard (issue #1287)
+ if (ios) input.style.border = "1px solid black";
+ input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
+
+ // Wraps and hides input textarea
+ d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
+ // The fake scrollbar elements.
+ d.scrollbarH = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
+ d.scrollbarV = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
+ // Covers bottom-right square when both scrollbars are present.
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
+ // Covers bottom of gutter when coverGutterNextToScrollbar is on
+ // and h scrollbar is present.
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
+ // Will contain the actual code, positioned to cover the viewport.
+ d.lineDiv = elt("div", null, "CodeMirror-code");
+ // Elements are added to these to represent selection and cursors.
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
+ d.cursorDiv = elt("div", null, "CodeMirror-cursors");
+ // A visibility: hidden element used to find the size of things.
+ d.measure = elt("div", null, "CodeMirror-measure");
+ // When lines outside of the viewport are measured, they are drawn in this.
+ d.lineMeasure = elt("div", null, "CodeMirror-measure");
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
+ d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
+ null, "position: relative; outline: none");
+ // Moved around its parent to cover visible view.
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
+ // Set to the height of the document, allowing scrolling.
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
+ // Behavior of elts with overflow: auto and padding is
+ // inconsistent across browsers. This is used to ensure the
+ // scrollable area is big enough.
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
+ // Will contain the gutters, if any.
+ d.gutters = elt("div", null, "CodeMirror-gutters");
+ d.lineGutter = null;
+ // Actual scrollable element.
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
+ d.scroller.setAttribute("tabIndex", "-1");
+ // The element in which the editor lives.
+ d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
+ d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
+
+ // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
+ if (ie_upto7) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
+ // Needed to hide big blue blinking cursor on Mobile Safari
+ if (ios) input.style.width = "0px";
+ if (!webkit) d.scroller.draggable = true;
+ // Needed to handle Tab key in KHTML
+ if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
+ if (ie_upto7) d.scrollbarH.style.minHeight = d.scrollbarV.style.minWidth = "18px";
+
+ if (place.appendChild) place.appendChild(d.wrapper);
+ else place(d.wrapper);
+
+ // Current rendered range (may be bigger than the view window).
+ d.viewFrom = d.viewTo = doc.first;
+ // Information about the rendered lines.
+ d.view = [];
+ // Holds info about a single rendered line when it was rendered
+ // for measurement, while not in view.
+ d.externalMeasured = null;
+ // Empty space (in pixels) above the view
+ d.viewOffset = 0;
+ d.lastSizeC = 0;
+ d.updateLineNumbers = null;
+
+ // Used to only resize the line number gutter when necessary (when
+ // the amount of lines crosses a boundary that makes its width change)
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
+ // See readInput and resetInput
+ d.prevInput = "";
+ // Set to true when a non-horizontal-scrolling line widget is
+ // added. As an optimization, line widget aligning is skipped when
+ // this is false.
+ d.alignWidgets = false;
+ // Flag that indicates whether we expect input to appear real soon
+ // now (after some event like 'keypress' or 'input') and are
+ // polling intensively.
+ d.pollingFast = false;
+ // Self-resetting timeout for the poller
+ d.poll = new Delayed();
+
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
+
+ // Tracks when resetInput has punted to just putting a short
+ // string into the textarea instead of the full selection.
+ d.inaccurateSelection = false;
+
+ // Tracks the maximum line length so that the horizontal scrollbar
+ // can be kept static when scrolling.
+ d.maxLine = null;
+ d.maxLineLength = 0;
+ d.maxLineChanged = false;
+
+ // Used for measuring wheel scrolling granularity
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
+
+ // True when shift is held down.
+ d.shift = false;
+ }
+
+ // STATE UPDATES
+
+ // Used to get the editor into a consistent state again when options change.
+
+ function loadMode(cm) {
+ cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
+ resetModeState(cm);
+ }
+
+ function resetModeState(cm) {
+ cm.doc.iter(function(line) {
+ if (line.stateAfter) line.stateAfter = null;
+ if (line.styles) line.styles = null;
+ });
+ cm.doc.frontier = cm.doc.first;
+ startWorker(cm, 100);
+ cm.state.modeGen++;
+ if (cm.curOp) regChange(cm);
+ }
+
+ function wrappingChanged(cm) {
+ if (cm.options.lineWrapping) {
+ cm.display.wrapper.className += " CodeMirror-wrap";
+ cm.display.sizer.style.minWidth = "";
+ } else {
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
+ findMaxLine(cm);
+ }
+ estimateLineHeights(cm);
+ regChange(cm);
+ clearCaches(cm);
+ setTimeout(function(){updateScrollbars(cm);}, 100);
+ }
+
+ // Returns a function that estimates the height of a line, to use as
+ // first approximation until the line becomes visible (and is thus
+ // properly measurable).
+ function estimateHeight(cm) {
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
+ return function(line) {
+ if (lineIsHidden(cm.doc, line)) return 0;
+
+ var widgetsHeight = 0;
+ if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {
+ if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;
+ }
+
+ if (wrapping)
+ return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;
+ else
+ return widgetsHeight + th;
+ };
+ }
+
+ function estimateLineHeights(cm) {
+ var doc = cm.doc, est = estimateHeight(cm);
+ doc.iter(function(line) {
+ var estHeight = est(line);
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
+ });
+ }
+
+ function keyMapChanged(cm) {
+ var map = keyMap[cm.options.keyMap], style = map.style;
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
+ (style ? " cm-keymap-" + style : "");
+ }
+
+ function themeChanged(cm) {
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
+ clearCaches(cm);
+ }
+
+ function guttersChanged(cm) {
+ updateGutters(cm);
+ regChange(cm);
+ setTimeout(function(){alignHorizontally(cm);}, 20);
+ }
+
+ // Rebuild the gutter elements, ensure the margin to the left of the
+ // code matches their width.
+ function updateGutters(cm) {
+ var gutters = cm.display.gutters, specs = cm.options.gutters;
+ removeChildren(gutters);
+ for (var i = 0; i < specs.length; ++i) {
+ var gutterClass = specs[i];
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
+ if (gutterClass == "CodeMirror-linenumbers") {
+ cm.display.lineGutter = gElt;
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
+ }
+ }
+ gutters.style.display = i ? "" : "none";
+ var width = gutters.offsetWidth;
+ cm.display.sizer.style.marginLeft = width + "px";
+ if (i) cm.display.scrollbarH.style.left = cm.options.fixedGutter ? width + "px" : 0;
+ }
+
+ // Compute the character length of a line, taking into account
+ // collapsed ranges (see markText) that might hide parts, and join
+ // other lines onto it.
+ function lineLength(line) {
+ if (line.height == 0) return 0;
+ var len = line.text.length, merged, cur = line;
+ while (merged = collapsedSpanAtStart(cur)) {
+ var found = merged.find(0, true);
+ cur = found.from.line;
+ len += found.from.ch - found.to.ch;
+ }
+ cur = line;
+ while (merged = collapsedSpanAtEnd(cur)) {
+ var found = merged.find(0, true);
+ len -= cur.text.length - found.from.ch;
+ cur = found.to.line;
+ len += cur.text.length - found.to.ch;
+ }
+ return len;
+ }
+
+ // Find the longest line in the document.
+ function findMaxLine(cm) {
+ var d = cm.display, doc = cm.doc;
+ d.maxLine = getLine(doc, doc.first);
+ d.maxLineLength = lineLength(d.maxLine);
+ d.maxLineChanged = true;
+ doc.iter(function(line) {
+ var len = lineLength(line);
+ if (len > d.maxLineLength) {
+ d.maxLineLength = len;
+ d.maxLine = line;
+ }
+ });
+ }
+
+ // Make sure the gutters options contains the element
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
+ function setGuttersForLineNumbers(options) {
+ var found = indexOf(options.gutters, "CodeMirror-linenumbers");
+ if (found == -1 && options.lineNumbers) {
+ options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
+ } else if (found > -1 && !options.lineNumbers) {
+ options.gutters = options.gutters.slice(0);
+ options.gutters.splice(found, 1);
+ }
+ }
+
+ // SCROLLBARS
+
+ // Prepare DOM reads needed to update the scrollbars. Done in one
+ // shot to minimize update/measure roundtrips.
+ function measureForScrollbars(cm) {
+ var scroll = cm.display.scroller;
+ return {
+ clientHeight: scroll.clientHeight,
+ barHeight: cm.display.scrollbarV.clientHeight,
+ scrollWidth: scroll.scrollWidth, clientWidth: scroll.clientWidth,
+ barWidth: cm.display.scrollbarH.clientWidth,
+ docHeight: Math.round(cm.doc.height + paddingVert(cm.display))
+ };
+ }
+
+ // Re-synchronize the fake scrollbars with the actual size of the
+ // content.
+ function updateScrollbars(cm, measure) {
+ if (!measure) measure = measureForScrollbars(cm);
+ var d = cm.display;
+ var scrollHeight = measure.docHeight + scrollerCutOff;
+ var needsH = measure.scrollWidth > measure.clientWidth;
+ var needsV = scrollHeight > measure.clientHeight;
+ if (needsV) {
+ d.scrollbarV.style.display = "block";
+ d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
+ // A bug in IE8 can cause this value to be negative, so guard it.
+ d.scrollbarV.firstChild.style.height =
+ Math.max(0, scrollHeight - measure.clientHeight + (measure.barHeight || d.scrollbarV.clientHeight)) + "px";
+ } else {
+ d.scrollbarV.style.display = "";
+ d.scrollbarV.firstChild.style.height = "0";
+ }
+ if (needsH) {
+ d.scrollbarH.style.display = "block";
+ d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
+ d.scrollbarH.firstChild.style.width =
+ (measure.scrollWidth - measure.clientWidth + (measure.barWidth || d.scrollbarH.clientWidth)) + "px";
+ } else {
+ d.scrollbarH.style.display = "";
+ d.scrollbarH.firstChild.style.width = "0";
+ }
+ if (needsH && needsV) {
+ d.scrollbarFiller.style.display = "block";
+ d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
+ } else d.scrollbarFiller.style.display = "";
+ if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
+ d.gutterFiller.style.display = "block";
+ d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
+ d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
+ } else d.gutterFiller.style.display = "";
+
+ if (mac_geLion && scrollbarWidth(d.measure) === 0) {
+ d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
+ var barMouseDown = function(e) {
+ if (e_target(e) != d.scrollbarV && e_target(e) != d.scrollbarH)
+ operation(cm, onMouseDown)(e);
+ };
+ on(d.scrollbarV, "mousedown", barMouseDown);
+ on(d.scrollbarH, "mousedown", barMouseDown);
+ }
+ }
+
+ // Compute the lines that are visible in a given viewport (defaults
+ // the the current scroll position). viewPort may contain top,
+ // height, and ensure (see op.scrollToPos) properties.
+ function visibleLines(display, doc, viewPort) {
+ var top = viewPort && viewPort.top != null ? viewPort.top : display.scroller.scrollTop;
+ top = Math.floor(top - paddingTop(display));
+ var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + display.wrapper.clientHeight;
+
+ var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
+ // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
+ // forces those lines into the viewport (if possible).
+ if (viewPort && viewPort.ensure) {
+ var ensureFrom = viewPort.ensure.from.line, ensureTo = viewPort.ensure.to.line;
+ if (ensureFrom < from)
+ return {from: ensureFrom,
+ to: lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)};
+ if (Math.min(ensureTo, doc.lastLine()) >= to)
+ return {from: lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight),
+ to: ensureTo};
+ }
+ return {from: from, to: to};
+ }
+
+ // LINE NUMBERS
+
+ // Re-align line numbers and gutter marks to compensate for
+ // horizontal scrolling.
+ function alignHorizontally(cm) {
+ var display = cm.display, view = display.view;
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
+ var gutterW = display.gutters.offsetWidth, left = comp + "px";
+ for (var i = 0; i < view.length; i++) if (!view[i].hidden) {
+ if (cm.options.fixedGutter && view[i].gutter)
+ view[i].gutter.style.left = left;
+ var align = view[i].alignable;
+ if (align) for (var j = 0; j < align.length; j++)
+ align[j].style.left = left;
+ }
+ if (cm.options.fixedGutter)
+ display.gutters.style.left = (comp + gutterW) + "px";
+ }
+
+ // Used to ensure that the line number gutter is still the right
+ // size for the current document size. Returns true when an update
+ // is needed.
+ function maybeUpdateLineNumberWidth(cm) {
+ if (!cm.options.lineNumbers) return false;
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
+ if (last.length != display.lineNumChars) {
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
+ display.lineGutter.style.width = "";
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
+ display.lineGutter.style.width = display.lineNumWidth + "px";
+ var width = display.gutters.offsetWidth;
+ display.scrollbarH.style.left = cm.options.fixedGutter ? width + "px" : 0;
+ display.sizer.style.marginLeft = width + "px";
+ return true;
+ }
+ return false;
+ }
+
+ function lineNumberFor(options, i) {
+ return String(options.lineNumberFormatter(i + options.firstLineNumber));
+ }
+
+ // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
+ // but using getBoundingClientRect to get a sub-pixel-accurate
+ // result.
+ function compensateForHScroll(display) {
+ return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
+ }
+
+ // DISPLAY DRAWING
+
+ // Updates the display, selection, and scrollbars, using the
+ // information in display.view to find out which nodes are no longer
+ // up-to-date. Tries to bail out early when no changes are needed,
+ // unless forced is true.
+ // Returns true if an actual update happened, false otherwise.
+ function updateDisplay(cm, viewPort, forced) {
+ var oldFrom = cm.display.viewFrom, oldTo = cm.display.viewTo, updated;
+ var visible = visibleLines(cm.display, cm.doc, viewPort);
+ for (var first = true;; first = false) {
+ var oldWidth = cm.display.scroller.clientWidth;
+ if (!updateDisplayInner(cm, visible, forced)) break;
+ updated = true;
+
+ // If the max line changed since it was last measured, measure it,
+ // and ensure the document's width matches it.
+ if (cm.display.maxLineChanged && !cm.options.lineWrapping)
+ adjustContentWidth(cm);
+
+ var barMeasure = measureForScrollbars(cm);
+ updateSelection(cm);
+ setDocumentHeight(cm, barMeasure);
+ updateScrollbars(cm, barMeasure);
+ if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {
+ forced = true;
+ continue;
+ }
+ forced = false;
+
+ // Clip forced viewport to actual scrollable area.
+ if (viewPort && viewPort.top != null)
+ viewPort = {top: Math.min(barMeasure.docHeight - scrollerCutOff - barMeasure.clientHeight, viewPort.top)};
+ // Updated line heights might result in the drawn area not
+ // actually covering the viewport. Keep looping until it does.
+ visible = visibleLines(cm.display, cm.doc, viewPort);
+ if (visible.from >= cm.display.viewFrom && visible.to <= cm.display.viewTo)
+ break;
+ }
+
+ cm.display.updateLineNumbers = null;
+ if (updated) {
+ signalLater(cm, "update", cm);
+ if (cm.display.viewFrom != oldFrom || cm.display.viewTo != oldTo)
+ signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
+ }
+ return updated;
+ }
+
+ // Does the actual updating of the line display. Bails out
+ // (returning false) when there is nothing to be done and forced is
+ // false.
+ function updateDisplayInner(cm, visible, forced) {
+ var display = cm.display, doc = cm.doc;
+ if (!display.wrapper.offsetWidth) {
+ resetView(cm);
+ return;
+ }
+
+ // Bail out if the visible area is already rendered and nothing changed.
+ if (!forced && visible.from >= display.viewFrom && visible.to <= display.viewTo &&
+ countDirtyView(cm) == 0)
+ return;
+
+ if (maybeUpdateLineNumberWidth(cm))
+ resetView(cm);
+ var dims = getDimensions(cm);
+
+ // Compute a suitable new viewport (from & to)
+ var end = doc.first + doc.size;
+ var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
+ var to = Math.min(end, visible.to + cm.options.viewportMargin);
+ if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
+ if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
+ if (sawCollapsedSpans) {
+ from = visualLineNo(cm.doc, from);
+ to = visualLineEndNo(cm.doc, to);
+ }
+
+ var different = from != display.viewFrom || to != display.viewTo ||
+ display.lastSizeC != display.wrapper.clientHeight;
+ adjustView(cm, from, to);
+
+ display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
+ // Position the mover div to align with the current scroll position
+ cm.display.mover.style.top = display.viewOffset + "px";
+
+ var toUpdate = countDirtyView(cm);
+ if (!different && toUpdate == 0 && !forced) return;
+
+ // For big changes, we hide the enclosing element during the
+ // update, since that speeds up the operations on most browsers.
+ var focused = activeElt();
+ if (toUpdate > 4) display.lineDiv.style.display = "none";
+ patchDisplay(cm, display.updateLineNumbers, dims);
+ if (toUpdate > 4) display.lineDiv.style.display = "";
+ // There might have been a widget with a focused element that got
+ // hidden or updated, if so re-focus it.
+ if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();
+
+ // Prevent selection and cursors from interfering with the scroll
+ // width.
+ removeChildren(display.cursorDiv);
+ removeChildren(display.selectionDiv);
+
+ if (different) {
+ display.lastSizeC = display.wrapper.clientHeight;
+ startWorker(cm, 400);
+ }
+
+ updateHeightsInViewport(cm);
+
+ return true;
+ }
+
+ function adjustContentWidth(cm) {
+ var display = cm.display;
+ var width = measureChar(cm, display.maxLine, display.maxLine.text.length).left;
+ display.maxLineChanged = false;
+ var minWidth = Math.max(0, width + 3);
+ var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + minWidth + scrollerCutOff - display.scroller.clientWidth);
+ display.sizer.style.minWidth = minWidth + "px";
+ if (maxScrollLeft < cm.doc.scrollLeft)
+ setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
+ }
+
+ function setDocumentHeight(cm, measure) {
+ cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = measure.docHeight + "px";
+ cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px";
+ }
+
+ // Read the actual heights of the rendered lines, and update their
+ // stored heights to match.
+ function updateHeightsInViewport(cm) {
+ var display = cm.display;
+ var prevBottom = display.lineDiv.offsetTop;
+ for (var i = 0; i < display.view.length; i++) {
+ var cur = display.view[i], height;
+ if (cur.hidden) continue;
+ if (ie_upto7) {
+ var bot = cur.node.offsetTop + cur.node.offsetHeight;
+ height = bot - prevBottom;
+ prevBottom = bot;
+ } else {
+ var box = cur.node.getBoundingClientRect();
+ height = box.bottom - box.top;
+ }
+ var diff = cur.line.height - height;
+ if (height < 2) height = textHeight(display);
+ if (diff > .001 || diff < -.001) {
+ updateLineHeight(cur.line, height);
+ updateWidgetHeight(cur.line);
+ if (cur.rest) for (var j = 0; j < cur.rest.length; j++)
+ updateWidgetHeight(cur.rest[j]);
+ }
+ }
+ }
+
+ // Read and store the height of line widgets associated with the
+ // given line.
+ function updateWidgetHeight(line) {
+ if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
+ line.widgets[i].height = line.widgets[i].node.offsetHeight;
+ }
+
+ // Do a bulk-read of the DOM positions and sizes needed to draw the
+ // view, so that we don't interleave reading and writing to the DOM.
+ function getDimensions(cm) {
+ var d = cm.display, left = {}, width = {};
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
+ left[cm.options.gutters[i]] = n.offsetLeft;
+ width[cm.options.gutters[i]] = n.offsetWidth;
+ }
+ return {fixedPos: compensateForHScroll(d),
+ gutterTotalWidth: d.gutters.offsetWidth,
+ gutterLeft: left,
+ gutterWidth: width,
+ wrapperWidth: d.wrapper.clientWidth};
+ }
+
+ // Sync the actual display DOM structure with display.view, removing
+ // nodes for lines that are no longer in view, and creating the ones
+ // that are not there yet, and updating the ones that are out of
+ // date.
+ function patchDisplay(cm, updateNumbersFrom, dims) {
+ var display = cm.display, lineNumbers = cm.options.lineNumbers;
+ var container = display.lineDiv, cur = container.firstChild;
+
+ function rm(node) {
+ var next = node.nextSibling;
+ // Works around a throw-scroll bug in OS X Webkit
+ if (webkit && mac && cm.display.currentWheelTarget == node)
+ node.style.display = "none";
+ else
+ node.parentNode.removeChild(node);
+ return next;
+ }
+
+ var view = display.view, lineN = display.viewFrom;
+ // Loop over the elements in the view, syncing cur (the DOM nodes
+ // in display.lineDiv) with the view as we go.
+ for (var i = 0; i < view.length; i++) {
+ var lineView = view[i];
+ if (lineView.hidden) {
+ } else if (!lineView.node) { // Not drawn yet
+ var node = buildLineElement(cm, lineView, lineN, dims);
+ container.insertBefore(node, cur);
+ } else { // Already drawn
+ while (cur != lineView.node) cur = rm(cur);
+ var updateNumber = lineNumbers && updateNumbersFrom != null &&
+ updateNumbersFrom <= lineN && lineView.lineNumber;
+ if (lineView.changes) {
+ if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false;
+ updateLineForChanges(cm, lineView, lineN, dims);
+ }
+ if (updateNumber) {
+ removeChildren(lineView.lineNumber);
+ lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
+ }
+ cur = lineView.node.nextSibling;
+ }
+ lineN += lineView.size;
+ }
+ while (cur) cur = rm(cur);
+ }
+
+ // When an aspect of a line changes, a string is added to
+ // lineView.changes. This updates the relevant part of the line's
+ // DOM structure.
+ function updateLineForChanges(cm, lineView, lineN, dims) {
+ for (var j = 0; j < lineView.changes.length; j++) {
+ var type = lineView.changes[j];
+ if (type == "text") updateLineText(cm, lineView);
+ else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);
+ else if (type == "class") updateLineClasses(lineView);
+ else if (type == "widget") updateLineWidgets(lineView, dims);
+ }
+ lineView.changes = null;
+ }
+
+ // Lines with gutter elements, widgets or a background class need to
+ // be wrapped, and have the extra elements added to the wrapper div
+ function ensureLineWrapped(lineView) {
+ if (lineView.node == lineView.text) {
+ lineView.node = elt("div", null, null, "position: relative");
+ if (lineView.text.parentNode)
+ lineView.text.parentNode.replaceChild(lineView.node, lineView.text);
+ lineView.node.appendChild(lineView.text);
+ if (ie_upto7) lineView.node.style.zIndex = 2;
+ }
+ return lineView.node;
+ }
+
+ function updateLineBackground(lineView) {
+ var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
+ if (cls) cls += " CodeMirror-linebackground";
+ if (lineView.background) {
+ if (cls) lineView.background.className = cls;
+ else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
+ } else if (cls) {
+ var wrap = ensureLineWrapped(lineView);
+ lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
+ }
+ }
+
+ // Wrapper around buildLineContent which will reuse the structure
+ // in display.externalMeasured when possible.
+ function getLineContent(cm, lineView) {
+ var ext = cm.display.externalMeasured;
+ if (ext && ext.line == lineView.line) {
+ cm.display.externalMeasured = null;
+ lineView.measure = ext.measure;
+ return ext.built;
+ }
+ return buildLineContent(cm, lineView);
+ }
+
+ // Redraw the line's text. Interacts with the background and text
+ // classes because the mode may output tokens that influence these
+ // classes.
+ function updateLineText(cm, lineView) {
+ var cls = lineView.text.className;
+ var built = getLineContent(cm, lineView);
+ if (lineView.text == lineView.node) lineView.node = built.pre;
+ lineView.text.parentNode.replaceChild(built.pre, lineView.text);
+ lineView.text = built.pre;
+ if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
+ lineView.bgClass = built.bgClass;
+ lineView.textClass = built.textClass;
+ updateLineClasses(lineView);
+ } else if (cls) {
+ lineView.text.className = cls;
+ }
+ }
+
+ function updateLineClasses(lineView) {
+ updateLineBackground(lineView);
+ if (lineView.line.wrapClass)
+ ensureLineWrapped(lineView).className = lineView.line.wrapClass;
+ else if (lineView.node != lineView.text)
+ lineView.node.className = "";
+ var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
+ lineView.text.className = textClass || "";
+ }
+
+ function updateLineGutter(cm, lineView, lineN, dims) {
+ if (lineView.gutter) {
+ lineView.node.removeChild(lineView.gutter);
+ lineView.gutter = null;
+ }
+ var markers = lineView.line.gutterMarkers;
+ if (cm.options.lineNumbers || markers) {
+ var wrap = ensureLineWrapped(lineView);
+ var gutterWrap = lineView.gutter =
+ wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "position: absolute; left: " +
+ (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
+ lineView.text);
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
+ lineView.lineNumber = gutterWrap.appendChild(
+ elt("div", lineNumberFor(cm.options, lineN),
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
+ "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
+ + cm.display.lineNumInnerWidth + "px"));
+ if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
+ if (found)
+ gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
+ dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
+ }
+ }
+ }
+
+ function updateLineWidgets(lineView, dims) {
+ if (lineView.alignable) lineView.alignable = null;
+ for (var node = lineView.node.firstChild, next; node; node = next) {
+ var next = node.nextSibling;
+ if (node.className == "CodeMirror-linewidget")
+ lineView.node.removeChild(node);
+ }
+ insertLineWidgets(lineView, dims);
+ }
+
+ // Build a line's DOM representation from scratch
+ function buildLineElement(cm, lineView, lineN, dims) {
+ var built = getLineContent(cm, lineView);
+ lineView.text = lineView.node = built.pre;
+ if (built.bgClass) lineView.bgClass = built.bgClass;
+ if (built.textClass) lineView.textClass = built.textClass;
+
+ updateLineClasses(lineView);
+ updateLineGutter(cm, lineView, lineN, dims);
+ insertLineWidgets(lineView, dims);
+ return lineView.node;
+ }
+
+ // A lineView may contain multiple logical lines (when merged by
+ // collapsed spans). The widgets for all of them need to be drawn.
+ function insertLineWidgets(lineView, dims) {
+ insertLineWidgetsFor(lineView.line, lineView, dims, true);
+ if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
+ insertLineWidgetsFor(lineView.rest[i], lineView, dims, false);
+ }
+
+ function insertLineWidgetsFor(line, lineView, dims, allowAbove) {
+ if (!line.widgets) return;
+ var wrap = ensureLineWrapped(lineView);
+ for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
+ if (!widget.handleMouseEvents) node.ignoreEvents = true;
+ positionLineWidget(widget, node, lineView, dims);
+ if (allowAbove && widget.above)
+ wrap.insertBefore(node, lineView.gutter || lineView.text);
+ else
+ wrap.appendChild(node);
+ signalLater(widget, "redraw");
+ }
+ }
+
+ function positionLineWidget(widget, node, lineView, dims) {
+ if (widget.noHScroll) {
+ (lineView.alignable || (lineView.alignable = [])).push(node);
+ var width = dims.wrapperWidth;
+ node.style.left = dims.fixedPos + "px";
+ if (!widget.coverGutter) {
+ width -= dims.gutterTotalWidth;
+ node.style.paddingLeft = dims.gutterTotalWidth + "px";
+ }
+ node.style.width = width + "px";
+ }
+ if (widget.coverGutter) {
+ node.style.zIndex = 5;
+ node.style.position = "relative";
+ if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
+ }
+ }
+
+ // POSITION OBJECT
+
+ // A Pos instance represents a position within the text.
+ var Pos = CodeMirror.Pos = function(line, ch) {
+ if (!(this instanceof Pos)) return new Pos(line, ch);
+ this.line = line; this.ch = ch;
+ };
+
+ // Compare two positions, return 0 if they are the same, a negative
+ // number when a is less, and a positive number otherwise.
+ var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };
+
+ function copyPos(x) {return Pos(x.line, x.ch);}
+ function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }
+ function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }
+
+ // SELECTION / CURSOR
+
+ // Selection objects are immutable. A new one is created every time
+ // the selection changes. A selection is one or more non-overlapping
+ // (and non-touching) ranges, sorted, and an integer that indicates
+ // which one is the primary selection (the one that's scrolled into
+ // view, that getCursor returns, etc).
+ function Selection(ranges, primIndex) {
+ this.ranges = ranges;
+ this.primIndex = primIndex;
+ }
+
+ Selection.prototype = {
+ primary: function() { return this.ranges[this.primIndex]; },
+ equals: function(other) {
+ if (other == this) return true;
+ if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;
+ for (var i = 0; i < this.ranges.length; i++) {
+ var here = this.ranges[i], there = other.ranges[i];
+ if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;
+ }
+ return true;
+ },
+ deepCopy: function() {
+ for (var out = [], i = 0; i < this.ranges.length; i++)
+ out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));
+ return new Selection(out, this.primIndex);
+ },
+ somethingSelected: function() {
+ for (var i = 0; i < this.ranges.length; i++)
+ if (!this.ranges[i].empty()) return true;
+ return false;
+ },
+ contains: function(pos, end) {
+ if (!end) end = pos;
+ for (var i = 0; i < this.ranges.length; i++) {
+ var range = this.ranges[i];
+ if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
+ return i;
+ }
+ return -1;
+ }
+ };
+
+ function Range(anchor, head) {
+ this.anchor = anchor; this.head = head;
+ }
+
+ Range.prototype = {
+ from: function() { return minPos(this.anchor, this.head); },
+ to: function() { return maxPos(this.anchor, this.head); },
+ empty: function() {
+ return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;
+ }
+ };
+
+ // Take an unsorted, potentially overlapping set of ranges, and
+ // build a selection out of it. 'Consumes' ranges array (modifying
+ // it).
+ function normalizeSelection(ranges, primIndex) {
+ var prim = ranges[primIndex];
+ ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });
+ primIndex = indexOf(ranges, prim);
+ for (var i = 1; i < ranges.length; i++) {
+ var cur = ranges[i], prev = ranges[i - 1];
+ if (cmp(prev.to(), cur.from()) >= 0) {
+ var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
+ var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
+ if (i <= primIndex) --primIndex;
+ ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
+ }
+ }
+ return new Selection(ranges, primIndex);
+ }
+
+ function simpleSelection(anchor, head) {
+ return new Selection([new Range(anchor, head || anchor)], 0);
+ }
+
+ // Most of the external API clips given positions to make sure they
+ // actually exist within the document.
+ function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
+ function clipPos(doc, pos) {
+ if (pos.line < doc.first) return Pos(doc.first, 0);
+ var last = doc.first + doc.size - 1;
+ if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
+ return clipToLen(pos, getLine(doc, pos.line).text.length);
+ }
+ function clipToLen(pos, linelen) {
+ var ch = pos.ch;
+ if (ch == null || ch > linelen) return Pos(pos.line, linelen);
+ else if (ch < 0) return Pos(pos.line, 0);
+ else return pos;
+ }
+ function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
+ function clipPosArray(doc, array) {
+ for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);
+ return out;
+ }
+
+ // SELECTION UPDATES
+
+ // The 'scroll' parameter given to many of these indicated whether
+ // the new cursor position should be scrolled into view after
+ // modifying the selection.
+
+ // If shift is held or the extend flag is set, extends a range to
+ // include a given position (and optionally a second position).
+ // Otherwise, simply returns the range between the given positions.
+ // Used for cursor motion and such.
+ function extendRange(doc, range, head, other) {
+ if (doc.cm && doc.cm.display.shift || doc.extend) {
+ var anchor = range.anchor;
+ if (other) {
+ var posBefore = cmp(head, anchor) < 0;
+ if (posBefore != (cmp(other, anchor) < 0)) {
+ anchor = head;
+ head = other;
+ } else if (posBefore != (cmp(head, other) < 0)) {
+ head = other;
+ }
+ }
+ return new Range(anchor, head);
+ } else {
+ return new Range(other || head, head);
+ }
+ }
+
+ // Extend the primary selection range, discard the rest.
+ function extendSelection(doc, head, other, options) {
+ setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);
+ }
+
+ // Extend all selections (pos is an array of selections with length
+ // equal the number of selections)
+ function extendSelections(doc, heads, options) {
+ for (var out = [], i = 0; i < doc.sel.ranges.length; i++)
+ out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);
+ var newSel = normalizeSelection(out, doc.sel.primIndex);
+ setSelection(doc, newSel, options);
+ }
+
+ // Updates a single range in the selection.
+ function replaceOneSelection(doc, i, range, options) {
+ var ranges = doc.sel.ranges.slice(0);
+ ranges[i] = range;
+ setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);
+ }
+
+ // Reset the selection to a single range.
+ function setSimpleSelection(doc, anchor, head, options) {
+ setSelection(doc, simpleSelection(anchor, head), options);
+ }
+
+ // Give beforeSelectionChange handlers a change to influence a
+ // selection update.
+ function filterSelectionChange(doc, sel) {
+ var obj = {
+ ranges: sel.ranges,
+ update: function(ranges) {
+ this.ranges = [];
+ for (var i = 0; i < ranges.length; i++)
+ this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
+ clipPos(doc, ranges[i].head));
+ }
+ };
+ signal(doc, "beforeSelectionChange", doc, obj);
+ if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
+ if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);
+ else return sel;
+ }
+
+ function setSelectionReplaceHistory(doc, sel, options) {
+ var done = doc.history.done, last = lst(done);
+ if (last && last.ranges) {
+ done[done.length - 1] = sel;
+ setSelectionNoUndo(doc, sel, options);
+ } else {
+ setSelection(doc, sel, options);
+ }
+ }
+
+ // Set a new selection.
+ function setSelection(doc, sel, options) {
+ setSelectionNoUndo(doc, sel, options);
+ addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
+ }
+
+ function setSelectionNoUndo(doc, sel, options) {
+ if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
+ sel = filterSelectionChange(doc, sel);
+
+ var bias = cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1;
+ setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
+
+ if (!(options && options.scroll === false) && doc.cm)
+ ensureCursorVisible(doc.cm);
+ }
+
+ function setSelectionInner(doc, sel) {
+ if (sel.equals(doc.sel)) return;
+
+ doc.sel = sel;
+
+ if (doc.cm)
+ doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
+ doc.cm.curOp.cursorActivity = true;
+ signalLater(doc, "cursorActivity", doc);
+ }
+
+ // Verify that the selection does not partially select any atomic
+ // marked ranges.
+ function reCheckSelection(doc) {
+ setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
+ }
+
+ // Return a selection that does not partially select any atomic
+ // ranges.
+ function skipAtomicInSelection(doc, sel, bias, mayClear) {
+ var out;
+ for (var i = 0; i < sel.ranges.length; i++) {
+ var range = sel.ranges[i];
+ var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
+ var newHead = skipAtomic(doc, range.head, bias, mayClear);
+ if (out || newAnchor != range.anchor || newHead != range.head) {
+ if (!out) out = sel.ranges.slice(0, i);
+ out[i] = new Range(newAnchor, newHead);
+ }
+ }
+ return out ? normalizeSelection(out, sel.primIndex) : sel;
+ }
+
+ // Ensure a given position is not inside an atomic range.
+ function skipAtomic(doc, pos, bias, mayClear) {
+ var flipped = false, curPos = pos;
+ var dir = bias || 1;
+ doc.cantEdit = false;
+ search: for (;;) {
+ var line = getLine(doc, curPos.line);
+ if (line.markedSpans) {
+ for (var i = 0; i < line.markedSpans.length; ++i) {
+ var sp = line.markedSpans[i], m = sp.marker;
+ if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
+ (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
+ if (mayClear) {
+ signal(m, "beforeCursorEnter");
+ if (m.explicitlyCleared) {
+ if (!line.markedSpans) break;
+ else {--i; continue;}
+ }
+ }
+ if (!m.atomic) continue;
+ var newPos = m.find(dir < 0 ? -1 : 1);
+ if (cmp(newPos, curPos) == 0) {
+ newPos.ch += dir;
+ if (newPos.ch < 0) {
+ if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
+ else newPos = null;
+ } else if (newPos.ch > line.text.length) {
+ if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
+ else newPos = null;
+ }
+ if (!newPos) {
+ if (flipped) {
+ // Driven in a corner -- no valid cursor position found at all
+ // -- try again *with* clearing, if we didn't already
+ if (!mayClear) return skipAtomic(doc, pos, bias, true);
+ // Otherwise, turn off editing until further notice, and return the start of the doc
+ doc.cantEdit = true;
+ return Pos(doc.first, 0);
+ }
+ flipped = true; newPos = pos; dir = -dir;
+ }
+ }
+ curPos = newPos;
+ continue search;
+ }
+ }
+ }
+ return curPos;
+ }
+ }
+
+ // SELECTION DRAWING
+
+ // Redraw the selection and/or cursor
+ function updateSelection(cm) {
+ var display = cm.display, doc = cm.doc;
+ var curFragment = document.createDocumentFragment();
+ var selFragment = document.createDocumentFragment();
+
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
+ var range = doc.sel.ranges[i];
+ var collapsed = range.empty();
+ if (collapsed || cm.options.showCursorWhenSelecting)
+ updateSelectionCursor(cm, range, curFragment);
+ if (!collapsed)
+ updateSelectionRange(cm, range, selFragment);
+ }
+
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
+ if (cm.options.moveInputWithCursor) {
+ var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
+ var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
+ var top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
+ headPos.top + lineOff.top - wrapOff.top));
+ var left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
+ headPos.left + lineOff.left - wrapOff.left));
+ display.inputDiv.style.top = top + "px";
+ display.inputDiv.style.left = left + "px";
+ }
+
+ removeChildrenAndAdd(display.cursorDiv, curFragment);
+ removeChildrenAndAdd(display.selectionDiv, selFragment);
+ }
+
+ // Draws a cursor for the given range
+ function updateSelectionCursor(cm, range, output) {
+ var pos = cursorCoords(cm, range.head, "div");
+
+ var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
+ cursor.style.left = pos.left + "px";
+ cursor.style.top = pos.top + "px";
+ cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
+
+ if (pos.other) {
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
+ var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
+ otherCursor.style.display = "";
+ otherCursor.style.left = pos.other.left + "px";
+ otherCursor.style.top = pos.other.top + "px";
+ otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
+ }
+ }
+
+ // Draws the given range as a highlighted selection
+ function updateSelectionRange(cm, range, output) {
+ var display = cm.display, doc = cm.doc;
+ var fragment = document.createDocumentFragment();
+ var padding = paddingH(cm.display), leftSide = padding.left, rightSide = display.lineSpace.offsetWidth - padding.right;
+
+ function add(left, top, width, bottom) {
+ if (top < 0) top = 0;
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
+ "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
+ "px; height: " + (bottom - top) + "px"));
+ }
+
+ function drawForLine(line, fromArg, toArg) {
+ var lineObj = getLine(doc, line);
+ var lineLen = lineObj.text.length;
+ var start, end;
+ function coords(ch, bias) {
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
+ }
+
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
+ var leftPos = coords(from, "left"), rightPos, left, right;
+ if (from == to) {
+ rightPos = leftPos;
+ left = right = leftPos.left;
+ } else {
+ rightPos = coords(to - 1, "right");
+ if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
+ left = leftPos.left;
+ right = rightPos.right;
+ }
+ if (fromArg == null && from == 0) left = leftSide;
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
+ add(left, leftPos.top, null, leftPos.bottom);
+ left = leftSide;
+ if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
+ }
+ if (toArg == null && to == lineLen) right = rightSide;
+ if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
+ start = leftPos;
+ if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
+ end = rightPos;
+ if (left < leftSide + 1) left = leftSide;
+ add(left, rightPos.top, right - left, rightPos.bottom);
+ });
+ return {start: start, end: end};
+ }
+
+ var sFrom = range.from(), sTo = range.to();
+ if (sFrom.line == sTo.line) {
+ drawForLine(sFrom.line, sFrom.ch, sTo.ch);
+ } else {
+ var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
+ var singleVLine = visualLine(fromLine) == visualLine(toLine);
+ var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
+ var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
+ if (singleVLine) {
+ if (leftEnd.top < rightStart.top - 2) {
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
+ add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
+ } else {
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
+ }
+ }
+ if (leftEnd.bottom < rightStart.top)
+ add(leftSide, leftEnd.bottom, null, rightStart.top);
+ }
+
+ output.appendChild(fragment);
+ }
+
+ // Cursor-blinking
+ function restartBlink(cm) {
+ if (!cm.state.focused) return;
+ var display = cm.display;
+ clearInterval(display.blinker);
+ var on = true;
+ display.cursorDiv.style.visibility = "";
+ if (cm.options.cursorBlinkRate > 0)
+ display.blinker = setInterval(function() {
+ display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
+ }, cm.options.cursorBlinkRate);
+ }
+
+ // HIGHLIGHT WORKER
+
+ function startWorker(cm, time) {
+ if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
+ cm.state.highlight.set(time, bind(highlightWorker, cm));
+ }
+
+ function highlightWorker(cm) {
+ var doc = cm.doc;
+ if (doc.frontier < doc.first) doc.frontier = doc.first;
+ if (doc.frontier >= cm.display.viewTo) return;
+ var end = +new Date + cm.options.workTime;
+ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
+
+ runInOp(cm, function() {
+ doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
+ if (doc.frontier >= cm.display.viewFrom) { // Visible
+ var oldStyles = line.styles;
+ line.styles = highlightLine(cm, line, state, true);
+ var ischange = !oldStyles || oldStyles.length != line.styles.length;
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
+ if (ischange) regLineChange(cm, doc.frontier, "text");
+ line.stateAfter = copyState(doc.mode, state);
+ } else {
+ processLine(cm, line.text, state);
+ line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
+ }
+ ++doc.frontier;
+ if (+new Date > end) {
+ startWorker(cm, cm.options.workDelay);
+ return true;
+ }
+ });
+ });
+ }
+
+ // Finds the line to start with when starting a parse. Tries to
+ // find a line with a stateAfter, so that it can start with a
+ // valid state. If that fails, it returns the line with the
+ // smallest indentation, which tends to need the least context to
+ // parse correctly.
+ function findStartLine(cm, n, precise) {
+ var minindent, minline, doc = cm.doc;
+ var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
+ for (var search = n; search > lim; --search) {
+ if (search <= doc.first) return doc.first;
+ var line = getLine(doc, search - 1);
+ if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
+ var indented = countColumn(line.text, null, cm.options.tabSize);
+ if (minline == null || minindent > indented) {
+ minline = search - 1;
+ minindent = indented;
+ }
+ }
+ return minline;
+ }
+
+ function getStateBefore(cm, n, precise) {
+ var doc = cm.doc, display = cm.display;
+ if (!doc.mode.startState) return true;
+ var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
+ if (!state) state = startState(doc.mode);
+ else state = copyState(doc.mode, state);
+ doc.iter(pos, n, function(line) {
+ processLine(cm, line.text, state);
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;
+ line.stateAfter = save ? copyState(doc.mode, state) : null;
+ ++pos;
+ });
+ if (precise) doc.frontier = pos;
+ return state;
+ }
+
+ // POSITION MEASUREMENT
+
+ function paddingTop(display) {return display.lineSpace.offsetTop;}
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
+ function paddingH(display) {
+ if (display.cachedPaddingH) return display.cachedPaddingH;
+ var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
+ var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
+ return display.cachedPaddingH = {left: parseInt(style.paddingLeft),
+ right: parseInt(style.paddingRight)};
+ }
+
+ // Ensure the lineView.wrapping.heights array is populated. This is
+ // an array of bottom offsets for the lines that make up a drawn
+ // line. When lineWrapping is on, there might be more than one
+ // height.
+ function ensureLineHeights(cm, lineView, rect) {
+ var wrapping = cm.options.lineWrapping;
+ var curWidth = wrapping && cm.display.scroller.clientWidth;
+ if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
+ var heights = lineView.measure.heights = [];
+ if (wrapping) {
+ lineView.measure.width = curWidth;
+ var rects = lineView.text.firstChild.getClientRects();
+ for (var i = 0; i < rects.length - 1; i++) {
+ var cur = rects[i], next = rects[i + 1];
+ if (Math.abs(cur.bottom - next.bottom) > 2)
+ heights.push((cur.bottom + next.top) / 2 - rect.top);
+ }
+ }
+ heights.push(rect.bottom - rect.top);
+ }
+ }
+
+ // Find a line map (mapping character offsets to text nodes) and a
+ // measurement cache for the given line number. (A line view might
+ // contain multiple lines when collapsed ranges are present.)
+ function mapFromLineView(lineView, line, lineN) {
+ if (lineView.line == line)
+ return {map: lineView.measure.map, cache: lineView.measure.cache};
+ for (var i = 0; i < lineView.rest.length; i++)
+ if (lineView.rest[i] == line)
+ return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
+ for (var i = 0; i < lineView.rest.length; i++)
+ if (lineNo(lineView.rest[i]) > lineN)
+ return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};
+ }
+
+ // Render a line into the hidden node display.externalMeasured. Used
+ // when measurement is needed for a line that's not in the viewport.
+ function updateExternalMeasurement(cm, line) {
+ line = visualLine(line);
+ var lineN = lineNo(line);
+ var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
+ view.lineN = lineN;
+ var built = view.built = buildLineContent(cm, view);
+ view.text = built.pre;
+ removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
+ return view;
+ }
+
+ // Get a {top, bottom, left, right} box (in line-local coordinates)
+ // for a given character.
+ function measureChar(cm, line, ch, bias) {
+ return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);
+ }
+
+ // Find a line view that corresponds to the given line number.
+ function findViewForLine(cm, lineN) {
+ if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
+ return cm.display.view[findViewIndex(cm, lineN)];
+ var ext = cm.display.externalMeasured;
+ if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
+ return ext;
+ }
+
+ // Measurement can be split in two steps, the set-up work that
+ // applies to the whole line, and the measurement of the actual
+ // character. Functions like coordsChar, that need to do a lot of
+ // measurements in a row, can thus ensure that the set-up work is
+ // only done once.
+ function prepareMeasureForLine(cm, line) {
+ var lineN = lineNo(line);
+ var view = findViewForLine(cm, lineN);
+ if (view && !view.text)
+ view = null;
+ else if (view && view.changes)
+ updateLineForChanges(cm, view, lineN, getDimensions(cm));
+ if (!view)
+ view = updateExternalMeasurement(cm, line);
+
+ var info = mapFromLineView(view, line, lineN);
+ return {
+ line: line, view: view, rect: null,
+ map: info.map, cache: info.cache, before: info.before,
+ hasHeights: false
+ };
+ }
+
+ // Given a prepared measurement object, measures the position of an
+ // actual character (or fetches it from the cache).
+ function measureCharPrepared(cm, prepared, ch, bias) {
+ if (prepared.before) ch = -1;
+ var key = ch + (bias || ""), found;
+ if (prepared.cache.hasOwnProperty(key)) {
+ found = prepared.cache[key];
+ } else {
+ if (!prepared.rect)
+ prepared.rect = prepared.view.text.getBoundingClientRect();
+ if (!prepared.hasHeights) {
+ ensureLineHeights(cm, prepared.view, prepared.rect);
+ prepared.hasHeights = true;
+ }
+ found = measureCharInner(cm, prepared, ch, bias);
+ if (!found.bogus) prepared.cache[key] = found;
+ }
+ return {left: found.left, right: found.right, top: found.top, bottom: found.bottom};
+ }
+
+ var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
+
+ function measureCharInner(cm, prepared, ch, bias) {
+ var map = prepared.map;
+
+ var node, start, end, collapse;
+ // First, search the line map for the text node corresponding to,
+ // or closest to, the target character.
+ for (var i = 0; i < map.length; i += 3) {
+ var mStart = map[i], mEnd = map[i + 1];
+ if (ch < mStart) {
+ start = 0; end = 1;
+ collapse = "left";
+ } else if (ch < mEnd) {
+ start = ch - mStart;
+ end = start + 1;
+ } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
+ end = mEnd - mStart;
+ start = end - 1;
+ if (ch >= mEnd) collapse = "right";
+ }
+ if (start != null) {
+ node = map[i + 2];
+ if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
+ collapse = bias;
+ if (bias == "left" && start == 0)
+ while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
+ node = map[(i -= 3) + 2];
+ collapse = "left";
+ }
+ if (bias == "right" && start == mEnd - mStart)
+ while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
+ node = map[(i += 3) + 2];
+ collapse = "right";
+ }
+ break;
+ }
+ }
+
+ var rect;
+ if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
+ while (start && isExtendingChar(prepared.line.text.charAt(mStart + start))) --start;
+ while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mStart + end))) ++end;
+ if (ie_upto8 && start == 0 && end == mEnd - mStart) {
+ rect = node.parentNode.getBoundingClientRect();
+ } else if (ie && cm.options.lineWrapping) {
+ var rects = range(node, start, end).getClientRects();
+ if (rects.length)
+ rect = rects[bias == "right" ? rects.length - 1 : 0];
+ else
+ rect = nullRect;
+ } else {
+ rect = range(node, start, end).getBoundingClientRect();
+ }
+ } else { // If it is a widget, simply get the box for the whole widget.
+ if (start > 0) collapse = bias = "right";
+ var rects;
+ if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
+ rect = rects[bias == "right" ? rects.length - 1 : 0];
+ else
+ rect = node.getBoundingClientRect();
+ }
+ if (ie_upto8 && !start && (!rect || !rect.left && !rect.right)) {
+ var rSpan = node.parentNode.getClientRects()[0];
+ if (rSpan)
+ rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};
+ else
+ rect = nullRect;
+ }
+
+ var top, bot = (rect.bottom + rect.top) / 2 - prepared.rect.top;
+ var heights = prepared.view.measure.heights;
+ for (var i = 0; i < heights.length - 1; i++)
+ if (bot < heights[i]) break;
+ top = i ? heights[i - 1] : 0; bot = heights[i];
+ var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
+ right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
+ top: top, bottom: bot};
+ if (!rect.left && !rect.right) result.bogus = true;
+ return result;
+ }
+
+ function clearLineMeasurementCacheFor(lineView) {
+ if (lineView.measure) {
+ lineView.measure.cache = {};
+ lineView.measure.heights = null;
+ if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
+ lineView.measure.caches[i] = {};
+ }
+ }
+
+ function clearLineMeasurementCache(cm) {
+ cm.display.externalMeasure = null;
+ removeChildren(cm.display.lineMeasure);
+ for (var i = 0; i < cm.display.view.length; i++)
+ clearLineMeasurementCacheFor(cm.display.view[i]);
+ }
+
+ function clearCaches(cm) {
+ clearLineMeasurementCache(cm);
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
+ if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
+ cm.display.lineNumChars = null;
+ }
+
+ function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
+ function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
+
+ // Converts a {top, bottom, left, right} box from line-local
+ // coordinates into another coordinate system. Context may be one of
+ // "line", "div" (display.lineDiv), "local"/null (editor), or "page".
+ function intoCoordSystem(cm, lineObj, rect, context) {
+ if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
+ var size = widgetHeight(lineObj.widgets[i]);
+ rect.top += size; rect.bottom += size;
+ }
+ if (context == "line") return rect;
+ if (!context) context = "local";
+ var yOff = heightAtLine(lineObj);
+ if (context == "local") yOff += paddingTop(cm.display);
+ else yOff -= cm.display.viewOffset;
+ if (context == "page" || context == "window") {
+ var lOff = cm.display.lineSpace.getBoundingClientRect();
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
+ rect.left += xOff; rect.right += xOff;
+ }
+ rect.top += yOff; rect.bottom += yOff;
+ return rect;
+ }
+
+ // Coverts a box from "div" coords to another coordinate system.
+ // Context may be "window", "page", "div", or "local"/null.
+ function fromCoordSystem(cm, coords, context) {
+ if (context == "div") return coords;
+ var left = coords.left, top = coords.top;
+ // First move into "page" coordinate system
+ if (context == "page") {
+ left -= pageScrollX();
+ top -= pageScrollY();
+ } else if (context == "local" || !context) {
+ var localBox = cm.display.sizer.getBoundingClientRect();
+ left += localBox.left;
+ top += localBox.top;
+ }
+
+ var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
+ }
+
+ function charCoords(cm, pos, context, lineObj, bias) {
+ if (!lineObj) lineObj = getLine(cm.doc, pos.line);
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);
+ }
+
+ // Returns a box for a given cursor position, which may have an
+ // 'other' property containing the position of the secondary cursor
+ // on a bidi boundary.
+ function cursorCoords(cm, pos, context, lineObj, preparedMeasure) {
+ lineObj = lineObj || getLine(cm.doc, pos.line);
+ if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);
+ function get(ch, right) {
+ var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left");
+ if (right) m.left = m.right; else m.right = m.left;
+ return intoCoordSystem(cm, lineObj, m, context);
+ }
+ function getBidi(ch, partPos) {
+ var part = order[partPos], right = part.level % 2;
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
+ part = order[--partPos];
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
+ right = true;
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
+ part = order[++partPos];
+ ch = bidiLeft(part) - part.level % 2;
+ right = false;
+ }
+ if (right && ch == part.to && ch > part.from) return get(ch - 1);
+ return get(ch, right);
+ }
+ var order = getOrder(lineObj), ch = pos.ch;
+ if (!order) return get(ch);
+ var partPos = getBidiPartAt(order, ch);
+ var val = getBidi(ch, partPos);
+ if (bidiOther != null) val.other = getBidi(ch, bidiOther);
+ return val;
+ }
+
+ // Used to cheaply estimate the coordinates for a position. Used for
+ // intermediate scroll updates.
+ function estimateCoords(cm, pos) {
+ var left = 0, pos = clipPos(cm.doc, pos);
+ if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;
+ var lineObj = getLine(cm.doc, pos.line);
+ var top = heightAtLine(lineObj) + paddingTop(cm.display);
+ return {left: left, right: left, top: top, bottom: top + lineObj.height};
+ }
+
+ // Positions returned by coordsChar contain some extra information.
+ // xRel is the relative x position of the input coordinates compared
+ // to the found position (so xRel > 0 means the coordinates are to
+ // the right of the character position, for example). When outside
+ // is true, that means the coordinates lie outside the line's
+ // vertical range.
+ function PosWithInfo(line, ch, outside, xRel) {
+ var pos = Pos(line, ch);
+ pos.xRel = xRel;
+ if (outside) pos.outside = true;
+ return pos;
+ }
+
+ // Compute the character position closest to the given coordinates.
+ // Input must be lineSpace-local ("div" coordinate system).
+ function coordsChar(cm, x, y) {
+ var doc = cm.doc;
+ y += cm.display.viewOffset;
+ if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
+ var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
+ if (lineN > last)
+ return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
+ if (x < 0) x = 0;
+
+ var lineObj = getLine(doc, lineN);
+ for (;;) {
+ var found = coordsCharInner(cm, lineObj, lineN, x, y);
+ var merged = collapsedSpanAtEnd(lineObj);
+ var mergedPos = merged && merged.find(0, true);
+ if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
+ lineN = lineNo(lineObj = mergedPos.to.line);
+ else
+ return found;
+ }
+ }
+
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
+ var innerOff = y - heightAtLine(lineObj);
+ var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
+ var preparedMeasure = prepareMeasureForLine(cm, lineObj);
+
+ function getX(ch) {
+ var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);
+ wrongLine = true;
+ if (innerOff > sp.bottom) return sp.left - adjust;
+ else if (innerOff < sp.top) return sp.left + adjust;
+ else wrongLine = false;
+ return sp.left;
+ }
+
+ var bidi = getOrder(lineObj), dist = lineObj.text.length;
+ var from = lineLeft(lineObj), to = lineRight(lineObj);
+ var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
+
+ if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
+ // Do a binary search between these bounds.
+ for (;;) {
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
+ var ch = x < fromX || x - fromX <= toX - x ? from : to;
+ var xDiff = x - (ch == from ? fromX : toX);
+ while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
+ var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
+ xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
+ return pos;
+ }
+ var step = Math.ceil(dist / 2), middle = from + step;
+ if (bidi) {
+ middle = from;
+ for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
+ }
+ var middleX = getX(middle);
+ if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
+ else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
+ }
+ }
+
+ var measureText;
+ // Compute the default text height.
+ function textHeight(display) {
+ if (display.cachedTextHeight != null) return display.cachedTextHeight;
+ if (measureText == null) {
+ measureText = elt("pre");
+ // Measure a bunch of lines, for browsers that compute
+ // fractional heights.
+ for (var i = 0; i < 49; ++i) {
+ measureText.appendChild(document.createTextNode("x"));
+ measureText.appendChild(elt("br"));
+ }
+ measureText.appendChild(document.createTextNode("x"));
+ }
+ removeChildrenAndAdd(display.measure, measureText);
+ var height = measureText.offsetHeight / 50;
+ if (height > 3) display.cachedTextHeight = height;
+ removeChildren(display.measure);
+ return height || 1;
+ }
+
+ // Compute the default character width.
+ function charWidth(display) {
+ if (display.cachedCharWidth != null) return display.cachedCharWidth;
+ var anchor = elt("span", "xxxxxxxxxx");
+ var pre = elt("pre", [anchor]);
+ removeChildrenAndAdd(display.measure, pre);
+ var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
+ if (width > 2) display.cachedCharWidth = width;
+ return width || 10;
+ }
+
+ // OPERATIONS
+
+ // Operations are used to wrap a series of changes to the editor
+ // state in such a way that each change won't have to update the
+ // cursor and display (which would be awkward, slow, and
+ // error-prone). Instead, display updates are batched and then all
+ // combined and executed at once.
+
+ var nextOpId = 0;
+ // Start a new operation.
+ function startOperation(cm) {
+ cm.curOp = {
+ viewChanged: false, // Flag that indicates that lines might need to be redrawn
+ startHeight: cm.doc.height, // Used to detect need to update scrollbar
+ forceUpdate: false, // Used to force a redraw
+ updateInput: null, // Whether to reset the input textarea
+ typing: false, // Whether this reset should be careful to leave existing text (for compositing)
+ changeObjs: null, // Accumulated changes, for firing change events
+ cursorActivity: false, // Whether to fire a cursorActivity event
+ selectionChanged: false, // Whether the selection needs to be redrawn
+ updateMaxLine: false, // Set when the widest line needs to be determined anew
+ scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
+ scrollToPos: null, // Used to scroll to a specific position
+ id: ++nextOpId // Unique ID
+ };
+ if (!delayedCallbackDepth++) delayedCallbacks = [];
+ }
+
+ // Finish an operation, updating the display and signalling delayed events
+ function endOperation(cm) {
+ var op = cm.curOp, doc = cm.doc, display = cm.display;
+ cm.curOp = null;
+
+ if (op.updateMaxLine) findMaxLine(cm);
+
+ // If it looks like an update might be needed, call updateDisplay
+ if (op.viewChanged || op.forceUpdate || op.scrollTop != null ||
+ op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
+ op.scrollToPos.to.line >= display.viewTo) ||
+ display.maxLineChanged && cm.options.lineWrapping) {
+ var updated = updateDisplay(cm, {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
+ if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
+ }
+ // If no update was run, but the selection changed, redraw that.
+ if (!updated && op.selectionChanged) updateSelection(cm);
+ if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm);
+
+ // Propagate the scroll position to the actual DOM scroller
+ if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) {
+ var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
+ display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;
+ }
+ if (op.scrollLeft != null && display.scroller.scrollLeft != op.scrollLeft) {
+ var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft));
+ display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left;
+ alignHorizontally(cm);
+ }
+ // If we need to scroll a specific position into view, do so.
+ if (op.scrollToPos) {
+ var coords = scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from),
+ clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin);
+ if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
+ }
+
+ if (op.selectionChanged) restartBlink(cm);
+
+ if (cm.state.focused && op.updateInput)
+ resetInput(cm, op.typing);
+
+ // Fire events for markers that are hidden/unidden by editing or
+ // undoing
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
+ if (hidden) for (var i = 0; i < hidden.length; ++i)
+ if (!hidden[i].lines.length) signal(hidden[i], "hide");
+ if (unhidden) for (var i = 0; i < unhidden.length; ++i)
+ if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
+
+ var delayed;
+ if (!--delayedCallbackDepth) {
+ delayed = delayedCallbacks;
+ delayedCallbacks = null;
+ }
+ // Fire change events, and delayed event handlers
+ if (op.changeObjs) {
+ for (var i = 0; i < op.changeObjs.length; i++)
+ signal(cm, "change", cm, op.changeObjs[i]);
+ signal(cm, "changes", cm, op.changeObjs);
+ }
+ if (op.cursorActivity) signal(cm, "cursorActivity", cm);
+ if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
+ }
+
+ // Run the given function in an operation
+ function runInOp(cm, f) {
+ if (cm.curOp) return f();
+ startOperation(cm);
+ try { return f(); }
+ finally { endOperation(cm); }
+ }
+ // Wraps a function in an operation. Returns the wrapped function.
+ function operation(cm, f) {
+ return function() {
+ if (cm.curOp) return f.apply(cm, arguments);
+ startOperation(cm);
+ try { return f.apply(cm, arguments); }
+ finally { endOperation(cm); }
+ };
+ }
+ // Used to add methods to editor and doc instances, wrapping them in
+ // operations.
+ function methodOp(f) {
+ return function() {
+ if (this.curOp) return f.apply(this, arguments);
+ startOperation(this);
+ try { return f.apply(this, arguments); }
+ finally { endOperation(this); }
+ };
+ }
+ function docMethodOp(f) {
+ return function() {
+ var cm = this.cm;
+ if (!cm || cm.curOp) return f.apply(this, arguments);
+ startOperation(cm);
+ try { return f.apply(this, arguments); }
+ finally { endOperation(cm); }
+ };
+ }
+
+ // VIEW TRACKING
+
+ // These objects are used to represent the visible (currently drawn)
+ // part of the document. A LineView may correspond to multiple
+ // logical lines, if those are connected by collapsed ranges.
+ function LineView(doc, line, lineN) {
+ // The starting line
+ this.line = line;
+ // Continuing lines, if any
+ this.rest = visualLineContinued(line);
+ // Number of logical lines in this visual line
+ this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
+ this.node = this.text = null;
+ this.hidden = lineIsHidden(doc, line);
+ }
+
+ // Create a range of LineView objects for the given lines.
+ function buildViewArray(cm, from, to) {
+ var array = [], nextPos;
+ for (var pos = from; pos < to; pos = nextPos) {
+ var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
+ nextPos = pos + view.size;
+ array.push(view);
+ }
+ return array;
+ }
+
+ // Updates the display.view data structure for a given change to the
+ // document. From and to are in pre-change coordinates. Lendiff is
+ // the amount of lines added or subtracted by the change. This is
+ // used for changes that span multiple lines, or change the way
+ // lines are divided into visual lines. regLineChange (below)
+ // registers single-line changes.
+ function regChange(cm, from, to, lendiff) {
+ if (from == null) from = cm.doc.first;
+ if (to == null) to = cm.doc.first + cm.doc.size;
+ if (!lendiff) lendiff = 0;
+
+ var display = cm.display;
+ if (lendiff && to < display.viewTo &&
+ (display.updateLineNumbers == null || display.updateLineNumbers > from))
+ display.updateLineNumbers = from;
+
+ cm.curOp.viewChanged = true;
+
+ if (from >= display.viewTo) { // Change after
+ if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
+ resetView(cm);
+ } else if (to <= display.viewFrom) { // Change before
+ if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
+ resetView(cm);
+ } else {
+ display.viewFrom += lendiff;
+ display.viewTo += lendiff;
+ }
+ } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
+ resetView(cm);
+ } else if (from <= display.viewFrom) { // Top overlap
+ var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
+ if (cut) {
+ display.view = display.view.slice(cut.index);
+ display.viewFrom = cut.lineN;
+ display.viewTo += lendiff;
+ } else {
+ resetView(cm);
+ }
+ } else if (to >= display.viewTo) { // Bottom overlap
+ var cut = viewCuttingPoint(cm, from, from, -1);
+ if (cut) {
+ display.view = display.view.slice(0, cut.index);
+ display.viewTo = cut.lineN;
+ } else {
+ resetView(cm);
+ }
+ } else { // Gap in the middle
+ var cutTop = viewCuttingPoint(cm, from, from, -1);
+ var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
+ if (cutTop && cutBot) {
+ display.view = display.view.slice(0, cutTop.index)
+ .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
+ .concat(display.view.slice(cutBot.index));
+ display.viewTo += lendiff;
+ } else {
+ resetView(cm);
+ }
+ }
+
+ var ext = display.externalMeasured;
+ if (ext) {
+ if (to < ext.lineN)
+ ext.lineN += lendiff;
+ else if (from < ext.lineN + ext.size)
+ display.externalMeasured = null;
+ }
+ }
+
+ // Register a change to a single line. Type must be one of "text",
+ // "gutter", "class", "widget"
+ function regLineChange(cm, line, type) {
+ cm.curOp.viewChanged = true;
+ var display = cm.display, ext = cm.display.externalMeasured;
+ if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
+ display.externalMeasured = null;
+
+ if (line < display.viewFrom || line >= display.viewTo) return;
+ var lineView = display.view[findViewIndex(cm, line)];
+ if (lineView.node == null) return;
+ var arr = lineView.changes || (lineView.changes = []);
+ if (indexOf(arr, type) == -1) arr.push(type);
+ }
+
+ // Clear the view.
+ function resetView(cm) {
+ cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
+ cm.display.view = [];
+ cm.display.viewOffset = 0;
+ }
+
+ // Find the view element corresponding to a given line. Return null
+ // when the line isn't visible.
+ function findViewIndex(cm, n) {
+ if (n >= cm.display.viewTo) return null;
+ n -= cm.display.viewFrom;
+ if (n < 0) return null;
+ var view = cm.display.view;
+ for (var i = 0; i < view.length; i++) {
+ n -= view[i].size;
+ if (n < 0) return i;
+ }
+ }
+
+ function viewCuttingPoint(cm, oldN, newN, dir) {
+ var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
+ if (!sawCollapsedSpans) return {index: index, lineN: newN};
+ for (var i = 0, n = cm.display.viewFrom; i < index; i++)
+ n += view[i].size;
+ if (n != oldN) {
+ if (dir > 0) {
+ if (index == view.length - 1) return null;
+ diff = (n + view[index].size) - oldN;
+ index++;
+ } else {
+ diff = n - oldN;
+ }
+ oldN += diff; newN += diff;
+ }
+ while (visualLineNo(cm.doc, newN) != newN) {
+ if (index == (dir < 0 ? 0 : view.length - 1)) return null;
+ newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
+ index += dir;
+ }
+ return {index: index, lineN: newN};
+ }
+
+ // Force the view to cover a given range, adding empty view element
+ // or clipping off existing ones as needed.
+ function adjustView(cm, from, to) {
+ var display = cm.display, view = display.view;
+ if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
+ display.view = buildViewArray(cm, from, to);
+ display.viewFrom = from;
+ } else {
+ if (display.viewFrom > from)
+ display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);
+ else if (display.viewFrom < from)
+ display.view = display.view.slice(findViewIndex(cm, from));
+ display.viewFrom = from;
+ if (display.viewTo < to)
+ display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));
+ else if (display.viewTo > to)
+ display.view = display.view.slice(0, findViewIndex(cm, to));
+ }
+ display.viewTo = to;
+ }
+
+ // Count the number of lines in the view whose DOM representation is
+ // out of date (or nonexistent).
+ function countDirtyView(cm) {
+ var view = cm.display.view, dirty = 0;
+ for (var i = 0; i < view.length; i++) {
+ var lineView = view[i];
+ if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;
+ }
+ return dirty;
+ }
+
+ // INPUT HANDLING
+
+ // Poll for input changes, using the normal rate of polling. This
+ // runs as long as the editor is focused.
+ function slowPoll(cm) {
+ if (cm.display.pollingFast) return;
+ cm.display.poll.set(cm.options.pollInterval, function() {
+ readInput(cm);
+ if (cm.state.focused) slowPoll(cm);
+ });
+ }
+
+ // When an event has just come in that is likely to add or change
+ // something in the input textarea, we poll faster, to ensure that
+ // the change appears on the screen quickly.
+ function fastPoll(cm) {
+ var missed = false;
+ cm.display.pollingFast = true;
+ function p() {
+ var changed = readInput(cm);
+ if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
+ else {cm.display.pollingFast = false; slowPoll(cm);}
+ }
+ cm.display.poll.set(20, p);
+ }
+
+ // Read input from the textarea, and update the document to match.
+ // When something is selected, it is present in the textarea, and
+ // selected (unless it is huge, in which case a placeholder is
+ // used). When nothing is selected, the cursor sits after previously
+ // seen text (can be empty), which is stored in prevInput (we must
+ // not reset the textarea when typing, because that breaks IME).
+ function readInput(cm) {
+ var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc;
+ // Since this is called a *lot*, try to bail out as cheaply as
+ // possible when it is clear that nothing happened. hasSelection
+ // will be the case when there is a lot of text in the textarea,
+ // in which case reading its value would be expensive.
+ if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false;
+ var text = input.value;
+ // If nothing changed, bail.
+ if (text == prevInput && !cm.somethingSelected()) return false;
+ // Work around nonsensical selection resetting in IE9/10
+ if (ie && !ie_upto8 && cm.display.inputHasSelection === text) {
+ resetInput(cm);
+ return false;
+ }
+
+ var withOp = !cm.curOp;
+ if (withOp) startOperation(cm);
+ cm.display.shift = false;
+
+ // Find the part of the input that is actually new
+ var same = 0, l = Math.min(prevInput.length, text.length);
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
+ var inserted = text.slice(same), textLines = splitLines(inserted);
+
+ // When pasing N lines into N selections, insert one line per selection
+ var multiPaste = cm.state.pasteIncoming && textLines.length > 1 && doc.sel.ranges.length == textLines.length;
+
+ // Normal behavior is to insert the new text into every selection
+ for (var i = doc.sel.ranges.length - 1; i >= 0; i--) {
+ var range = doc.sel.ranges[i];
+ var from = range.from(), to = range.to();
+ // Handle deletion
+ if (same < prevInput.length)
+ from = Pos(from.line, from.ch - (prevInput.length - same));
+ // Handle overwrite
+ else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming)
+ to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
+ var updateInput = cm.curOp.updateInput;
+ var changeEvent = {from: from, to: to, text: multiPaste ? [textLines[i]] : textLines,
+ origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
+ makeChange(cm.doc, changeEvent);
+ signalLater(cm, "inputRead", cm, changeEvent);
+ // When an 'electric' character is inserted, immediately trigger a reindent
+ if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
+ cm.options.smartIndent && range.head.ch < 100 &&
+ (!i || doc.sel.ranges[i - 1].head.line != range.head.line)) {
+ var electric = cm.getModeAt(range.head).electricChars;
+ if (electric) for (var j = 0; j < electric.length; j++)
+ if (inserted.indexOf(electric.charAt(j)) > -1) {
+ indentLine(cm, range.head.line, "smart");
+ break;
+ }
+ }
+ }
+ ensureCursorVisible(cm);
+ cm.curOp.updateInput = updateInput;
+ cm.curOp.typing = true;
+
+ // Don't leave long text in the textarea, since it makes further polling slow
+ if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
+ else cm.display.prevInput = text;
+ if (withOp) endOperation(cm);
+ cm.state.pasteIncoming = cm.state.cutIncoming = false;
+ return true;
+ }
+
+ // Reset the input to correspond to the selection (or to be empty,
+ // when not typing and nothing is selected)
+ function resetInput(cm, typing) {
+ var minimal, selected, doc = cm.doc;
+ if (cm.somethingSelected()) {
+ cm.display.prevInput = "";
+ var range = doc.sel.primary();
+ minimal = hasCopyEvent &&
+ (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
+ var content = minimal ? "-" : selected || cm.getSelection();
+ cm.display.input.value = content;
+ if (cm.state.focused) selectInput(cm.display.input);
+ if (ie && !ie_upto8) cm.display.inputHasSelection = content;
+ } else if (!typing) {
+ cm.display.prevInput = cm.display.input.value = "";
+ if (ie && !ie_upto8) cm.display.inputHasSelection = null;
+ }
+ cm.display.inaccurateSelection = minimal;
+ }
+
+ function focusInput(cm) {
+ if (cm.options.readOnly != "nocursor" && (!mobile || activeElt() != cm.display.input))
+ cm.display.input.focus();
+ }
+
+ function ensureFocus(cm) {
+ if (!cm.state.focused) { focusInput(cm); onFocus(cm); }
+ }
+
+ function isReadOnly(cm) {
+ return cm.options.readOnly || cm.doc.cantEdit;
+ }
+
+ // EVENT HANDLERS
+
+ // Attach the necessary event handlers when initializing the editor
+ function registerEventHandlers(cm) {
+ var d = cm.display;
+ on(d.scroller, "mousedown", operation(cm, onMouseDown));
+ // Older IE's will not fire a second mousedown for a double click
+ if (ie_upto10)
+ on(d.scroller, "dblclick", operation(cm, function(e) {
+ if (signalDOMEvent(cm, e)) return;
+ var pos = posFromMouse(cm, e);
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
+ e_preventDefault(e);
+ var word = findWordAt(cm.doc, pos);
+ extendSelection(cm.doc, word.anchor, word.head);
+ }));
+ else
+ on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
+ // Prevent normal selection in the editor (we handle our own)
+ on(d.lineSpace, "selectstart", function(e) {
+ if (!eventInWidget(d, e)) e_preventDefault(e);
+ });
+ // Some browsers fire contextmenu *after* opening the menu, at
+ // which point we can't mess with it anymore. Context menu is
+ // handled in onMouseDown for these browsers.
+ if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
+
+ // Sync scrolling between fake scrollbars and real scrollable
+ // area, ensure viewport is updated when scrolling.
+ on(d.scroller, "scroll", function() {
+ if (d.scroller.clientHeight) {
+ setScrollTop(cm, d.scroller.scrollTop);
+ setScrollLeft(cm, d.scroller.scrollLeft, true);
+ signal(cm, "scroll", cm);
+ }
+ });
+ on(d.scrollbarV, "scroll", function() {
+ if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
+ });
+ on(d.scrollbarH, "scroll", function() {
+ if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
+ });
+
+ // Listen to wheel events in order to try and update the viewport on time.
+ on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
+ on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
+
+ // Prevent clicks in the scrollbars from killing focus
+ function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
+ on(d.scrollbarH, "mousedown", reFocus);
+ on(d.scrollbarV, "mousedown", reFocus);
+ // Prevent wrapper from ever scrolling
+ on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
+
+ // When the window resizes, we need to refresh active editors.
+ var resizeTimer;
+ function onResize() {
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
+ resizeTimer = null;
+ // Might be a text scaling operation, clear size caches.
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = knownScrollbarWidth = null;
+ cm.setSize();
+ }, 100);
+ }
+ on(window, "resize", onResize);
+ // The above handler holds on to the editor and its data
+ // structures. Here we poll to unregister it when the editor is no
+ // longer in the document, so that it can be garbage-collected.
+ function unregister() {
+ if (contains(document.body, d.wrapper)) setTimeout(unregister, 5000);
+ else off(window, "resize", onResize);
+ }
+ setTimeout(unregister, 5000);
+
+ on(d.input, "keyup", operation(cm, onKeyUp));
+ on(d.input, "input", function() {
+ if (ie && !ie_upto8 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;
+ fastPoll(cm);
+ });
+ on(d.input, "keydown", operation(cm, onKeyDown));
+ on(d.input, "keypress", operation(cm, onKeyPress));
+ on(d.input, "focus", bind(onFocus, cm));
+ on(d.input, "blur", bind(onBlur, cm));
+
+ function drag_(e) {
+ if (!signalDOMEvent(cm, e)) e_stop(e);
+ }
+ if (cm.options.dragDrop) {
+ on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
+ on(d.scroller, "dragenter", drag_);
+ on(d.scroller, "dragover", drag_);
+ on(d.scroller, "drop", operation(cm, onDrop));
+ }
+ on(d.scroller, "paste", function(e) {
+ if (eventInWidget(d, e)) return;
+ cm.state.pasteIncoming = true;
+ focusInput(cm);
+ fastPoll(cm);
+ });
+ on(d.input, "paste", function() {
+ cm.state.pasteIncoming = true;
+ fastPoll(cm);
+ });
+
+ function prepareCopy(e) {
+ if (d.inaccurateSelection) {
+ d.prevInput = "";
+ d.inaccurateSelection = false;
+ d.input.value = cm.getSelection();
+ selectInput(d.input);
+ }
+ if (e.type == "cut") cm.state.cutIncoming = true;
+ }
+ on(d.input, "cut", prepareCopy);
+ on(d.input, "copy", prepareCopy);
+
+ // Needed to handle Tab key in KHTML
+ if (khtml) on(d.sizer, "mouseup", function() {
+ if (activeElt() == d.input) d.input.blur();
+ focusInput(cm);
+ });
+ }
+
+ // MOUSE EVENTS
+
+ // Return true when the given mouse event happened in a widget
+ function eventInWidget(display, e) {
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
+ if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
+ }
+ }
+
+ // Given a mouse event, find the corresponding position. If liberal
+ // is false, it checks whether a gutter or scrollbar was clicked,
+ // and returns null if it was. forRect is used by rectangular
+ // selections, and tries to estimate a character position even for
+ // coordinates beyond the right of the text.
+ function posFromMouse(cm, e, liberal, forRect) {
+ var display = cm.display;
+ if (!liberal) {
+ var target = e_target(e);
+ if (target == display.scrollbarH || target == display.scrollbarV ||
+ target == display.scrollbarFiller || target == display.gutterFiller) return null;
+ }
+ var x, y, space = display.lineSpace.getBoundingClientRect();
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
+ try { x = e.clientX - space.left; y = e.clientY - space.top; }
+ catch (e) { return null; }
+ var coords = coordsChar(cm, x, y), line;
+ if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
+ var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
+ coords = Pos(coords.line, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff);
+ }
+ return coords;
+ }
+
+ // A mouse down can be a single click, double click, triple click,
+ // start of selection drag, start of text drag, new cursor
+ // (ctrl-click), rectangle drag (alt-drag), or xwin
+ // middle-click-paste. Or it might be a click on something we should
+ // not interfere with, such as a scrollbar or widget.
+ function onMouseDown(e) {
+ if (signalDOMEvent(this, e)) return;
+ var cm = this, display = cm.display;
+ display.shift = e.shiftKey;
+
+ if (eventInWidget(display, e)) {
+ if (!webkit) {
+ // Briefly turn off draggability, to allow widgets to do
+ // normal dragging things.
+ display.scroller.draggable = false;
+ setTimeout(function(){display.scroller.draggable = true;}, 100);
+ }
+ return;
+ }
+ if (clickInGutter(cm, e)) return;
+ var start = posFromMouse(cm, e);
+ window.focus();
+
+ switch (e_button(e)) {
+ case 1:
+ if (start)
+ leftButtonDown(cm, e, start);
+ else if (e_target(e) == display.scroller)
+ e_preventDefault(e);
+ break;
+ case 2:
+ if (webkit) cm.state.lastMiddleDown = +new Date;
+ if (start) extendSelection(cm.doc, start);
+ setTimeout(bind(focusInput, cm), 20);
+ e_preventDefault(e);
+ break;
+ case 3:
+ if (captureRightClick) onContextMenu(cm, e);
+ break;
+ }
+ }
+
+ var lastClick, lastDoubleClick;
+ function leftButtonDown(cm, e, start) {
+ setTimeout(bind(ensureFocus, cm), 0);
+
+ var now = +new Date, type;
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
+ type = "triple";
+ } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
+ type = "double";
+ lastDoubleClick = {time: now, pos: start};
+ } else {
+ type = "single";
+ lastClick = {time: now, pos: start};
+ }
+
+ var sel = cm.doc.sel, addNew = mac ? e.metaKey : e.ctrlKey;
+ if (cm.options.dragDrop && dragAndDrop && !addNew && !isReadOnly(cm) &&
+ type == "single" && sel.contains(start) > -1 && sel.somethingSelected())
+ leftButtonStartDrag(cm, e, start);
+ else
+ leftButtonSelect(cm, e, start, type, addNew);
+ }
+
+ // Start a text drag. When it ends, see if any dragging actually
+ // happen, and treat as a click if it didn't.
+ function leftButtonStartDrag(cm, e, start) {
+ var display = cm.display;
+ var dragEnd = operation(cm, function(e2) {
+ if (webkit) display.scroller.draggable = false;
+ cm.state.draggingText = false;
+ off(document, "mouseup", dragEnd);
+ off(display.scroller, "drop", dragEnd);
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
+ e_preventDefault(e2);
+ extendSelection(cm.doc, start);
+ focusInput(cm);
+ // Work around unexplainable focus problem in IE9 (#2127)
+ if (ie_upto10 && !ie_upto8)
+ setTimeout(function() {document.body.focus(); focusInput(cm);}, 20);
+ }
+ });
+ // Let the drag handler handle this.
+ if (webkit) display.scroller.draggable = true;
+ cm.state.draggingText = dragEnd;
+ // IE's approach to draggable
+ if (display.scroller.dragDrop) display.scroller.dragDrop();
+ on(document, "mouseup", dragEnd);
+ on(display.scroller, "drop", dragEnd);
+ }
+
+ // Normal selection, as opposed to text dragging.
+ function leftButtonSelect(cm, e, start, type, addNew) {
+ var display = cm.display, doc = cm.doc;
+ e_preventDefault(e);
+
+ var ourRange, ourIndex, startSel = doc.sel;
+ if (addNew) {
+ ourIndex = doc.sel.contains(start);
+ if (ourIndex > -1)
+ ourRange = doc.sel.ranges[ourIndex];
+ else
+ ourRange = new Range(start, start);
+ } else {
+ ourRange = doc.sel.primary();
+ }
+
+ if (e.altKey) {
+ type = "rect";
+ if (!addNew) ourRange = new Range(start, start);
+ start = posFromMouse(cm, e, true, true);
+ ourIndex = -1;
+ } else if (type == "double") {
+ var word = findWordAt(doc, start);
+ if (cm.display.shift || doc.extend)
+ ourRange = extendRange(doc, ourRange, word.anchor, word.head);
+ else
+ ourRange = word;
+ } else if (type == "triple") {
+ var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));
+ if (cm.display.shift || doc.extend)
+ ourRange = extendRange(doc, ourRange, line.anchor, line.head);
+ else
+ ourRange = line;
+ } else {
+ ourRange = extendRange(doc, ourRange, start);
+ }
+
+ if (!addNew) {
+ ourIndex = 0;
+ setSelection(doc, new Selection([ourRange], 0), sel_mouse);
+ } else if (ourIndex > -1) {
+ replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
+ } else {
+ ourIndex = doc.sel.ranges.length;
+ setSelection(doc, normalizeSelection(doc.sel.ranges.concat([ourRange]), ourIndex),
+ {scroll: false, origin: "*mouse"});
+ }
+
+ var lastPos = start;
+ function extendTo(pos) {
+ if (cmp(lastPos, pos) == 0) return;
+ lastPos = pos;
+
+ if (type == "rect") {
+ var ranges = [], tabSize = cm.options.tabSize;
+ var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
+ var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
+ var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
+ for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
+ line <= end; line++) {
+ var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
+ if (left == right)
+ ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));
+ else if (text.length > leftPos)
+ ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
+ }
+ if (!ranges.length) ranges.push(new Range(start, start));
+ setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), sel_mouse);
+ } else {
+ var oldRange = ourRange;
+ var anchor = oldRange.anchor, head = pos;
+ if (type != "single") {
+ if (type == "double")
+ var range = findWordAt(doc, pos);
+ else
+ var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
+ if (cmp(range.anchor, anchor) > 0) {
+ head = range.head;
+ anchor = minPos(oldRange.from(), range.anchor);
+ } else {
+ head = range.anchor;
+ anchor = maxPos(oldRange.to(), range.head);
+ }
+ }
+ var ranges = startSel.ranges.slice(0);
+ ranges[ourIndex] = new Range(clipPos(doc, anchor), head);
+ setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);
+ }
+ }
+
+ var editorSize = display.wrapper.getBoundingClientRect();
+ // Used to ensure timeout re-tries don't fire when another extend
+ // happened in the meantime (clearTimeout isn't reliable -- at
+ // least on Chrome, the timeouts still happen even when cleared,
+ // if the clear happens after their scheduled firing time).
+ var counter = 0;
+
+ function extend(e) {
+ var curCount = ++counter;
+ var cur = posFromMouse(cm, e, true, type == "rect");
+ if (!cur) return;
+ if (cmp(cur, lastPos) != 0) {
+ ensureFocus(cm);
+ extendTo(cur);
+ var visible = visibleLines(display, doc);
+ if (cur.line >= visible.to || cur.line < visible.from)
+ setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
+ } else {
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
+ if (outside) setTimeout(operation(cm, function() {
+ if (counter != curCount) return;
+ display.scroller.scrollTop += outside;
+ extend(e);
+ }), 50);
+ }
+ }
+
+ function done(e) {
+ counter = Infinity;
+ e_preventDefault(e);
+ focusInput(cm);
+ off(document, "mousemove", move);
+ off(document, "mouseup", up);
+ doc.history.lastSelOrigin = null;
+ }
+
+ var move = operation(cm, function(e) {
+ if ((ie && !ie_upto9) ? !e.buttons : !e_button(e)) done(e);
+ else extend(e);
+ });
+ var up = operation(cm, done);
+ on(document, "mousemove", move);
+ on(document, "mouseup", up);
+ }
+
+ // Determines whether an event happened in the gutter, and fires the
+ // handlers for the corresponding event.
+ function gutterEvent(cm, e, type, prevent, signalfn) {
+ try { var mX = e.clientX, mY = e.clientY; }
+ catch(e) { return false; }
+ if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
+ if (prevent) e_preventDefault(e);
+
+ var display = cm.display;
+ var lineBox = display.lineDiv.getBoundingClientRect();
+
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
+ mY -= lineBox.top - display.viewOffset;
+
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
+ var g = display.gutters.childNodes[i];
+ if (g && g.getBoundingClientRect().right >= mX) {
+ var line = lineAtHeight(cm.doc, mY);
+ var gutter = cm.options.gutters[i];
+ signalfn(cm, type, cm, line, gutter, e);
+ return e_defaultPrevented(e);
+ }
+ }
+ }
+
+ function clickInGutter(cm, e) {
+ return gutterEvent(cm, e, "gutterClick", true, signalLater);
+ }
+
+ // Kludge to work around strange IE behavior where it'll sometimes
+ // re-fire a series of drag-related events right after the drop (#1551)
+ var lastDrop = 0;
+
+ function onDrop(e) {
+ var cm = this;
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
+ return;
+ e_preventDefault(e);
+ if (ie_upto10) lastDrop = +new Date;
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
+ if (!pos || isReadOnly(cm)) return;
+ // Might be a file drop, in which case we simply extract the text
+ // and insert it.
+ if (files && files.length && window.FileReader && window.File) {
+ var n = files.length, text = Array(n), read = 0;
+ var loadFile = function(file, i) {
+ var reader = new FileReader;
+ reader.onload = function() {
+ text[i] = reader.result;
+ if (++read == n) {
+ pos = clipPos(cm.doc, pos);
+ var change = {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"};
+ makeChange(cm.doc, change);
+ setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
+ }
+ };
+ reader.readAsText(file);
+ };
+ for (var i = 0; i < n; ++i) loadFile(files[i], i);
+ } else { // Normal drop
+ // Don't do a replace if the drop happened inside of the selected text.
+ if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
+ cm.state.draggingText(e);
+ // Ensure the editor is re-focused
+ setTimeout(bind(focusInput, cm), 20);
+ return;
+ }
+ try {
+ var text = e.dataTransfer.getData("Text");
+ if (text) {
+ var selected = cm.state.draggingText && cm.listSelections();
+ setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
+ if (selected) for (var i = 0; i < selected.length; ++i)
+ replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
+ cm.replaceSelection(text, "around", "paste");
+ focusInput(cm);
+ }
+ }
+ catch(e){}
+ }
+ }
+
+ function onDragStart(cm, e) {
+ if (ie_upto10 && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
+
+ e.dataTransfer.setData("Text", cm.getSelection());
+
+ // Use dummy image instead of default browsers image.
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
+ if (e.dataTransfer.setDragImage && !safari) {
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
+ img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
+ if (presto) {
+ img.width = img.height = 1;
+ cm.display.wrapper.appendChild(img);
+ // Force a relayout, or Opera won't use our image for some obscure reason
+ img._top = img.offsetTop;
+ }
+ e.dataTransfer.setDragImage(img, 0, 0);
+ if (presto) img.parentNode.removeChild(img);
+ }
+ }
+
+ // SCROLL EVENTS
+
+ // Sync the scrollable area and scrollbars, ensure the viewport
+ // covers the visible area.
+ function setScrollTop(cm, val) {
+ if (Math.abs(cm.doc.scrollTop - val) < 2) return;
+ cm.doc.scrollTop = val;
+ if (!gecko) updateDisplay(cm, {top: val});
+ if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
+ if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
+ if (gecko) updateDisplay(cm);
+ startWorker(cm, 100);
+ }
+ // Sync scroller and scrollbar, ensure the gutter elements are
+ // aligned.
+ function setScrollLeft(cm, val, isScroller) {
+ if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
+ cm.doc.scrollLeft = val;
+ alignHorizontally(cm);
+ if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
+ if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
+ }
+
+ // Since the delta values reported on mouse wheel events are
+ // unstandardized between browsers and even browser versions, and
+ // generally horribly unpredictable, this code starts by measuring
+ // the scroll effect that the first few mouse wheel events have,
+ // and, from that, detects the way it can convert deltas to pixel
+ // offsets afterwards.
+ //
+ // The reason we want to know the amount a wheel event will scroll
+ // is that it gives us a chance to update the display before the
+ // actual scrolling happens, reducing flickering.
+
+ var wheelSamples = 0, wheelPixelsPerUnit = null;
+ // Fill in a browser-detected starting value on browsers where we
+ // know one. These don't have to be accurate -- the result of them
+ // being wrong would just be a slight flicker on the first wheel
+ // scroll (if it is large enough).
+ if (ie) wheelPixelsPerUnit = -.53;
+ else if (gecko) wheelPixelsPerUnit = 15;
+ else if (chrome) wheelPixelsPerUnit = -.7;
+ else if (safari) wheelPixelsPerUnit = -1/3;
+
+ function onScrollWheel(cm, e) {
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
+ else if (dy == null) dy = e.wheelDelta;
+
+ var display = cm.display, scroll = display.scroller;
+ // Quit if there's nothing to scroll here
+ if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
+ dy && scroll.scrollHeight > scroll.clientHeight)) return;
+
+ // Webkit browsers on OS X abort momentum scrolls when the target
+ // of the scroll event is removed from the scrollable element.
+ // This hack (see related code in patchDisplay) makes sure the
+ // element is kept around.
+ if (dy && mac && webkit) {
+ outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
+ for (var i = 0; i < view.length; i++) {
+ if (view[i].node == cur) {
+ cm.display.currentWheelTarget = cur;
+ break outer;
+ }
+ }
+ }
+ }
+
+ // On some browsers, horizontal scrolling will cause redraws to
+ // happen before the gutter has been realigned, causing it to
+ // wriggle around in a most unseemly way. When we have an
+ // estimated pixels/delta value, we just handle horizontal
+ // scrolling entirely here. It'll be slightly off from native, but
+ // better than glitching out.
+ if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
+ if (dy)
+ setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
+ e_preventDefault(e);
+ display.wheelStartX = null; // Abort measurement, if in progress
+ return;
+ }
+
+ // 'Project' the visible viewport to cover the area that is being
+ // scrolled into view (if we know enough to estimate it).
+ if (dy && wheelPixelsPerUnit != null) {
+ var pixels = dy * wheelPixelsPerUnit;
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
+ if (pixels < 0) top = Math.max(0, top + pixels - 50);
+ else bot = Math.min(cm.doc.height, bot + pixels + 50);
+ updateDisplay(cm, {top: top, bottom: bot});
+ }
+
+ if (wheelSamples < 20) {
+ if (display.wheelStartX == null) {
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
+ display.wheelDX = dx; display.wheelDY = dy;
+ setTimeout(function() {
+ if (display.wheelStartX == null) return;
+ var movedX = scroll.scrollLeft - display.wheelStartX;
+ var movedY = scroll.scrollTop - display.wheelStartY;
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
+ (movedX && display.wheelDX && movedX / display.wheelDX);
+ display.wheelStartX = display.wheelStartY = null;
+ if (!sample) return;
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
+ ++wheelSamples;
+ }, 200);
+ } else {
+ display.wheelDX += dx; display.wheelDY += dy;
+ }
+ }
+ }
+
+ // KEY EVENTS
+
+ // Run a handler that was bound to a key.
+ function doHandleBinding(cm, bound, dropShift) {
+ if (typeof bound == "string") {
+ bound = commands[bound];
+ if (!bound) return false;
+ }
+ // Ensure previous input has been read, so that the handler sees a
+ // consistent view of the document
+ if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
+ var prevShift = cm.display.shift, done = false;
+ try {
+ if (isReadOnly(cm)) cm.state.suppressEdits = true;
+ if (dropShift) cm.display.shift = false;
+ done = bound(cm) != Pass;
+ } finally {
+ cm.display.shift = prevShift;
+ cm.state.suppressEdits = false;
+ }
+ return done;
+ }
+
+ // Collect the currently active keymaps.
+ function allKeyMaps(cm) {
+ var maps = cm.state.keyMaps.slice(0);
+ if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
+ maps.push(cm.options.keyMap);
+ return maps;
+ }
+
+ var maybeTransition;
+ // Handle a key from the keydown event.
+ function handleKeyBinding(cm, e) {
+ // Handle automatic keymap transitions
+ var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
+ clearTimeout(maybeTransition);
+ if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
+ if (getKeyMap(cm.options.keyMap) == startMap) {
+ cm.options.keyMap = (next.call ? next.call(null, cm) : next);
+ keyMapChanged(cm);
+ }
+ }, 50);
+
+ var name = keyName(e, true), handled = false;
+ if (!name) return false;
+ var keymaps = allKeyMaps(cm);
+
+ if (e.shiftKey) {
+ // First try to resolve full name (including 'Shift-'). Failing
+ // that, see if there is a cursor-motion command (starting with
+ // 'go') bound to the keyname without 'Shift-'.
+ handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
+ || lookupKey(name, keymaps, function(b) {
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
+ return doHandleBinding(cm, b);
+ });
+ } else {
+ handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
+ }
+
+ if (handled) {
+ e_preventDefault(e);
+ restartBlink(cm);
+ signalLater(cm, "keyHandled", cm, name, e);
+ }
+ return handled;
+ }
+
+ // Handle a key from the keypress event
+ function handleCharBinding(cm, e, ch) {
+ var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
+ function(b) { return doHandleBinding(cm, b, true); });
+ if (handled) {
+ e_preventDefault(e);
+ restartBlink(cm);
+ signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
+ }
+ return handled;
+ }
+
+ var lastStoppedKey = null;
+ function onKeyDown(e) {
+ var cm = this;
+ ensureFocus(cm);
+ if (signalDOMEvent(cm, e)) return;
+ // IE does strange things with escape.
+ if (ie_upto10 && e.keyCode == 27) e.returnValue = false;
+ var code = e.keyCode;
+ cm.display.shift = code == 16 || e.shiftKey;
+ var handled = handleKeyBinding(cm, e);
+ if (presto) {
+ lastStoppedKey = handled ? code : null;
+ // Opera has no cut event... we try to at least catch the key combo
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
+ cm.replaceSelection("", null, "cut");
+ }
+ }
+
+ function onKeyUp(e) {
+ if (signalDOMEvent(this, e)) return;
+ if (e.keyCode == 16) this.doc.sel.shift = false;
+ }
+
+ function onKeyPress(e) {
+ var cm = this;
+ if (signalDOMEvent(cm, e)) return;
+ var keyCode = e.keyCode, charCode = e.charCode;
+ if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
+ if (((presto && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
+ if (handleCharBinding(cm, e, ch)) return;
+ if (ie && !ie_upto8) cm.display.inputHasSelection = null;
+ fastPoll(cm);
+ }
+
+ // FOCUS/BLUR EVENTS
+
+ function onFocus(cm) {
+ if (cm.options.readOnly == "nocursor") return;
+ if (!cm.state.focused) {
+ signal(cm, "focus", cm);
+ cm.state.focused = true;
+ if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
+ cm.display.wrapper.className += " CodeMirror-focused";
+ if (!cm.curOp) {
+ resetInput(cm);
+ if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730
+ }
+ }
+ slowPoll(cm);
+ restartBlink(cm);
+ }
+ function onBlur(cm) {
+ if (cm.state.focused) {
+ signal(cm, "blur", cm);
+ cm.state.focused = false;
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
+ }
+ clearInterval(cm.display.blinker);
+ setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);
+ }
+
+ // CONTEXT MENU HANDLING
+
+ var detectingSelectAll;
+ // To make the context menu work, we need to briefly unhide the
+ // textarea (making it as unobtrusive as possible) to let the
+ // right-click take effect on it.
+ function onContextMenu(cm, e) {
+ if (signalDOMEvent(cm, e, "contextmenu")) return;
+ var display = cm.display;
+ if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;
+
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
+ if (!pos || presto) return; // Opera is difficult.
+
+ // Reset the current text selection only if the click is done outside of the selection
+ // and 'resetSelectionOnContextMenu' option is true.
+ var reset = cm.options.resetSelectionOnContextMenu;
+ if (reset && cm.doc.sel.contains(pos) == -1)
+ operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
+
+ var oldCSS = display.input.style.cssText;
+ display.inputDiv.style.position = "absolute";
+ display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
+ (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
+ "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
+ focusInput(cm);
+ resetInput(cm);
+ // Adds "Select all" to context menu in FF
+ if (!cm.somethingSelected()) display.input.value = display.prevInput = " ";
+
+ // Select-all will be greyed out if there's nothing to select, so
+ // this adds a zero-width space so that we can later check whether
+ // it got selected.
+ function prepareSelectAllHack() {
+ if (display.input.selectionStart != null) {
+ var extval = display.input.value = "\u200b" + (cm.somethingSelected() ? display.input.value : "");
+ display.prevInput = "\u200b";
+ display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
+ }
+ }
+ function rehide() {
+ display.inputDiv.style.position = "relative";
+ display.input.style.cssText = oldCSS;
+ if (ie_upto8) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
+ slowPoll(cm);
+
+ // Try to detect the user choosing select-all
+ if (display.input.selectionStart != null) {
+ if (!ie || ie_upto8) prepareSelectAllHack();
+ clearTimeout(detectingSelectAll);
+ var i = 0, poll = function(){
+ if (display.prevInput == "\u200b" && display.input.selectionStart == 0)
+ operation(cm, commands.selectAll)(cm);
+ else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
+ else resetInput(cm);
+ };
+ detectingSelectAll = setTimeout(poll, 200);
+ }
+ }
+
+ if (ie && !ie_upto8) prepareSelectAllHack();
+ if (captureRightClick) {
+ e_stop(e);
+ var mouseup = function() {
+ off(window, "mouseup", mouseup);
+ setTimeout(rehide, 20);
+ };
+ on(window, "mouseup", mouseup);
+ } else {
+ setTimeout(rehide, 50);
+ }
+ }
+
+ function contextMenuInGutter(cm, e) {
+ if (!hasHandler(cm, "gutterContextMenu")) return false;
+ return gutterEvent(cm, e, "gutterContextMenu", false, signal);
+ }
+
+ // UPDATING
+
+ // Compute the position of the end of a change (its 'to' property
+ // refers to the pre-change end).
+ var changeEnd = CodeMirror.changeEnd = function(change) {
+ if (!change.text) return change.to;
+ return Pos(change.from.line + change.text.length - 1,
+ lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
+ };
+
+ // Adjust a position to refer to the post-change position of the
+ // same text, or the end of the change if the change covers it.
+ function adjustForChange(pos, change) {
+ if (cmp(pos, change.from) < 0) return pos;
+ if (cmp(pos, change.to) <= 0) return changeEnd(change);
+
+ var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
+ if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;
+ return Pos(line, ch);
+ }
+
+ function computeSelAfterChange(doc, change) {
+ var out = [];
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
+ var range = doc.sel.ranges[i];
+ out.push(new Range(adjustForChange(range.anchor, change),
+ adjustForChange(range.head, change)));
+ }
+ return normalizeSelection(out, doc.sel.primIndex);
+ }
+
+ function offsetPos(pos, old, nw) {
+ if (pos.line == old.line)
+ return Pos(nw.line, pos.ch - old.ch + nw.ch);
+ else
+ return Pos(nw.line + (pos.line - old.line), pos.ch);
+ }
+
+ // Used by replaceSelections to allow moving the selection to the
+ // start or around the replaced test. Hint may be "start" or "around".
+ function computeReplacedSel(doc, changes, hint) {
+ var out = [];
+ var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
+ for (var i = 0; i < changes.length; i++) {
+ var change = changes[i];
+ var from = offsetPos(change.from, oldPrev, newPrev);
+ var to = offsetPos(changeEnd(change), oldPrev, newPrev);
+ oldPrev = change.to;
+ newPrev = to;
+ if (hint == "around") {
+ var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
+ out[i] = new Range(inv ? to : from, inv ? from : to);
+ } else {
+ out[i] = new Range(from, from);
+ }
+ }
+ return new Selection(out, doc.sel.primIndex);
+ }
+
+ // Allow "beforeChange" event handlers to influence a change
+ function filterChange(doc, change, update) {
+ var obj = {
+ canceled: false,
+ from: change.from,
+ to: change.to,
+ text: change.text,
+ origin: change.origin,
+ cancel: function() { this.canceled = true; }
+ };
+ if (update) obj.update = function(from, to, text, origin) {
+ if (from) this.from = clipPos(doc, from);
+ if (to) this.to = clipPos(doc, to);
+ if (text) this.text = text;
+ if (origin !== undefined) this.origin = origin;
+ };
+ signal(doc, "beforeChange", doc, obj);
+ if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
+
+ if (obj.canceled) return null;
+ return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
+ }
+
+ // Apply a change to a document, and add it to the document's
+ // history, and propagating it to all linked documents.
+ function makeChange(doc, change, ignoreReadOnly) {
+ if (doc.cm) {
+ if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);
+ if (doc.cm.state.suppressEdits) return;
+ }
+
+ if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
+ change = filterChange(doc, change, true);
+ if (!change) return;
+ }
+
+ // Possibly split or suppress the update based on the presence
+ // of read-only spans in its range.
+ var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
+ if (split) {
+ for (var i = split.length - 1; i >= 0; --i)
+ makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text});
+ } else {
+ makeChangeInner(doc, change);
+ }
+ }
+
+ function makeChangeInner(doc, change) {
+ if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return;
+ var selAfter = computeSelAfterChange(doc, change);
+ addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
+
+ makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
+ var rebased = [];
+
+ linkedDocs(doc, function(doc, sharedHist) {
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
+ rebaseHist(doc.history, change);
+ rebased.push(doc.history);
+ }
+ makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
+ });
+ }
+
+ // Revert a change stored in a document's history.
+ function makeChangeFromHistory(doc, type, allowSelectionOnly) {
+ if (doc.cm && doc.cm.state.suppressEdits) return;
+
+ var hist = doc.history, event, selAfter = doc.sel;
+ var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
+
+ // Verify that there is a useable event (so that ctrl-z won't
+ // needlessly clear selection events)
+ for (var i = 0; i < source.length; i++) {
+ event = source[i];
+ if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
+ break;
+ }
+ if (i == source.length) return;
+ hist.lastOrigin = hist.lastSelOrigin = null;
+
+ for (;;) {
+ event = source.pop();
+ if (event.ranges) {
+ pushSelectionToHistory(event, dest);
+ if (allowSelectionOnly && !event.equals(doc.sel)) {
+ setSelection(doc, event, {clearRedo: false});
+ return;
+ }
+ selAfter = event;
+ }
+ else break;
+ }
+
+ // Build up a reverse change object to add to the opposite history
+ // stack (redo when undoing, and vice versa).
+ var antiChanges = [];
+ pushSelectionToHistory(selAfter, dest);
+ dest.push({changes: antiChanges, generation: hist.generation});
+ hist.generation = event.generation || ++hist.maxGeneration;
+
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
+
+ for (var i = event.changes.length - 1; i >= 0; --i) {
+ var change = event.changes[i];
+ change.origin = type;
+ if (filter && !filterChange(doc, change, false)) {
+ source.length = 0;
+ return;
+ }
+
+ antiChanges.push(historyChangeFromChange(doc, change));
+
+ var after = i ? computeSelAfterChange(doc, change, null) : lst(source);
+ makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
+ if (doc.cm) ensureCursorVisible(doc.cm);
+ var rebased = [];
+
+ // Propagate to the linked documents
+ linkedDocs(doc, function(doc, sharedHist) {
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
+ rebaseHist(doc.history, change);
+ rebased.push(doc.history);
+ }
+ makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
+ });
+ }
+ }
+
+ // Sub-views need their line numbers shifted when text is added
+ // above or below them in the parent document.
+ function shiftDoc(doc, distance) {
+ doc.first += distance;
+ doc.sel = new Selection(map(doc.sel.ranges, function(range) {
+ return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
+ Pos(range.head.line + distance, range.head.ch));
+ }), doc.sel.primIndex);
+ if (doc.cm) regChange(doc.cm, doc.first, doc.first - distance, distance);
+ }
+
+ // More lower-level change function, handling only a single document
+ // (not linked ones).
+ function makeChangeSingleDoc(doc, change, selAfter, spans) {
+ if (doc.cm && !doc.cm.curOp)
+ return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
+
+ if (change.to.line < doc.first) {
+ shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
+ return;
+ }
+ if (change.from.line > doc.lastLine()) return;
+
+ // Clip the change to the size of this doc
+ if (change.from.line < doc.first) {
+ var shift = change.text.length - 1 - (doc.first - change.from.line);
+ shiftDoc(doc, shift);
+ change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
+ text: [lst(change.text)], origin: change.origin};
+ }
+ var last = doc.lastLine();
+ if (change.to.line > last) {
+ change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
+ text: [change.text[0]], origin: change.origin};
+ }
+
+ change.removed = getBetween(doc, change.from, change.to);
+
+ if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
+ if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
+ else updateDoc(doc, change, spans);
+ setSelectionNoUndo(doc, selAfter, sel_dontScroll);
+ }
+
+ // Handle the interaction of a change to a document with the editor
+ // that this document is part of.
+ function makeChangeSingleDocInEditor(cm, change, spans) {
+ var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
+
+ var recomputeMaxLength = false, checkWidthStart = from.line;
+ if (!cm.options.lineWrapping) {
+ checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
+ doc.iter(checkWidthStart, to.line + 1, function(line) {
+ if (line == display.maxLine) {
+ recomputeMaxLength = true;
+ return true;
+ }
+ });
+ }
+
+ if (doc.sel.contains(change.from, change.to) > -1)
+ cm.curOp.cursorActivity = true;
+
+ updateDoc(doc, change, spans, estimateHeight(cm));
+
+ if (!cm.options.lineWrapping) {
+ doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
+ var len = lineLength(line);
+ if (len > display.maxLineLength) {
+ display.maxLine = line;
+ display.maxLineLength = len;
+ display.maxLineChanged = true;
+ recomputeMaxLength = false;
+ }
+ });
+ if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
+ }
+
+ // Adjust frontier, schedule worker
+ doc.frontier = Math.min(doc.frontier, from.line);
+ startWorker(cm, 400);
+
+ var lendiff = change.text.length - (to.line - from.line) - 1;
+ // Remember that these lines changed, for updating the display
+ if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
+ regLineChange(cm, from.line, "text");
+ else
+ regChange(cm, from.line, to.line + 1, lendiff);
+
+ if (hasHandler(cm, "change") || hasHandler(cm, "changes"))
+ (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push({
+ from: from, to: to,
+ text: change.text,
+ removed: change.removed,
+ origin: change.origin
+ });
+ }
+
+ function replaceRange(doc, code, from, to, origin) {
+ if (!to) to = from;
+ if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
+ if (typeof code == "string") code = splitLines(code);
+ makeChange(doc, {from: from, to: to, text: code, origin: origin});
+ }
+
+ // SCROLLING THINGS INTO VIEW
+
+ // If an editor sits on the top or bottom of the window, partially
+ // scrolled out of view, this ensures that the cursor is visible.
+ function maybeScrollWindow(cm, coords) {
+ var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
+ if (coords.top + box.top < 0) doScroll = true;
+ else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
+ if (doScroll != null && !phantom) {
+ var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
+ (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +
+ (coords.bottom - coords.top + scrollerCutOff) + "px; left: " +
+ coords.left + "px; width: 2px;");
+ cm.display.lineSpace.appendChild(scrollNode);
+ scrollNode.scrollIntoView(doScroll);
+ cm.display.lineSpace.removeChild(scrollNode);
+ }
+ }
+
+ // Scroll a given position into view (immediately), verifying that
+ // it actually became visible (as line heights are accurately
+ // measured, the position of something may 'drift' during drawing).
+ function scrollPosIntoView(cm, pos, end, margin) {
+ if (margin == null) margin = 0;
+ for (;;) {
+ var changed = false, coords = cursorCoords(cm, pos);
+ var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
+ var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
+ Math.min(coords.top, endCoords.top) - margin,
+ Math.max(coords.left, endCoords.left),
+ Math.max(coords.bottom, endCoords.bottom) + margin);
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
+ if (scrollPos.scrollTop != null) {
+ setScrollTop(cm, scrollPos.scrollTop);
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
+ }
+ if (scrollPos.scrollLeft != null) {
+ setScrollLeft(cm, scrollPos.scrollLeft);
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
+ }
+ if (!changed) return coords;
+ }
+ }
+
+ // Scroll a given set of coordinates into view (immediately).
+ function scrollIntoView(cm, x1, y1, x2, y2) {
+ var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
+ if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
+ if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
+ }
+
+ // Calculate a new scroll position needed to scroll the given
+ // rectangle into view. Returns an object with scrollTop and
+ // scrollLeft properties. When these are undefined, the
+ // vertical/horizontal position does not need to be adjusted.
+ function calculateScrollPos(cm, x1, y1, x2, y2) {
+ var display = cm.display, snapMargin = textHeight(cm.display);
+ if (y1 < 0) y1 = 0;
+ var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
+ var screen = display.scroller.clientHeight - scrollerCutOff, result = {};
+ var docBottom = cm.doc.height + paddingVert(display);
+ var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
+ if (y1 < screentop) {
+ result.scrollTop = atTop ? 0 : y1;
+ } else if (y2 > screentop + screen) {
+ var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
+ if (newTop != screentop) result.scrollTop = newTop;
+ }
+
+ var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
+ var screenw = display.scroller.clientWidth - scrollerCutOff;
+ x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
+ var gutterw = display.gutters.offsetWidth;
+ var atLeft = x1 < gutterw + 10;
+ if (x1 < screenleft + gutterw || atLeft) {
+ if (atLeft) x1 = 0;
+ result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
+ } else if (x2 > screenw + screenleft - 3) {
+ result.scrollLeft = x2 + 10 - screenw;
+ }
+ return result;
+ }
+
+ // Store a relative adjustment to the scroll position in the current
+ // operation (to be applied when the operation finishes).
+ function addToScrollPos(cm, left, top) {
+ if (left != null || top != null) resolveScrollToPos(cm);
+ if (left != null)
+ cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;
+ if (top != null)
+ cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
+ }
+
+ // Make sure that at the end of the operation the current cursor is
+ // shown.
+ function ensureCursorVisible(cm) {
+ resolveScrollToPos(cm);
+ var cur = cm.getCursor(), from = cur, to = cur;
+ if (!cm.options.lineWrapping) {
+ from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
+ to = Pos(cur.line, cur.ch + 1);
+ }
+ cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};
+ }
+
+ // When an operation has its scrollToPos property set, and another
+ // scroll action is applied before the end of the operation, this
+ // 'simulates' scrolling that position into view in a cheap way, so
+ // that the effect of intermediate scroll commands is not ignored.
+ function resolveScrollToPos(cm) {
+ var range = cm.curOp.scrollToPos;
+ if (range) {
+ cm.curOp.scrollToPos = null;
+ var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
+ var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
+ Math.min(from.top, to.top) - range.margin,
+ Math.max(from.right, to.right),
+ Math.max(from.bottom, to.bottom) + range.margin);
+ cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);
+ }
+ }
+
+ // API UTILITIES
+
+ // Indent the given line. The how parameter can be "smart",
+ // "add"/null, "subtract", or "prev". When aggressive is false
+ // (typically set to true for forced single-line indents), empty
+ // lines are not indented, and places where the mode returns Pass
+ // are left alone.
+ function indentLine(cm, n, how, aggressive) {
+ var doc = cm.doc, state;
+ if (how == null) how = "add";
+ if (how == "smart") {
+ // Fall back to "prev" when the mode doesn't have an indentation
+ // method.
+ if (!cm.doc.mode.indent) how = "prev";
+ else state = getStateBefore(cm, n);
+ }
+
+ var tabSize = cm.options.tabSize;
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
+ if (line.stateAfter) line.stateAfter = null;
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation;
+ if (!aggressive && !/\S/.test(line.text)) {
+ indentation = 0;
+ how = "not";
+ } else if (how == "smart") {
+ indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
+ if (indentation == Pass) {
+ if (!aggressive) return;
+ how = "prev";
+ }
+ }
+ if (how == "prev") {
+ if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
+ else indentation = 0;
+ } else if (how == "add") {
+ indentation = curSpace + cm.options.indentUnit;
+ } else if (how == "subtract") {
+ indentation = curSpace - cm.options.indentUnit;
+ } else if (typeof how == "number") {
+ indentation = curSpace + how;
+ }
+ indentation = Math.max(0, indentation);
+
+ var indentString = "", pos = 0;
+ if (cm.options.indentWithTabs)
+ for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
+ if (pos < indentation) indentString += spaceStr(indentation - pos);
+
+ if (indentString != curSpaceString) {
+ replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
+ } else {
+ // Ensure that, if the cursor was in the whitespace at the start
+ // of the line, it is moved to the end of that space.
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
+ var range = doc.sel.ranges[i];
+ if (range.head.line == n && range.head.ch < curSpaceString.length) {
+ var pos = Pos(n, curSpaceString.length);
+ replaceOneSelection(doc, i, new Range(pos, pos));
+ break;
+ }
+ }
+ }
+ line.stateAfter = null;
+ }
+
+ // Utility for applying a change to a line by handle or number,
+ // returning the number and optionally registering the line as
+ // changed.
+ function changeLine(cm, handle, changeType, op) {
+ var no = handle, line = handle, doc = cm.doc;
+ if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
+ else no = lineNo(handle);
+ if (no == null) return null;
+ if (op(line, no)) regLineChange(cm, no, changeType);
+ else return null;
+ return line;
+ }
+
+ // Helper for deleting text near the selection(s), used to implement
+ // backspace, delete, and similar functionality.
+ function deleteNearSelection(cm, compute) {
+ var ranges = cm.doc.sel.ranges, kill = [];
+ // Build up a set of ranges to kill first, merging overlapping
+ // ranges.
+ for (var i = 0; i < ranges.length; i++) {
+ var toKill = compute(ranges[i]);
+ while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
+ var replaced = kill.pop();
+ if (cmp(replaced.from, toKill.from) < 0) {
+ toKill.from = replaced.from;
+ break;
+ }
+ }
+ kill.push(toKill);
+ }
+ // Next, remove those actual ranges.
+ runInOp(cm, function() {
+ for (var i = kill.length - 1; i >= 0; i--)
+ replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete");
+ ensureCursorVisible(cm);
+ });
+ }
+
+ // Used for horizontal relative motion. Dir is -1 or 1 (left or
+ // right), unit can be "char", "column" (like char, but doesn't
+ // cross line boundaries), "word" (across next word), or "group" (to
+ // the start of next group of word or non-word-non-whitespace
+ // chars). The visually param controls whether, in right-to-left
+ // text, direction 1 means to move towards the next index in the
+ // string, or towards the character to the right of the current
+ // position. The resulting position will have a hitSide=true
+ // property if it reached the end of the document.
+ function findPosH(doc, pos, dir, unit, visually) {
+ var line = pos.line, ch = pos.ch, origDir = dir;
+ var lineObj = getLine(doc, line);
+ var possible = true;
+ function findNextLine() {
+ var l = line + dir;
+ if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
+ line = l;
+ return lineObj = getLine(doc, l);
+ }
+ function moveOnce(boundToLine) {
+ var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
+ if (next == null) {
+ if (!boundToLine && findNextLine()) {
+ if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
+ else ch = dir < 0 ? lineObj.text.length : 0;
+ } else return (possible = false);
+ } else ch = next;
+ return true;
+ }
+
+ if (unit == "char") moveOnce();
+ else if (unit == "column") moveOnce(true);
+ else if (unit == "word" || unit == "group") {
+ var sawType = null, group = unit == "group";
+ for (var first = true;; first = false) {
+ if (dir < 0 && !moveOnce(!first)) break;
+ var cur = lineObj.text.charAt(ch) || "\n";
+ var type = isWordChar(cur) ? "w"
+ : group && cur == "\n" ? "n"
+ : !group || /\s/.test(cur) ? null
+ : "p";
+ if (group && !first && !type) type = "s";
+ if (sawType && sawType != type) {
+ if (dir < 0) {dir = 1; moveOnce();}
+ break;
+ }
+
+ if (type) sawType = type;
+ if (dir > 0 && !moveOnce(!first)) break;
+ }
+ }
+ var result = skipAtomic(doc, Pos(line, ch), origDir, true);
+ if (!possible) result.hitSide = true;
+ return result;
+ }
+
+ // For relative vertical movement. Dir may be -1 or 1. Unit can be
+ // "page" or "line". The resulting position will have a hitSide=true
+ // property if it reached the end of the document.
+ function findPosV(cm, pos, dir, unit) {
+ var doc = cm.doc, x = pos.left, y;
+ if (unit == "page") {
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
+ y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
+ } else if (unit == "line") {
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
+ }
+ for (;;) {
+ var target = coordsChar(cm, x, y);
+ if (!target.outside) break;
+ if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
+ y += dir * 5;
+ }
+ return target;
+ }
+
+ // Find the word at the given position (as returned by coordsChar).
+ function findWordAt(doc, pos) {
+ var line = getLine(doc, pos.line).text;
+ var start = pos.ch, end = pos.ch;
+ if (line) {
+ if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
+ var startChar = line.charAt(start);
+ var check = isWordChar(startChar) ? isWordChar
+ : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
+ : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
+ while (start > 0 && check(line.charAt(start - 1))) --start;
+ while (end < line.length && check(line.charAt(end))) ++end;
+ }
+ return new Range(Pos(pos.line, start), Pos(pos.line, end));
+ }
+
+ // EDITOR METHODS
+
+ // The publicly visible API. Note that methodOp(f) means
+ // 'wrap f in an operation, performed on its `this` parameter'.
+
+ // This is not the complete set of editor methods. Most of the
+ // methods defined on the Doc type are also injected into
+ // CodeMirror.prototype, for backwards compatibility and
+ // convenience.
+
+ CodeMirror.prototype = {
+ constructor: CodeMirror,
+ focus: function(){window.focus(); focusInput(this); fastPoll(this);},
+
+ setOption: function(option, value) {
+ var options = this.options, old = options[option];
+ if (options[option] == value && option != "mode") return;
+ options[option] = value;
+ if (optionHandlers.hasOwnProperty(option))
+ operation(this, optionHandlers[option])(this, value, old);
+ },
+
+ getOption: function(option) {return this.options[option];},
+ getDoc: function() {return this.doc;},
+
+ addKeyMap: function(map, bottom) {
+ this.state.keyMaps[bottom ? "push" : "unshift"](map);
+ },
+ removeKeyMap: function(map) {
+ var maps = this.state.keyMaps;
+ for (var i = 0; i < maps.length; ++i)
+ if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
+ maps.splice(i, 1);
+ return true;
+ }
+ },
+
+ addOverlay: methodOp(function(spec, options) {
+ var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
+ if (mode.startState) throw new Error("Overlays may not be stateful.");
+ this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
+ this.state.modeGen++;
+ regChange(this);
+ }),
+ removeOverlay: methodOp(function(spec) {
+ var overlays = this.state.overlays;
+ for (var i = 0; i < overlays.length; ++i) {
+ var cur = overlays[i].modeSpec;
+ if (cur == spec || typeof spec == "string" && cur.name == spec) {
+ overlays.splice(i, 1);
+ this.state.modeGen++;
+ regChange(this);
+ return;
+ }
+ }
+ }),
+
+ indentLine: methodOp(function(n, dir, aggressive) {
+ if (typeof dir != "string" && typeof dir != "number") {
+ if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
+ else dir = dir ? "add" : "subtract";
+ }
+ if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
+ }),
+ indentSelection: methodOp(function(how) {
+ var ranges = this.doc.sel.ranges, end = -1;
+ for (var i = 0; i < ranges.length; i++) {
+ var range = ranges[i];
+ if (!range.empty()) {
+ var start = Math.max(end, range.from().line);
+ var to = range.to();
+ end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
+ for (var j = start; j < end; ++j)
+ indentLine(this, j, how);
+ } else if (range.head.line > end) {
+ indentLine(this, range.head.line, how, true);
+ end = range.head.line;
+ if (i == this.doc.sel.primIndex) ensureCursorVisible(this);
+ }
+ }
+ }),
+
+ // Fetch the parser token for a given character. Useful for hacks
+ // that want to inspect the mode state (say, for completion).
+ getTokenAt: function(pos, precise) {
+ var doc = this.doc;
+ pos = clipPos(doc, pos);
+ var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
+ var line = getLine(doc, pos.line);
+ var stream = new StringStream(line.text, this.options.tabSize);
+ while (stream.pos < pos.ch && !stream.eol()) {
+ stream.start = stream.pos;
+ var style = mode.token(stream, state);
+ }
+ return {start: stream.start,
+ end: stream.pos,
+ string: stream.current(),
+ type: style || null,
+ state: state};
+ },
+
+ getTokenTypeAt: function(pos) {
+ pos = clipPos(this.doc, pos);
+ var styles = getLineStyles(this, getLine(this.doc, pos.line));
+ var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
+ if (ch == 0) return styles[2];
+ for (;;) {
+ var mid = (before + after) >> 1;
+ if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
+ else if (styles[mid * 2 + 1] < ch) before = mid + 1;
+ else return styles[mid * 2 + 2];
+ }
+ },
+
+ getModeAt: function(pos) {
+ var mode = this.doc.mode;
+ if (!mode.innerMode) return mode;
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
+ },
+
+ getHelper: function(pos, type) {
+ return this.getHelpers(pos, type)[0];
+ },
+
+ getHelpers: function(pos, type) {
+ var found = [];
+ if (!helpers.hasOwnProperty(type)) return helpers;
+ var help = helpers[type], mode = this.getModeAt(pos);
+ if (typeof mode[type] == "string") {
+ if (help[mode[type]]) found.push(help[mode[type]]);
+ } else if (mode[type]) {
+ for (var i = 0; i < mode[type].length; i++) {
+ var val = help[mode[type][i]];
+ if (val) found.push(val);
+ }
+ } else if (mode.helperType && help[mode.helperType]) {
+ found.push(help[mode.helperType]);
+ } else if (help[mode.name]) {
+ found.push(help[mode.name]);
+ }
+ for (var i = 0; i < help._global.length; i++) {
+ var cur = help._global[i];
+ if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
+ found.push(cur.val);
+ }
+ return found;
+ },
+
+ getStateAfter: function(line, precise) {
+ var doc = this.doc;
+ line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
+ return getStateBefore(this, line + 1, precise);
+ },
+
+ cursorCoords: function(start, mode) {
+ var pos, range = this.doc.sel.primary();
+ if (start == null) pos = range.head;
+ else if (typeof start == "object") pos = clipPos(this.doc, start);
+ else pos = start ? range.from() : range.to();
+ return cursorCoords(this, pos, mode || "page");
+ },
+
+ charCoords: function(pos, mode) {
+ return charCoords(this, clipPos(this.doc, pos), mode || "page");
+ },
+
+ coordsChar: function(coords, mode) {
+ coords = fromCoordSystem(this, coords, mode || "page");
+ return coordsChar(this, coords.left, coords.top);
+ },
+
+ lineAtHeight: function(height, mode) {
+ height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
+ return lineAtHeight(this.doc, height + this.display.viewOffset);
+ },
+ heightAtLine: function(line, mode) {
+ var end = false, last = this.doc.first + this.doc.size - 1;
+ if (line < this.doc.first) line = this.doc.first;
+ else if (line > last) { line = last; end = true; }
+ var lineObj = getLine(this.doc, line);
+ return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
+ (end ? this.doc.height - heightAtLine(lineObj) : 0);
+ },
+
+ defaultTextHeight: function() { return textHeight(this.display); },
+ defaultCharWidth: function() { return charWidth(this.display); },
+
+ setGutterMarker: methodOp(function(line, gutterID, value) {
+ return changeLine(this, line, "gutter", function(line) {
+ var markers = line.gutterMarkers || (line.gutterMarkers = {});
+ markers[gutterID] = value;
+ if (!value && isEmpty(markers)) line.gutterMarkers = null;
+ return true;
+ });
+ }),
+
+ clearGutter: methodOp(function(gutterID) {
+ var cm = this, doc = cm.doc, i = doc.first;
+ doc.iter(function(line) {
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
+ line.gutterMarkers[gutterID] = null;
+ regLineChange(cm, i, "gutter");
+ if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
+ }
+ ++i;
+ });
+ }),
+
+ addLineClass: methodOp(function(handle, where, cls) {
+ return changeLine(this, handle, "class", function(line) {
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
+ if (!line[prop]) line[prop] = cls;
+ else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
+ else line[prop] += " " + cls;
+ return true;
+ });
+ }),
+
+ removeLineClass: methodOp(function(handle, where, cls) {
+ return changeLine(this, handle, "class", function(line) {
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
+ var cur = line[prop];
+ if (!cur) return false;
+ else if (cls == null) line[prop] = null;
+ else {
+ var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
+ if (!found) return false;
+ var end = found.index + found[0].length;
+ line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
+ }
+ return true;
+ });
+ }),
+
+ addLineWidget: methodOp(function(handle, node, options) {
+ return addLineWidget(this, handle, node, options);
+ }),
+
+ removeLineWidget: function(widget) { widget.clear(); },
+
+ lineInfo: function(line) {
+ if (typeof line == "number") {
+ if (!isLine(this.doc, line)) return null;
+ var n = line;
+ line = getLine(this.doc, line);
+ if (!line) return null;
+ } else {
+ var n = lineNo(line);
+ if (n == null) return null;
+ }
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
+ widgets: line.widgets};
+ },
+
+ getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},
+
+ addWidget: function(pos, node, scroll, vert, horiz) {
+ var display = this.display;
+ pos = cursorCoords(this, clipPos(this.doc, pos));
+ var top = pos.bottom, left = pos.left;
+ node.style.position = "absolute";
+ display.sizer.appendChild(node);
+ if (vert == "over") {
+ top = pos.top;
+ } else if (vert == "above" || vert == "near") {
+ var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
+ // Default to positioning above (if specified and possible); otherwise default to positioning below
+ if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
+ top = pos.top - node.offsetHeight;
+ else if (pos.bottom + node.offsetHeight <= vspace)
+ top = pos.bottom;
+ if (left + node.offsetWidth > hspace)
+ left = hspace - node.offsetWidth;
+ }
+ node.style.top = top + "px";
+ node.style.left = node.style.right = "";
+ if (horiz == "right") {
+ left = display.sizer.clientWidth - node.offsetWidth;
+ node.style.right = "0px";
+ } else {
+ if (horiz == "left") left = 0;
+ else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
+ node.style.left = left + "px";
+ }
+ if (scroll)
+ scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
+ },
+
+ triggerOnKeyDown: methodOp(onKeyDown),
+ triggerOnKeyPress: methodOp(onKeyPress),
+ triggerOnKeyUp: methodOp(onKeyUp),
+
+ execCommand: function(cmd) {
+ if (commands.hasOwnProperty(cmd))
+ return commands[cmd](this);
+ },
+
+ findPosH: function(from, amount, unit, visually) {
+ var dir = 1;
+ if (amount < 0) { dir = -1; amount = -amount; }
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
+ cur = findPosH(this.doc, cur, dir, unit, visually);
+ if (cur.hitSide) break;
+ }
+ return cur;
+ },
+
+ moveH: methodOp(function(dir, unit) {
+ var cm = this;
+ cm.extendSelectionsBy(function(range) {
+ if (cm.display.shift || cm.doc.extend || range.empty())
+ return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);
+ else
+ return dir < 0 ? range.from() : range.to();
+ }, sel_move);
+ }),
+
+ deleteH: methodOp(function(dir, unit) {
+ var sel = this.doc.sel, doc = this.doc;
+ if (sel.somethingSelected())
+ doc.replaceSelection("", null, "+delete");
+ else
+ deleteNearSelection(this, function(range) {
+ var other = findPosH(doc, range.head, dir, unit, false);
+ return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
+ });
+ }),
+
+ findPosV: function(from, amount, unit, goalColumn) {
+ var dir = 1, x = goalColumn;
+ if (amount < 0) { dir = -1; amount = -amount; }
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
+ var coords = cursorCoords(this, cur, "div");
+ if (x == null) x = coords.left;
+ else coords.left = x;
+ cur = findPosV(this, coords, dir, unit);
+ if (cur.hitSide) break;
+ }
+ return cur;
+ },
+
+ moveV: methodOp(function(dir, unit) {
+ var cm = this, doc = this.doc, goals = [];
+ var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();
+ doc.extendSelectionsBy(function(range) {
+ if (collapse)
+ return dir < 0 ? range.from() : range.to();
+ var headPos = cursorCoords(cm, range.head, "div");
+ if (range.goalColumn != null) headPos.left = range.goalColumn;
+ goals.push(headPos.left);
+ var pos = findPosV(cm, headPos, dir, unit);
+ if (unit == "page" && range == doc.sel.primary())
+ addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top);
+ return pos;
+ }, sel_move);
+ if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
+ doc.sel.ranges[i].goalColumn = goals[i];
+ }),
+
+ toggleOverwrite: function(value) {
+ if (value != null && value == this.state.overwrite) return;
+ if (this.state.overwrite = !this.state.overwrite)
+ this.display.cursorDiv.className += " CodeMirror-overwrite";
+ else
+ this.display.cursorDiv.className = this.display.cursorDiv.className.replace(" CodeMirror-overwrite", "");
+
+ signal(this, "overwriteToggle", this, this.state.overwrite);
+ },
+ hasFocus: function() { return activeElt() == this.display.input; },
+
+ scrollTo: methodOp(function(x, y) {
+ if (x != null || y != null) resolveScrollToPos(this);
+ if (x != null) this.curOp.scrollLeft = x;
+ if (y != null) this.curOp.scrollTop = y;
+ }),
+ getScrollInfo: function() {
+ var scroller = this.display.scroller, co = scrollerCutOff;
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
+ height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
+ clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
+ },
+
+ scrollIntoView: methodOp(function(range, margin) {
+ if (range == null) {
+ range = {from: this.doc.sel.primary().head, to: null};
+ if (margin == null) margin = this.options.cursorScrollMargin;
+ } else if (typeof range == "number") {
+ range = {from: Pos(range, 0), to: null};
+ } else if (range.from == null) {
+ range = {from: range, to: null};
+ }
+ if (!range.to) range.to = range.from;
+ range.margin = margin || 0;
+
+ if (range.from.line != null) {
+ resolveScrollToPos(this);
+ this.curOp.scrollToPos = range;
+ } else {
+ var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
+ Math.min(range.from.top, range.to.top) - range.margin,
+ Math.max(range.from.right, range.to.right),
+ Math.max(range.from.bottom, range.to.bottom) + range.margin);
+ this.scrollTo(sPos.scrollLeft, sPos.scrollTop);
+ }
+ }),
+
+ setSize: methodOp(function(width, height) {
+ function interpret(val) {
+ return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
+ }
+ if (width != null) this.display.wrapper.style.width = interpret(width);
+ if (height != null) this.display.wrapper.style.height = interpret(height);
+ if (this.options.lineWrapping) clearLineMeasurementCache(this);
+ this.curOp.forceUpdate = true;
+ signal(this, "refresh", this);
+ }),
+
+ operation: function(f){return runInOp(this, f);},
+
+ refresh: methodOp(function() {
+ var oldHeight = this.display.cachedTextHeight;
+ regChange(this);
+ clearCaches(this);
+ this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
+ if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
+ estimateLineHeights(this);
+ signal(this, "refresh", this);
+ }),
+
+ swapDoc: methodOp(function(doc) {
+ var old = this.doc;
+ old.cm = null;
+ attachDoc(this, doc);
+ clearCaches(this);
+ resetInput(this);
+ this.scrollTo(doc.scrollLeft, doc.scrollTop);
+ signalLater(this, "swapDoc", this, old);
+ return old;
+ }),
+
+ getInputField: function(){return this.display.input;},
+ getWrapperElement: function(){return this.display.wrapper;},
+ getScrollerElement: function(){return this.display.scroller;},
+ getGutterElement: function(){return this.display.gutters;}
+ };
+ eventMixin(CodeMirror);
+
+ // OPTION DEFAULTS
+
+ // The default configuration options.
+ var defaults = CodeMirror.defaults = {};
+ // Functions to run when options are changed.
+ var optionHandlers = CodeMirror.optionHandlers = {};
+
+ function option(name, deflt, handle, notOnInit) {
+ CodeMirror.defaults[name] = deflt;
+ if (handle) optionHandlers[name] =
+ notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
+ }
+
+ // Passed to option handlers when there is no old value.
+ var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
+
+ // These two are, on init, called from the constructor because they
+ // have to be initialized before the editor can start at all.
+ option("value", "", function(cm, val) {
+ cm.setValue(val);
+ }, true);
+ option("mode", null, function(cm, val) {
+ cm.doc.modeOption = val;
+ loadMode(cm);
+ }, true);
+
+ option("indentUnit", 2, loadMode, true);
+ option("indentWithTabs", false);
+ option("smartIndent", true);
+ option("tabSize", 4, function(cm) {
+ resetModeState(cm);
+ clearCaches(cm);
+ regChange(cm);
+ }, true);
+ option("specialChars", /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g, function(cm, val) {
+ cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
+ cm.refresh();
+ }, true);
+ option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
+ option("electricChars", true);
+ option("rtlMoveVisually", !windows);
+ option("wholeLineUpdateBefore", true);
+
+ option("theme", "default", function(cm) {
+ themeChanged(cm);
+ guttersChanged(cm);
+ }, true);
+ option("keyMap", "default", keyMapChanged);
+ option("extraKeys", null);
+
+ option("lineWrapping", false, wrappingChanged, true);
+ option("gutters", [], function(cm) {
+ setGuttersForLineNumbers(cm.options);
+ guttersChanged(cm);
+ }, true);
+ option("fixedGutter", true, function(cm, val) {
+ cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
+ cm.refresh();
+ }, true);
+ option("coverGutterNextToScrollbar", false, updateScrollbars, true);
+ option("lineNumbers", false, function(cm) {
+ setGuttersForLineNumbers(cm.options);
+ guttersChanged(cm);
+ }, true);
+ option("firstLineNumber", 1, guttersChanged, true);
+ option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
+ option("showCursorWhenSelecting", false, updateSelection, true);
+
+ option("resetSelectionOnContextMenu", true);
+
+ option("readOnly", false, function(cm, val) {
+ if (val == "nocursor") {
+ onBlur(cm);
+ cm.display.input.blur();
+ cm.display.disabled = true;
+ } else {
+ cm.display.disabled = false;
+ if (!val) resetInput(cm);
+ }
+ });
+ option("disableInput", false, function(cm, val) {if (!val) resetInput(cm);}, true);
+ option("dragDrop", true);
+
+ option("cursorBlinkRate", 530);
+ option("cursorScrollMargin", 0);
+ option("cursorHeight", 1);
+ option("workTime", 100);
+ option("workDelay", 100);
+ option("flattenSpans", true, resetModeState, true);
+ option("addModeClass", false, resetModeState, true);
+ option("pollInterval", 100);
+ option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;});
+ option("historyEventDelay", 1250);
+ option("viewportMargin", 10, function(cm){cm.refresh();}, true);
+ option("maxHighlightLength", 10000, resetModeState, true);
+ option("moveInputWithCursor", true, function(cm, val) {
+ if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
+ });
+
+ option("tabindex", null, function(cm, val) {
+ cm.display.input.tabIndex = val || "";
+ });
+ option("autofocus", null);
+
+ // MODE DEFINITION AND QUERYING
+
+ // Known modes, by name and by MIME
+ var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
+
+ // Extra arguments are stored as the mode's dependencies, which is
+ // used by (legacy) mechanisms like loadmode.js to automatically
+ // load a mode. (Preferred mechanism is the require/define calls.)
+ CodeMirror.defineMode = function(name, mode) {
+ if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
+ if (arguments.length > 2) {
+ mode.dependencies = [];
+ for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
+ }
+ modes[name] = mode;
+ };
+
+ CodeMirror.defineMIME = function(mime, spec) {
+ mimeModes[mime] = spec;
+ };
+
+ // Given a MIME type, a {name, ...options} config object, or a name
+ // string, return a mode config object.
+ CodeMirror.resolveMode = function(spec) {
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
+ spec = mimeModes[spec];
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
+ var found = mimeModes[spec.name];
+ if (typeof found == "string") found = {name: found};
+ spec = createObj(found, spec);
+ spec.name = found.name;
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
+ return CodeMirror.resolveMode("application/xml");
+ }
+ if (typeof spec == "string") return {name: spec};
+ else return spec || {name: "null"};
+ };
+
+ // Given a mode spec (anything that resolveMode accepts), find and
+ // initialize an actual mode object.
+ CodeMirror.getMode = function(options, spec) {
+ var spec = CodeMirror.resolveMode(spec);
+ var mfactory = modes[spec.name];
+ if (!mfactory) return CodeMirror.getMode(options, "text/plain");
+ var modeObj = mfactory(options, spec);
+ if (modeExtensions.hasOwnProperty(spec.name)) {
+ var exts = modeExtensions[spec.name];
+ for (var prop in exts) {
+ if (!exts.hasOwnProperty(prop)) continue;
+ if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
+ modeObj[prop] = exts[prop];
+ }
+ }
+ modeObj.name = spec.name;
+ if (spec.helperType) modeObj.helperType = spec.helperType;
+ if (spec.modeProps) for (var prop in spec.modeProps)
+ modeObj[prop] = spec.modeProps[prop];
+
+ return modeObj;
+ };
+
+ // Minimal default mode.
+ CodeMirror.defineMode("null", function() {
+ return {token: function(stream) {stream.skipToEnd();}};
+ });
+ CodeMirror.defineMIME("text/plain", "null");
+
+ // This can be used to attach properties to mode objects from
+ // outside the actual mode definition.
+ var modeExtensions = CodeMirror.modeExtensions = {};
+ CodeMirror.extendMode = function(mode, properties) {
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
+ copyObj(properties, exts);
+ };
+
+ // EXTENSIONS
+
+ CodeMirror.defineExtension = function(name, func) {
+ CodeMirror.prototype[name] = func;
+ };
+ CodeMirror.defineDocExtension = function(name, func) {
+ Doc.prototype[name] = func;
+ };
+ CodeMirror.defineOption = option;
+
+ var initHooks = [];
+ CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
+
+ var helpers = CodeMirror.helpers = {};
+ CodeMirror.registerHelper = function(type, name, value) {
+ if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};
+ helpers[type][name] = value;
+ };
+ CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
+ CodeMirror.registerHelper(type, name, value);
+ helpers[type]._global.push({pred: predicate, val: value});
+ };
+
+ // MODE STATE HANDLING
+
+ // Utility functions for working with state. Exported because nested
+ // modes need to do this for their inner modes.
+
+ var copyState = CodeMirror.copyState = function(mode, state) {
+ if (state === true) return state;
+ if (mode.copyState) return mode.copyState(state);
+ var nstate = {};
+ for (var n in state) {
+ var val = state[n];
+ if (val instanceof Array) val = val.concat([]);
+ nstate[n] = val;
+ }
+ return nstate;
+ };
+
+ var startState = CodeMirror.startState = function(mode, a1, a2) {
+ return mode.startState ? mode.startState(a1, a2) : true;
+ };
+
+ // Given a mode and a state (for that mode), find the inner mode and
+ // state at the position that the state refers to.
+ CodeMirror.innerMode = function(mode, state) {
+ while (mode.innerMode) {
+ var info = mode.innerMode(state);
+ if (!info || info.mode == mode) break;
+ state = info.state;
+ mode = info.mode;
+ }
+ return info || {mode: mode, state: state};
+ };
+
+ // STANDARD COMMANDS
+
+ // Commands are parameter-less actions that can be performed on an
+ // editor, mostly used for keybindings.
+ var commands = CodeMirror.commands = {
+ selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},
+ singleSelection: function(cm) {
+ cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll);
+ },
+ killLine: function(cm) {
+ deleteNearSelection(cm, function(range) {
+ if (range.empty()) {
+ var len = getLine(cm.doc, range.head.line).text.length;
+ if (range.head.ch == len && range.head.line < cm.lastLine())
+ return {from: range.head, to: Pos(range.head.line + 1, 0)};
+ else
+ return {from: range.head, to: Pos(range.head.line, len)};
+ } else {
+ return {from: range.from(), to: range.to()};
+ }
+ });
+ },
+ deleteLine: function(cm) {
+ deleteNearSelection(cm, function(range) {
+ return {from: Pos(range.from().line, 0),
+ to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};
+ });
+ },
+ delLineLeft: function(cm) {
+ deleteNearSelection(cm, function(range) {
+ return {from: Pos(range.from().line, 0), to: range.from()};
+ });
+ },
+ undo: function(cm) {cm.undo();},
+ redo: function(cm) {cm.redo();},
+ undoSelection: function(cm) {cm.undoSelection();},
+ redoSelection: function(cm) {cm.redoSelection();},
+ goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
+ goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
+ goLineStart: function(cm) {
+ cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); }, sel_move);
+ },
+ goLineStartSmart: function(cm) {
+ cm.extendSelectionsBy(function(range) {
+ var start = lineStart(cm, range.head.line);
+ var line = cm.getLineHandle(start.line);
+ var order = getOrder(line);
+ if (!order || order[0].level == 0) {
+ var firstNonWS = Math.max(0, line.text.search(/\S/));
+ var inWS = range.head.line == start.line && range.head.ch <= firstNonWS && range.head.ch;
+ return Pos(start.line, inWS ? 0 : firstNonWS);
+ }
+ return start;
+ }, sel_move);
+ },
+ goLineEnd: function(cm) {
+ cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); }, sel_move);
+ },
+ goLineRight: function(cm) {
+ cm.extendSelectionsBy(function(range) {
+ var top = cm.charCoords(range.head, "div").top + 5;
+ return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
+ }, sel_move);
+ },
+ goLineLeft: function(cm) {
+ cm.extendSelectionsBy(function(range) {
+ var top = cm.charCoords(range.head, "div").top + 5;
+ return cm.coordsChar({left: 0, top: top}, "div");
+ }, sel_move);
+ },
+ goLineUp: function(cm) {cm.moveV(-1, "line");},
+ goLineDown: function(cm) {cm.moveV(1, "line");},
+ goPageUp: function(cm) {cm.moveV(-1, "page");},
+ goPageDown: function(cm) {cm.moveV(1, "page");},
+ goCharLeft: function(cm) {cm.moveH(-1, "char");},
+ goCharRight: function(cm) {cm.moveH(1, "char");},
+ goColumnLeft: function(cm) {cm.moveH(-1, "column");},
+ goColumnRight: function(cm) {cm.moveH(1, "column");},
+ goWordLeft: function(cm) {cm.moveH(-1, "word");},
+ goGroupRight: function(cm) {cm.moveH(1, "group");},
+ goGroupLeft: function(cm) {cm.moveH(-1, "group");},
+ goWordRight: function(cm) {cm.moveH(1, "word");},
+ delCharBefore: function(cm) {cm.deleteH(-1, "char");},
+ delCharAfter: function(cm) {cm.deleteH(1, "char");},
+ delWordBefore: function(cm) {cm.deleteH(-1, "word");},
+ delWordAfter: function(cm) {cm.deleteH(1, "word");},
+ delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
+ delGroupAfter: function(cm) {cm.deleteH(1, "group");},
+ indentAuto: function(cm) {cm.indentSelection("smart");},
+ indentMore: function(cm) {cm.indentSelection("add");},
+ indentLess: function(cm) {cm.indentSelection("subtract");},
+ insertTab: function(cm) {cm.replaceSelection("\t");},
+ defaultTab: function(cm) {
+ if (cm.somethingSelected()) cm.indentSelection("add");
+ else cm.execCommand("insertTab");
+ },
+ transposeChars: function(cm) {
+ runInOp(cm, function() {
+ var ranges = cm.listSelections();
+ for (var i = 0; i < ranges.length; i++) {
+ var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
+ if (cur.ch > 0 && cur.ch < line.length - 1)
+ cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
+ Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
+ }
+ });
+ },
+ newlineAndIndent: function(cm) {
+ runInOp(cm, function() {
+ var len = cm.listSelections().length;
+ for (var i = 0; i < len; i++) {
+ var range = cm.listSelections()[i];
+ cm.replaceRange("\n", range.anchor, range.head, "+input");
+ cm.indentLine(range.from().line + 1, null, true);
+ ensureCursorVisible(cm);
+ }
+ });
+ },
+ toggleOverwrite: function(cm) {cm.toggleOverwrite();}
+ };
+
+ // STANDARD KEYMAPS
+
+ var keyMap = CodeMirror.keyMap = {};
+ keyMap.basic = {
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
+ "Tab": "defaultTab", "Shift-Tab": "indentAuto",
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
+ "Esc": "singleSelection"
+ };
+ // Note that the save and find-related commands aren't defined by
+ // default. User code or addons can define them. Unknown commands
+ // are simply ignored.
+ keyMap.pcDefault = {
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
+ "Ctrl-Home": "goDocStart", "Ctrl-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
+ "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
+ "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
+ "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
+ fallthrough: "basic"
+ };
+ keyMap.macDefault = {
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
+ "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
+ "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
+ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
+ "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection",
+ fallthrough: ["basic", "emacsy"]
+ };
+ // Very basic readline/emacs-style bindings, which are standard on Mac.
+ keyMap.emacsy = {
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
+ };
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
+
+ // KEYMAP DISPATCH
+
+ function getKeyMap(val) {
+ if (typeof val == "string") return keyMap[val];
+ else return val;
+ }
+
+ // Given an array of keymaps and a key name, call handle on any
+ // bindings found, until that returns a truthy value, at which point
+ // we consider the key handled. Implements things like binding a key
+ // to false stopping further handling and keymap fallthrough.
+ var lookupKey = CodeMirror.lookupKey = function(name, maps, handle) {
+ function lookup(map) {
+ map = getKeyMap(map);
+ var found = map[name];
+ if (found === false) return "stop";
+ if (found != null && handle(found)) return true;
+ if (map.nofallthrough) return "stop";
+
+ var fallthrough = map.fallthrough;
+ if (fallthrough == null) return false;
+ if (Object.prototype.toString.call(fallthrough) != "[object Array]")
+ return lookup(fallthrough);
+ for (var i = 0; i < fallthrough.length; ++i) {
+ var done = lookup(fallthrough[i]);
+ if (done) return done;
+ }
+ return false;
+ }
+
+ for (var i = 0; i < maps.length; ++i) {
+ var done = lookup(maps[i]);
+ if (done) return done != "stop";
+ }
+ };
+
+ // Modifier key presses don't count as 'real' key presses for the
+ // purpose of keymap fallthrough.
+ var isModifierKey = CodeMirror.isModifierKey = function(event) {
+ var name = keyNames[event.keyCode];
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
+ };
+
+ // Look up the name of a key as indicated by an event object.
+ var keyName = CodeMirror.keyName = function(event, noShift) {
+ if (presto && event.keyCode == 34 && event["char"]) return false;
+ var name = keyNames[event.keyCode];
+ if (name == null || event.altGraphKey) return false;
+ if (event.altKey) name = "Alt-" + name;
+ if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
+ if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
+ if (!noShift && event.shiftKey) name = "Shift-" + name;
+ return name;
+ };
+
+ // FROMTEXTAREA
+
+ CodeMirror.fromTextArea = function(textarea, options) {
+ if (!options) options = {};
+ options.value = textarea.value;
+ if (!options.tabindex && textarea.tabindex)
+ options.tabindex = textarea.tabindex;
+ if (!options.placeholder && textarea.placeholder)
+ options.placeholder = textarea.placeholder;
+ // Set autofocus to true if this textarea is focused, or if it has
+ // autofocus and no other element is focused.
+ if (options.autofocus == null) {
+ var hasFocus = activeElt();
+ options.autofocus = hasFocus == textarea ||
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body;
+ }
+
+ function save() {textarea.value = cm.getValue();}
+ if (textarea.form) {
+ on(textarea.form, "submit", save);
+ // Deplorable hack to make the submit method do the right thing.
+ if (!options.leaveSubmitMethodAlone) {
+ var form = textarea.form, realSubmit = form.submit;
+ try {
+ var wrappedSubmit = form.submit = function() {
+ save();
+ form.submit = realSubmit;
+ form.submit();
+ form.submit = wrappedSubmit;
+ };
+ } catch(e) {}
+ }
+ }
+
+ textarea.style.display = "none";
+ var cm = CodeMirror(function(node) {
+ textarea.parentNode.insertBefore(node, textarea.nextSibling);
+ }, options);
+ cm.save = save;
+ cm.getTextArea = function() { return textarea; };
+ cm.toTextArea = function() {
+ save();
+ textarea.parentNode.removeChild(cm.getWrapperElement());
+ textarea.style.display = "";
+ if (textarea.form) {
+ off(textarea.form, "submit", save);
+ if (typeof textarea.form.submit == "function")
+ textarea.form.submit = realSubmit;
+ }
+ };
+ return cm;
+ };
+
+ // STRING STREAM
+
+ // Fed to the mode parsers, provides helper functions to make
+ // parsers more succinct.
+
+ var StringStream = CodeMirror.StringStream = function(string, tabSize) {
+ this.pos = this.start = 0;
+ this.string = string;
+ this.tabSize = tabSize || 8;
+ this.lastColumnPos = this.lastColumnValue = 0;
+ this.lineStart = 0;
+ };
+
+ StringStream.prototype = {
+ eol: function() {return this.pos >= this.string.length;},
+ sol: function() {return this.pos == this.lineStart;},
+ peek: function() {return this.string.charAt(this.pos) || undefined;},
+ next: function() {
+ if (this.pos < this.string.length)
+ return this.string.charAt(this.pos++);
+ },
+ eat: function(match) {
+ var ch = this.string.charAt(this.pos);
+ if (typeof match == "string") var ok = ch == match;
+ else var ok = ch && (match.test ? match.test(ch) : match(ch));
+ if (ok) {++this.pos; return ch;}
+ },
+ eatWhile: function(match) {
+ var start = this.pos;
+ while (this.eat(match)){}
+ return this.pos > start;
+ },
+ eatSpace: function() {
+ var start = this.pos;
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
+ return this.pos > start;
+ },
+ skipToEnd: function() {this.pos = this.string.length;},
+ skipTo: function(ch) {
+ var found = this.string.indexOf(ch, this.pos);
+ if (found > -1) {this.pos = found; return true;}
+ },
+ backUp: function(n) {this.pos -= n;},
+ column: function() {
+ if (this.lastColumnPos < this.start) {
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
+ this.lastColumnPos = this.start;
+ }
+ return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
+ },
+ indentation: function() {
+ return countColumn(this.string, null, this.tabSize) -
+ (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
+ },
+ match: function(pattern, consume, caseInsensitive) {
+ if (typeof pattern == "string") {
+ var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
+ var substr = this.string.substr(this.pos, pattern.length);
+ if (cased(substr) == cased(pattern)) {
+ if (consume !== false) this.pos += pattern.length;
+ return true;
+ }
+ } else {
+ var match = this.string.slice(this.pos).match(pattern);
+ if (match && match.index > 0) return null;
+ if (match && consume !== false) this.pos += match[0].length;
+ return match;
+ }
+ },
+ current: function(){return this.string.slice(this.start, this.pos);},
+ hideFirstChars: function(n, inner) {
+ this.lineStart += n;
+ try { return inner(); }
+ finally { this.lineStart -= n; }
+ }
+ };
+
+ // TEXTMARKERS
+
+ // Created with markText and setBookmark methods. A TextMarker is a
+ // handle that can be used to clear or find a marked position in the
+ // document. Line objects hold arrays (markedSpans) containing
+ // {from, to, marker} object pointing to such marker objects, and
+ // indicating that such a marker is present on that line. Multiple
+ // lines may point to the same marker when it spans across lines.
+ // The spans will have null for their from/to properties when the
+ // marker continues beyond the start/end of the line. Markers have
+ // links back to the lines they currently touch.
+
+ var TextMarker = CodeMirror.TextMarker = function(doc, type) {
+ this.lines = [];
+ this.type = type;
+ this.doc = doc;
+ };
+ eventMixin(TextMarker);
+
+ // Clear the marker.
+ TextMarker.prototype.clear = function() {
+ if (this.explicitlyCleared) return;
+ var cm = this.doc.cm, withOp = cm && !cm.curOp;
+ if (withOp) startOperation(cm);
+ if (hasHandler(this, "clear")) {
+ var found = this.find();
+ if (found) signalLater(this, "clear", found.from, found.to);
+ }
+ var min = null, max = null;
+ for (var i = 0; i < this.lines.length; ++i) {
+ var line = this.lines[i];
+ var span = getMarkedSpanFor(line.markedSpans, this);
+ if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text");
+ else if (cm) {
+ if (span.to != null) max = lineNo(line);
+ if (span.from != null) min = lineNo(line);
+ }
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span);
+ if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
+ updateLineHeight(line, textHeight(cm.display));
+ }
+ if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
+ var visual = visualLine(this.lines[i]), len = lineLength(visual);
+ if (len > cm.display.maxLineLength) {
+ cm.display.maxLine = visual;
+ cm.display.maxLineLength = len;
+ cm.display.maxLineChanged = true;
+ }
+ }
+
+ if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);
+ this.lines.length = 0;
+ this.explicitlyCleared = true;
+ if (this.atomic && this.doc.cantEdit) {
+ this.doc.cantEdit = false;
+ if (cm) reCheckSelection(cm.doc);
+ }
+ if (cm) signalLater(cm, "markerCleared", cm, this);
+ if (withOp) endOperation(cm);
+ };
+
+ // Find the position of the marker in the document. Returns a {from,
+ // to} object by default. Side can be passed to get a specific side
+ // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
+ // Pos objects returned contain a line object, rather than a line
+ // number (used to prevent looking up the same line twice).
+ TextMarker.prototype.find = function(side, lineObj) {
+ if (side == null && this.type == "bookmark") side = 1;
+ var from, to;
+ for (var i = 0; i < this.lines.length; ++i) {
+ var line = this.lines[i];
+ var span = getMarkedSpanFor(line.markedSpans, this);
+ if (span.from != null) {
+ from = Pos(lineObj ? line : lineNo(line), span.from);
+ if (side == -1) return from;
+ }
+ if (span.to != null) {
+ to = Pos(lineObj ? line : lineNo(line), span.to);
+ if (side == 1) return to;
+ }
+ }
+ return from && {from: from, to: to};
+ };
+
+ // Signals that the marker's widget changed, and surrounding layout
+ // should be recomputed.
+ TextMarker.prototype.changed = function() {
+ var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
+ if (!pos || !cm) return;
+ runInOp(cm, function() {
+ var line = pos.line, lineN = lineNo(pos.line);
+ var view = findViewForLine(cm, lineN);
+ if (view) {
+ clearLineMeasurementCacheFor(view);
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
+ }
+ cm.curOp.updateMaxLine = true;
+ if (!lineIsHidden(widget.doc, line) && widget.height != null) {
+ var oldHeight = widget.height;
+ widget.height = null;
+ var dHeight = widgetHeight(widget) - oldHeight;
+ if (dHeight)
+ updateLineHeight(line, line.height + dHeight);
+ }
+ });
+ };
+
+ TextMarker.prototype.attachLine = function(line) {
+ if (!this.lines.length && this.doc.cm) {
+ var op = this.doc.cm.curOp;
+ if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
+ (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
+ }
+ this.lines.push(line);
+ };
+ TextMarker.prototype.detachLine = function(line) {
+ this.lines.splice(indexOf(this.lines, line), 1);
+ if (!this.lines.length && this.doc.cm) {
+ var op = this.doc.cm.curOp;
+ (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
+ }
+ };
+
+ // Collapsed markers have unique ids, in order to be able to order
+ // them, which is needed for uniquely determining an outer marker
+ // when they overlap (they may nest, but not partially overlap).
+ var nextMarkerId = 0;
+
+ // Create a marker, wire it up to the right lines, and
+ function markText(doc, from, to, options, type) {
+ // Shared markers (across linked documents) are handled separately
+ // (markTextShared will call out to this again, once per
+ // document).
+ if (options && options.shared) return markTextShared(doc, from, to, options, type);
+ // Ensure we are in an operation.
+ if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
+
+ var marker = new TextMarker(doc, type), diff = cmp(from, to);
+ if (options) copyObj(options, marker);
+ // Don't connect empty markers unless clearWhenEmpty is false
+ if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
+ return marker;
+ if (marker.replacedWith) {
+ // Showing up as a widget implies collapsed (widget replaces text)
+ marker.collapsed = true;
+ marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");
+ if (!options.handleMouseEvents) marker.widgetNode.ignoreEvents = true;
+ if (options.insertLeft) marker.widgetNode.insertLeft = true;
+ }
+ if (marker.collapsed) {
+ if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
+ from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
+ throw new Error("Inserting collapsed marker partially overlapping an existing one");
+ sawCollapsedSpans = true;
+ }
+
+ if (marker.addToHistory)
+ addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN);
+
+ var curLine = from.line, cm = doc.cm, updateMaxLine;
+ doc.iter(curLine, to.line + 1, function(line) {
+ if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
+ updateMaxLine = true;
+ if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);
+ addMarkedSpan(line, new MarkedSpan(marker,
+ curLine == from.line ? from.ch : null,
+ curLine == to.line ? to.ch : null));
+ ++curLine;
+ });
+ // lineIsHidden depends on the presence of the spans, so needs a second pass
+ if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
+ if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
+ });
+
+ if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
+
+ if (marker.readOnly) {
+ sawReadOnlySpans = true;
+ if (doc.history.done.length || doc.history.undone.length)
+ doc.clearHistory();
+ }
+ if (marker.collapsed) {
+ marker.id = ++nextMarkerId;
+ marker.atomic = true;
+ }
+ if (cm) {
+ // Sync editor state
+ if (updateMaxLine) cm.curOp.updateMaxLine = true;
+ if (marker.collapsed)
+ regChange(cm, from.line, to.line + 1);
+ else if (marker.className || marker.title || marker.startStyle || marker.endStyle)
+ for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
+ if (marker.atomic) reCheckSelection(cm.doc);
+ signalLater(cm, "markerAdded", cm, marker);
+ }
+ return marker;
+ }
+
+ // SHARED TEXTMARKERS
+
+ // A shared marker spans multiple linked documents. It is
+ // implemented as a meta-marker-object controlling multiple normal
+ // markers.
+ var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {
+ this.markers = markers;
+ this.primary = primary;
+ for (var i = 0, me = this; i < markers.length; ++i) {
+ markers[i].parent = this;
+ on(markers[i], "clear", function(){me.clear();});
+ }
+ };
+ eventMixin(SharedTextMarker);
+
+ SharedTextMarker.prototype.clear = function() {
+ if (this.explicitlyCleared) return;
+ this.explicitlyCleared = true;
+ for (var i = 0; i < this.markers.length; ++i)
+ this.markers[i].clear();
+ signalLater(this, "clear");
+ };
+ SharedTextMarker.prototype.find = function(side, lineObj) {
+ return this.primary.find(side, lineObj);
+ };
+
+ function markTextShared(doc, from, to, options, type) {
+ options = copyObj(options);
+ options.shared = false;
+ var markers = [markText(doc, from, to, options, type)], primary = markers[0];
+ var widget = options.widgetNode;
+ linkedDocs(doc, function(doc) {
+ if (widget) options.widgetNode = widget.cloneNode(true);
+ markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
+ for (var i = 0; i < doc.linked.length; ++i)
+ if (doc.linked[i].isParent) return;
+ primary = lst(markers);
+ });
+ return new SharedTextMarker(markers, primary);
+ }
+
+ // TEXTMARKER SPANS
+
+ function MarkedSpan(marker, from, to) {
+ this.marker = marker;
+ this.from = from; this.to = to;
+ }
+
+ // Search an array of spans for a span matching the given marker.
+ function getMarkedSpanFor(spans, marker) {
+ if (spans) for (var i = 0; i < spans.length; ++i) {
+ var span = spans[i];
+ if (span.marker == marker) return span;
+ }
+ }
+ // Remove a span from an array, returning undefined if no spans are
+ // left (we don't store arrays for lines without spans).
+ function removeMarkedSpan(spans, span) {
+ for (var r, i = 0; i < spans.length; ++i)
+ if (spans[i] != span) (r || (r = [])).push(spans[i]);
+ return r;
+ }
+ // Add a span to a line.
+ function addMarkedSpan(line, span) {
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
+ span.marker.attachLine(line);
+ }
+
+ // Used for the algorithm that adjusts markers for a change in the
+ // document. These functions cut an array of spans at a given
+ // character position, returning an array of remaining chunks (or
+ // undefined if nothing remains).
+ function markedSpansBefore(old, startCh, isInsert) {
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
+ var span = old[i], marker = span.marker;
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
+ if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
+ (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
+ }
+ }
+ return nw;
+ }
+ function markedSpansAfter(old, endCh, isInsert) {
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
+ var span = old[i], marker = span.marker;
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
+ if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
+ (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
+ span.to == null ? null : span.to - endCh));
+ }
+ }
+ return nw;
+ }
+
+ // Given a change object, compute the new set of marker spans that
+ // cover the line in which the change took place. Removes spans
+ // entirely within the change, reconnects spans belonging to the
+ // same marker that appear on both sides of the change, and cuts off
+ // spans partially within the change. Returns an array of span
+ // arrays with one element for each line in (after) the change.
+ function stretchSpansOverChange(doc, change) {
+ var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
+ var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
+ if (!oldFirst && !oldLast) return null;
+
+ var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
+ // Get the spans that 'stick out' on both sides
+ var first = markedSpansBefore(oldFirst, startCh, isInsert);
+ var last = markedSpansAfter(oldLast, endCh, isInsert);
+
+ // Next, merge those two ends
+ var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
+ if (first) {
+ // Fix up .to properties of first
+ for (var i = 0; i < first.length; ++i) {
+ var span = first[i];
+ if (span.to == null) {
+ var found = getMarkedSpanFor(last, span.marker);
+ if (!found) span.to = startCh;
+ else if (sameLine) span.to = found.to == null ? null : found.to + offset;
+ }
+ }
+ }
+ if (last) {
+ // Fix up .from in last (or move them into first in case of sameLine)
+ for (var i = 0; i < last.length; ++i) {
+ var span = last[i];
+ if (span.to != null) span.to += offset;
+ if (span.from == null) {
+ var found = getMarkedSpanFor(first, span.marker);
+ if (!found) {
+ span.from = offset;
+ if (sameLine) (first || (first = [])).push(span);
+ }
+ } else {
+ span.from += offset;
+ if (sameLine) (first || (first = [])).push(span);
+ }
+ }
+ }
+ // Make sure we didn't create any zero-length spans
+ if (first) first = clearEmptySpans(first);
+ if (last && last != first) last = clearEmptySpans(last);
+
+ var newMarkers = [first];
+ if (!sameLine) {
+ // Fill gap with whole-line-spans
+ var gap = change.text.length - 2, gapMarkers;
+ if (gap > 0 && first)
+ for (var i = 0; i < first.length; ++i)
+ if (first[i].to == null)
+ (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));
+ for (var i = 0; i < gap; ++i)
+ newMarkers.push(gapMarkers);
+ newMarkers.push(last);
+ }
+ return newMarkers;
+ }
+
+ // Remove spans that are empty and don't have a clearWhenEmpty
+ // option of false.
+ function clearEmptySpans(spans) {
+ for (var i = 0; i < spans.length; ++i) {
+ var span = spans[i];
+ if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
+ spans.splice(i--, 1);
+ }
+ if (!spans.length) return null;
+ return spans;
+ }
+
+ // Used for un/re-doing changes from the history. Combines the
+ // result of computing the existing spans with the set of spans that
+ // existed in the history (so that deleting around a span and then
+ // undoing brings back the span).
+ function mergeOldSpans(doc, change) {
+ var old = getOldSpans(doc, change);
+ var stretched = stretchSpansOverChange(doc, change);
+ if (!old) return stretched;
+ if (!stretched) return old;
+
+ for (var i = 0; i < old.length; ++i) {
+ var oldCur = old[i], stretchCur = stretched[i];
+ if (oldCur && stretchCur) {
+ spans: for (var j = 0; j < stretchCur.length; ++j) {
+ var span = stretchCur[j];
+ for (var k = 0; k < oldCur.length; ++k)
+ if (oldCur[k].marker == span.marker) continue spans;
+ oldCur.push(span);
+ }
+ } else if (stretchCur) {
+ old[i] = stretchCur;
+ }
+ }
+ return old;
+ }
+
+ // Used to 'clip' out readOnly ranges when making a change.
+ function removeReadOnlyRanges(doc, from, to) {
+ var markers = null;
+ doc.iter(from.line, to.line + 1, function(line) {
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
+ var mark = line.markedSpans[i].marker;
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
+ (markers || (markers = [])).push(mark);
+ }
+ });
+ if (!markers) return null;
+ var parts = [{from: from, to: to}];
+ for (var i = 0; i < markers.length; ++i) {
+ var mk = markers[i], m = mk.find(0);
+ for (var j = 0; j < parts.length; ++j) {
+ var p = parts[j];
+ if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;
+ var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
+ if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
+ newParts.push({from: p.from, to: m.from});
+ if (dto > 0 || !mk.inclusiveRight && !dto)
+ newParts.push({from: m.to, to: p.to});
+ parts.splice.apply(parts, newParts);
+ j += newParts.length - 1;
+ }
+ }
+ return parts;
+ }
+
+ // Connect or disconnect spans from a line.
+ function detachMarkedSpans(line) {
+ var spans = line.markedSpans;
+ if (!spans) return;
+ for (var i = 0; i < spans.length; ++i)
+ spans[i].marker.detachLine(line);
+ line.markedSpans = null;
+ }
+ function attachMarkedSpans(line, spans) {
+ if (!spans) return;
+ for (var i = 0; i < spans.length; ++i)
+ spans[i].marker.attachLine(line);
+ line.markedSpans = spans;
+ }
+
+ // Helpers used when computing which overlapping collapsed span
+ // counts as the larger one.
+ function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }
+ function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }
+
+ // Returns a number indicating which of two overlapping collapsed
+ // spans is larger (and thus includes the other). Falls back to
+ // comparing ids when the spans cover exactly the same range.
+ function compareCollapsedMarkers(a, b) {
+ var lenDiff = a.lines.length - b.lines.length;
+ if (lenDiff != 0) return lenDiff;
+ var aPos = a.find(), bPos = b.find();
+ var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
+ if (fromCmp) return -fromCmp;
+ var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
+ if (toCmp) return toCmp;
+ return b.id - a.id;
+ }
+
+ // Find out whether a line ends or starts in a collapsed span. If
+ // so, return the marker for that span.
+ function collapsedSpanAtSide(line, start) {
+ var sps = sawCollapsedSpans && line.markedSpans, found;
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
+ sp = sps[i];
+ if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
+ (!found || compareCollapsedMarkers(found, sp.marker) < 0))
+ found = sp.marker;
+ }
+ return found;
+ }
+ function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }
+ function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }
+
+ // Test whether there exists a collapsed span that partially
+ // overlaps (covers the start or end, but not both) of a new span.
+ // Such overlap is not allowed.
+ function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
+ var line = getLine(doc, lineNo);
+ var sps = sawCollapsedSpans && line.markedSpans;
+ if (sps) for (var i = 0; i < sps.length; ++i) {
+ var sp = sps[i];
+ if (!sp.marker.collapsed) continue;
+ var found = sp.marker.find(0);
+ var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
+ var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
+ if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
+ if (fromCmp <= 0 && (cmp(found.to, from) || extraRight(sp.marker) - extraLeft(marker)) > 0 ||
+ fromCmp >= 0 && (cmp(found.from, to) || extraLeft(sp.marker) - extraRight(marker)) < 0)
+ return true;
+ }
+ }
+
+ // A visual line is a line as drawn on the screen. Folding, for
+ // example, can cause multiple logical lines to appear on the same
+ // visual line. This finds the start of the visual line that the
+ // given line is part of (usually that is the line itself).
+ function visualLine(line) {
+ var merged;
+ while (merged = collapsedSpanAtStart(line))
+ line = merged.find(-1, true).line;
+ return line;
+ }
+
+ // Returns an array of logical lines that continue the visual line
+ // started by the argument, or undefined if there are no such lines.
+ function visualLineContinued(line) {
+ var merged, lines;
+ while (merged = collapsedSpanAtEnd(line)) {
+ line = merged.find(1, true).line;
+ (lines || (lines = [])).push(line);
+ }
+ return lines;
+ }
+
+ // Get the line number of the start of the visual line that the
+ // given line number is part of.
+ function visualLineNo(doc, lineN) {
+ var line = getLine(doc, lineN), vis = visualLine(line);
+ if (line == vis) return lineN;
+ return lineNo(vis);
+ }
+ // Get the line number of the start of the next visual line after
+ // the given line.
+ function visualLineEndNo(doc, lineN) {
+ if (lineN > doc.lastLine()) return lineN;
+ var line = getLine(doc, lineN), merged;
+ if (!lineIsHidden(doc, line)) return lineN;
+ while (merged = collapsedSpanAtEnd(line))
+ line = merged.find(1, true).line;
+ return lineNo(line) + 1;
+ }
+
+ // Compute whether a line is hidden. Lines count as hidden when they
+ // are part of a visual line that starts with another line, or when
+ // they are entirely covered by collapsed, non-widget span.
+ function lineIsHidden(doc, line) {
+ var sps = sawCollapsedSpans && line.markedSpans;
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
+ sp = sps[i];
+ if (!sp.marker.collapsed) continue;
+ if (sp.from == null) return true;
+ if (sp.marker.widgetNode) continue;
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
+ return true;
+ }
+ }
+ function lineIsHiddenInner(doc, line, span) {
+ if (span.to == null) {
+ var end = span.marker.find(1, true);
+ return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));
+ }
+ if (span.marker.inclusiveRight && span.to == line.text.length)
+ return true;
+ for (var sp, i = 0; i < line.markedSpans.length; ++i) {
+ sp = line.markedSpans[i];
+ if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
+ (sp.to == null || sp.to != span.from) &&
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
+ lineIsHiddenInner(doc, line, sp)) return true;
+ }
+ }
+
+ // LINE WIDGETS
+
+ // Line widgets are block elements displayed above or below a line.
+
+ var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
+ if (options) for (var opt in options) if (options.hasOwnProperty(opt))
+ this[opt] = options[opt];
+ this.cm = cm;
+ this.node = node;
+ };
+ eventMixin(LineWidget);
+
+ function adjustScrollWhenAboveVisible(cm, line, diff) {
+ if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
+ addToScrollPos(cm, null, diff);
+ }
+
+ LineWidget.prototype.clear = function() {
+ var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
+ if (no == null || !ws) return;
+ for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
+ if (!ws.length) line.widgets = null;
+ var height = widgetHeight(this);
+ runInOp(cm, function() {
+ adjustScrollWhenAboveVisible(cm, line, -height);
+ regLineChange(cm, no, "widget");
+ updateLineHeight(line, Math.max(0, line.height - height));
+ });
+ };
+ LineWidget.prototype.changed = function() {
+ var oldH = this.height, cm = this.cm, line = this.line;
+ this.height = null;
+ var diff = widgetHeight(this) - oldH;
+ if (!diff) return;
+ runInOp(cm, function() {
+ cm.curOp.forceUpdate = true;
+ adjustScrollWhenAboveVisible(cm, line, diff);
+ updateLineHeight(line, line.height + diff);
+ });
+ };
+
+ function widgetHeight(widget) {
+ if (widget.height != null) return widget.height;
+ if (!contains(document.body, widget.node))
+ removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
+ return widget.height = widget.node.offsetHeight;
+ }
+
+ function addLineWidget(cm, handle, node, options) {
+ var widget = new LineWidget(cm, node, options);
+ if (widget.noHScroll) cm.display.alignWidgets = true;
+ changeLine(cm, handle, "widget", function(line) {
+ var widgets = line.widgets || (line.widgets = []);
+ if (widget.insertAt == null) widgets.push(widget);
+ else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
+ widget.line = line;
+ if (!lineIsHidden(cm.doc, line)) {
+ var aboveVisible = heightAtLine(line) < cm.doc.scrollTop;
+ updateLineHeight(line, line.height + widgetHeight(widget));
+ if (aboveVisible) addToScrollPos(cm, null, widget.height);
+ cm.curOp.forceUpdate = true;
+ }
+ return true;
+ });
+ return widget;
+ }
+
+ // LINE DATA STRUCTURE
+
+ // Line objects. These hold state related to a line, including
+ // highlighting info (the styles array).
+ var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
+ this.text = text;
+ attachMarkedSpans(this, markedSpans);
+ this.height = estimateHeight ? estimateHeight(this) : 1;
+ };
+ eventMixin(Line);
+ Line.prototype.lineNo = function() { return lineNo(this); };
+
+ // Change the content (text, markers) of a line. Automatically
+ // invalidates cached information and tries to re-estimate the
+ // line's height.
+ function updateLine(line, text, markedSpans, estimateHeight) {
+ line.text = text;
+ if (line.stateAfter) line.stateAfter = null;
+ if (line.styles) line.styles = null;
+ if (line.order != null) line.order = null;
+ detachMarkedSpans(line);
+ attachMarkedSpans(line, markedSpans);
+ var estHeight = estimateHeight ? estimateHeight(line) : 1;
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
+ }
+
+ // Detach a line from the document tree and its markers.
+ function cleanUpLine(line) {
+ line.parent = null;
+ detachMarkedSpans(line);
+ }
+
+ // Run the given mode's parser over a line, calling f for each token.
+ function runMode(cm, text, mode, state, f, forceToEnd) {
+ var flattenSpans = mode.flattenSpans;
+ if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
+ var curStart = 0, curStyle = null;
+ var stream = new StringStream(text, cm.options.tabSize), style;
+ if (text == "" && mode.blankLine) mode.blankLine(state);
+ while (!stream.eol()) {
+ if (stream.pos > cm.options.maxHighlightLength) {
+ flattenSpans = false;
+ if (forceToEnd) processLine(cm, text, state, stream.pos);
+ stream.pos = text.length;
+ style = null;
+ } else {
+ style = mode.token(stream, state);
+ }
+ if (cm.options.addModeClass) {
+ var mName = CodeMirror.innerMode(mode, state).mode.name;
+ if (mName) style = "m-" + (style ? mName + " " + style : mName);
+ }
+ if (!flattenSpans || curStyle != style) {
+ if (curStart < stream.start) f(stream.start, curStyle);
+ curStart = stream.start; curStyle = style;
+ }
+ stream.start = stream.pos;
+ }
+ while (curStart < stream.pos) {
+ // Webkit seems to refuse to render text nodes longer than 57444 characters
+ var pos = Math.min(stream.pos, curStart + 50000);
+ f(pos, curStyle);
+ curStart = pos;
+ }
+ }
+
+ // Compute a style array (an array starting with a mode generation
+ // -- for invalidation -- followed by pairs of end positions and
+ // style strings), which is used to highlight the tokens on the
+ // line.
+ function highlightLine(cm, line, state, forceToEnd) {
+ // A styles array always starts with a number identifying the
+ // mode/overlays that it is based on (for easy invalidation).
+ var st = [cm.state.modeGen];
+ // Compute the base array of styles
+ runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
+ st.push(end, style);
+ }, forceToEnd);
+
+ // Run overlays, adjust style array.
+ for (var o = 0; o < cm.state.overlays.length; ++o) {
+ var overlay = cm.state.overlays[o], i = 1, at = 0;
+ runMode(cm, line.text, overlay.mode, true, function(end, style) {
+ var start = i;
+ // Ensure there's a token end at the current position, and that i points at it
+ while (at < end) {
+ var i_end = st[i];
+ if (i_end > end)
+ st.splice(i, 1, end, st[i+1], i_end);
+ i += 2;
+ at = Math.min(end, i_end);
+ }
+ if (!style) return;
+ if (overlay.opaque) {
+ st.splice(start, i - start, end, style);
+ i = start + 2;
+ } else {
+ for (; start < i; start += 2) {
+ var cur = st[start+1];
+ st[start+1] = cur ? cur + " " + style : style;
+ }
+ }
+ });
+ }
+
+ return st;
+ }
+
+ function getLineStyles(cm, line) {
+ if (!line.styles || line.styles[0] != cm.state.modeGen)
+ line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
+ return line.styles;
+ }
+
+ // Lightweight form of highlight -- proceed over this line and
+ // update state, but don't save a style array. Used for lines that
+ // aren't currently visible.
+ function processLine(cm, text, state, startAt) {
+ var mode = cm.doc.mode;
+ var stream = new StringStream(text, cm.options.tabSize);
+ stream.start = stream.pos = startAt || 0;
+ if (text == "" && mode.blankLine) mode.blankLine(state);
+ while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
+ mode.token(stream, state);
+ stream.start = stream.pos;
+ }
+ }
+
+ // Convert a style as returned by a mode (either null, or a string
+ // containing one or more styles) to a CSS style. This is cached,
+ // and also looks for line-wide styles.
+ var styleToClassCache = {}, styleToClassCacheWithMode = {};
+ function interpretTokenStyle(style, builder) {
+ if (!style) return null;
+ for (;;) {
+ var lineClass = style.match(/(?:^|\s+)line-(background-)?(\S+)/);
+ if (!lineClass) break;
+ style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length);
+ var prop = lineClass[1] ? "bgClass" : "textClass";
+ if (builder[prop] == null)
+ builder[prop] = lineClass[2];
+ else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(builder[prop]))
+ builder[prop] += " " + lineClass[2];
+ }
+ if (/^\s*$/.test(style)) return null;
+ var cache = builder.cm.options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
+ return cache[style] ||
+ (cache[style] = style.replace(/\S+/g, "cm-$&"));
+ }
+
+ // Render the DOM representation of the text of a line. Also builds
+ // up a 'line map', which points at the DOM nodes that represent
+ // specific stretches of text, and is used by the measuring code.
+ // The returned object contains the DOM node, this map, and
+ // information about line-wide styles that were set by the mode.
+ function buildLineContent(cm, lineView) {
+ // The padding-right forces the element to have a 'border', which
+ // is needed on Webkit to be able to get line-level bounding
+ // rectangles for it (in measureChar).
+ var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
+ var builder = {pre: elt("pre", [content]), content: content, col: 0, pos: 0, cm: cm};
+ lineView.measure = {};
+
+ // Iterate over the logical lines that make up this visual line.
+ for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
+ var line = i ? lineView.rest[i - 1] : lineView.line, order;
+ builder.pos = 0;
+ builder.addToken = buildToken;
+ // Optionally wire in some hacks into the token-rendering
+ // algorithm, to deal with browser quirks.
+ if ((ie || webkit) && cm.getOption("lineWrapping"))
+ builder.addToken = buildTokenSplitSpaces(builder.addToken);
+ if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
+ builder.addToken = buildTokenBadBidi(builder.addToken, order);
+ builder.map = [];
+ insertLineContent(line, builder, getLineStyles(cm, line));
+
+ // Ensure at least a single node is present, for measuring.
+ if (builder.map.length == 0)
+ builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));
+
+ // Store the map and a cache object for the current logical line
+ if (i == 0) {
+ lineView.measure.map = builder.map;
+ lineView.measure.cache = {};
+ } else {
+ (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);
+ (lineView.measure.caches || (lineView.measure.caches = [])).push({});
+ }
+ }
+
+ signal(cm, "renderLine", cm, lineView.line, builder.pre);
+ return builder;
+ }
+
+ function defaultSpecialCharPlaceholder(ch) {
+ var token = elt("span", "\u2022", "cm-invalidchar");
+ token.title = "\\u" + ch.charCodeAt(0).toString(16);
+ return token;
+ }
+
+ // Build up the DOM representation for a single token, and add it to
+ // the line map. Takes care to render special characters separately.
+ function buildToken(builder, text, style, startStyle, endStyle, title) {
+ if (!text) return;
+ var special = builder.cm.options.specialChars, mustWrap = false;
+ if (!special.test(text)) {
+ builder.col += text.length;
+ var content = document.createTextNode(text);
+ builder.map.push(builder.pos, builder.pos + text.length, content);
+ if (ie_upto8) mustWrap = true;
+ builder.pos += text.length;
+ } else {
+ var content = document.createDocumentFragment(), pos = 0;
+ while (true) {
+ special.lastIndex = pos;
+ var m = special.exec(text);
+ var skipped = m ? m.index - pos : text.length - pos;
+ if (skipped) {
+ var txt = document.createTextNode(text.slice(pos, pos + skipped));
+ if (ie_upto8) content.appendChild(elt("span", [txt]));
+ else content.appendChild(txt);
+ builder.map.push(builder.pos, builder.pos + skipped, txt);
+ builder.col += skipped;
+ builder.pos += skipped;
+ }
+ if (!m) break;
+ pos += skipped + 1;
+ if (m[0] == "\t") {
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
+ var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
+ builder.col += tabWidth;
+ } else {
+ var txt = builder.cm.options.specialCharPlaceholder(m[0]);
+ if (ie_upto8) content.appendChild(elt("span", [txt]));
+ else content.appendChild(txt);
+ builder.col += 1;
+ }
+ builder.map.push(builder.pos, builder.pos + 1, txt);
+ builder.pos++;
+ }
+ }
+ if (style || startStyle || endStyle || mustWrap) {
+ var fullStyle = style || "";
+ if (startStyle) fullStyle += startStyle;
+ if (endStyle) fullStyle += endStyle;
+ var token = elt("span", [content], fullStyle);
+ if (title) token.title = title;
+ return builder.content.appendChild(token);
+ }
+ builder.content.appendChild(content);
+ }
+
+ function buildTokenSplitSpaces(inner) {
+ function split(old) {
+ var out = " ";
+ for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
+ out += " ";
+ return out;
+ }
+ return function(builder, text, style, startStyle, endStyle, title) {
+ inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
+ };
+ }
+
+ // Work around nonsense dimensions being reported for stretches of
+ // right-to-left text.
+ function buildTokenBadBidi(inner, order) {
+ return function(builder, text, style, startStyle, endStyle, title) {
+ style = style ? style + " cm-force-border" : "cm-force-border";
+ var start = builder.pos, end = start + text.length;
+ for (;;) {
+ // Find the part that overlaps with the start of this text
+ for (var i = 0; i < order.length; i++) {
+ var part = order[i];
+ if (part.to > start && part.from <= start) break;
+ }
+ if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title);
+ inner(builder, text.slice(0, part.to - start), style, startStyle, null, title);
+ startStyle = null;
+ text = text.slice(part.to - start);
+ start = part.to;
+ }
+ };
+ }
+
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
+ var widget = !ignoreWidget && marker.widgetNode;
+ if (widget) {
+ builder.map.push(builder.pos, builder.pos + size, widget);
+ builder.content.appendChild(widget);
+ }
+ builder.pos += size;
+ }
+
+ // Outputs a number of spans to make up a line, taking highlighting
+ // and marked text into account.
+ function insertLineContent(line, builder, styles) {
+ var spans = line.markedSpans, allText = line.text, at = 0;
+ if (!spans) {
+ for (var i = 1; i < styles.length; i+=2)
+ builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder));
+ return;
+ }
+
+ var len = allText.length, pos = 0, i = 1, text = "", style;
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
+ for (;;) {
+ if (nextChange == pos) { // Update current marker set
+ spanStyle = spanEndStyle = spanStartStyle = title = "";
+ collapsed = null; nextChange = Infinity;
+ var foundBookmarks = [];
+ for (var j = 0; j < spans.length; ++j) {
+ var sp = spans[j], m = sp.marker;
+ if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
+ if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
+ if (m.className) spanStyle += " " + m.className;
+ if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
+ if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
+ if (m.title && !title) title = m.title;
+ if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
+ collapsed = sp;
+ } else if (sp.from > pos && nextChange > sp.from) {
+ nextChange = sp.from;
+ }
+ if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);
+ }
+ if (collapsed && (collapsed.from || 0) == pos) {
+ buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
+ collapsed.marker, collapsed.from == null);
+ if (collapsed.to == null) return;
+ }
+ if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
+ buildCollapsedSpan(builder, 0, foundBookmarks[j]);
+ }
+ if (pos >= len) break;
+
+ var upto = Math.min(len, nextChange);
+ while (true) {
+ if (text) {
+ var end = pos + text.length;
+ if (!collapsed) {
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text;
+ builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
+ }
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
+ pos = end;
+ spanStartStyle = "";
+ }
+ text = allText.slice(at, at = styles[i++]);
+ style = interpretTokenStyle(styles[i++], builder);
+ }
+ }
+ }
+
+ // DOCUMENT DATA STRUCTURE
+
+ // By default, updates that start and end at the beginning of a line
+ // are treated specially, in order to make the association of line
+ // widgets and marker elements with the text behave more intuitive.
+ function isWholeLineUpdate(doc, change) {
+ return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
+ (!doc.cm || doc.cm.options.wholeLineUpdateBefore);
+ }
+
+ // Perform a change on the document data structure.
+ function updateDoc(doc, change, markedSpans, estimateHeight) {
+ function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
+ function update(line, text, spans) {
+ updateLine(line, text, spans, estimateHeight);
+ signalLater(line, "change", line, change);
+ }
+
+ var from = change.from, to = change.to, text = change.text;
+ var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
+ var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
+
+ // Adjust the line structure
+ if (isWholeLineUpdate(doc, change)) {
+ // This is a whole-line replace. Treated specially to make
+ // sure line objects move the way they are supposed to.
+ for (var i = 0, added = []; i < text.length - 1; ++i)
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
+ update(lastLine, lastLine.text, lastSpans);
+ if (nlines) doc.remove(from.line, nlines);
+ if (added.length) doc.insert(from.line, added);
+ } else if (firstLine == lastLine) {
+ if (text.length == 1) {
+ update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
+ } else {
+ for (var added = [], i = 1; i < text.length - 1; ++i)
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
+ added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
+ doc.insert(from.line + 1, added);
+ }
+ } else if (text.length == 1) {
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
+ doc.remove(from.line + 1, nlines);
+ } else {
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
+ update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
+ for (var i = 1, added = []; i < text.length - 1; ++i)
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
+ if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
+ doc.insert(from.line + 1, added);
+ }
+
+ signalLater(doc, "change", doc, change);
+ }
+
+ // The document is represented as a BTree consisting of leaves, with
+ // chunk of lines in them, and branches, with up to ten leaves or
+ // other branch nodes below them. The top node is always a branch
+ // node, and is the document object itself (meaning it has
+ // additional methods and properties).
+ //
+ // All nodes have parent links. The tree is used both to go from
+ // line numbers to line objects, and to go from objects to numbers.
+ // It also indexes by height, and is used to convert between height
+ // and line object, and to find the total height of the document.
+ //
+ // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
+
+ function LeafChunk(lines) {
+ this.lines = lines;
+ this.parent = null;
+ for (var i = 0, height = 0; i < lines.length; ++i) {
+ lines[i].parent = this;
+ height += lines[i].height;
+ }
+ this.height = height;
+ }
+
+ LeafChunk.prototype = {
+ chunkSize: function() { return this.lines.length; },
+ // Remove the n lines at offset 'at'.
+ removeInner: function(at, n) {
+ for (var i = at, e = at + n; i < e; ++i) {
+ var line = this.lines[i];
+ this.height -= line.height;
+ cleanUpLine(line);
+ signalLater(line, "delete");
+ }
+ this.lines.splice(at, n);
+ },
+ // Helper used to collapse a small branch into a single leaf.
+ collapse: function(lines) {
+ lines.push.apply(lines, this.lines);
+ },
+ // Insert the given array of lines at offset 'at', count them as
+ // having the given height.
+ insertInner: function(at, lines, height) {
+ this.height += height;
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
+ for (var i = 0; i < lines.length; ++i) lines[i].parent = this;
+ },
+ // Used to iterate over a part of the tree.
+ iterN: function(at, n, op) {
+ for (var e = at + n; at < e; ++at)
+ if (op(this.lines[at])) return true;
+ }
+ };
+
+ function BranchChunk(children) {
+ this.children = children;
+ var size = 0, height = 0;
+ for (var i = 0; i < children.length; ++i) {
+ var ch = children[i];
+ size += ch.chunkSize(); height += ch.height;
+ ch.parent = this;
+ }
+ this.size = size;
+ this.height = height;
+ this.parent = null;
+ }
+
+ BranchChunk.prototype = {
+ chunkSize: function() { return this.size; },
+ removeInner: function(at, n) {
+ this.size -= n;
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i], sz = child.chunkSize();
+ if (at < sz) {
+ var rm = Math.min(n, sz - at), oldHeight = child.height;
+ child.removeInner(at, rm);
+ this.height -= oldHeight - child.height;
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
+ if ((n -= rm) == 0) break;
+ at = 0;
+ } else at -= sz;
+ }
+ // If the result is smaller than 25 lines, ensure that it is a
+ // single leaf node.
+ if (this.size - n < 25 &&
+ (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
+ var lines = [];
+ this.collapse(lines);
+ this.children = [new LeafChunk(lines)];
+ this.children[0].parent = this;
+ }
+ },
+ collapse: function(lines) {
+ for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);
+ },
+ insertInner: function(at, lines, height) {
+ this.size += lines.length;
+ this.height += height;
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i], sz = child.chunkSize();
+ if (at <= sz) {
+ child.insertInner(at, lines, height);
+ if (child.lines && child.lines.length > 50) {
+ while (child.lines.length > 50) {
+ var spilled = child.lines.splice(child.lines.length - 25, 25);
+ var newleaf = new LeafChunk(spilled);
+ child.height -= newleaf.height;
+ this.children.splice(i + 1, 0, newleaf);
+ newleaf.parent = this;
+ }
+ this.maybeSpill();
+ }
+ break;
+ }
+ at -= sz;
+ }
+ },
+ // When a node has grown, check whether it should be split.
+ maybeSpill: function() {
+ if (this.children.length <= 10) return;
+ var me = this;
+ do {
+ var spilled = me.children.splice(me.children.length - 5, 5);
+ var sibling = new BranchChunk(spilled);
+ if (!me.parent) { // Become the parent node
+ var copy = new BranchChunk(me.children);
+ copy.parent = me;
+ me.children = [copy, sibling];
+ me = copy;
+ } else {
+ me.size -= sibling.size;
+ me.height -= sibling.height;
+ var myIndex = indexOf(me.parent.children, me);
+ me.parent.children.splice(myIndex + 1, 0, sibling);
+ }
+ sibling.parent = me.parent;
+ } while (me.children.length > 10);
+ me.parent.maybeSpill();
+ },
+ iterN: function(at, n, op) {
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i], sz = child.chunkSize();
+ if (at < sz) {
+ var used = Math.min(n, sz - at);
+ if (child.iterN(at, used, op)) return true;
+ if ((n -= used) == 0) break;
+ at = 0;
+ } else at -= sz;
+ }
+ }
+ };
+
+ var nextDocId = 0;
+ var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
+ if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
+ if (firstLine == null) firstLine = 0;
+
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
+ this.first = firstLine;
+ this.scrollTop = this.scrollLeft = 0;
+ this.cantEdit = false;
+ this.cleanGeneration = 1;
+ this.frontier = firstLine;
+ var start = Pos(firstLine, 0);
+ this.sel = simpleSelection(start);
+ this.history = new History(null);
+ this.id = ++nextDocId;
+ this.modeOption = mode;
+
+ if (typeof text == "string") text = splitLines(text);
+ updateDoc(this, {from: start, to: start, text: text});
+ setSelection(this, simpleSelection(start), sel_dontScroll);
+ };
+
+ Doc.prototype = createObj(BranchChunk.prototype, {
+ constructor: Doc,
+ // Iterate over the document. Supports two forms -- with only one
+ // argument, it calls that for each line in the document. With
+ // three, it iterates over the range given by the first two (with
+ // the second being non-inclusive).
+ iter: function(from, to, op) {
+ if (op) this.iterN(from - this.first, to - from, op);
+ else this.iterN(this.first, this.first + this.size, from);
+ },
+
+ // Non-public interface for adding and removing lines.
+ insert: function(at, lines) {
+ var height = 0;
+ for (var i = 0; i < lines.length; ++i) height += lines[i].height;
+ this.insertInner(at - this.first, lines, height);
+ },
+ remove: function(at, n) { this.removeInner(at - this.first, n); },
+
+ // From here, the methods are part of the public interface. Most
+ // are also available from CodeMirror (editor) instances.
+
+ getValue: function(lineSep) {
+ var lines = getLines(this, this.first, this.first + this.size);
+ if (lineSep === false) return lines;
+ return lines.join(lineSep || "\n");
+ },
+ setValue: docMethodOp(function(code) {
+ var top = Pos(this.first, 0), last = this.first + this.size - 1;
+ makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
+ text: splitLines(code), origin: "setValue"}, true);
+ setSelection(this, simpleSelection(top));
+ }),
+ replaceRange: function(code, from, to, origin) {
+ from = clipPos(this, from);
+ to = to ? clipPos(this, to) : from;
+ replaceRange(this, code, from, to, origin);
+ },
+ getRange: function(from, to, lineSep) {
+ var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
+ if (lineSep === false) return lines;
+ return lines.join(lineSep || "\n");
+ },
+
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
+
+ getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
+ getLineNumber: function(line) {return lineNo(line);},
+
+ getLineHandleVisualStart: function(line) {
+ if (typeof line == "number") line = getLine(this, line);
+ return visualLine(line);
+ },
+
+ lineCount: function() {return this.size;},
+ firstLine: function() {return this.first;},
+ lastLine: function() {return this.first + this.size - 1;},
+
+ clipPos: function(pos) {return clipPos(this, pos);},
+
+ getCursor: function(start) {
+ var range = this.sel.primary(), pos;
+ if (start == null || start == "head") pos = range.head;
+ else if (start == "anchor") pos = range.anchor;
+ else if (start == "end" || start == "to" || start === false) pos = range.to();
+ else pos = range.from();
+ return pos;
+ },
+ listSelections: function() { return this.sel.ranges; },
+ somethingSelected: function() {return this.sel.somethingSelected();},
+
+ setCursor: docMethodOp(function(line, ch, options) {
+ setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
+ }),
+ setSelection: docMethodOp(function(anchor, head, options) {
+ setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
+ }),
+ extendSelection: docMethodOp(function(head, other, options) {
+ extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
+ }),
+ extendSelections: docMethodOp(function(heads, options) {
+ extendSelections(this, clipPosArray(this, heads, options));
+ }),
+ extendSelectionsBy: docMethodOp(function(f, options) {
+ extendSelections(this, map(this.sel.ranges, f), options);
+ }),
+ setSelections: docMethodOp(function(ranges, primary, options) {
+ if (!ranges.length) return;
+ for (var i = 0, out = []; i < ranges.length; i++)
+ out[i] = new Range(clipPos(this, ranges[i].anchor),
+ clipPos(this, ranges[i].head));
+ if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);
+ setSelection(this, normalizeSelection(out, primary), options);
+ }),
+ addSelection: docMethodOp(function(anchor, head, options) {
+ var ranges = this.sel.ranges.slice(0);
+ ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
+ setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);
+ }),
+
+ getSelection: function(lineSep) {
+ var ranges = this.sel.ranges, lines;
+ for (var i = 0; i < ranges.length; i++) {
+ var sel = getBetween(this, ranges[i].from(), ranges[i].to());
+ lines = lines ? lines.concat(sel) : sel;
+ }
+ if (lineSep === false) return lines;
+ else return lines.join(lineSep || "\n");
+ },
+ getSelections: function(lineSep) {
+ var parts = [], ranges = this.sel.ranges;
+ for (var i = 0; i < ranges.length; i++) {
+ var sel = getBetween(this, ranges[i].from(), ranges[i].to());
+ if (lineSep !== false) sel = sel.join(lineSep || "\n");
+ parts[i] = sel;
+ }
+ return parts;
+ },
+ replaceSelection: docMethodOp(function(code, collapse, origin) {
+ var dup = [];
+ for (var i = 0; i < this.sel.ranges.length; i++)
+ dup[i] = code;
+ this.replaceSelections(dup, collapse, origin || "+input");
+ }),
+ replaceSelections: function(code, collapse, origin) {
+ var changes = [], sel = this.sel;
+ for (var i = 0; i < sel.ranges.length; i++) {
+ var range = sel.ranges[i];
+ changes[i] = {from: range.from(), to: range.to(), text: splitLines(code[i]), origin: origin};
+ }
+ var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
+ for (var i = changes.length - 1; i >= 0; i--)
+ makeChange(this, changes[i]);
+ if (newSel) setSelectionReplaceHistory(this, newSel);
+ else if (this.cm) ensureCursorVisible(this.cm);
+ },
+ undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
+ redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
+ undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
+ redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
+
+ setExtending: function(val) {this.extend = val;},
+ getExtending: function() {return this.extend;},
+
+ historySize: function() {
+ var hist = this.history, done = 0, undone = 0;
+ for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;
+ for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;
+ return {undo: done, redo: undone};
+ },
+ clearHistory: function() {this.history = new History(this.history.maxGeneration);},
+
+ markClean: function() {
+ this.cleanGeneration = this.changeGeneration(true);
+ },
+ changeGeneration: function(forceSplit) {
+ if (forceSplit)
+ this.history.lastOp = this.history.lastOrigin = null;
+ return this.history.generation;
+ },
+ isClean: function (gen) {
+ return this.history.generation == (gen || this.cleanGeneration);
+ },
+
+ getHistory: function() {
+ return {done: copyHistoryArray(this.history.done),
+ undone: copyHistoryArray(this.history.undone)};
+ },
+ setHistory: function(histData) {
+ var hist = this.history = new History(this.history.maxGeneration);
+ hist.done = copyHistoryArray(histData.done.slice(0), null, true);
+ hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
+ },
+
+ markText: function(from, to, options) {
+ return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
+ },
+ setBookmark: function(pos, options) {
+ var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
+ insertLeft: options && options.insertLeft,
+ clearWhenEmpty: false, shared: options && options.shared};
+ pos = clipPos(this, pos);
+ return markText(this, pos, pos, realOpts, "bookmark");
+ },
+ findMarksAt: function(pos) {
+ pos = clipPos(this, pos);
+ var markers = [], spans = getLine(this, pos.line).markedSpans;
+ if (spans) for (var i = 0; i < spans.length; ++i) {
+ var span = spans[i];
+ if ((span.from == null || span.from <= pos.ch) &&
+ (span.to == null || span.to >= pos.ch))
+ markers.push(span.marker.parent || span.marker);
+ }
+ return markers;
+ },
+ findMarks: function(from, to) {
+ from = clipPos(this, from); to = clipPos(this, to);
+ var found = [], lineNo = from.line;
+ this.iter(from.line, to.line + 1, function(line) {
+ var spans = line.markedSpans;
+ if (spans) for (var i = 0; i < spans.length; i++) {
+ var span = spans[i];
+ if (!(lineNo == from.line && from.ch > span.to ||
+ span.from == null && lineNo != from.line||
+ lineNo == to.line && span.from > to.ch))
+ found.push(span.marker.parent || span.marker);
+ }
+ ++lineNo;
+ });
+ return found;
+ },
+ getAllMarks: function() {
+ var markers = [];
+ this.iter(function(line) {
+ var sps = line.markedSpans;
+ if (sps) for (var i = 0; i < sps.length; ++i)
+ if (sps[i].from != null) markers.push(sps[i].marker);
+ });
+ return markers;
+ },
+
+ posFromIndex: function(off) {
+ var ch, lineNo = this.first;
+ this.iter(function(line) {
+ var sz = line.text.length + 1;
+ if (sz > off) { ch = off; return true; }
+ off -= sz;
+ ++lineNo;
+ });
+ return clipPos(this, Pos(lineNo, ch));
+ },
+ indexFromPos: function (coords) {
+ coords = clipPos(this, coords);
+ var index = coords.ch;
+ if (coords.line < this.first || coords.ch < 0) return 0;
+ this.iter(this.first, coords.line, function (line) {
+ index += line.text.length + 1;
+ });
+ return index;
+ },
+
+ copy: function(copyHistory) {
+ var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
+ doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
+ doc.sel = this.sel;
+ doc.extend = false;
+ if (copyHistory) {
+ doc.history.undoDepth = this.history.undoDepth;
+ doc.setHistory(this.getHistory());
+ }
+ return doc;
+ },
+
+ linkedDoc: function(options) {
+ if (!options) options = {};
+ var from = this.first, to = this.first + this.size;
+ if (options.from != null && options.from > from) from = options.from;
+ if (options.to != null && options.to < to) to = options.to;
+ var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
+ if (options.sharedHist) copy.history = this.history;
+ (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
+ copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
+ return copy;
+ },
+ unlinkDoc: function(other) {
+ if (other instanceof CodeMirror) other = other.doc;
+ if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
+ var link = this.linked[i];
+ if (link.doc != other) continue;
+ this.linked.splice(i, 1);
+ other.unlinkDoc(this);
+ break;
+ }
+ // If the histories were shared, split them again
+ if (other.history == this.history) {
+ var splitIds = [other.id];
+ linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
+ other.history = new History(null);
+ other.history.done = copyHistoryArray(this.history.done, splitIds);
+ other.history.undone = copyHistoryArray(this.history.undone, splitIds);
+ }
+ },
+ iterLinkedDocs: function(f) {linkedDocs(this, f);},
+
+ getMode: function() {return this.mode;},
+ getEditor: function() {return this.cm;}
+ });
+
+ // Public alias.
+ Doc.prototype.eachLine = Doc.prototype.iter;
+
+ // Set up methods on CodeMirror's prototype to redirect to the editor's document.
+ var dontDelegate = "iter insert remove copy getEditor".split(" ");
+ for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
+ CodeMirror.prototype[prop] = (function(method) {
+ return function() {return method.apply(this.doc, arguments);};
+ })(Doc.prototype[prop]);
+
+ eventMixin(Doc);
+
+ // Call f for all linked documents.
+ function linkedDocs(doc, f, sharedHistOnly) {
+ function propagate(doc, skip, sharedHist) {
+ if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
+ var rel = doc.linked[i];
+ if (rel.doc == skip) continue;
+ var shared = sharedHist && rel.sharedHist;
+ if (sharedHistOnly && !shared) continue;
+ f(rel.doc, shared);
+ propagate(rel.doc, doc, shared);
+ }
+ }
+ propagate(doc, null, true);
+ }
+
+ // Attach a document to an editor.
+ function attachDoc(cm, doc) {
+ if (doc.cm) throw new Error("This document is already in use.");
+ cm.doc = doc;
+ doc.cm = cm;
+ estimateLineHeights(cm);
+ loadMode(cm);
+ if (!cm.options.lineWrapping) findMaxLine(cm);
+ cm.options.mode = doc.modeOption;
+ regChange(cm);
+ }
+
+ // LINE UTILITIES
+
+ // Find the line object corresponding to the given line number.
+ function getLine(doc, n) {
+ n -= doc.first;
+ if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document.");
+ for (var chunk = doc; !chunk.lines;) {
+ for (var i = 0;; ++i) {
+ var child = chunk.children[i], sz = child.chunkSize();
+ if (n < sz) { chunk = child; break; }
+ n -= sz;
+ }
+ }
+ return chunk.lines[n];
+ }
+
+ // Get the part of a document between two positions, as an array of
+ // strings.
+ function getBetween(doc, start, end) {
+ var out = [], n = start.line;
+ doc.iter(start.line, end.line + 1, function(line) {
+ var text = line.text;
+ if (n == end.line) text = text.slice(0, end.ch);
+ if (n == start.line) text = text.slice(start.ch);
+ out.push(text);
+ ++n;
+ });
+ return out;
+ }
+ // Get the lines between from and to, as array of strings.
+ function getLines(doc, from, to) {
+ var out = [];
+ doc.iter(from, to, function(line) { out.push(line.text); });
+ return out;
+ }
+
+ // Update the height of a line, propagating the height change
+ // upwards to parent nodes.
+ function updateLineHeight(line, height) {
+ var diff = height - line.height;
+ if (diff) for (var n = line; n; n = n.parent) n.height += diff;
+ }
+
+ // Given a line object, find its line number by walking up through
+ // its parent links.
+ function lineNo(line) {
+ if (line.parent == null) return null;
+ var cur = line.parent, no = indexOf(cur.lines, line);
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
+ for (var i = 0;; ++i) {
+ if (chunk.children[i] == cur) break;
+ no += chunk.children[i].chunkSize();
+ }
+ }
+ return no + cur.first;
+ }
+
+ // Find the line at the given vertical position, using the height
+ // information in the document tree.
+ function lineAtHeight(chunk, h) {
+ var n = chunk.first;
+ outer: do {
+ for (var i = 0; i < chunk.children.length; ++i) {
+ var child = chunk.children[i], ch = child.height;
+ if (h < ch) { chunk = child; continue outer; }
+ h -= ch;
+ n += child.chunkSize();
+ }
+ return n;
+ } while (!chunk.lines);
+ for (var i = 0; i < chunk.lines.length; ++i) {
+ var line = chunk.lines[i], lh = line.height;
+ if (h < lh) break;
+ h -= lh;
+ }
+ return n + i;
+ }
+
+
+ // Find the height above the given line.
+ function heightAtLine(lineObj) {
+ lineObj = visualLine(lineObj);
+
+ var h = 0, chunk = lineObj.parent;
+ for (var i = 0; i < chunk.lines.length; ++i) {
+ var line = chunk.lines[i];
+ if (line == lineObj) break;
+ else h += line.height;
+ }
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
+ for (var i = 0; i < p.children.length; ++i) {
+ var cur = p.children[i];
+ if (cur == chunk) break;
+ else h += cur.height;
+ }
+ }
+ return h;
+ }
+
+ // Get the bidi ordering for the given line (and cache it). Returns
+ // false for lines that are fully left-to-right, and an array of
+ // BidiSpan objects otherwise.
+ function getOrder(line) {
+ var order = line.order;
+ if (order == null) order = line.order = bidiOrdering(line.text);
+ return order;
+ }
+
+ // HISTORY
+
+ function History(startGen) {
+ // Arrays of change events and selections. Doing something adds an
+ // event to done and clears undo. Undoing moves events from done
+ // to undone, redoing moves them in the other direction.
+ this.done = []; this.undone = [];
+ this.undoDepth = Infinity;
+ // Used to track when changes can be merged into a single undo
+ // event
+ this.lastModTime = this.lastSelTime = 0;
+ this.lastOp = null;
+ this.lastOrigin = this.lastSelOrigin = null;
+ // Used by the isClean() method
+ this.generation = this.maxGeneration = startGen || 1;
+ }
+
+ // Create a history change event from an updateDoc-style change
+ // object.
+ function historyChangeFromChange(doc, change) {
+ var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
+ attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
+ linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
+ return histChange;
+ }
+
+ // Pop all selection events off the end of a history array. Stop at
+ // a change event.
+ function clearSelectionEvents(array) {
+ while (array.length) {
+ var last = lst(array);
+ if (last.ranges) array.pop();
+ else break;
+ }
+ }
+
+ // Find the top change event in the history. Pop off selection
+ // events that are in the way.
+ function lastChangeEvent(hist, force) {
+ if (force) {
+ clearSelectionEvents(hist.done);
+ return lst(hist.done);
+ } else if (hist.done.length && !lst(hist.done).ranges) {
+ return lst(hist.done);
+ } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
+ hist.done.pop();
+ return lst(hist.done);
+ }
+ }
+
+ // Register a change in the history. Merges changes that are within
+ // a single operation, ore are close together with an origin that
+ // allows merging (starting with "+") into a single event.
+ function addChangeToHistory(doc, change, selAfter, opId) {
+ var hist = doc.history;
+ hist.undone.length = 0;
+ var time = +new Date, cur;
+
+ if ((hist.lastOp == opId ||
+ hist.lastOrigin == change.origin && change.origin &&
+ ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
+ change.origin.charAt(0) == "*")) &&
+ (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
+ // Merge this change into the last event
+ var last = lst(cur.changes);
+ if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
+ // Optimized case for simple insertion -- don't want to add
+ // new changesets for every character typed
+ last.to = changeEnd(change);
+ } else {
+ // Add new sub-event
+ cur.changes.push(historyChangeFromChange(doc, change));
+ }
+ } else {
+ // Can not be merged, start a new event.
+ var before = lst(hist.done);
+ if (!before || !before.ranges)
+ pushSelectionToHistory(doc.sel, hist.done);
+ cur = {changes: [historyChangeFromChange(doc, change)],
+ generation: hist.generation};
+ hist.done.push(cur);
+ while (hist.done.length > hist.undoDepth) {
+ hist.done.shift();
+ if (!hist.done[0].ranges) hist.done.shift();
+ }
+ }
+ hist.done.push(selAfter);
+ hist.generation = ++hist.maxGeneration;
+ hist.lastModTime = hist.lastSelTime = time;
+ hist.lastOp = opId;
+ hist.lastOrigin = hist.lastSelOrigin = change.origin;
+
+ if (!last) signal(doc, "historyAdded");
+ }
+
+ function selectionEventCanBeMerged(doc, origin, prev, sel) {
+ var ch = origin.charAt(0);
+ return ch == "*" ||
+ ch == "+" &&
+ prev.ranges.length == sel.ranges.length &&
+ prev.somethingSelected() == sel.somethingSelected() &&
+ new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);
+ }
+
+ // Called whenever the selection changes, sets the new selection as
+ // the pending selection in the history, and pushes the old pending
+ // selection into the 'done' array when it was significantly
+ // different (in number of selected ranges, emptiness, or time).
+ function addSelectionToHistory(doc, sel, opId, options) {
+ var hist = doc.history, origin = options && options.origin;
+
+ // A new event is started when the previous origin does not match
+ // the current, or the origins don't allow matching. Origins
+ // starting with * are always merged, those starting with + are
+ // merged when similar and close together in time.
+ if (opId == hist.lastOp ||
+ (origin && hist.lastSelOrigin == origin &&
+ (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
+ selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
+ hist.done[hist.done.length - 1] = sel;
+ else
+ pushSelectionToHistory(sel, hist.done);
+
+ hist.lastSelTime = +new Date;
+ hist.lastSelOrigin = origin;
+ hist.lastOp = opId;
+ if (options && options.clearRedo !== false)
+ clearSelectionEvents(hist.undone);
+ }
+
+ function pushSelectionToHistory(sel, dest) {
+ var top = lst(dest);
+ if (!(top && top.ranges && top.equals(sel)))
+ dest.push(sel);
+ }
+
+ // Used to store marked span information in the history.
+ function attachLocalSpans(doc, change, from, to) {
+ var existing = change["spans_" + doc.id], n = 0;
+ doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
+ if (line.markedSpans)
+ (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
+ ++n;
+ });
+ }
+
+ // When un/re-doing restores text containing marked spans, those
+ // that have been explicitly cleared should not be restored.
+ function removeClearedSpans(spans) {
+ if (!spans) return null;
+ for (var i = 0, out; i < spans.length; ++i) {
+ if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
+ else if (out) out.push(spans[i]);
+ }
+ return !out ? spans : out.length ? out : null;
+ }
+
+ // Retrieve and filter the old marked spans stored in a change event.
+ function getOldSpans(doc, change) {
+ var found = change["spans_" + doc.id];
+ if (!found) return null;
+ for (var i = 0, nw = []; i < change.text.length; ++i)
+ nw.push(removeClearedSpans(found[i]));
+ return nw;
+ }
+
+ // Used both to provide a JSON-safe object in .getHistory, and, when
+ // detaching a document, to split the history in two
+ function copyHistoryArray(events, newGroup, instantiateSel) {
+ for (var i = 0, copy = []; i < events.length; ++i) {
+ var event = events[i];
+ if (event.ranges) {
+ copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
+ continue;
+ }
+ var changes = event.changes, newChanges = [];
+ copy.push({changes: newChanges});
+ for (var j = 0; j < changes.length; ++j) {
+ var change = changes[j], m;
+ newChanges.push({from: change.from, to: change.to, text: change.text});
+ if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
+ if (indexOf(newGroup, Number(m[1])) > -1) {
+ lst(newChanges)[prop] = change[prop];
+ delete change[prop];
+ }
+ }
+ }
+ }
+ return copy;
+ }
+
+ // Rebasing/resetting history to deal with externally-sourced changes
+
+ function rebaseHistSelSingle(pos, from, to, diff) {
+ if (to < pos.line) {
+ pos.line += diff;
+ } else if (from < pos.line) {
+ pos.line = from;
+ pos.ch = 0;
+ }
+ }
+
+ // Tries to rebase an array of history events given a change in the
+ // document. If the change touches the same lines as the event, the
+ // event, and everything 'behind' it, is discarded. If the change is
+ // before the event, the event's positions are updated. Uses a
+ // copy-on-write scheme for the positions, to avoid having to
+ // reallocate them all on every rebase, but also avoid problems with
+ // shared position objects being unsafely updated.
+ function rebaseHistArray(array, from, to, diff) {
+ for (var i = 0; i < array.length; ++i) {
+ var sub = array[i], ok = true;
+ if (sub.ranges) {
+ if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
+ for (var j = 0; j < sub.ranges.length; j++) {
+ rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
+ rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
+ }
+ continue;
+ }
+ for (var j = 0; j < sub.changes.length; ++j) {
+ var cur = sub.changes[j];
+ if (to < cur.from.line) {
+ cur.from = Pos(cur.from.line + diff, cur.from.ch);
+ cur.to = Pos(cur.to.line + diff, cur.to.ch);
+ } else if (from <= cur.to.line) {
+ ok = false;
+ break;
+ }
+ }
+ if (!ok) {
+ array.splice(0, i + 1);
+ i = 0;
+ }
+ }
+ }
+
+ function rebaseHist(hist, change) {
+ var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
+ rebaseHistArray(hist.done, from, to, diff);
+ rebaseHistArray(hist.undone, from, to, diff);
+ }
+
+ // EVENT UTILITIES
+
+ // Due to the fact that we still support jurassic IE versions, some
+ // compatibility wrappers are needed.
+
+ var e_preventDefault = CodeMirror.e_preventDefault = function(e) {
+ if (e.preventDefault) e.preventDefault();
+ else e.returnValue = false;
+ };
+ var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {
+ if (e.stopPropagation) e.stopPropagation();
+ else e.cancelBubble = true;
+ };
+ function e_defaultPrevented(e) {
+ return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
+ }
+ var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};
+
+ function e_target(e) {return e.target || e.srcElement;}
+ function e_button(e) {
+ var b = e.which;
+ if (b == null) {
+ if (e.button & 1) b = 1;
+ else if (e.button & 2) b = 3;
+ else if (e.button & 4) b = 2;
+ }
+ if (mac && e.ctrlKey && b == 1) b = 3;
+ return b;
+ }
+
+ // EVENT HANDLING
+
+ // Lightweight event framework. on/off also work on DOM nodes,
+ // registering native DOM handlers.
+
+ var on = CodeMirror.on = function(emitter, type, f) {
+ if (emitter.addEventListener)
+ emitter.addEventListener(type, f, false);
+ else if (emitter.attachEvent)
+ emitter.attachEvent("on" + type, f);
+ else {
+ var map = emitter._handlers || (emitter._handlers = {});
+ var arr = map[type] || (map[type] = []);
+ arr.push(f);
+ }
+ };
+
+ var off = CodeMirror.off = function(emitter, type, f) {
+ if (emitter.removeEventListener)
+ emitter.removeEventListener(type, f, false);
+ else if (emitter.detachEvent)
+ emitter.detachEvent("on" + type, f);
+ else {
+ var arr = emitter._handlers && emitter._handlers[type];
+ if (!arr) return;
+ for (var i = 0; i < arr.length; ++i)
+ if (arr[i] == f) { arr.splice(i, 1); break; }
+ }
+ };
+
+ var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
+ var arr = emitter._handlers && emitter._handlers[type];
+ if (!arr) return;
+ var args = Array.prototype.slice.call(arguments, 2);
+ for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
+ };
+
+ // Often, we want to signal events at a point where we are in the
+ // middle of some work, but don't want the handler to start calling
+ // other methods on the editor, which might be in an inconsistent
+ // state or simply not expect any other events to happen.
+ // signalLater looks whether there are any handlers, and schedules
+ // them to be executed when the last operation ends, or, if no
+ // operation is active, when a timeout fires.
+ var delayedCallbacks, delayedCallbackDepth = 0;
+ function signalLater(emitter, type /*, values...*/) {
+ var arr = emitter._handlers && emitter._handlers[type];
+ if (!arr) return;
+ var args = Array.prototype.slice.call(arguments, 2);
+ if (!delayedCallbacks) {
+ ++delayedCallbackDepth;
+ delayedCallbacks = [];
+ setTimeout(fireDelayed, 0);
+ }
+ function bnd(f) {return function(){f.apply(null, args);};};
+ for (var i = 0; i < arr.length; ++i)
+ delayedCallbacks.push(bnd(arr[i]));
+ }
+
+ function fireDelayed() {
+ --delayedCallbackDepth;
+ var delayed = delayedCallbacks;
+ delayedCallbacks = null;
+ for (var i = 0; i < delayed.length; ++i) delayed[i]();
+ }
+
+ // The DOM events that CodeMirror handles can be overridden by
+ // registering a (non-DOM) handler on the editor for the event name,
+ // and preventDefault-ing the event in that handler.
+ function signalDOMEvent(cm, e, override) {
+ signal(cm, override || e.type, cm, e);
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
+ }
+
+ function hasHandler(emitter, type) {
+ var arr = emitter._handlers && emitter._handlers[type];
+ return arr && arr.length > 0;
+ }
+
+ // Add on and off methods to a constructor's prototype, to make
+ // registering events on such objects more convenient.
+ function eventMixin(ctor) {
+ ctor.prototype.on = function(type, f) {on(this, type, f);};
+ ctor.prototype.off = function(type, f) {off(this, type, f);};
+ }
+
+ // MISC UTILITIES
+
+ // Number of pixels added to scroller and sizer to hide scrollbar
+ var scrollerCutOff = 30;
+
+ // Returned or thrown by various protocols to signal 'I'm not
+ // handling this'.
+ var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
+
+ // Reused option objects for setSelection & friends
+ var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
+
+ function Delayed() {this.id = null;}
+ Delayed.prototype.set = function(ms, f) {
+ clearTimeout(this.id);
+ this.id = setTimeout(f, ms);
+ };
+
+ // Counts the column offset in a string, taking tabs into account.
+ // Used mostly to find indentation.
+ var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {
+ if (end == null) {
+ end = string.search(/[^\s\u00a0]/);
+ if (end == -1) end = string.length;
+ }
+ for (var i = startIndex || 0, n = startValue || 0;;) {
+ var nextTab = string.indexOf("\t", i);
+ if (nextTab < 0 || nextTab >= end)
+ return n + (end - i);
+ n += nextTab - i;
+ n += tabSize - (n % tabSize);
+ i = nextTab + 1;
+ }
+ };
+
+ // The inverse of countColumn -- find the offset that corresponds to
+ // a particular column.
+ function findColumn(string, goal, tabSize) {
+ for (var pos = 0, col = 0;;) {
+ var nextTab = string.indexOf("\t", pos);
+ if (nextTab == -1) nextTab = string.length;
+ var skipped = nextTab - pos;
+ if (nextTab == string.length || col + skipped >= goal)
+ return pos + Math.min(skipped, goal - col);
+ col += nextTab - pos;
+ col += tabSize - (col % tabSize);
+ pos = nextTab + 1;
+ if (col >= goal) return pos;
+ }
+ }
+
+ var spaceStrs = [""];
+ function spaceStr(n) {
+ while (spaceStrs.length <= n)
+ spaceStrs.push(lst(spaceStrs) + " ");
+ return spaceStrs[n];
+ }
+
+ function lst(arr) { return arr[arr.length-1]; }
+
+ var selectInput = function(node) { node.select(); };
+ if (ios) // Mobile Safari apparently has a bug where select() is broken.
+ selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };
+ else if (ie) // Suppress mysterious IE10 errors
+ selectInput = function(node) { try { node.select(); } catch(_e) {} };
+
+ function indexOf(array, elt) {
+ for (var i = 0; i < array.length; ++i)
+ if (array[i] == elt) return i;
+ return -1;
+ }
+ if ([].indexOf) indexOf = function(array, elt) { return array.indexOf(elt); };
+ function map(array, f) {
+ var out = [];
+ for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
+ return out;
+ }
+ if ([].map) map = function(array, f) { return array.map(f); };
+
+ function createObj(base, props) {
+ var inst;
+ if (Object.create) {
+ inst = Object.create(base);
+ } else {
+ var ctor = function() {};
+ ctor.prototype = base;
+ inst = new ctor();
+ }
+ if (props) copyObj(props, inst);
+ return inst;
+ };
+
+ function copyObj(obj, target) {
+ if (!target) target = {};
+ for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
+ return target;
+ }
+
+ function bind(f) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function(){return f.apply(null, args);};
+ }
+
+ var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
+ var isWordChar = CodeMirror.isWordChar = function(ch) {
+ return /\w/.test(ch) || ch > "\x80" &&
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
+ };
+
+ function isEmpty(obj) {
+ for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
+ return true;
+ }
+
+ // Extending unicode characters. A series of a non-extending char +
+ // any number of extending chars is treated as a single unit as far
+ // as editing and measuring is concerned. This is not fully correct,
+ // since some scripts/fonts/browsers also treat other configurations
+ // of code points as a group.
+ var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
+ function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
+
+ // DOM UTILITIES
+
+ function elt(tag, content, className, style) {
+ var e = document.createElement(tag);
+ if (className) e.className = className;
+ if (style) e.style.cssText = style;
+ if (typeof content == "string") e.appendChild(document.createTextNode(content));
+ else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
+ return e;
+ }
+
+ var range;
+ if (document.createRange) range = function(node, start, end) {
+ var r = document.createRange();
+ r.setEnd(node, end);
+ r.setStart(node, start);
+ return r;
+ };
+ else range = function(node, start, end) {
+ var r = document.body.createTextRange();
+ r.moveToElementText(node.parentNode);
+ r.collapse(true);
+ r.moveEnd("character", end);
+ r.moveStart("character", start);
+ return r;
+ };
+
+ function removeChildren(e) {
+ for (var count = e.childNodes.length; count > 0; --count)
+ e.removeChild(e.firstChild);
+ return e;
+ }
+
+ function removeChildrenAndAdd(parent, e) {
+ return removeChildren(parent).appendChild(e);
+ }
+
+ function contains(parent, child) {
+ if (parent.contains)
+ return parent.contains(child);
+ while (child = child.parentNode)
+ if (child == parent) return true;
+ }
+
+ function activeElt() { return document.activeElement; }
+ // Older versions of IE throws unspecified error when touching
+ // document.activeElement in some cases (during loading, in iframe)
+ if (ie_upto10) activeElt = function() {
+ try { return document.activeElement; }
+ catch(e) { return document.body; }
+ };
+
+ // FEATURE DETECTION
+
+ // Detect drag-and-drop
+ var dragAndDrop = function() {
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
+ // couldn't get it to work yet.
+ if (ie_upto8) return false;
+ var div = elt('div');
+ return "draggable" in div || "dragDrop" in div;
+ }();
+
+ var knownScrollbarWidth;
+ function scrollbarWidth(measure) {
+ if (knownScrollbarWidth != null) return knownScrollbarWidth;
+ var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
+ removeChildrenAndAdd(measure, test);
+ if (test.offsetWidth)
+ knownScrollbarWidth = test.offsetHeight - test.clientHeight;
+ return knownScrollbarWidth || 0;
+ }
+
+ var zwspSupported;
+ function zeroWidthElement(measure) {
+ if (zwspSupported == null) {
+ var test = elt("span", "\u200b");
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
+ if (measure.firstChild.offsetHeight != 0)
+ zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_upto7;
+ }
+ if (zwspSupported) return elt("span", "\u200b");
+ else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
+ }
+
+ // Feature-detect IE's crummy client rect reporting for bidi text
+ var badBidiRects;
+ function hasBadBidiRects(measure) {
+ if (badBidiRects != null) return badBidiRects;
+ var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
+ var r0 = range(txt, 0, 1).getBoundingClientRect();
+ if (r0.left == r0.right) return false;
+ var r1 = range(txt, 1, 2).getBoundingClientRect();
+ return badBidiRects = (r1.right - r0.right < 3);
+ }
+
+ // See if "".split is the broken IE version, if so, provide an
+ // alternative way to split lines.
+ var splitLines = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
+ var pos = 0, result = [], l = string.length;
+ while (pos <= l) {
+ var nl = string.indexOf("\n", pos);
+ if (nl == -1) nl = string.length;
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
+ var rt = line.indexOf("\r");
+ if (rt != -1) {
+ result.push(line.slice(0, rt));
+ pos += rt + 1;
+ } else {
+ result.push(line);
+ pos = nl + 1;
+ }
+ }
+ return result;
+ } : function(string){return string.split(/\r\n?|\n/);};
+
+ var hasSelection = window.getSelection ? function(te) {
+ try { return te.selectionStart != te.selectionEnd; }
+ catch(e) { return false; }
+ } : function(te) {
+ try {var range = te.ownerDocument.selection.createRange();}
+ catch(e) {}
+ if (!range || range.parentElement() != te) return false;
+ return range.compareEndPoints("StartToEnd", range) != 0;
+ };
+
+ var hasCopyEvent = (function() {
+ var e = elt("div");
+ if ("oncopy" in e) return true;
+ e.setAttribute("oncopy", "return;");
+ return typeof e.oncopy == "function";
+ })();
+
+ // KEY NAMES
+
+ var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
+ 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete",
+ 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
+ 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
+ 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"};
+ CodeMirror.keyNames = keyNames;
+ (function() {
+ // Number keys
+ for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
+ // Alphabetic keys
+ for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
+ // Function keys
+ for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
+ })();
+
+ // BIDI HELPERS
+
+ function iterateBidiSections(order, from, to, f) {
+ if (!order) return f(from, to, "ltr");
+ var found = false;
+ for (var i = 0; i < order.length; ++i) {
+ var part = order[i];
+ if (part.from < to && part.to > from || from == to && part.to == from) {
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
+ found = true;
+ }
+ }
+ if (!found) f(from, to, "ltr");
+ }
+
+ function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
+ function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
+
+ function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
+ function lineRight(line) {
+ var order = getOrder(line);
+ if (!order) return line.text.length;
+ return bidiRight(lst(order));
+ }
+
+ function lineStart(cm, lineN) {
+ var line = getLine(cm.doc, lineN);
+ var visual = visualLine(line);
+ if (visual != line) lineN = lineNo(visual);
+ var order = getOrder(visual);
+ var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
+ return Pos(lineN, ch);
+ }
+ function lineEnd(cm, lineN) {
+ var merged, line = getLine(cm.doc, lineN);
+ while (merged = collapsedSpanAtEnd(line)) {
+ line = merged.find(1, true).line;
+ lineN = null;
+ }
+ var order = getOrder(line);
+ var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
+ return Pos(lineN == null ? lineNo(line) : lineN, ch);
+ }
+
+ function compareBidiLevel(order, a, b) {
+ var linedir = order[0].level;
+ if (a == linedir) return true;
+ if (b == linedir) return false;
+ return a < b;
+ }
+ var bidiOther;
+ function getBidiPartAt(order, pos) {
+ bidiOther = null;
+ for (var i = 0, found; i < order.length; ++i) {
+ var cur = order[i];
+ if (cur.from < pos && cur.to > pos) return i;
+ if ((cur.from == pos || cur.to == pos)) {
+ if (found == null) {
+ found = i;
+ } else if (compareBidiLevel(order, cur.level, order[found].level)) {
+ if (cur.from != cur.to) bidiOther = found;
+ return i;
+ } else {
+ if (cur.from != cur.to) bidiOther = i;
+ return found;
+ }
+ }
+ }
+ return found;
+ }
+
+ function moveInLine(line, pos, dir, byUnit) {
+ if (!byUnit) return pos + dir;
+ do pos += dir;
+ while (pos > 0 && isExtendingChar(line.text.charAt(pos)));
+ return pos;
+ }
+
+ // This is needed in order to move 'visually' through bi-directional
+ // text -- i.e., pressing left should make the cursor go left, even
+ // when in RTL text. The tricky part is the 'jumps', where RTL and
+ // LTR text touch each other. This often requires the cursor offset
+ // to move more than one unit, in order to visually move one unit.
+ function moveVisually(line, start, dir, byUnit) {
+ var bidi = getOrder(line);
+ if (!bidi) return moveLogically(line, start, dir, byUnit);
+ var pos = getBidiPartAt(bidi, start), part = bidi[pos];
+ var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
+
+ for (;;) {
+ if (target > part.from && target < part.to) return target;
+ if (target == part.from || target == part.to) {
+ if (getBidiPartAt(bidi, target) == pos) return target;
+ part = bidi[pos += dir];
+ return (dir > 0) == part.level % 2 ? part.to : part.from;
+ } else {
+ part = bidi[pos += dir];
+ if (!part) return null;
+ if ((dir > 0) == part.level % 2)
+ target = moveInLine(line, part.to, -1, byUnit);
+ else
+ target = moveInLine(line, part.from, 1, byUnit);
+ }
+ }
+ }
+
+ function moveLogically(line, start, dir, byUnit) {
+ var target = start + dir;
+ if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;
+ return target < 0 || target > line.text.length ? null : target;
+ }
+
+ // Bidirectional ordering algorithm
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
+ // that this (partially) implements.
+
+ // One-char codes used for character types:
+ // L (L): Left-to-Right
+ // R (R): Right-to-Left
+ // r (AL): Right-to-Left Arabic
+ // 1 (EN): European Number
+ // + (ES): European Number Separator
+ // % (ET): European Number Terminator
+ // n (AN): Arabic Number
+ // , (CS): Common Number Separator
+ // m (NSM): Non-Spacing Mark
+ // b (BN): Boundary Neutral
+ // s (B): Paragraph Separator
+ // t (S): Segment Separator
+ // w (WS): Whitespace
+ // N (ON): Other Neutrals
+
+ // Returns null if characters are ordered as they appear
+ // (left-to-right), or an array of sections ({from, to, level}
+ // objects) in the order in which they occur visually.
+ var bidiOrdering = (function() {
+ // Character types for codepoints 0 to 0xff
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
+ // Character types for codepoints 0x600 to 0x6ff
+ var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";
+ function charType(code) {
+ if (code <= 0xf7) return lowTypes.charAt(code);
+ else if (0x590 <= code && code <= 0x5f4) return "R";
+ else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);
+ else if (0x6ee <= code && code <= 0x8ac) return "r";
+ else if (0x2000 <= code && code <= 0x200b) return "w";
+ else if (code == 0x200c) return "b";
+ else return "L";
+ }
+
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
+ // Browsers seem to always treat the boundaries of block elements as being L.
+ var outerType = "L";
+
+ function BidiSpan(level, from, to) {
+ this.level = level;
+ this.from = from; this.to = to;
+ }
+
+ return function(str) {
+ if (!bidiRE.test(str)) return false;
+ var len = str.length, types = [];
+ for (var i = 0, type; i < len; ++i)
+ types.push(type = charType(str.charCodeAt(i)));
+
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
+ // change the type of the NSM to the type of the previous
+ // character. If the NSM is at the start of the level run, it will
+ // get the type of sor.
+ for (var i = 0, prev = outerType; i < len; ++i) {
+ var type = types[i];
+ if (type == "m") types[i] = prev;
+ else prev = type;
+ }
+
+ // W2. Search backwards from each instance of a European number
+ // until the first strong type (R, L, AL, or sor) is found. If an
+ // AL is found, change the type of the European number to Arabic
+ // number.
+ // W3. Change all ALs to R.
+ for (var i = 0, cur = outerType; i < len; ++i) {
+ var type = types[i];
+ if (type == "1" && cur == "r") types[i] = "n";
+ else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
+ }
+
+ // W4. A single European separator between two European numbers
+ // changes to a European number. A single common separator between
+ // two numbers of the same type changes to that type.
+ for (var i = 1, prev = types[0]; i < len - 1; ++i) {
+ var type = types[i];
+ if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
+ else if (type == "," && prev == types[i+1] &&
+ (prev == "1" || prev == "n")) types[i] = prev;
+ prev = type;
+ }
+
+ // W5. A sequence of European terminators adjacent to European
+ // numbers changes to all European numbers.
+ // W6. Otherwise, separators and terminators change to Other
+ // Neutral.
+ for (var i = 0; i < len; ++i) {
+ var type = types[i];
+ if (type == ",") types[i] = "N";
+ else if (type == "%") {
+ for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
+ var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
+ for (var j = i; j < end; ++j) types[j] = replace;
+ i = end - 1;
+ }
+ }
+
+ // W7. Search backwards from each instance of a European number
+ // until the first strong type (R, L, or sor) is found. If an L is
+ // found, then change the type of the European number to L.
+ for (var i = 0, cur = outerType; i < len; ++i) {
+ var type = types[i];
+ if (cur == "L" && type == "1") types[i] = "L";
+ else if (isStrong.test(type)) cur = type;
+ }
+
+ // N1. A sequence of neutrals takes the direction of the
+ // surrounding strong text if the text on both sides has the same
+ // direction. European and Arabic numbers act as if they were R in
+ // terms of their influence on neutrals. Start-of-level-run (sor)
+ // and end-of-level-run (eor) are used at level run boundaries.
+ // N2. Any remaining neutrals take the embedding direction.
+ for (var i = 0; i < len; ++i) {
+ if (isNeutral.test(types[i])) {
+ for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
+ var before = (i ? types[i-1] : outerType) == "L";
+ var after = (end < len ? types[end] : outerType) == "L";
+ var replace = before || after ? "L" : "R";
+ for (var j = i; j < end; ++j) types[j] = replace;
+ i = end - 1;
+ }
+ }
+
+ // Here we depart from the documented algorithm, in order to avoid
+ // building up an actual levels array. Since there are only three
+ // levels (0, 1, 2) in an implementation that doesn't take
+ // explicit embedding into account, we can build up the order on
+ // the fly, without following the level-based algorithm.
+ var order = [], m;
+ for (var i = 0; i < len;) {
+ if (countsAsLeft.test(types[i])) {
+ var start = i;
+ for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
+ order.push(new BidiSpan(0, start, i));
+ } else {
+ var pos = i, at = order.length;
+ for (++i; i < len && types[i] != "L"; ++i) {}
+ for (var j = pos; j < i;) {
+ if (countsAsNum.test(types[j])) {
+ if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));
+ var nstart = j;
+ for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
+ order.splice(at, 0, new BidiSpan(2, nstart, j));
+ pos = j;
+ } else ++j;
+ }
+ if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));
+ }
+ }
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
+ order[0].from = m[0].length;
+ order.unshift(new BidiSpan(0, 0, m[0].length));
+ }
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
+ lst(order).to -= m[0].length;
+ order.push(new BidiSpan(0, len - m[0].length, len));
+ }
+ if (order[0].level != lst(order).level)
+ order.push(new BidiSpan(order[0].level, len, len));
+
+ return order;
+ };
+ })();
+
+ // THE END
+
+ CodeMirror.version = "4.0.3";
+
+ return CodeMirror;
+});
+;(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
+CodeMirror.defineMode("xml", function(config, parserConfig) {
+ var indentUnit = config.indentUnit;
+ var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
+ var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
+ if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
+
+ var Kludges = parserConfig.htmlMode ? {
+ autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
+ 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
+ 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
+ 'track': true, 'wbr': true},
+ implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
+ 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
+ 'th': true, 'tr': true},
+ contextGrabbers: {
+ 'dd': {'dd': true, 'dt': true},
+ 'dt': {'dd': true, 'dt': true},
+ 'li': {'li': true},
+ 'option': {'option': true, 'optgroup': true},
+ 'optgroup': {'optgroup': true},
+ 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
+ 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
+ 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
+ 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
+ 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
+ 'rp': {'rp': true, 'rt': true},
+ 'rt': {'rp': true, 'rt': true},
+ 'tbody': {'tbody': true, 'tfoot': true},
+ 'td': {'td': true, 'th': true},
+ 'tfoot': {'tbody': true},
+ 'th': {'td': true, 'th': true},
+ 'thead': {'tbody': true, 'tfoot': true},
+ 'tr': {'tr': true}
+ },
+ doNotIndent: {"pre": true},
+ allowUnquoted: true,
+ allowMissing: true,
+ caseFold: true
+ } : {
+ autoSelfClosers: {},
+ implicitlyClosed: {},
+ contextGrabbers: {},
+ doNotIndent: {},
+ allowUnquoted: false,
+ allowMissing: false,
+ caseFold: false
+ };
+ var alignCDATA = parserConfig.alignCDATA;
+
+ // Return variables for tokenizers
+ var tagName, type, setStyle;
+
+ function inText(stream, state) {
+ function chain(parser) {
+ state.tokenize = parser;
+ return parser(stream, state);
+ }
+
+ var ch = stream.next();
+ if (ch == "<") {
+ if (stream.eat("!")) {
+ if (stream.eat("[")) {
+ if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
+ else return null;
+ } else if (stream.match("--")) {
+ return chain(inBlock("comment", "-->"));
+ } else if (stream.match("DOCTYPE", true, true)) {
+ stream.eatWhile(/[\w\._\-]/);
+ return chain(doctype(1));
+ } else {
+ return null;
+ }
+ } else if (stream.eat("?")) {
+ stream.eatWhile(/[\w\._\-]/);
+ state.tokenize = inBlock("meta", "?>");
+ return "meta";
+ } else {
+ var isClose = stream.eat("/");
+ tagName = "";
+ var c;
+ while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
+ if (Kludges.caseFold) tagName = tagName.toLowerCase();
+ if (!tagName) return "tag error";
+ type = isClose ? "closeTag" : "openTag";
+ state.tokenize = inTag;
+ return "tag";
+ }
+ } else if (ch == "&") {
+ var ok;
+ if (stream.eat("#")) {
+ if (stream.eat("x")) {
+ ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
+ } else {
+ ok = stream.eatWhile(/[\d]/) && stream.eat(";");
+ }
+ } else {
+ ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
+ }
+ return ok ? "atom" : "error";
+ } else {
+ stream.eatWhile(/[^&<]/);
+ return null;
+ }
+ }
+
+ function inTag(stream, state) {
+ var ch = stream.next();
+ if (ch == ">" || (ch == "/" && stream.eat(">"))) {
+ state.tokenize = inText;
+ type = ch == ">" ? "endTag" : "selfcloseTag";
+ return "tag";
+ } else if (ch == "=") {
+ type = "equals";
+ return null;
+ } else if (ch == "<") {
+ state.tokenize = inText;
+ state.state = baseState;
+ state.tagName = state.tagStart = null;
+ var next = state.tokenize(stream, state);
+ return next ? next + " error" : "error";
+ } else if (/[\'\"]/.test(ch)) {
+ state.tokenize = inAttribute(ch);
+ state.stringStartCol = stream.column();
+ return state.tokenize(stream, state);
+ } else {
+ stream.eatWhile(/[^\s\u00a0=<>\"\']/);
+ return "word";
+ }
+ }
+
+ function inAttribute(quote) {
+ var closure = function(stream, state) {
+ while (!stream.eol()) {
+ if (stream.next() == quote) {
+ state.tokenize = inTag;
+ break;
+ }
+ }
+ return "string";
+ };
+ closure.isInAttribute = true;
+ return closure;
+ }
+
+ function inBlock(style, terminator) {
+ return function(stream, state) {
+ while (!stream.eol()) {
+ if (stream.match(terminator)) {
+ state.tokenize = inText;
+ break;
+ }
+ stream.next();
+ }
+ return style;
+ };
+ }
+ function doctype(depth) {
+ return function(stream, state) {
+ var ch;
+ while ((ch = stream.next()) != null) {
+ if (ch == "<") {
+ state.tokenize = doctype(depth + 1);
+ return state.tokenize(stream, state);
+ } else if (ch == ">") {
+ if (depth == 1) {
+ state.tokenize = inText;
+ break;
+ } else {
+ state.tokenize = doctype(depth - 1);
+ return state.tokenize(stream, state);
+ }
+ }
+ }
+ return "meta";
+ };
+ }
+
+ function Context(state, tagName, startOfLine) {
+ this.prev = state.context;
+ this.tagName = tagName;
+ this.indent = state.indented;
+ this.startOfLine = startOfLine;
+ if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
+ this.noIndent = true;
+ }
+ function popContext(state) {
+ if (state.context) state.context = state.context.prev;
+ }
+ function maybePopContext(state, nextTagName) {
+ var parentTagName;
+ while (true) {
+ if (!state.context) {
+ return;
+ }
+ parentTagName = state.context.tagName;
+ if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
+ !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
+ return;
+ }
+ popContext(state);
+ }
+ }
+
+ function baseState(type, stream, state) {
+ if (type == "openTag") {
+ state.tagName = tagName;
+ state.tagStart = stream.column();
+ return attrState;
+ } else if (type == "closeTag") {
+ var err = false;
+ if (state.context) {
+ if (state.context.tagName != tagName) {
+ if (Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
+ popContext(state);
+ err = !state.context || state.context.tagName != tagName;
+ }
+ } else {
+ err = true;
+ }
+ if (err) setStyle = "error";
+ return err ? closeStateErr : closeState;
+ } else {
+ return baseState;
+ }
+ }
+
+ function closeState(type, _stream, state) {
+ if (type != "endTag") {
+ setStyle = "error";
+ return closeState;
+ }
+ popContext(state);
+ return baseState;
+ }
+ function closeStateErr(type, stream, state) {
+ setStyle = "error";
+ return closeState(type, stream, state);
+ }
+
+ function attrState(type, _stream, state) {
+ if (type == "word") {
+ setStyle = "attribute";
+ return attrEqState;
+ } else if (type == "endTag" || type == "selfcloseTag") {
+ var tagName = state.tagName, tagStart = state.tagStart;
+ state.tagName = state.tagStart = null;
+ if (type == "selfcloseTag" ||
+ Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
+ maybePopContext(state, tagName);
+ } else {
+ maybePopContext(state, tagName);
+ state.context = new Context(state, tagName, tagStart == state.indented);
+ }
+ return baseState;
+ }
+ setStyle = "error";
+ return attrState;
+ }
+ function attrEqState(type, stream, state) {
+ if (type == "equals") return attrValueState;
+ if (!Kludges.allowMissing) setStyle = "error";
+ return attrState(type, stream, state);
+ }
+ function attrValueState(type, stream, state) {
+ if (type == "string") return attrContinuedState;
+ if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
+ setStyle = "error";
+ return attrState(type, stream, state);
+ }
+ function attrContinuedState(type, stream, state) {
+ if (type == "string") return attrContinuedState;
+ return attrState(type, stream, state);
+ }
+
+ return {
+ startState: function() {
+ return {tokenize: inText,
+ state: baseState,
+ indented: 0,
+ tagName: null, tagStart: null,
+ context: null};
+ },
+
+ token: function(stream, state) {
+ if (!state.tagName && stream.sol())
+ state.indented = stream.indentation();
+
+ if (stream.eatSpace()) return null;
+ tagName = type = null;
+ var style = state.tokenize(stream, state);
+ if ((style || type) && style != "comment") {
+ setStyle = null;
+ state.state = state.state(type || style, stream, state);
+ if (setStyle)
+ style = setStyle == "error" ? style + " error" : setStyle;
+ }
+ return style;
+ },
+
+ indent: function(state, textAfter, fullLine) {
+ var context = state.context;
+ // Indent multi-line strings (e.g. css).
+ if (state.tokenize.isInAttribute) {
+ return state.stringStartCol + 1;
+ }
+ if (context && context.noIndent) return CodeMirror.Pass;
+ if (state.tokenize != inTag && state.tokenize != inText)
+ return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
+ // Indent the starts of attribute names.
+ if (state.tagName) {
+ if (multilineTagIndentPastTag)
+ return state.tagStart + state.tagName.length + 2;
+ else
+ return state.tagStart + indentUnit * multilineTagIndentFactor;
+ }
+ if (alignCDATA && /",
+
+ configuration: parserConfig.htmlMode ? "html" : "xml",
+ helperType: parserConfig.htmlMode ? "html" : "xml"
+ };
+});
+
+CodeMirror.defineMIME("text/xml", "xml");
+CodeMirror.defineMIME("application/xml", "xml");
+if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
+ CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
+
+});
+;(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
+CodeMirror.defineMode("css", function(config, parserConfig) {
+ if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
+
+ var indentUnit = config.indentUnit,
+ tokenHooks = parserConfig.tokenHooks,
+ mediaTypes = parserConfig.mediaTypes || {},
+ mediaFeatures = parserConfig.mediaFeatures || {},
+ propertyKeywords = parserConfig.propertyKeywords || {},
+ colorKeywords = parserConfig.colorKeywords || {},
+ valueKeywords = parserConfig.valueKeywords || {},
+ fontProperties = parserConfig.fontProperties || {},
+ allowNested = parserConfig.allowNested;
+
+ var type, override;
+ function ret(style, tp) { type = tp; return style; }
+
+ // Tokenizers
+
+ function tokenBase(stream, state) {
+ var ch = stream.next();
+ if (tokenHooks[ch]) {
+ var result = tokenHooks[ch](stream, state);
+ if (result !== false) return result;
+ }
+ if (ch == "@") {
+ stream.eatWhile(/[\w\\\-]/);
+ return ret("def", stream.current());
+ } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
+ return ret(null, "compare");
+ } else if (ch == "\"" || ch == "'") {
+ state.tokenize = tokenString(ch);
+ return state.tokenize(stream, state);
+ } else if (ch == "#") {
+ stream.eatWhile(/[\w\\\-]/);
+ return ret("atom", "hash");
+ } else if (ch == "!") {
+ stream.match(/^\s*\w*/);
+ return ret("keyword", "important");
+ } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
+ stream.eatWhile(/[\w.%]/);
+ return ret("number", "unit");
+ } else if (ch === "-") {
+ if (/[\d.]/.test(stream.peek())) {
+ stream.eatWhile(/[\w.%]/);
+ return ret("number", "unit");
+ } else if (stream.match(/^[^-]+-/)) {
+ return ret("meta", "meta");
+ }
+ } else if (/[,+>*\/]/.test(ch)) {
+ return ret(null, "select-op");
+ } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
+ return ret("qualifier", "qualifier");
+ } else if (/[:;{}\[\]\(\)]/.test(ch)) {
+ return ret(null, ch);
+ } else if (ch == "u" && stream.match("rl(")) {
+ stream.backUp(1);
+ state.tokenize = tokenParenthesized;
+ return ret("property", "word");
+ } else if (/[\w\\\-]/.test(ch)) {
+ stream.eatWhile(/[\w\\\-]/);
+ return ret("property", "word");
+ } else {
+ return ret(null, null);
+ }
+ }
+
+ function tokenString(quote) {
+ return function(stream, state) {
+ var escaped = false, ch;
+ while ((ch = stream.next()) != null) {
+ if (ch == quote && !escaped) {
+ if (quote == ")") stream.backUp(1);
+ break;
+ }
+ escaped = !escaped && ch == "\\";
+ }
+ if (ch == quote || !escaped && quote != ")") state.tokenize = null;
+ return ret("string", "string");
+ };
+ }
+
+ function tokenParenthesized(stream, state) {
+ stream.next(); // Must be '('
+ if (!stream.match(/\s*[\"\']/, false))
+ state.tokenize = tokenString(")");
+ else
+ state.tokenize = null;
+ return ret(null, "(");
+ }
+
+ // Context management
+
+ function Context(type, indent, prev) {
+ this.type = type;
+ this.indent = indent;
+ this.prev = prev;
+ }
+
+ function pushContext(state, stream, type) {
+ state.context = new Context(type, stream.indentation() + indentUnit, state.context);
+ return type;
+ }
+
+ function popContext(state) {
+ state.context = state.context.prev;
+ return state.context.type;
+ }
+
+ function pass(type, stream, state) {
+ return states[state.context.type](type, stream, state);
+ }
+ function popAndPass(type, stream, state, n) {
+ for (var i = n || 1; i > 0; i--)
+ state.context = state.context.prev;
+ return pass(type, stream, state);
+ }
+
+ // Parser
+
+ function wordAsValue(stream) {
+ var word = stream.current().toLowerCase();
+ if (valueKeywords.hasOwnProperty(word))
+ override = "atom";
+ else if (colorKeywords.hasOwnProperty(word))
+ override = "keyword";
+ else
+ override = "variable";
+ }
+
+ var states = {};
+
+ states.top = function(type, stream, state) {
+ if (type == "{") {
+ return pushContext(state, stream, "block");
+ } else if (type == "}" && state.context.prev) {
+ return popContext(state);
+ } else if (type == "@media") {
+ return pushContext(state, stream, "media");
+ } else if (type == "@font-face") {
+ return "font_face_before";
+ } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
+ return "keyframes";
+ } else if (type && type.charAt(0) == "@") {
+ return pushContext(state, stream, "at");
+ } else if (type == "hash") {
+ override = "builtin";
+ } else if (type == "word") {
+ override = "tag";
+ } else if (type == "variable-definition") {
+ return "maybeprop";
+ } else if (type == "interpolation") {
+ return pushContext(state, stream, "interpolation");
+ } else if (type == ":") {
+ return "pseudo";
+ } else if (allowNested && type == "(") {
+ return pushContext(state, stream, "params");
+ }
+ return state.context.type;
+ };
+
+ states.block = function(type, stream, state) {
+ if (type == "word") {
+ if (propertyKeywords.hasOwnProperty(stream.current().toLowerCase())) {
+ override = "property";
+ return "maybeprop";
+ } else if (allowNested) {
+ override = stream.match(/^\s*:/, false) ? "property" : "tag";
+ return "block";
+ } else {
+ override += " error";
+ return "maybeprop";
+ }
+ } else if (type == "meta") {
+ return "block";
+ } else if (!allowNested && (type == "hash" || type == "qualifier")) {
+ override = "error";
+ return "block";
+ } else {
+ return states.top(type, stream, state);
+ }
+ };
+
+ states.maybeprop = function(type, stream, state) {
+ if (type == ":") return pushContext(state, stream, "prop");
+ return pass(type, stream, state);
+ };
+
+ states.prop = function(type, stream, state) {
+ if (type == ";") return popContext(state);
+ if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
+ if (type == "}" || type == "{") return popAndPass(type, stream, state);
+ if (type == "(") return pushContext(state, stream, "parens");
+
+ if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
+ override += " error";
+ } else if (type == "word") {
+ wordAsValue(stream);
+ } else if (type == "interpolation") {
+ return pushContext(state, stream, "interpolation");
+ }
+ return "prop";
+ };
+
+ states.propBlock = function(type, _stream, state) {
+ if (type == "}") return popContext(state);
+ if (type == "word") { override = "property"; return "maybeprop"; }
+ return state.context.type;
+ };
+
+ states.parens = function(type, stream, state) {
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
+ if (type == ")") return popContext(state);
+ return "parens";
+ };
+
+ states.pseudo = function(type, stream, state) {
+ if (type == "word") {
+ override = "variable-3";
+ return state.context.type;
+ }
+ return pass(type, stream, state);
+ };
+
+ states.media = function(type, stream, state) {
+ if (type == "(") return pushContext(state, stream, "media_parens");
+ if (type == "}") return popAndPass(type, stream, state);
+ if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
+
+ if (type == "word") {
+ var word = stream.current().toLowerCase();
+ if (word == "only" || word == "not" || word == "and")
+ override = "keyword";
+ else if (mediaTypes.hasOwnProperty(word))
+ override = "attribute";
+ else if (mediaFeatures.hasOwnProperty(word))
+ override = "property";
+ else
+ override = "error";
+ }
+ return state.context.type;
+ };
+
+ states.media_parens = function(type, stream, state) {
+ if (type == ")") return popContext(state);
+ if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
+ return states.media(type, stream, state);
+ };
+
+ states.font_face_before = function(type, stream, state) {
+ if (type == "{")
+ return pushContext(state, stream, "font_face");
+ return pass(type, stream, state);
+ };
+
+ states.font_face = function(type, stream, state) {
+ if (type == "}") return popContext(state);
+ if (type == "word") {
+ if (!fontProperties.hasOwnProperty(stream.current().toLowerCase()))
+ override = "error";
+ else
+ override = "property";
+ return "maybeprop";
+ }
+ return "font_face";
+ };
+
+ states.keyframes = function(type, stream, state) {
+ if (type == "word") { override = "variable"; return "keyframes"; }
+ if (type == "{") return pushContext(state, stream, "top");
+ return pass(type, stream, state);
+ };
+
+ states.at = function(type, stream, state) {
+ if (type == ";") return popContext(state);
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
+ if (type == "word") override = "tag";
+ else if (type == "hash") override = "builtin";
+ return "at";
+ };
+
+ states.interpolation = function(type, stream, state) {
+ if (type == "}") return popContext(state);
+ if (type == "{" || type == ";") return popAndPass(type, stream, state);
+ if (type != "variable") override = "error";
+ return "interpolation";
+ };
+
+ states.params = function(type, stream, state) {
+ if (type == ")") return popContext(state);
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
+ if (type == "word") wordAsValue(stream);
+ return "params";
+ };
+
+ return {
+ startState: function(base) {
+ return {tokenize: null,
+ state: "top",
+ context: new Context("top", base || 0, null)};
+ },
+
+ token: function(stream, state) {
+ if (!state.tokenize && stream.eatSpace()) return null;
+ var style = (state.tokenize || tokenBase)(stream, state);
+ if (style && typeof style == "object") {
+ type = style[1];
+ style = style[0];
+ }
+ override = style;
+ state.state = states[state.state](type, stream, state);
+ return override;
+ },
+
+ indent: function(state, textAfter) {
+ var cx = state.context, ch = textAfter && textAfter.charAt(0);
+ var indent = cx.indent;
+ if (cx.type == "prop" && ch == "}") cx = cx.prev;
+ if (cx.prev &&
+ (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||
+ ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") ||
+ ch == "{" && (cx.type == "at" || cx.type == "media"))) {
+ indent = cx.indent - indentUnit;
+ cx = cx.prev;
+ }
+ return indent;
+ },
+
+ electricChars: "}",
+ blockCommentStart: "/*",
+ blockCommentEnd: "*/",
+ fold: "brace"
+ };
+});
+
+ function keySet(array) {
+ var keys = {};
+ for (var i = 0; i < array.length; ++i) {
+ keys[array[i]] = true;
+ }
+ return keys;
+ }
+
+ var mediaTypes_ = [
+ "all", "aural", "braille", "handheld", "print", "projection", "screen",
+ "tty", "tv", "embossed"
+ ], mediaTypes = keySet(mediaTypes_);
+
+ var mediaFeatures_ = [
+ "width", "min-width", "max-width", "height", "min-height", "max-height",
+ "device-width", "min-device-width", "max-device-width", "device-height",
+ "min-device-height", "max-device-height", "aspect-ratio",
+ "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
+ "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
+ "max-color", "color-index", "min-color-index", "max-color-index",
+ "monochrome", "min-monochrome", "max-monochrome", "resolution",
+ "min-resolution", "max-resolution", "scan", "grid"
+ ], mediaFeatures = keySet(mediaFeatures_);
+
+ var propertyKeywords_ = [
+ "align-content", "align-items", "align-self", "alignment-adjust",
+ "alignment-baseline", "anchor-point", "animation", "animation-delay",
+ "animation-direction", "animation-duration", "animation-fill-mode",
+ "animation-iteration-count", "animation-name", "animation-play-state",
+ "animation-timing-function", "appearance", "azimuth", "backface-visibility",
+ "background", "background-attachment", "background-clip", "background-color",
+ "background-image", "background-origin", "background-position",
+ "background-repeat", "background-size", "baseline-shift", "binding",
+ "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
+ "bookmark-target", "border", "border-bottom", "border-bottom-color",
+ "border-bottom-left-radius", "border-bottom-right-radius",
+ "border-bottom-style", "border-bottom-width", "border-collapse",
+ "border-color", "border-image", "border-image-outset",
+ "border-image-repeat", "border-image-slice", "border-image-source",
+ "border-image-width", "border-left", "border-left-color",
+ "border-left-style", "border-left-width", "border-radius", "border-right",
+ "border-right-color", "border-right-style", "border-right-width",
+ "border-spacing", "border-style", "border-top", "border-top-color",
+ "border-top-left-radius", "border-top-right-radius", "border-top-style",
+ "border-top-width", "border-width", "bottom", "box-decoration-break",
+ "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
+ "caption-side", "clear", "clip", "color", "color-profile", "column-count",
+ "column-fill", "column-gap", "column-rule", "column-rule-color",
+ "column-rule-style", "column-rule-width", "column-span", "column-width",
+ "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
+ "cue-after", "cue-before", "cursor", "direction", "display",
+ "dominant-baseline", "drop-initial-after-adjust",
+ "drop-initial-after-align", "drop-initial-before-adjust",
+ "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
+ "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
+ "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
+ "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
+ "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
+ "font-stretch", "font-style", "font-synthesis", "font-variant",
+ "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
+ "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
+ "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
+ "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
+ "grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
+ "grid-template", "grid-template-areas", "grid-template-columns",
+ "grid-template-rows", "hanging-punctuation", "height", "hyphens",
+ "icon", "image-orientation", "image-rendering", "image-resolution",
+ "inline-box-align", "justify-content", "left", "letter-spacing",
+ "line-break", "line-height", "line-stacking", "line-stacking-ruby",
+ "line-stacking-shift", "line-stacking-strategy", "list-style",
+ "list-style-image", "list-style-position", "list-style-type", "margin",
+ "margin-bottom", "margin-left", "margin-right", "margin-top",
+ "marker-offset", "marks", "marquee-direction", "marquee-loop",
+ "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
+ "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
+ "nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline",
+ "outline-color", "outline-offset", "outline-style", "outline-width",
+ "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
+ "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
+ "page", "page-break-after", "page-break-before", "page-break-inside",
+ "page-policy", "pause", "pause-after", "pause-before", "perspective",
+ "perspective-origin", "pitch", "pitch-range", "play-during", "position",
+ "presentation-level", "punctuation-trim", "quotes", "region-break-after",
+ "region-break-before", "region-break-inside", "region-fragment",
+ "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
+ "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
+ "ruby-position", "ruby-span", "shape-inside", "shape-outside", "size",
+ "speak", "speak-as", "speak-header",
+ "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
+ "tab-size", "table-layout", "target", "target-name", "target-new",
+ "target-position", "text-align", "text-align-last", "text-decoration",
+ "text-decoration-color", "text-decoration-line", "text-decoration-skip",
+ "text-decoration-style", "text-emphasis", "text-emphasis-color",
+ "text-emphasis-position", "text-emphasis-style", "text-height",
+ "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
+ "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
+ "text-wrap", "top", "transform", "transform-origin", "transform-style",
+ "transition", "transition-delay", "transition-duration",
+ "transition-property", "transition-timing-function", "unicode-bidi",
+ "vertical-align", "visibility", "voice-balance", "voice-duration",
+ "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
+ "voice-volume", "volume", "white-space", "widows", "width", "word-break",
+ "word-spacing", "word-wrap", "z-index", "zoom",
+ // SVG-specific
+ "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
+ "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
+ "color-interpolation", "color-interpolation-filters", "color-profile",
+ "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
+ "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
+ "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
+ "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
+ "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
+ "glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode"
+ ], propertyKeywords = keySet(propertyKeywords_);
+
+ var colorKeywords_ = [
+ "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
+ "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
+ "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
+ "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
+ "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
+ "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
+ "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
+ "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
+ "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
+ "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
+ "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
+ "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
+ "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
+ "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
+ "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
+ "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
+ "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
+ "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
+ "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
+ "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
+ "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
+ "purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon",
+ "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
+ "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
+ "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
+ "whitesmoke", "yellow", "yellowgreen"
+ ], colorKeywords = keySet(colorKeywords_);
+
+ var valueKeywords_ = [
+ "above", "absolute", "activeborder", "activecaption", "afar",
+ "after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
+ "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
+ "arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page",
+ "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
+ "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
+ "both", "bottom", "break", "break-all", "break-word", "button", "button-bevel",
+ "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
+ "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
+ "cell", "center", "checkbox", "circle", "cjk-earthly-branch",
+ "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
+ "col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
+ "content-box", "context-menu", "continuous", "copy", "cover", "crop",
+ "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
+ "decimal-leading-zero", "default", "default-button", "destination-atop",
+ "destination-in", "destination-out", "destination-over", "devanagari",
+ "disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
+ "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
+ "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
+ "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
+ "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
+ "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
+ "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
+ "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
+ "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
+ "ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
+ "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes",
+ "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
+ "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
+ "help", "hidden", "hide", "higher", "highlight", "highlighttext",
+ "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
+ "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
+ "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
+ "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
+ "italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer",
+ "landscape", "lao", "large", "larger", "left", "level", "lighter",
+ "line-through", "linear", "lines", "list-item", "listbox", "listitem",
+ "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
+ "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
+ "lower-roman", "lowercase", "ltr", "malayalam", "match",
+ "media-controls-background", "media-current-time-display",
+ "media-fullscreen-button", "media-mute-button", "media-play-button",
+ "media-return-to-realtime-button", "media-rewind-button",
+ "media-seek-back-button", "media-seek-forward-button", "media-slider",
+ "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
+ "media-volume-slider-container", "media-volume-sliderthumb", "medium",
+ "menu", "menulist", "menulist-button", "menulist-text",
+ "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
+ "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
+ "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
+ "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
+ "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
+ "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
+ "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
+ "painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer",
+ "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
+ "radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region",
+ "relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
+ "ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
+ "s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
+ "searchfield-cancel-button", "searchfield-decoration",
+ "searchfield-results-button", "searchfield-results-decoration",
+ "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
+ "single", "skip-white-space", "slide", "slider-horizontal",
+ "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
+ "small", "small-caps", "small-caption", "smaller", "solid", "somali",
+ "source-atop", "source-in", "source-out", "source-over", "space", "square",
+ "square-button", "start", "static", "status-bar", "stretch", "stroke",
+ "sub", "subpixel-antialiased", "super", "sw-resize", "table",
+ "table-caption", "table-cell", "table-column", "table-column-group",
+ "table-footer-group", "table-header-group", "table-row", "table-row-group",
+ "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
+ "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
+ "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
+ "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
+ "transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
+ "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
+ "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
+ "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
+ "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
+ "window", "windowframe", "windowtext", "x-large", "x-small", "xor",
+ "xx-large", "xx-small"
+ ], valueKeywords = keySet(valueKeywords_);
+
+ var fontProperties_ = [
+ "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
+ "font-stretch", "font-weight", "font-style"
+ ], fontProperties = keySet(fontProperties_);
+
+ var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
+ CodeMirror.registerHelper("hintWords", "css", allWords);
+
+ function tokenCComment(stream, state) {
+ var maybeEnd = false, ch;
+ while ((ch = stream.next()) != null) {
+ if (maybeEnd && ch == "/") {
+ state.tokenize = null;
+ break;
+ }
+ maybeEnd = (ch == "*");
+ }
+ return ["comment", "comment"];
+ }
+
+ function tokenSGMLComment(stream, state) {
+ if (stream.skipTo("-->")) {
+ stream.match("-->");
+ state.tokenize = null;
+ } else {
+ stream.skipToEnd();
+ }
+ return ["comment", "comment"];
+ }
+
+ CodeMirror.defineMIME("text/css", {
+ mediaTypes: mediaTypes,
+ mediaFeatures: mediaFeatures,
+ propertyKeywords: propertyKeywords,
+ colorKeywords: colorKeywords,
+ valueKeywords: valueKeywords,
+ fontProperties: fontProperties,
+ tokenHooks: {
+ "<": function(stream, state) {
+ if (!stream.match("!--")) return false;
+ state.tokenize = tokenSGMLComment;
+ return tokenSGMLComment(stream, state);
+ },
+ "/": function(stream, state) {
+ if (!stream.eat("*")) return false;
+ state.tokenize = tokenCComment;
+ return tokenCComment(stream, state);
+ }
+ },
+ name: "css"
+ });
+
+ CodeMirror.defineMIME("text/x-scss", {
+ mediaTypes: mediaTypes,
+ mediaFeatures: mediaFeatures,
+ propertyKeywords: propertyKeywords,
+ colorKeywords: colorKeywords,
+ valueKeywords: valueKeywords,
+ fontProperties: fontProperties,
+ allowNested: true,
+ tokenHooks: {
+ "/": function(stream, state) {
+ if (stream.eat("/")) {
+ stream.skipToEnd();
+ return ["comment", "comment"];
+ } else if (stream.eat("*")) {
+ state.tokenize = tokenCComment;
+ return tokenCComment(stream, state);
+ } else {
+ return ["operator", "operator"];
+ }
+ },
+ ":": function(stream) {
+ if (stream.match(/\s*{/))
+ return [null, "{"];
+ return false;
+ },
+ "$": function(stream) {
+ stream.match(/^[\w-]+/);
+ if (stream.match(/^\s*:/, false))
+ return ["variable-2", "variable-definition"];
+ return ["variable-2", "variable"];
+ },
+ "#": function(stream) {
+ if (!stream.eat("{")) return false;
+ return [null, "interpolation"];
+ }
+ },
+ name: "css",
+ helperType: "scss"
+ });
+
+ CodeMirror.defineMIME("text/x-less", {
+ mediaTypes: mediaTypes,
+ mediaFeatures: mediaFeatures,
+ propertyKeywords: propertyKeywords,
+ colorKeywords: colorKeywords,
+ valueKeywords: valueKeywords,
+ fontProperties: fontProperties,
+ allowNested: true,
+ tokenHooks: {
+ "/": function(stream, state) {
+ if (stream.eat("/")) {
+ stream.skipToEnd();
+ return ["comment", "comment"];
+ } else if (stream.eat("*")) {
+ state.tokenize = tokenCComment;
+ return tokenCComment(stream, state);
+ } else {
+ return ["operator", "operator"];
+ }
+ },
+ "@": function(stream) {
+ if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
+ stream.eatWhile(/[\w\\\-]/);
+ if (stream.match(/^\s*:/, false))
+ return ["variable-2", "variable-definition"];
+ return ["variable-2", "variable"];
+ },
+ "&": function() {
+ return ["atom", "atom"];
+ }
+ },
+ name: "css",
+ helperType: "less"
+ });
+
+});
+;// TODO actually recognize syntax of TypeScript constructs
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
+CodeMirror.defineMode("javascript", function(config, parserConfig) {
+ var indentUnit = config.indentUnit;
+ var statementIndent = parserConfig.statementIndent;
+ var jsonldMode = parserConfig.jsonld;
+ var jsonMode = parserConfig.json || jsonldMode;
+ var isTS = parserConfig.typescript;
+
+ // Tokenizer
+
+ var keywords = function(){
+ function kw(type) {return {type: type, style: "keyword"};}
+ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
+ var operator = kw("operator"), atom = {type: "atom", style: "atom"};
+
+ var jsKeywords = {
+ "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
+ "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
+ "var": kw("var"), "const": kw("var"), "let": kw("var"),
+ "function": kw("function"), "catch": kw("catch"),
+ "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
+ "in": operator, "typeof": operator, "instanceof": operator,
+ "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
+ "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
+ "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
+ };
+
+ // Extend the 'normal' keywords with the TypeScript language extensions
+ if (isTS) {
+ var type = {type: "variable", style: "variable-3"};
+ var tsKeywords = {
+ // object-like things
+ "interface": kw("interface"),
+ "extends": kw("extends"),
+ "constructor": kw("constructor"),
+
+ // scope modifiers
+ "public": kw("public"),
+ "private": kw("private"),
+ "protected": kw("protected"),
+ "static": kw("static"),
+
+ // types
+ "string": type, "number": type, "bool": type, "any": type
+ };
+
+ for (var attr in tsKeywords) {
+ jsKeywords[attr] = tsKeywords[attr];
+ }
+ }
+
+ return jsKeywords;
+ }();
+
+ var isOperatorChar = /[+\-*&%=<>!?|~^]/;
+ var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
+
+ function readRegexp(stream) {
+ var escaped = false, next, inSet = false;
+ while ((next = stream.next()) != null) {
+ if (!escaped) {
+ if (next == "/" && !inSet) return;
+ if (next == "[") inSet = true;
+ else if (inSet && next == "]") inSet = false;
+ }
+ escaped = !escaped && next == "\\";
+ }
+ }
+
+ // Used as scratch variables to communicate multiple values without
+ // consing up tons of objects.
+ var type, content;
+ function ret(tp, style, cont) {
+ type = tp; content = cont;
+ return style;
+ }
+ function tokenBase(stream, state) {
+ var ch = stream.next();
+ if (ch == '"' || ch == "'") {
+ state.tokenize = tokenString(ch);
+ return state.tokenize(stream, state);
+ } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
+ return ret("number", "number");
+ } else if (ch == "." && stream.match("..")) {
+ return ret("spread", "meta");
+ } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
+ return ret(ch);
+ } else if (ch == "=" && stream.eat(">")) {
+ return ret("=>", "operator");
+ } else if (ch == "0" && stream.eat(/x/i)) {
+ stream.eatWhile(/[\da-f]/i);
+ return ret("number", "number");
+ } else if (/\d/.test(ch)) {
+ stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
+ return ret("number", "number");
+ } else if (ch == "/") {
+ if (stream.eat("*")) {
+ state.tokenize = tokenComment;
+ return tokenComment(stream, state);
+ } else if (stream.eat("/")) {
+ stream.skipToEnd();
+ return ret("comment", "comment");
+ } else if (state.lastType == "operator" || state.lastType == "keyword c" ||
+ state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
+ readRegexp(stream);
+ stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
+ return ret("regexp", "string-2");
+ } else {
+ stream.eatWhile(isOperatorChar);
+ return ret("operator", "operator", stream.current());
+ }
+ } else if (ch == "`") {
+ state.tokenize = tokenQuasi;
+ return tokenQuasi(stream, state);
+ } else if (ch == "#") {
+ stream.skipToEnd();
+ return ret("error", "error");
+ } else if (isOperatorChar.test(ch)) {
+ stream.eatWhile(isOperatorChar);
+ return ret("operator", "operator", stream.current());
+ } else {
+ stream.eatWhile(/[\w\$_]/);
+ var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
+ return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
+ ret("variable", "variable", word);
+ }
+ }
+
+ function tokenString(quote) {
+ return function(stream, state) {
+ var escaped = false, next;
+ if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
+ state.tokenize = tokenBase;
+ return ret("jsonld-keyword", "meta");
+ }
+ while ((next = stream.next()) != null) {
+ if (next == quote && !escaped) break;
+ escaped = !escaped && next == "\\";
+ }
+ if (!escaped) state.tokenize = tokenBase;
+ return ret("string", "string");
+ };
+ }
+
+ function tokenComment(stream, state) {
+ var maybeEnd = false, ch;
+ while (ch = stream.next()) {
+ if (ch == "/" && maybeEnd) {
+ state.tokenize = tokenBase;
+ break;
+ }
+ maybeEnd = (ch == "*");
+ }
+ return ret("comment", "comment");
+ }
+
+ function tokenQuasi(stream, state) {
+ var escaped = false, next;
+ while ((next = stream.next()) != null) {
+ if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
+ state.tokenize = tokenBase;
+ break;
+ }
+ escaped = !escaped && next == "\\";
+ }
+ return ret("quasi", "string-2", stream.current());
+ }
+
+ var brackets = "([{}])";
+ // This is a crude lookahead trick to try and notice that we're
+ // parsing the argument patterns for a fat-arrow function before we
+ // actually hit the arrow token. It only works if the arrow is on
+ // the same line as the arguments and there's no strange noise
+ // (comments) in between. Fallback is to only notice when we hit the
+ // arrow, and not declare the arguments as locals for the arrow
+ // body.
+ function findFatArrow(stream, state) {
+ if (state.fatArrowAt) state.fatArrowAt = null;
+ var arrow = stream.string.indexOf("=>", stream.start);
+ if (arrow < 0) return;
+
+ var depth = 0, sawSomething = false;
+ for (var pos = arrow - 1; pos >= 0; --pos) {
+ var ch = stream.string.charAt(pos);
+ var bracket = brackets.indexOf(ch);
+ if (bracket >= 0 && bracket < 3) {
+ if (!depth) { ++pos; break; }
+ if (--depth == 0) break;
+ } else if (bracket >= 3 && bracket < 6) {
+ ++depth;
+ } else if (/[$\w]/.test(ch)) {
+ sawSomething = true;
+ } else if (sawSomething && !depth) {
+ ++pos;
+ break;
+ }
+ }
+ if (sawSomething && !depth) state.fatArrowAt = pos;
+ }
+
+ // Parser
+
+ var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
+
+ function JSLexical(indented, column, type, align, prev, info) {
+ this.indented = indented;
+ this.column = column;
+ this.type = type;
+ this.prev = prev;
+ this.info = info;
+ if (align != null) this.align = align;
+ }
+
+ function inScope(state, varname) {
+ for (var v = state.localVars; v; v = v.next)
+ if (v.name == varname) return true;
+ for (var cx = state.context; cx; cx = cx.prev) {
+ for (var v = cx.vars; v; v = v.next)
+ if (v.name == varname) return true;
+ }
+ }
+
+ function parseJS(state, style, type, content, stream) {
+ var cc = state.cc;
+ // Communicate our context to the combinators.
+ // (Less wasteful than consing up a hundred closures on every call.)
+ cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
+
+ if (!state.lexical.hasOwnProperty("align"))
+ state.lexical.align = true;
+
+ while(true) {
+ var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
+ if (combinator(type, content)) {
+ while(cc.length && cc[cc.length - 1].lex)
+ cc.pop()();
+ if (cx.marked) return cx.marked;
+ if (type == "variable" && inScope(state, content)) return "variable-2";
+ return style;
+ }
+ }
+ }
+
+ // Combinator utils
+
+ var cx = {state: null, column: null, marked: null, cc: null};
+ function pass() {
+ for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
+ }
+ function cont() {
+ pass.apply(null, arguments);
+ return true;
+ }
+ function register(varname) {
+ function inList(list) {
+ for (var v = list; v; v = v.next)
+ if (v.name == varname) return true;
+ return false;
+ }
+ var state = cx.state;
+ if (state.context) {
+ cx.marked = "def";
+ if (inList(state.localVars)) return;
+ state.localVars = {name: varname, next: state.localVars};
+ } else {
+ if (inList(state.globalVars)) return;
+ if (parserConfig.globalVars)
+ state.globalVars = {name: varname, next: state.globalVars};
+ }
+ }
+
+ // Combinators
+
+ var defaultVars = {name: "this", next: {name: "arguments"}};
+ function pushcontext() {
+ cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
+ cx.state.localVars = defaultVars;
+ }
+ function popcontext() {
+ cx.state.localVars = cx.state.context.vars;
+ cx.state.context = cx.state.context.prev;
+ }
+ function pushlex(type, info) {
+ var result = function() {
+ var state = cx.state, indent = state.indented;
+ if (state.lexical.type == "stat") indent = state.lexical.indented;
+ state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
+ };
+ result.lex = true;
+ return result;
+ }
+ function poplex() {
+ var state = cx.state;
+ if (state.lexical.prev) {
+ if (state.lexical.type == ")")
+ state.indented = state.lexical.indented;
+ state.lexical = state.lexical.prev;
+ }
+ }
+ poplex.lex = true;
+
+ function expect(wanted) {
+ function exp(type) {
+ if (type == wanted) return cont();
+ else if (wanted == ";") return pass();
+ else return cont(exp);
+ };
+ return exp;
+ }
+
+ function statement(type, value) {
+ if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
+ if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
+ if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
+ if (type == "{") return cont(pushlex("}"), block, poplex);
+ if (type == ";") return cont();
+ if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse);
+ if (type == "function") return cont(functiondef);
+ if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
+ if (type == "variable") return cont(pushlex("stat"), maybelabel);
+ if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
+ block, poplex, poplex);
+ if (type == "case") return cont(expression, expect(":"));
+ if (type == "default") return cont(expect(":"));
+ if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
+ statement, poplex, popcontext);
+ if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
+ if (type == "class") return cont(pushlex("form"), className, objlit, poplex);
+ if (type == "export") return cont(pushlex("form"), afterExport, poplex);
+ if (type == "import") return cont(pushlex("form"), afterImport, poplex);
+ return pass(pushlex("stat"), expression, expect(";"), poplex);
+ }
+ function expression(type) {
+ return expressionInner(type, false);
+ }
+ function expressionNoComma(type) {
+ return expressionInner(type, true);
+ }
+ function expressionInner(type, noComma) {
+ if (cx.state.fatArrowAt == cx.stream.start) {
+ var body = noComma ? arrowBodyNoComma : arrowBody;
+ if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
+ else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
+ }
+
+ var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
+ if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
+ if (type == "function") return cont(functiondef);
+ if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
+ if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
+ if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
+ if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
+ if (type == "{") return contCommasep(objprop, "}", null, maybeop);
+ return cont();
+ }
+ function maybeexpression(type) {
+ if (type.match(/[;\}\)\],]/)) return pass();
+ return pass(expression);
+ }
+ function maybeexpressionNoComma(type) {
+ if (type.match(/[;\}\)\],]/)) return pass();
+ return pass(expressionNoComma);
+ }
+
+ function maybeoperatorComma(type, value) {
+ if (type == ",") return cont(expression);
+ return maybeoperatorNoComma(type, value, false);
+ }
+ function maybeoperatorNoComma(type, value, noComma) {
+ var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
+ var expr = noComma == false ? expression : expressionNoComma;
+ if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
+ if (type == "operator") {
+ if (/\+\+|--/.test(value)) return cont(me);
+ if (value == "?") return cont(expression, expect(":"), expr);
+ return cont(expr);
+ }
+ if (type == "quasi") { cx.cc.push(me); return quasi(value); }
+ if (type == ";") return;
+ if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
+ if (type == ".") return cont(property, me);
+ if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
+ }
+ function quasi(value) {
+ if (value.slice(value.length - 2) != "${") return cont();
+ return cont(expression, continueQuasi);
+ }
+ function continueQuasi(type) {
+ if (type == "}") {
+ cx.marked = "string-2";
+ cx.state.tokenize = tokenQuasi;
+ return cont();
+ }
+ }
+ function arrowBody(type) {
+ findFatArrow(cx.stream, cx.state);
+ if (type == "{") return pass(statement);
+ return pass(expression);
+ }
+ function arrowBodyNoComma(type) {
+ findFatArrow(cx.stream, cx.state);
+ if (type == "{") return pass(statement);
+ return pass(expressionNoComma);
+ }
+ function maybelabel(type) {
+ if (type == ":") return cont(poplex, statement);
+ return pass(maybeoperatorComma, expect(";"), poplex);
+ }
+ function property(type) {
+ if (type == "variable") {cx.marked = "property"; return cont();}
+ }
+ function objprop(type, value) {
+ if (type == "variable") {
+ cx.marked = "property";
+ if (value == "get" || value == "set") return cont(getterSetter);
+ } else if (type == "number" || type == "string") {
+ cx.marked = jsonldMode ? "property" : (type + " property");
+ } else if (type == "[") {
+ return cont(expression, expect("]"), afterprop);
+ }
+ if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);
+ }
+ function getterSetter(type) {
+ if (type != "variable") return pass(afterprop);
+ cx.marked = "property";
+ return cont(functiondef);
+ }
+ function afterprop(type) {
+ if (type == ":") return cont(expressionNoComma);
+ if (type == "(") return pass(functiondef);
+ }
+ function commasep(what, end) {
+ function proceed(type) {
+ if (type == ",") {
+ var lex = cx.state.lexical;
+ if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
+ return cont(what, proceed);
+ }
+ if (type == end) return cont();
+ return cont(expect(end));
+ }
+ return function(type) {
+ if (type == end) return cont();
+ return pass(what, proceed);
+ };
+ }
+ function contCommasep(what, end, info) {
+ for (var i = 3; i < arguments.length; i++)
+ cx.cc.push(arguments[i]);
+ return cont(pushlex(end, info), commasep(what, end), poplex);
+ }
+ function block(type) {
+ if (type == "}") return cont();
+ return pass(statement, block);
+ }
+ function maybetype(type) {
+ if (isTS && type == ":") return cont(typedef);
+ }
+ function typedef(type) {
+ if (type == "variable"){cx.marked = "variable-3"; return cont();}
+ }
+ function vardef() {
+ return pass(pattern, maybetype, maybeAssign, vardefCont);
+ }
+ function pattern(type, value) {
+ if (type == "variable") { register(value); return cont(); }
+ if (type == "[") return contCommasep(pattern, "]");
+ if (type == "{") return contCommasep(proppattern, "}");
+ }
+ function proppattern(type, value) {
+ if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
+ register(value);
+ return cont(maybeAssign);
+ }
+ if (type == "variable") cx.marked = "property";
+ return cont(expect(":"), pattern, maybeAssign);
+ }
+ function maybeAssign(_type, value) {
+ if (value == "=") return cont(expressionNoComma);
+ }
+ function vardefCont(type) {
+ if (type == ",") return cont(vardef);
+ }
+ function maybeelse(type, value) {
+ if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex);
+ }
+ function forspec(type) {
+ if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
+ }
+ function forspec1(type) {
+ if (type == "var") return cont(vardef, expect(";"), forspec2);
+ if (type == ";") return cont(forspec2);
+ if (type == "variable") return cont(formaybeinof);
+ return pass(expression, expect(";"), forspec2);
+ }
+ function formaybeinof(_type, value) {
+ if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
+ return cont(maybeoperatorComma, forspec2);
+ }
+ function forspec2(type, value) {
+ if (type == ";") return cont(forspec3);
+ if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
+ return pass(expression, expect(";"), forspec3);
+ }
+ function forspec3(type) {
+ if (type != ")") cont(expression);
+ }
+ function functiondef(type, value) {
+ if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
+ if (type == "variable") {register(value); return cont(functiondef);}
+ if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
+ }
+ function funarg(type) {
+ if (type == "spread") return cont(funarg);
+ return pass(pattern, maybetype);
+ }
+ function className(type, value) {
+ if (type == "variable") {register(value); return cont(classNameAfter);}
+ }
+ function classNameAfter(_type, value) {
+ if (value == "extends") return cont(expression);
+ }
+ function objlit(type) {
+ if (type == "{") return contCommasep(objprop, "}");
+ }
+ function afterModule(type, value) {
+ if (type == "string") return cont(statement);
+ if (type == "variable") { register(value); return cont(maybeFrom); }
+ }
+ function afterExport(_type, value) {
+ if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
+ if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
+ return pass(statement);
+ }
+ function afterImport(type) {
+ if (type == "string") return cont();
+ return pass(importSpec, maybeFrom);
+ }
+ function importSpec(type, value) {
+ if (type == "{") return contCommasep(importSpec, "}");
+ if (type == "variable") register(value);
+ return cont();
+ }
+ function maybeFrom(_type, value) {
+ if (value == "from") { cx.marked = "keyword"; return cont(expression); }
+ }
+ function arrayLiteral(type) {
+ if (type == "]") return cont();
+ return pass(expressionNoComma, maybeArrayComprehension);
+ }
+ function maybeArrayComprehension(type) {
+ if (type == "for") return pass(comprehension, expect("]"));
+ if (type == ",") return cont(commasep(expressionNoComma, "]"));
+ return pass(commasep(expressionNoComma, "]"));
+ }
+ function comprehension(type) {
+ if (type == "for") return cont(forspec, comprehension);
+ if (type == "if") return cont(expression, comprehension);
+ }
+
+ // Interface
+
+ return {
+ startState: function(basecolumn) {
+ var state = {
+ tokenize: tokenBase,
+ lastType: "sof",
+ cc: [],
+ lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
+ localVars: parserConfig.localVars,
+ context: parserConfig.localVars && {vars: parserConfig.localVars},
+ indented: 0
+ };
+ if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
+ state.globalVars = parserConfig.globalVars;
+ return state;
+ },
+
+ token: function(stream, state) {
+ if (stream.sol()) {
+ if (!state.lexical.hasOwnProperty("align"))
+ state.lexical.align = false;
+ state.indented = stream.indentation();
+ findFatArrow(stream, state);
+ }
+ if (state.tokenize != tokenComment && stream.eatSpace()) return null;
+ var style = state.tokenize(stream, state);
+ if (type == "comment") return style;
+ state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
+ return parseJS(state, style, type, content, stream);
+ },
+
+ indent: function(state, textAfter) {
+ if (state.tokenize == tokenComment) return CodeMirror.Pass;
+ if (state.tokenize != tokenBase) return 0;
+ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
+ // Kludge to prevent 'maybelse' from blocking lexical scope pops
+ for (var i = state.cc.length - 1; i >= 0; --i) {
+ var c = state.cc[i];
+ if (c == poplex) lexical = lexical.prev;
+ else if (c != maybeelse) break;
+ }
+ if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
+ if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
+ lexical = lexical.prev;
+ var type = lexical.type, closing = firstChar == type;
+
+ if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
+ else if (type == "form" && firstChar == "{") return lexical.indented;
+ else if (type == "form") return lexical.indented + indentUnit;
+ else if (type == "stat")
+ return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0);
+ else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
+ return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
+ else if (lexical.align) return lexical.column + (closing ? 0 : 1);
+ else return lexical.indented + (closing ? 0 : indentUnit);
+ },
+
+ electricChars: ":{}",
+ blockCommentStart: jsonMode ? null : "/*",
+ blockCommentEnd: jsonMode ? null : "*/",
+ lineComment: jsonMode ? null : "//",
+ fold: "brace",
+
+ helperType: jsonMode ? "json" : "javascript",
+ jsonldMode: jsonldMode,
+ jsonMode: jsonMode
+ };
+});
+
+CodeMirror.defineMIME("text/javascript", "javascript");
+CodeMirror.defineMIME("text/ecmascript", "javascript");
+CodeMirror.defineMIME("application/javascript", "javascript");
+CodeMirror.defineMIME("application/ecmascript", "javascript");
+CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
+CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
+CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
+CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
+CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
+
+});
+;(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
+CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
+ var htmlMode = CodeMirror.getMode(config, {name: "xml",
+ htmlMode: true,
+ multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
+ multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
+ var cssMode = CodeMirror.getMode(config, "css");
+
+ var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
+ scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
+ mode: CodeMirror.getMode(config, "javascript")});
+ if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
+ var conf = scriptTypesConf[i];
+ scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
+ }
+ scriptTypes.push({matches: /./,
+ mode: CodeMirror.getMode(config, "text/plain")});
+
+ function html(stream, state) {
+ var tagName = state.htmlState.tagName;
+ var style = htmlMode.token(stream, state.htmlState);
+ if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
+ // Script block: mode to change to depends on type attribute
+ var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
+ scriptType = scriptType ? scriptType[1] : "";
+ if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
+ for (var i = 0; i < scriptTypes.length; ++i) {
+ var tp = scriptTypes[i];
+ if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
+ if (tp.mode) {
+ state.token = script;
+ state.localMode = tp.mode;
+ state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
+ }
+ break;
+ }
+ }
+ } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
+ state.token = css;
+ state.localMode = cssMode;
+ state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
+ }
+ return style;
+ }
+ function maybeBackup(stream, pat, style) {
+ var cur = stream.current();
+ var close = cur.search(pat), m;
+ if (close > -1) stream.backUp(cur.length - close);
+ else if (m = cur.match(/<\/?$/)) {
+ stream.backUp(cur.length);
+ if (!stream.match(pat, false)) stream.match(cur);
+ }
+ return style;
+ }
+ function script(stream, state) {
+ if (stream.match(/^<\/\s*script\s*>/i, false)) {
+ state.token = html;
+ state.localState = state.localMode = null;
+ return html(stream, state);
+ }
+ return maybeBackup(stream, /<\/\s*script\s*>/,
+ state.localMode.token(stream, state.localState));
+ }
+ function css(stream, state) {
+ if (stream.match(/^<\/\s*style\s*>/i, false)) {
+ state.token = html;
+ state.localState = state.localMode = null;
+ return html(stream, state);
+ }
+ return maybeBackup(stream, /<\/\s*style\s*>/,
+ cssMode.token(stream, state.localState));
+ }
+
+ return {
+ startState: function() {
+ var state = htmlMode.startState();
+ return {token: html, localMode: null, localState: null, htmlState: state};
+ },
+
+ copyState: function(state) {
+ if (state.localState)
+ var local = CodeMirror.copyState(state.localMode, state.localState);
+ return {token: state.token, localMode: state.localMode, localState: local,
+ htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
+ },
+
+ token: function(stream, state) {
+ return state.token(stream, state);
+ },
+
+ indent: function(state, textAfter) {
+ if (!state.localMode || /^\s*<\//.test(textAfter))
+ return htmlMode.indent(state.htmlState, textAfter);
+ else if (state.localMode.indent)
+ return state.localMode.indent(state.localState, textAfter);
+ else
+ return CodeMirror.Pass;
+ },
+
+ innerMode: function(state) {
+ return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
+ }
+ };
+}, "xml", "javascript", "css");
+
+CodeMirror.defineMIME("text/html", "htmlmixed");
+
+});
+;// Underscore.js 1.3.3
+// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+
+var _ = (function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `global` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Establish the object that gets returned to break out of a loop iteration.
+ var breaker = {};
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var slice = ArrayProto.slice,
+ unshift = ArrayProto.unshift,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeForEach = ArrayProto.forEach,
+ nativeMap = ArrayProto.map,
+ nativeReduce = ArrayProto.reduce,
+ nativeReduceRight = ArrayProto.reduceRight,
+ nativeFilter = ArrayProto.filter,
+ nativeEvery = ArrayProto.every,
+ nativeSome = ArrayProto.some,
+ nativeIndexOf = ArrayProto.indexOf,
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind;
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) { return new wrapper(obj); };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object via a string identifier,
+ // for Closure Compiler "advanced" mode.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root['_'] = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.3.3';
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles objects with the built-in `forEach`, arrays, and raw objects.
+ // Delegates to **ECMAScript 5**'s native `forEach` if available.
+ var each = _.each = _.forEach = function(obj, iterator, context) {
+ if (obj == null) return;
+ if (nativeForEach && obj.forEach === nativeForEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length === +obj.length) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
+ }
+ } else {
+ for (var key in obj) {
+ if (_.has(obj, key)) {
+ if (iterator.call(context, obj[key], key, obj) === breaker) return;
+ }
+ }
+ }
+ };
+
+ // Return the results of applying the iterator to each element.
+ // Delegates to **ECMAScript 5**'s native `map` if available.
+ _.map = _.collect = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+ each(obj, function(value, index, list) {
+ results[results.length] = iterator.call(context, value, index, list);
+ });
+ if (obj.length === +obj.length) results.length = obj.length;
+ return results;
+ };
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
+ _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduce && obj.reduce === nativeReduce) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+ }
+ each(obj, function(value, index, list) {
+ if (!initial) {
+ memo = value;
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, value, index, list);
+ }
+ });
+ if (!initial) throw new TypeError('Reduce of empty array with no initial value');
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as `foldr`.
+ // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+ _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ }
+ var reversed = _.toArray(obj).reverse();
+ if (context && !initial) iterator = _.bind(iterator, context);
+ return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
+ };
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, iterator, context) {
+ var result;
+ any(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test.
+ // Delegates to **ECMAScript 5**'s native `filter` if available.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+ each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ each(obj, function(value, index, list) {
+ if (!iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Delegates to **ECMAScript 5**'s native `every` if available.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, iterator, context) {
+ var result = true;
+ if (obj == null) return result;
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+ each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Delegates to **ECMAScript 5**'s native `some` if available.
+ // Aliased as `any`.
+ var any = _.some = _.any = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = false;
+ if (obj == null) return result;
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+ each(obj, function(value, index, list) {
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if a given value is included in the array or object using `===`.
+ // Aliased as `contains`.
+ _.include = _.contains = function(obj, target) {
+ var found = false;
+ if (obj == null) return found;
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ found = any(obj, function(value) {
+ return value === target;
+ });
+ return found;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ return _.map(obj, function(value) {
+ return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ // Return the maximum element or (element-based computation).
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.max.apply(Math, obj);
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
+ var result = {computed : -Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj);
+ if (!iterator && _.isEmpty(obj)) return Infinity;
+ var result = {computed : Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Shuffle an array.
+ _.shuffle = function(obj) {
+ var shuffled = [], rand;
+ each(obj, function(value, index, list) {
+ rand = Math.floor(Math.random() * (index + 1));
+ shuffled[index] = shuffled[rand];
+ shuffled[rand] = value;
+ });
+ return shuffled;
+ };
+
+ // Sort the object's values by a criterion produced by an iterator.
+ _.sortBy = function(obj, val, context) {
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ if (a === void 0) return 1;
+ if (b === void 0) return -1;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }), 'value');
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = function(obj, val) {
+ var result = {};
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
+ each(obj, function(value, index) {
+ var key = iterator(value, index);
+ (result[key] || (result[key] = [])).push(value);
+ });
+ return result;
+ };
+
+ // Use a comparator function to figure out at what index an object should
+ // be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator) {
+ iterator || (iterator = _.identity);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >> 1;
+ iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ // Safely convert anything iterable into a real, live array.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (_.isArguments(obj)) return slice.call(obj);
+ if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ return _.isArray(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ // Returns everything but the last entry of the array. Especcialy useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N. The **guard** check allows it to work with
+ // `_.map`.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array. The **guard** check allows it to work with `_.map`.
+ _.last = function(array, n, guard) {
+ if ((n != null) && !guard) {
+ return slice.call(array, Math.max(array.length - n, 0));
+ } else {
+ return array[array.length - 1];
+ }
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail`.
+ // Especially useful on the arguments object. Passing an **index** will return
+ // the rest of the values in the array from that index onward. The **guard**
+ // check allows it to work with `_.map`.
+ _.rest = _.tail = function(array, index, guard) {
+ return slice.call(array, (index == null) || guard ? 1 : index);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, function(value){ return !!value; });
+ };
+
+ // Return a completely flattened version of an array.
+ _.flatten = function(array, shallow) {
+ return _.reduce(array, function(memo, value) {
+ if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
+ memo[memo.length] = value;
+ return memo;
+ }, []);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iterator) {
+ var initial = iterator ? _.map(array, iterator) : array;
+ var results = [];
+ // The `isSorted` flag is irrelevant if the array only contains two elements.
+ if (array.length < 3) isSorted = true;
+ _.reduce(initial, function (memo, value, index) {
+ if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {
+ memo.push(value);
+ results.push(array[index]);
+ }
+ return memo;
+ }, []);
+ return results;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(_.flatten(arguments, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays. (Aliased as "intersect" for back-compat.)
+ _.intersection = _.intersect = function(array) {
+ var rest = slice.call(arguments, 1);
+ return _.filter(_.uniq(array), function(item) {
+ return _.every(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = _.flatten(slice.call(arguments, 1), true);
+ return _.filter(array, function(value){ return !_.include(rest, value); });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ var args = slice.call(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
+ return results;
+ };
+
+ // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+ // we need this function. Return the position of the first occurrence of an
+ // item in an array, or -1 if the item is not included in the array.
+ // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = function(array, item, isSorted) {
+ if (array == null) return -1;
+ var i, l;
+ if (isSorted) {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
+ for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
+ return -1;
+ };
+
+ // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+ _.lastIndexOf = function(array, item) {
+ if (array == null) return -1;
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
+ var i = array.length;
+ while (i--) if (i in array && array[i] === item) return i;
+ return -1;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (arguments.length <= 1) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = arguments[2] || 1;
+
+ var len = Math.max(Math.ceil((stop - start) / step), 0);
+ var idx = 0;
+ var range = new Array(len);
+
+ while(idx < len) {
+ range[idx++] = start;
+ start += step;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Reusable constructor function for prototype setting.
+ var ctor = function(){};
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Binding with arguments is also known as `curry`.
+ // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
+ // We check for `func.bind` first, to fail fast when `func` is undefined.
+ _.bind = function bind(func, context) {
+ var bound, args;
+ if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError;
+ args = slice.call(arguments, 2);
+ return bound = function() {
+ if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
+ ctor.prototype = func.prototype;
+ var self = new ctor;
+ var result = func.apply(self, args.concat(slice.call(arguments)));
+ if (Object(result) === result) return result;
+ return self;
+ };
+ };
+
+ // Bind all of an object's methods to that object. Useful for ensuring that
+ // all callbacks defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var funcs = slice.call(arguments, 1);
+ if (funcs.length == 0) funcs = _.functions(obj);
+ each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memo = {};
+ hasher || (hasher = _.identity);
+ return function() {
+ var key = hasher.apply(this, arguments);
+ return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+ };
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){ return func.apply(null, args); }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+ };
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time.
+ _.throttle = function(func, wait) {
+ var context, args, timeout, throttling, more, result;
+ var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
+ return function() {
+ context = this; args = arguments;
+ var later = function() {
+ timeout = null;
+ if (more) func.apply(context, args);
+ whenDone();
+ };
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (throttling) {
+ more = true;
+ } else {
+ result = func.apply(context, args);
+ }
+ whenDone();
+ throttling = true;
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) func.apply(context, args);
+ };
+ if (immediate && !timeout) func.apply(context, args);
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = function(func) {
+ var ran = false, memo;
+ return function() {
+ if (ran) return memo;
+ ran = true;
+ return memo = func.apply(this, arguments);
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func].concat(slice.call(arguments, 0));
+ return wrapper.apply(this, args);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var funcs = arguments;
+ return function() {
+ var args = arguments;
+ for (var i = funcs.length - 1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+
+ // Returns a function that will only be executed after being called N times.
+ _.after = function(times, func) {
+ if (times <= 0) return func();
+ return function() {
+ if (--times < 1) { return func.apply(this, arguments); }
+ };
+ };
+
+ // Object Functions
+ // ----------------
+
+ // Retrieve the names of an object's properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = nativeKeys || function(obj) {
+ if (obj !== Object(obj)) throw new TypeError('Invalid object');
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ return _.map(obj, _.identity);
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ obj[prop] = source[prop];
+ }
+ });
+ return obj;
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(obj) {
+ var result = {};
+ each(_.flatten(slice.call(arguments, 1)), function(key) {
+ if (key in obj) result[key] = obj[key];
+ });
+ return result;
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ if (obj[prop] == null) obj[prop] = source[prop];
+ }
+ });
+ return obj;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Internal recursive comparison function.
+ function eq(a, b, stack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
+ if (a === b) return a !== 0 || 1 / a == 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a._chain) a = a._wrapped;
+ if (b._chain) b = b._wrapped;
+ // Invoke a custom `isEqual` method if one is provided.
+ if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
+ if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className != toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, dates, and booleans are compared by value.
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return a == String(b);
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
+ // other numeric values.
+ return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a == +b;
+ // RegExps are compared by their source patterns and flags.
+ case '[object RegExp]':
+ return a.source == b.source &&
+ a.global == b.global &&
+ a.multiline == b.multiline &&
+ a.ignoreCase == b.ignoreCase;
+ }
+ if (typeof a != 'object' || typeof b != 'object') return false;
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+ var length = stack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (stack[length] == a) return true;
+ }
+ // Add the first object to the stack of traversed objects.
+ stack.push(a);
+ var size = 0, result = true;
+ // Recursively compare objects and arrays.
+ if (className == '[object Array]') {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ size = a.length;
+ result = size == b.length;
+ if (result) {
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (size--) {
+ // Ensure commutative equality for sparse arrays.
+ if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
+ }
+ }
+ } else {
+ // Objects with different constructors are not equivalent.
+ if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
+ // Deep compare objects.
+ for (var key in a) {
+ if (_.has(a, key)) {
+ // Count the expected number of properties.
+ size++;
+ // Deep compare each member.
+ if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
+ }
+ }
+ // Ensure that both objects contain the same number of properties.
+ if (result) {
+ for (key in b) {
+ if (_.has(b, key) && !(size--)) break;
+ }
+ result = !size;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ stack.pop();
+ return result;
+ }
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b, []);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+ for (var key in obj) if (_.has(obj, key)) return false;
+ return true;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType == 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) == '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ return obj === Object(obj);
+ };
+
+ // Is a given variable an arguments object?
+ _.isArguments = function(obj) {
+ return toString.call(obj) == '[object Arguments]';
+ };
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return !!(obj && _.has(obj, 'callee'));
+ };
+ }
+
+ // Is a given value a function?
+ _.isFunction = function(obj) {
+ return toString.call(obj) == '[object Function]';
+ };
+
+ // Is a given value a string?
+ _.isString = function(obj) {
+ return toString.call(obj) == '[object String]';
+ };
+
+ // Is a given value a number?
+ _.isNumber = function(obj) {
+ return toString.call(obj) == '[object Number]';
+ };
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return _.isNumber(obj) && isFinite(obj);
+ };
+
+ // Is the given value `NaN`?
+ _.isNaN = function(obj) {
+ // `NaN` is the only value for which `===` is not reflexive.
+ return obj !== obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+ };
+
+ // Is a given value a date?
+ _.isDate = function(obj) {
+ return toString.call(obj) == '[object Date]';
+ };
+
+ // Is the given value a regular expression?
+ _.isRegExp = function(obj) {
+ return toString.call(obj) == '[object RegExp]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Has own property?
+ _.has = function(obj, key) {
+ return hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iterators.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Run a function **n** times.
+ _.times = function (n, iterator, context) {
+ for (var i = 0; i < n; i++) iterator.call(context, i);
+ };
+
+ // Escape a string for HTML interpolation.
+ _.escape = function(string) {
+ return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
+ };
+
+ // If the value of the named property is a function then invoke it;
+ // otherwise, return it.
+ _.result = function(object, property) {
+ if (object == null) return null;
+ var value = object[property];
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Add your own custom functions to the Underscore object, ensuring that
+ // they're correctly added to the OOP wrapper as well.
+ _.mixin = function(obj) {
+ each(_.functions(obj), function(name){
+ addToWrapper(name, _[name] = obj[name]);
+ });
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = idCounter++;
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /.^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ '\\': '\\',
+ "'": "'",
+ 'r': '\r',
+ 'n': '\n',
+ 't': '\t',
+ 'u2028': '\u2028',
+ 'u2029': '\u2029'
+ };
+
+ for (var p in escapes) escapes[escapes[p]] = p;
+ var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
+ var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
+
+ // Within an interpolation, evaluation, or escaping, remove HTML escaping
+ // that had been previously added.
+ var unescape = function(code) {
+ return code.replace(unescaper, function(match, escape) {
+ return escapes[escape];
+ });
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ _.template = function(text, data, settings) {
+ settings = _.defaults(settings || {}, _.templateSettings);
+
+ // Compile the template source, taking care to escape characters that
+ // cannot be included in a string literal and then unescape them in code
+ // blocks.
+ var source = "__p+='" + text
+ .replace(escaper, function(match) {
+ return '\\' + escapes[match];
+ })
+ .replace(settings.escape || noMatch, function(match, code) {
+ return "'+\n_.escape(" + unescape(code) + ")+\n'";
+ })
+ .replace(settings.interpolate || noMatch, function(match, code) {
+ return "'+\n(" + unescape(code) + ")+\n'";
+ })
+ .replace(settings.evaluate || noMatch, function(match, code) {
+ return "';\n" + unescape(code) + "\n;__p+='";
+ }) + "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __p='';" +
+ "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" +
+ source + "return __p;\n";
+
+ var render = new Function(settings.variable || 'obj', '_', source);
+ if (data) return render(data, _);
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled function source as a convenience for build time
+ // precompilation.
+ template.source = 'function(' + (settings.variable || 'obj') + '){\n' +
+ source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function, which will delegate to the wrapper.
+ _.chain = function(obj) {
+ return _(obj).chain();
+ };
+
+ // The OOP Wrapper
+ // ---------------
+
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+ var wrapper = function(obj) { this._wrapped = obj; };
+
+ // Expose `wrapper.prototype` as `_.prototype`
+ _.prototype = wrapper.prototype;
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(obj, chain) {
+ return chain ? _(obj).chain() : obj;
+ };
+
+ // A method to easily add functions to the OOP wrapper.
+ var addToWrapper = function(name, func) {
+ wrapper.prototype[name] = function() {
+ var args = slice.call(arguments);
+ unshift.call(args, this._wrapped);
+ return result(func.apply(_, args), this._chain);
+ };
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ wrapper.prototype[name] = function() {
+ var wrapped = this._wrapped;
+ method.apply(wrapped, arguments);
+ var length = wrapped.length;
+ if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
+ return result(wrapped, this._chain);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ wrapper.prototype[name] = function() {
+ return result(method.apply(this._wrapped, arguments), this._chain);
+ };
+ });
+
+ // Start chaining a wrapped Underscore object.
+ wrapper.prototype.chain = function() {
+ this._chain = true;
+ return this;
+ };
+
+ // Extracts the result from a wrapped and chained object.
+ wrapper.prototype.value = function() {
+ return this._wrapped;
+ };
+ return _;
+}).call({});
+/**
+ * Core Emmet object, available in global scope
+ */
+var emmet = (function(global) {
+ var defaultSyntax = 'html';
+ var defaultProfile = 'plain';
+
+ if (typeof _ == 'undefined') {
+ try {
+ // avoid collisions with RequireJS loader
+ // also, JS obfuscators tends to translate
+ // a["name"] to a.name, which also breaks RequireJS
+ _ = global[['require'][0]]('underscore'); // node.js
+ } catch (e) {}
+ }
+
+ if (typeof _ == 'undefined') {
+ throw 'Cannot access to Underscore.js lib';
+ }
+
+ /** List of registered modules */
+ var modules = {
+ _ : _
+ };
+
+ /**
+ * Shared empty constructor function to aid in prototype-chain creation.
+ */
+ var ctor = function(){};
+
+ /**
+ * Helper function to correctly set up the prototype chain, for subclasses.
+ * Similar to `goog.inherits`, but uses a hash of prototype properties and
+ * class properties to be extended.
+ * Took it from Backbone.
+ * @param {Object} parent
+ * @param {Object} protoProps
+ * @param {Object} staticProps
+ * @returns {Object}
+ */
+ function inherits(parent, protoProps, staticProps) {
+ var child;
+
+ // The constructor function for the new subclass is either defined by
+ // you (the "constructor" property in your `extend` definition), or
+ // defaulted by us to simply call the parent's constructor.
+ if (protoProps && protoProps.hasOwnProperty('constructor')) {
+ child = protoProps.constructor;
+ } else {
+ child = function() {
+ parent.apply(this, arguments);
+ };
+ }
+
+ // Inherit class (static) properties from parent.
+ _.extend(child, parent);
+
+ // Set the prototype chain to inherit from `parent`, without calling
+ // `parent`'s constructor function.
+ ctor.prototype = parent.prototype;
+ child.prototype = new ctor();
+
+ // Add prototype properties (instance properties) to the subclass,
+ // if supplied.
+ if (protoProps)
+ _.extend(child.prototype, protoProps);
+
+ // Add static properties to the constructor function, if supplied.
+ if (staticProps)
+ _.extend(child, staticProps);
+
+ // Correctly set child's `prototype.constructor`.
+ child.prototype.constructor = child;
+
+ // Set a convenience property in case the parent's prototype is needed
+ // later.
+ child.__super__ = parent.prototype;
+
+ return child;
+ };
+
+ /**
+ * @type Function Function that loads module definition if it's not defined
+ */
+ var moduleLoader = null;
+
+ /**
+ * Generic Emmet module loader (actually, it doesn’t load anything, just
+ * returns module reference). Not using `require` name to avoid conflicts
+ * with Node.js and RequireJS
+ */
+ function r(name) {
+ if (!(name in modules) && moduleLoader)
+ moduleLoader(name);
+
+ return modules[name];
+ }
+
+ return {
+ /**
+ * Simple, AMD-like module definition. The module will be added into
+ * emmet object and will be available via
+ * emmet.require(name) or emmet[name]
+ * @param {String} name
+ * @param {Function} factory
+ * @memberOf emmet
+ */
+ define: function(name, factory) {
+ // do not let redefine existing properties
+ if (!(name in modules)) {
+ modules[name] = _.isFunction(factory)
+ ? this.exec(factory)
+ : factory;
+ }
+ },
+
+ /**
+ * Returns reference to Emmet module
+ * @param {String} name Module name
+ */
+ require: r,
+
+ /**
+ * Helper method that just executes passed function but with all
+ * important arguments like 'require' and '_'
+ * @param {Function} fn
+ * @param {Object} context Execution context
+ */
+ exec: function(fn, context) {
+ return fn.call(context || global, _.bind(r, this), _, this);
+ },
+
+ /**
+ * The self-propagating extend function for classes.
+ * Took it from Backbone
+ * @param {Object} protoProps
+ * @param {Object} classProps
+ * @returns {Object}
+ */
+ extend: function(protoProps, classProps) {
+ var child = inherits(this, protoProps, classProps);
+ child.extend = this.extend;
+ // a hack required to WSH inherit `toString` method
+ if (protoProps.hasOwnProperty('toString'))
+ child.prototype.toString = protoProps.toString;
+ return child;
+ },
+
+ /**
+ * The essential function that expands Emmet abbreviation
+ * @param {String} abbr Abbreviation to parse
+ * @param {String} syntax Abbreviation's context syntax
+ * @param {String} profile Output profile (or its name)
+ * @param {Object} contextNode Contextual node where abbreviation is
+ * written
+ * @return {String}
+ */
+ expandAbbreviation: function(abbr, syntax, profile, contextNode) {
+ if (!abbr) return '';
+
+ syntax = syntax || defaultSyntax;
+// profile = profile || defaultProfile;
+
+ var filters = r('filters');
+ var parser = r('abbreviationParser');
+
+ profile = r('profile').get(profile, syntax);
+ r('tabStops').resetTabstopIndex();
+
+ var data = filters.extractFromAbbreviation(abbr);
+ var outputTree = parser.parse(data[0], {
+ syntax: syntax,
+ contextNode: contextNode
+ });
+
+ var filtersList = filters.composeList(syntax, profile, data[1]);
+ filters.apply(outputTree, filtersList, profile);
+ return outputTree.toString();
+ },
+
+ /**
+ * Returns default syntax name used in abbreviation engine
+ * @returns {String}
+ */
+ defaultSyntax: function() {
+ return defaultSyntax;
+ },
+
+ /**
+ * Returns default profile name used in abbreviation engine
+ * @returns {String}
+ */
+ defaultProfile: function() {
+ return defaultProfile;
+ },
+
+ /**
+ * Log message into console if it exists
+ */
+ log: function() {
+ if (global.console && global.console.log)
+ global.console.log.apply(global.console, arguments);
+ },
+
+ /**
+ * Setups function that should synchronously load undefined modules
+ * @param {Function} fn
+ */
+ setModuleLoader: function(fn) {
+ moduleLoader = fn;
+ }
+ };
+})(this);
+
+// export core for Node.JS
+if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = emmet;
+ }
+ exports.emmet = emmet;
+}
+
+// export as Require.js module
+if (typeof define !== 'undefined') {
+ define(emmet);
+}/**
+ * Emmet abbreviation parser.
+ * Takes string abbreviation and recursively parses it into a tree. The parsed
+ * tree can be transformed into a string representation with
+ * toString() method. Note that string representation is defined
+ * by custom processors (called filters ), not by abbreviation parser
+ * itself.
+ *
+ * This module can be extended with custom pre-/post-processors to shape-up
+ * final tree or its representation. Actually, many features of abbreviation
+ * engine are defined in other modules as tree processors
+ *
+ *
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ * @memberOf __abbreviationParser
+ * @constructor
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('abbreviationParser', function(require, _) {
+ var reValidName = /^[\w\-\$\:@\!%]+\+?$/i;
+ var reWord = /[\w\-:\$@]/;
+
+ var pairs = {
+ '[': ']',
+ '(': ')',
+ '{': '}'
+ };
+
+ var spliceFn = Array.prototype.splice;
+
+ var preprocessors = [];
+ var postprocessors = [];
+ var outputProcessors = [];
+
+ /**
+ * @type AbbreviationNode
+ */
+ function AbbreviationNode(parent) {
+ /** @type AbbreviationNode */
+ this.parent = null;
+ this.children = [];
+ this._attributes = [];
+
+ /** @type String Raw abbreviation for current node */
+ this.abbreviation = '';
+ this.counter = 1;
+ this._name = null;
+ this._text = '';
+ this.repeatCount = 1;
+ this.hasImplicitRepeat = false;
+
+ /** Custom data dictionary */
+ this._data = {};
+
+ // output properties
+ this.start = '';
+ this.end = '';
+ this.content = '';
+ this.padding = '';
+ }
+
+ AbbreviationNode.prototype = {
+ /**
+ * Adds passed node as child or creates new child
+ * @param {AbbreviationNode} child
+ * @param {Number} position Index in children array where child should
+ * be inserted
+ * @return {AbbreviationNode}
+ */
+ addChild: function(child, position) {
+ child = child || new AbbreviationNode;
+ child.parent = this;
+
+ if (_.isUndefined(position)) {
+ this.children.push(child);
+ } else {
+ this.children.splice(position, 0, child);
+ }
+
+ return child;
+ },
+
+ /**
+ * Creates a deep copy of current node
+ * @returns {AbbreviationNode}
+ */
+ clone: function() {
+ var node = new AbbreviationNode();
+ var attrs = ['abbreviation', 'counter', '_name', '_text', 'repeatCount', 'hasImplicitRepeat', 'start', 'end', 'content', 'padding'];
+ _.each(attrs, function(a) {
+ node[a] = this[a];
+ }, this);
+
+ // clone attributes
+ node._attributes = _.map(this._attributes, function(attr) {
+ return _.clone(attr);
+ });
+
+ node._data = _.clone(this._data);
+
+ // clone children
+ node.children = _.map(this.children, function(child) {
+ child = child.clone();
+ child.parent = node;
+ return child;
+ });
+
+ return node;
+ },
+
+ /**
+ * Removes current node from parent‘s child list
+ * @returns {AbbreviationNode} Current node itself
+ */
+ remove: function() {
+ if (this.parent) {
+ this.parent.children = _.without(this.parent.children, this);
+ }
+
+ return this;
+ },
+
+ /**
+ * Replaces current node in parent‘s children list with passed nodes
+ * @param {AbbreviationNode} node Replacement node or array of nodes
+ */
+ replace: function() {
+ var parent = this.parent;
+ var ix = _.indexOf(parent.children, this);
+ var items = _.flatten(arguments);
+ spliceFn.apply(parent.children, [ix, 1].concat(items));
+
+ // update parent
+ _.each(items, function(item) {
+ item.parent = parent;
+ });
+ },
+
+ /**
+ * Recursively sets property to value of current
+ * node and its children
+ * @param {String} name Property to update
+ * @param {Object} value New property value
+ */
+ updateProperty: function(name, value) {
+ this[name] = value;
+ _.each(this.children, function(child) {
+ child.updateProperty(name, value);
+ });
+
+ return this;
+ },
+
+ /**
+ * Finds first child node that matches truth test for passed
+ * fn function
+ * @param {Function} fn
+ * @returns {AbbreviationNode}
+ */
+ find: function(fn) {
+ return this.findAll(fn)[0];
+// if (!_.isFunction(fn)) {
+// var elemName = fn.toLowerCase();
+// fn = function(item) {return item.name().toLowerCase() == elemName;};
+// }
+//
+// var result = null;
+// _.find(this.children, function(child) {
+// if (fn(child)) {
+// return result = child;
+// }
+//
+// return result = child.find(fn);
+// });
+//
+// return result;
+ },
+
+ /**
+ * Finds all child nodes that matches truth test for passed
+ * fn function
+ * @param {Function} fn
+ * @returns {Array}
+ */
+ findAll: function(fn) {
+ if (!_.isFunction(fn)) {
+ var elemName = fn.toLowerCase();
+ fn = function(item) {return item.name().toLowerCase() == elemName;};
+ }
+
+ var result = [];
+ _.each(this.children, function(child) {
+ if (fn(child))
+ result.push(child);
+
+ result = result.concat(child.findAll(fn));
+ });
+
+ return _.compact(result);
+ },
+
+ /**
+ * Sets/gets custom data
+ * @param {String} name
+ * @param {Object} value
+ * @returns {Object}
+ */
+ data: function(name, value) {
+ if (arguments.length == 2) {
+ this._data[name] = value;
+
+ if (name == 'resource' && require('elements').is(value, 'snippet')) {
+ // setting snippet as matched resource: update `content`
+ // property with snippet value
+ this.content = value.data;
+ if (this._text) {
+ this.content = require('abbreviationUtils')
+ .insertChildContent(value.data, this._text);
+ }
+ }
+ }
+
+ return this._data[name];
+ },
+
+ /**
+ * Returns name of current node
+ * @returns {String}
+ */
+ name: function() {
+ var res = this.matchedResource();
+ if (require('elements').is(res, 'element')) {
+ return res.name;
+ }
+
+ return this._name;
+ },
+
+ /**
+ * Returns list of attributes for current node
+ * @returns {Array}
+ */
+ attributeList: function() {
+ var attrs = [];
+
+ var res = this.matchedResource();
+ if (require('elements').is(res, 'element') && _.isArray(res.attributes)) {
+ attrs = attrs.concat(res.attributes);
+ }
+
+ return optimizeAttributes(attrs.concat(this._attributes));
+ },
+
+ /**
+ * Returns or sets attribute value
+ * @param {String} name Attribute name
+ * @param {String} value New attribute value
+ * @returns {String}
+ */
+ attribute: function(name, value) {
+ if (arguments.length == 2) {
+ // modifying attribute
+ var ix = _.indexOf(_.pluck(this._attributes, 'name'), name.toLowerCase());
+ if (~ix) {
+ this._attributes[ix].value = value;
+ } else {
+ this._attributes.push({
+ name: name,
+ value: value
+ });
+ }
+ }
+
+ return (_.find(this.attributeList(), function(attr) {
+ return attr.name == name;
+ }) || {}).value;
+ },
+
+ /**
+ * Returns reference to the matched element, if any.
+ * See {@link elements} module for a list of available elements
+ * @returns {Object}
+ */
+ matchedResource: function() {
+ return this.data('resource');
+ },
+
+ /**
+ * Returns index of current node in parent‘s children list
+ * @returns {Number}
+ */
+ index: function() {
+ return this.parent ? _.indexOf(this.parent.children, this) : -1;
+ },
+
+ /**
+ * Sets how many times current element should be repeated
+ * @private
+ */
+ _setRepeat: function(count) {
+ if (count) {
+ this.repeatCount = parseInt(count, 10) || 1;
+ } else {
+ this.hasImplicitRepeat = true;
+ }
+ },
+
+ /**
+ * Sets abbreviation that belongs to current node
+ * @param {String} abbr
+ */
+ setAbbreviation: function(abbr) {
+ abbr = abbr || '';
+
+ var that = this;
+
+ // find multiplier
+ abbr = abbr.replace(/\*(\d+)?$/, function(str, repeatCount) {
+ that._setRepeat(repeatCount);
+ return '';
+ });
+
+ this.abbreviation = abbr;
+
+ var abbrText = extractText(abbr);
+ if (abbrText) {
+ abbr = abbrText.element;
+ this.content = this._text = abbrText.text;
+ }
+
+ var abbrAttrs = parseAttributes(abbr);
+ if (abbrAttrs) {
+ abbr = abbrAttrs.element;
+ this._attributes = abbrAttrs.attributes;
+ }
+
+ this._name = abbr;
+
+ // validate name
+ if (this._name && !reValidName.test(this._name)) {
+ throw 'Invalid abbreviation';
+ }
+ },
+
+ /**
+ * Returns string representation of current node
+ * @return {String}
+ */
+ toString: function() {
+ var utils = require('utils');
+
+ var start = this.start;
+ var end = this.end;
+ var content = this.content;
+
+ // apply output processors
+ var node = this;
+ _.each(outputProcessors, function(fn) {
+ start = fn(start, node, 'start');
+ content = fn(content, node, 'content');
+ end = fn(end, node, 'end');
+ });
+
+
+ var innerContent = _.map(this.children, function(child) {
+ return child.toString();
+ }).join('');
+
+ content = require('abbreviationUtils').insertChildContent(content, innerContent, {
+ keepVariable: false
+ });
+
+ return start + utils.padString(content, this.padding) + end;
+ },
+
+ /**
+ * Check if current node contains children with empty expr
+ * property
+ * @return {Boolean}
+ */
+ hasEmptyChildren: function() {
+ return !!_.find(this.children, function(child) {
+ return child.isEmpty();
+ });
+ },
+
+ /**
+ * Check if current node has implied name that should be resolved
+ * @returns {Boolean}
+ */
+ hasImplicitName: function() {
+ return !this._name && !this.isTextNode();
+ },
+
+ /**
+ * Indicates that current element is a grouping one, e.g. has no
+ * representation but serves as a container for other nodes
+ * @returns {Boolean}
+ */
+ isGroup: function() {
+ return !this.abbreviation;
+ },
+
+ /**
+ * Indicates empty node (i.e. without abbreviation). It may be a
+ * grouping node and should not be outputted
+ * @return {Boolean}
+ */
+ isEmpty: function() {
+ return !this.abbreviation && !this.children.length;
+ },
+
+ /**
+ * Indicates that current node should be repeated
+ * @returns {Boolean}
+ */
+ isRepeating: function() {
+ return this.repeatCount > 1 || this.hasImplicitRepeat;
+ },
+
+ /**
+ * Check if current node is a text-only node
+ * @return {Boolean}
+ */
+ isTextNode: function() {
+ return !this.name() && !this.attributeList().length;
+ },
+
+ /**
+ * Indicates whether this node may be used to build elements or snippets
+ * @returns {Boolean}
+ */
+ isElement: function() {
+ return !this.isEmpty() && !this.isTextNode();
+ },
+
+ /**
+ * Returns latest and deepest child of current tree
+ * @returns {AbbreviationNode}
+ */
+ deepestChild: function() {
+ if (!this.children.length)
+ return null;
+
+ var deepestChild = this;
+ while (deepestChild.children.length) {
+ deepestChild = _.last(deepestChild.children);
+ }
+
+ return deepestChild;
+ }
+ };
+
+ /**
+ * Returns stripped string: a string without first and last character.
+ * Used for “unquoting” strings
+ * @param {String} str
+ * @returns {String}
+ */
+ function stripped(str) {
+ return str.substring(1, str.length - 1);
+ }
+
+ function consumeQuotedValue(stream, quote) {
+ var ch;
+ while (ch = stream.next()) {
+ if (ch === quote)
+ return true;
+
+ if (ch == '\\')
+ continue;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parses abbreviation into a tree
+ * @param {String} abbr
+ * @returns {AbbreviationNode}
+ */
+ function parseAbbreviation(abbr) {
+ abbr = require('utils').trim(abbr);
+
+ var root = new AbbreviationNode;
+ var context = root.addChild(), ch;
+
+ /** @type StringStream */
+ var stream = require('stringStream').create(abbr);
+ var loopProtector = 1000, multiplier;
+
+ while (!stream.eol() && --loopProtector > 0) {
+ ch = stream.peek();
+
+ switch (ch) {
+ case '(': // abbreviation group
+ stream.start = stream.pos;
+ if (stream.skipToPair('(', ')')) {
+ var inner = parseAbbreviation(stripped(stream.current()));
+ if (multiplier = stream.match(/^\*(\d+)?/, true)) {
+ context._setRepeat(multiplier[1]);
+ }
+
+ _.each(inner.children, function(child) {
+ context.addChild(child);
+ });
+ } else {
+ throw 'Invalid abbreviation: mo matching ")" found for character at ' + stream.pos;
+ }
+ break;
+
+ case '>': // child operator
+ context = context.addChild();
+ stream.next();
+ break;
+
+ case '+': // sibling operator
+ context = context.parent.addChild();
+ stream.next();
+ break;
+
+ case '^': // climb up operator
+ var parent = context.parent || context;
+ context = (parent.parent || parent).addChild();
+ stream.next();
+ break;
+
+ default: // consume abbreviation
+ stream.start = stream.pos;
+ stream.eatWhile(function(c) {
+ if (c == '[' || c == '{') {
+ if (stream.skipToPair(c, pairs[c])) {
+ stream.backUp(1);
+ return true;
+ }
+
+ throw 'Invalid abbreviation: mo matching "' + pairs[c] + '" found for character at ' + stream.pos;
+ }
+
+ if (c == '+') {
+ // let's see if this is an expando marker
+ stream.next();
+ var isMarker = stream.eol() || ~'+>^*'.indexOf(stream.peek());
+ stream.backUp(1);
+ return isMarker;
+ }
+
+ return c != '(' && isAllowedChar(c);
+ });
+
+ context.setAbbreviation(stream.current());
+ stream.start = stream.pos;
+ }
+ }
+
+ if (loopProtector < 1)
+ throw 'Endless loop detected';
+
+ return root;
+ }
+
+ /**
+ * Extract attributes and their values from attribute set:
+ * [attr col=3 title="Quoted string"]
+ * @param {String} attrSet
+ * @returns {Array}
+ */
+ function extractAttributes(attrSet, attrs) {
+ attrSet = require('utils').trim(attrSet);
+ var result = [];
+
+ /** @type StringStream */
+ var stream = require('stringStream').create(attrSet);
+ stream.eatSpace();
+
+ while (!stream.eol()) {
+ stream.start = stream.pos;
+ if (stream.eatWhile(reWord)) {
+ var attrName = stream.current();
+ var attrValue = '';
+ if (stream.peek() == '=') {
+ stream.next();
+ stream.start = stream.pos;
+ var quote = stream.peek();
+
+ if (quote == '"' || quote == "'") {
+ stream.next();
+ if (consumeQuotedValue(stream, quote)) {
+ attrValue = stream.current();
+ // strip quotes
+ attrValue = attrValue.substring(1, attrValue.length - 1);
+ } else {
+ throw 'Invalid attribute value';
+ }
+ } else if (stream.eatWhile(/[^\s\]]/)) {
+ attrValue = stream.current();
+ } else {
+ throw 'Invalid attribute value';
+ }
+ }
+
+ result.push({
+ name: attrName,
+ value: attrValue
+ });
+ stream.eatSpace();
+ } else {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Parses tag attributes extracted from abbreviation. If attributes found,
+ * returns object with element and attributes
+ * properties
+ * @param {String} abbr
+ * @returns {Object} Returns null if no attributes found in
+ * abbreviation
+ */
+ function parseAttributes(abbr) {
+ /*
+ * Example of incoming data:
+ * #header
+ * .some.data
+ * .some.data#header
+ * [attr]
+ * #item[attr=Hello other="World"].class
+ */
+ var result = [];
+ var attrMap = {'#': 'id', '.': 'class'};
+ var nameEnd = null;
+
+ /** @type StringStream */
+ var stream = require('stringStream').create(abbr);
+ while (!stream.eol()) {
+ switch (stream.peek()) {
+ case '#': // id
+ case '.': // class
+ if (nameEnd === null)
+ nameEnd = stream.pos;
+
+ var attrName = attrMap[stream.peek()];
+
+ stream.next();
+ stream.start = stream.pos;
+ stream.eatWhile(reWord);
+ result.push({
+ name: attrName,
+ value: stream.current()
+ });
+ break;
+ case '[': //begin attribute set
+ if (nameEnd === null)
+ nameEnd = stream.pos;
+
+ stream.start = stream.pos;
+ if (!stream.skipToPair('[', ']'))
+ throw 'Invalid attribute set definition';
+
+ result = result.concat(
+ extractAttributes(stripped(stream.current()))
+ );
+ break;
+ default:
+ stream.next();
+ }
+ }
+
+ if (!result.length)
+ return null;
+
+ return {
+ element: abbr.substring(0, nameEnd),
+ attributes: optimizeAttributes(result)
+ };
+ }
+
+ /**
+ * Optimize attribute set: remove duplicates and merge class attributes
+ * @param attrs
+ */
+ function optimizeAttributes(attrs) {
+ // clone all attributes to make sure that original objects are
+ // not modified
+ attrs = _.map(attrs, function(attr) {
+ return _.clone(attr);
+ });
+
+ var lookup = {};
+ return _.filter(attrs, function(attr) {
+ if (!(attr.name in lookup)) {
+ return lookup[attr.name] = attr;
+ }
+
+ var la = lookup[attr.name];
+
+ if (attr.name.toLowerCase() == 'class') {
+ la.value += (la.value.length ? ' ' : '') + attr.value;
+ } else {
+ la.value = attr.value;
+ }
+
+ return false;
+ });
+ }
+
+ /**
+ * Extract text data from abbreviation: if a{hello} abbreviation
+ * is passed, returns object {element: 'a', text: 'hello'}.
+ * If nothing found, returns null
+ * @param {String} abbr
+ *
+ */
+ function extractText(abbr) {
+ if (!~abbr.indexOf('{'))
+ return null;
+
+ /** @type StringStream */
+ var stream = require('stringStream').create(abbr);
+ while (!stream.eol()) {
+ switch (stream.peek()) {
+ case '[':
+ case '(':
+ stream.skipToPair(stream.peek(), pairs[stream.peek()]); break;
+
+ case '{':
+ stream.start = stream.pos;
+ stream.skipToPair('{', '}');
+ return {
+ element: abbr.substring(0, stream.start),
+ text: stripped(stream.current())
+ };
+
+ default:
+ stream.next();
+ }
+ }
+ }
+
+ /**
+ * “Un-rolls“ contents of current node: recursively replaces all repeating
+ * children with their repeated clones
+ * @param {AbbreviationNode} node
+ * @returns {AbbreviationNode}
+ */
+ function unroll(node) {
+ for (var i = node.children.length - 1, j, child, maxCount; i >= 0; i--) {
+ child = node.children[i];
+
+ if (child.isRepeating()) {
+ maxCount = j = child.repeatCount;
+ child.repeatCount = 1;
+ child.updateProperty('counter', 1);
+ child.updateProperty('maxCount', maxCount);
+ while (--j > 0) {
+ child.parent.addChild(child.clone(), i + 1)
+ .updateProperty('counter', j + 1)
+ .updateProperty('maxCount', maxCount);
+ }
+ }
+ }
+
+ // to keep proper 'counter' property, we need to walk
+ // on children once again
+ _.each(node.children, unroll);
+
+ return node;
+ }
+
+ /**
+ * Optimizes tree node: replaces empty nodes with their children
+ * @param {AbbreviationNode} node
+ * @return {AbbreviationNode}
+ */
+ function squash(node) {
+ for (var i = node.children.length - 1; i >= 0; i--) {
+ /** @type AbbreviationNode */
+ var n = node.children[i];
+ if (n.isGroup()) {
+ n.replace(squash(n).children);
+ } else if (n.isEmpty()) {
+ n.remove();
+ }
+ }
+
+ _.each(node.children, squash);
+
+ return node;
+ }
+
+ function isAllowedChar(ch) {
+ var charCode = ch.charCodeAt(0);
+ var specialChars = '#.*:$-_!@|%';
+
+ return (charCode > 64 && charCode < 91) // uppercase letter
+ || (charCode > 96 && charCode < 123) // lowercase letter
+ || (charCode > 47 && charCode < 58) // number
+ || specialChars.indexOf(ch) != -1; // special character
+ }
+
+ // XXX add counter replacer function as output processor
+ outputProcessors.push(function(text, node) {
+ return require('utils').replaceCounter(text, node.counter, node.maxCount);
+ });
+
+ return {
+ /**
+ * Parses abbreviation into tree with respect of groups,
+ * text nodes and attributes. Each node of the tree is a single
+ * abbreviation. Tree represents actual structure of the outputted
+ * result
+ * @memberOf abbreviationParser
+ * @param {String} abbr Abbreviation to parse
+ * @param {Object} options Additional options for parser and processors
+ *
+ * @return {AbbreviationNode}
+ */
+ parse: function(abbr, options) {
+ options = options || {};
+
+ var tree = parseAbbreviation(abbr);
+
+ if (options.contextNode) {
+ // add info about context node –
+ // a parent XHTML node in editor inside which abbreviation is
+ // expanded
+ tree._name = options.contextNode.name;
+ var attrLookup = {};
+ _.each(tree._attributes, function(attr) {
+ attrLookup[attr.name] = attr;
+ });
+
+ _.each(options.contextNode.attributes, function(attr) {
+ if (attr.name in attrLookup) {
+ attrLookup[attr.name].value = attr.value;
+ } else {
+ attr = _.clone(attr);
+ tree._attributes.push(attr);
+ attrLookup[attr.name] = attr;
+ }
+ });
+ }
+
+
+ // apply preprocessors
+ _.each(preprocessors, function(fn) {
+ fn(tree, options);
+ });
+
+ tree = squash(unroll(tree));
+
+ // apply postprocessors
+ _.each(postprocessors, function(fn) {
+ fn(tree, options);
+ });
+
+ return tree;
+ },
+
+ AbbreviationNode: AbbreviationNode,
+
+ /**
+ * Add new abbreviation preprocessor. Preprocessor is a function
+ * that applies to a parsed abbreviation tree right after it get parsed.
+ * The passed tree is in unoptimized state.
+ * @param {Function} fn Preprocessor function. This function receives
+ * two arguments: parsed abbreviation tree (AbbreviationNode)
+ * and options hash that was passed to parse
+ * method
+ */
+ addPreprocessor: function(fn) {
+ if (!_.include(preprocessors, fn))
+ preprocessors.push(fn);
+ },
+
+ /**
+ * Removes registered preprocessor
+ */
+ removeFilter: function(fn) {
+ preprocessor = _.without(preprocessors, fn);
+ },
+
+ /**
+ * Adds new abbreviation postprocessor. Postprocessor is a
+ * functinon that applies to optimized parsed abbreviation tree
+ * right before it returns from parse() method
+ * @param {Function} fn Postprocessor function. This function receives
+ * two arguments: parsed abbreviation tree (AbbreviationNode)
+ * and options hash that was passed to parse
+ * method
+ */
+ addPostprocessor: function(fn) {
+ if (!_.include(postprocessors, fn))
+ postprocessors.push(fn);
+ },
+
+ /**
+ * Removes registered postprocessor function
+ */
+ removePostprocessor: function(fn) {
+ postprocessors = _.without(postprocessors, fn);
+ },
+
+ /**
+ * Registers output postprocessor. Output processor is a
+ * function that applies to output part (start,
+ * end and content) when
+ * AbbreviationNode.toString() method is called
+ */
+ addOutputProcessor: function(fn) {
+ if (!_.include(outputProcessors, fn))
+ outputProcessors.push(fn);
+ },
+
+ /**
+ * Removes registered output processor
+ */
+ removeOutputProcessor: function(fn) {
+ outputProcessors = _.without(outputProcessors, fn);
+ },
+
+ /**
+ * Check if passed symbol is valid symbol for abbreviation expression
+ * @param {String} ch
+ * @return {Boolean}
+ */
+ isAllowedChar: function(ch) {
+ ch = String(ch); // convert Java object to JS
+ return isAllowedChar(ch) || ~'>+^[](){}'.indexOf(ch);
+ }
+ };
+});/**
+ * Processor function that matches parsed AbbreviationNode
+ * against resources defined in resource module
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ /**
+ * Finds matched resources for child nodes of passed node
+ * element. A matched resource is a reference to snippets.json entry
+ * that describes output of parsed node
+ * @param {AbbreviationNode} node
+ * @param {String} syntax
+ */
+ function matchResources(node, syntax) {
+ var resources = require('resources');
+ var elements = require('elements');
+ var parser = require('abbreviationParser');
+
+ // do a shallow copy because the children list can be modified during
+ // resource matching
+ _.each(_.clone(node.children), /** @param {AbbreviationNode} child */ function(child) {
+ var r = resources.getMatchedResource(child, syntax);
+ if (_.isString(r)) {
+ child.data('resource', elements.create('snippet', r));
+ } else if (elements.is(r, 'reference')) {
+ // it’s a reference to another abbreviation:
+ // parse it and insert instead of current child
+ /** @type AbbreviationNode */
+ var subtree = parser.parse(r.data, {
+ syntax: syntax
+ });
+
+ // if context element should be repeated, check if we need to
+ // transfer repeated element to specific child node
+ if (child.repeatCount > 1) {
+ var repeatedChildren = subtree.findAll(function(node) {
+ return node.hasImplicitRepeat;
+ });
+
+ _.each(repeatedChildren, function(node) {
+ node.repeatCount = child.repeatCount;
+ node.hasImplicitRepeat = false;
+ });
+ }
+
+ // move child‘s children into the deepest child of new subtree
+ var deepestChild = subtree.deepestChild();
+ if (deepestChild) {
+ _.each(child.children, function(c) {
+ deepestChild.addChild(c);
+ });
+ }
+
+ // copy current attributes to children
+ _.each(subtree.children, function(node) {
+ _.each(child.attributeList(), function(attr) {
+ node.attribute(attr.name, attr.value);
+ });
+ });
+
+ child.replace(subtree.children);
+ } else {
+ child.data('resource', r);
+ }
+
+ matchResources(child, syntax);
+ });
+ }
+
+ // XXX register abbreviation filter that creates references to resources
+ // on abbreviation nodes
+ /**
+ * @param {AbbreviationNode} tree
+ */
+ require('abbreviationParser').addPreprocessor(function(tree, options) {
+ var syntax = options.syntax || emmet.defaultSyntax();
+ matchResources(tree, syntax);
+ });
+
+});/**
+ * Pasted content abbreviation processor. A pasted content is a content that
+ * should be inserted into implicitly repeated abbreviation nodes.
+ * This processor powers “Wrap With Abbreviation” action
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ var parser = require('abbreviationParser');
+ var outputPlaceholder = '$#';
+
+ /**
+ * Locates output placeholders inside text
+ * @param {String} text
+ * @returns {Array} Array of ranges of output placeholder in text
+ */
+ function locateOutputPlaceholder(text) {
+ var range = require('range');
+ var result = [];
+
+ /** @type StringStream */
+ var stream = require('stringStream').create(text);
+
+ while (!stream.eol()) {
+ if (stream.peek() == '\\') {
+ stream.next();
+ } else {
+ stream.start = stream.pos;
+ if (stream.match(outputPlaceholder, true)) {
+ result.push(range.create(stream.start, outputPlaceholder));
+ continue;
+ }
+ }
+ stream.next();
+ }
+
+ return result;
+ }
+
+ /**
+ * Replaces output placeholders inside source with
+ * value
+ * @param {String} source
+ * @param {String} value
+ * @returns {String}
+ */
+ function replaceOutputPlaceholders(source, value) {
+ var utils = require('utils');
+ var ranges = locateOutputPlaceholder(source);
+
+ ranges.reverse();
+ _.each(ranges, function(r) {
+ source = utils.replaceSubstring(source, value, r);
+ });
+
+ return source;
+ }
+
+ /**
+ * Check if parsed node contains output placeholder – a target where
+ * pasted content should be inserted
+ * @param {AbbreviationNode} node
+ * @returns {Boolean}
+ */
+ function hasOutputPlaceholder(node) {
+ if (locateOutputPlaceholder(node.content).length)
+ return true;
+
+ // check if attributes contains placeholder
+ return !!_.find(node.attributeList(), function(attr) {
+ return !!locateOutputPlaceholder(attr.value).length;
+ });
+ }
+
+ /**
+ * Insert pasted content into correct positions of parsed node
+ * @param {AbbreviationNode} node
+ * @param {String} content
+ * @param {Boolean} overwrite Overwrite node content if no value placeholders
+ * found instead of appending to existing content
+ */
+ function insertPastedContent(node, content, overwrite) {
+ var nodesWithPlaceholders = node.findAll(function(item) {
+ return hasOutputPlaceholder(item);
+ });
+
+ if (hasOutputPlaceholder(node))
+ nodesWithPlaceholders.unshift(node);
+
+ if (nodesWithPlaceholders.length) {
+ _.each(nodesWithPlaceholders, function(item) {
+ item.content = replaceOutputPlaceholders(item.content, content);
+ _.each(item._attributes, function(attr) {
+ attr.value = replaceOutputPlaceholders(attr.value, content);
+ });
+ });
+ } else {
+ // on output placeholders in subtree, insert content in the deepest
+ // child node
+ var deepest = node.deepestChild() || node;
+ if (overwrite) {
+ deepest.content = content;
+ } else {
+ deepest.content = require('abbreviationUtils').insertChildContent(deepest.content, content);
+ }
+ }
+ }
+
+ /**
+ * @param {AbbreviationNode} tree
+ * @param {Object} options
+ */
+ parser.addPreprocessor(function(tree, options) {
+ if (options.pastedContent) {
+ var utils = require('utils');
+ var lines = _.map(utils.splitByLines(options.pastedContent, true), utils.trim);
+
+ // set repeat count for implicitly repeated elements before
+ // tree is unrolled
+ tree.findAll(function(item) {
+ if (item.hasImplicitRepeat) {
+ item.data('paste', lines);
+ return item.repeatCount = lines.length;
+ }
+ });
+ }
+ });
+
+ /**
+ * @param {AbbreviationNode} tree
+ * @param {Object} options
+ */
+ parser.addPostprocessor(function(tree, options) {
+ // for each node with pasted content, update text data
+ var targets = tree.findAll(function(item) {
+ var pastedContentObj = item.data('paste');
+ var pastedContent = '';
+ if (_.isArray(pastedContentObj)) {
+ pastedContent = pastedContentObj[item.counter - 1];
+ } else if (_.isFunction(pastedContentObj)) {
+ pastedContent = pastedContentObj(item.counter - 1, item.content);
+ } else if (pastedContentObj) {
+ pastedContent = pastedContentObj;
+ }
+
+ if (pastedContent) {
+ insertPastedContent(item, pastedContent, !!item.data('pasteOverwrites'));
+ }
+
+ item.data('paste', null);
+ return !!pastedContentObj;
+ });
+
+ if (!targets.length && options.pastedContent) {
+ // no implicitly repeated elements, put pasted content in
+ // the deepest child
+ insertPastedContent(tree, options.pastedContent);
+ }
+ });
+});/**
+ * Resolves tag names in abbreviations with implied name
+ */
+emmet.exec(function(require, _) {
+ /**
+ * Resolves implicit node names in parsed tree
+ * @param {AbbreviationNode} tree
+ */
+ function resolveNodeNames(tree) {
+ var tagName = require('tagName');
+ _.each(tree.children, function(node) {
+ if (node.hasImplicitName() || node.data('forceNameResolving')) {
+ node._name = tagName.resolve(node.parent.name());
+ }
+ resolveNodeNames(node);
+ });
+
+ return tree;
+ }
+
+ require('abbreviationParser').addPostprocessor(resolveNodeNames);
+});/**
+ * @author Stoyan Stefanov
+ * @link https://github.com/stoyan/etc/tree/master/cssex
+ */
+
+emmet.define('cssParser', function(require, _) {
+var walker, tokens = [], isOp, isNameChar, isDigit;
+
+ // walks around the source
+ walker = {
+ lines: null,
+ total_lines: 0,
+ linenum: -1,
+ line: '',
+ ch: '',
+ chnum: -1,
+ init: function (source) {
+ var me = walker;
+
+ // source, yumm
+ me.lines = source
+ .replace(/\r\n/g, '\n')
+ .replace(/\r/g, '\n')
+ .split('\n');
+ me.total_lines = me.lines.length;
+
+ // reset
+ me.chnum = -1;
+ me.linenum = -1;
+ me.ch = '';
+ me.line = '';
+
+ // advance
+ me.nextLine();
+ me.nextChar();
+ },
+ nextLine: function () {
+ var me = this;
+ me.linenum += 1;
+ if (me.total_lines <= me.linenum) {
+ me.line = false;
+ } else {
+ me.line = me.lines[me.linenum];
+ }
+ if (me.chnum !== -1) {
+ me.chnum = 0;
+ }
+ return me.line;
+ },
+ nextChar: function () {
+ var me = this;
+ me.chnum += 1;
+ while (me.line.charAt(me.chnum) === '') {
+ if (this.nextLine() === false) {
+ me.ch = false;
+ return false; // end of source
+ }
+ me.chnum = -1;
+ me.ch = '\n';
+ return '\n';
+ }
+ me.ch = me.line.charAt(me.chnum);
+ return me.ch;
+ },
+ peek: function() {
+ return this.line.charAt(this.chnum + 1);
+ }
+ };
+
+ // utility helpers
+ isNameChar = function (c) {
+ // be more tolerate for name tokens: allow & character for LESS syntax
+ return (c == '&' || c === '_' || c === '-' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ };
+
+ isDigit = function (ch) {
+ return (ch !== false && ch >= '0' && ch <= '9');
+ };
+
+ isOp = (function () {
+ var opsa = "{}[]()+*=.,;:>~|\\%$#@^!".split(''),
+ opsmatcha = "*^|$~".split(''),
+ ops = {},
+ opsmatch = {},
+ i = 0;
+ for (; i < opsa.length; i += 1) {
+ ops[opsa[i]] = true;
+ }
+ for (i = 0; i < opsmatcha.length; i += 1) {
+ opsmatch[opsmatcha[i]] = true;
+ }
+ return function (ch, matchattr) {
+ if (matchattr) {
+ return !!opsmatch[ch];
+ }
+ return !!ops[ch];
+ };
+ }());
+
+ // shorthands
+ function isset(v) {
+ return typeof v !== 'undefined';
+ }
+ function getConf() {
+ return {
+ 'char': walker.chnum,
+ line: walker.linenum
+ };
+ }
+
+
+ // creates token objects and pushes them to a list
+ function tokener(value, type, conf) {
+ var w = walker, c = conf || {};
+ tokens.push({
+ charstart: isset(c['char']) ? c['char'] : w.chnum,
+ charend: isset(c.charend) ? c.charend : w.chnum,
+ linestart: isset(c.line) ? c.line : w.linenum,
+ lineend: isset(c.lineend) ? c.lineend : w.linenum,
+ value: value,
+ type: type || value
+ });
+ }
+
+ // oops
+ function error(m, config) {
+ var w = walker,
+ conf = config || {},
+ c = isset(conf['char']) ? conf['char'] : w.chnum,
+ l = isset(conf.line) ? conf.line : w.linenum;
+ return {
+ name: "ParseError",
+ message: m + " at line " + (l + 1) + ' char ' + (c + 1),
+ walker: w,
+ tokens: tokens
+ };
+ }
+
+
+ // token handlers follow for:
+ // white space, comment, string, identifier, number, operator
+ function white() {
+
+ var c = walker.ch,
+ token = '',
+ conf = getConf();
+
+ while (c === " " || c === "\t") {
+ token += c;
+ c = walker.nextChar();
+ }
+
+ tokener(token, 'white', conf);
+
+ }
+
+ function comment() {
+
+ var w = walker,
+ c = w.ch,
+ token = c,
+ cnext,
+ conf = getConf();
+
+ cnext = w.nextChar();
+
+ if (cnext !== '*') {
+ // oops, not a comment, just a /
+ conf.charend = conf['char'];
+ conf.lineend = conf.line;
+ return tokener(token, token, conf);
+ }
+
+ while (!(c === "*" && cnext === "/")) {
+ token += cnext;
+ c = cnext;
+ cnext = w.nextChar();
+ }
+ token += cnext;
+ w.nextChar();
+ tokener(token, 'comment', conf);
+ }
+
+ function str() {
+ var w = walker,
+ c = w.ch,
+ q = c,
+ token = c,
+ cnext,
+ conf = getConf();
+
+ c = w.nextChar();
+
+ while (c !== q) {
+
+ if (c === '\n') {
+ cnext = w.nextChar();
+ if (cnext === "\\") {
+ token += c + cnext;
+ } else {
+ // end of line with no \ escape = bad
+ throw error("Unterminated string", conf);
+ }
+ } else {
+ if (c === "\\") {
+ token += c + w.nextChar();
+ } else {
+ token += c;
+ }
+ }
+
+ c = w.nextChar();
+
+ }
+ token += c;
+ w.nextChar();
+ tokener(token, 'string', conf);
+ }
+
+ function brace() {
+ var w = walker,
+ c = w.ch,
+ depth = 0,
+ token = c,
+ conf = getConf();
+
+ c = w.nextChar();
+
+ while (c !== ')' && !depth) {
+ if (c === '(') {
+ depth++;
+ } else if (c === ')') {
+ depth--;
+ } else if (c === false) {
+ throw error("Unterminated brace", conf);
+ }
+
+ token += c;
+ c = w.nextChar();
+ }
+
+ token += c;
+ w.nextChar();
+ tokener(token, 'brace', conf);
+ }
+
+ function identifier(pre) {
+ var w = walker,
+ c = w.ch,
+ conf = getConf(),
+ token = (pre) ? pre + c : c;
+
+ c = w.nextChar();
+
+ if (pre) { // adjust token position
+ conf['char'] -= pre.length;
+ }
+
+ while (isNameChar(c) || isDigit(c)) {
+ token += c;
+ c = w.nextChar();
+ }
+
+ tokener(token, 'identifier', conf);
+ }
+
+ function num() {
+ var w = walker,
+ c = w.ch,
+ conf = getConf(),
+ token = c,
+ point = token === '.',
+ nondigit;
+
+ c = w.nextChar();
+ nondigit = !isDigit(c);
+
+ // .2px or .classname?
+ if (point && nondigit) {
+ // meh, NaN, could be a class name, so it's an operator for now
+ conf.charend = conf['char'];
+ conf.lineend = conf.line;
+ return tokener(token, '.', conf);
+ }
+
+ // -2px or -moz-something
+ if (token === '-' && nondigit) {
+ return identifier('-');
+ }
+
+ while (c !== false && (isDigit(c) || (!point && c === '.'))) { // not end of source && digit or first instance of .
+ if (c === '.') {
+ point = true;
+ }
+ token += c;
+ c = w.nextChar();
+ }
+
+ tokener(token, 'number', conf);
+
+ }
+
+ function op() {
+ var w = walker,
+ c = w.ch,
+ conf = getConf(),
+ token = c,
+ next = w.nextChar();
+
+ if (next === "=" && isOp(token, true)) {
+ token += next;
+ tokener(token, 'match', conf);
+ w.nextChar();
+ return;
+ }
+
+ conf.charend = conf['char'] + 1;
+ conf.lineend = conf.line;
+ tokener(token, token, conf);
+ }
+
+
+ // call the appropriate handler based on the first character in a token suspect
+ function tokenize() {
+
+ var ch = walker.ch;
+
+ if (ch === " " || ch === "\t") {
+ return white();
+ }
+
+ if (ch === '/') {
+ return comment();
+ }
+
+ if (ch === '"' || ch === "'") {
+ return str();
+ }
+
+ if (ch === '(') {
+ return brace();
+ }
+
+ if (ch === '-' || ch === '.' || isDigit(ch)) { // tricky - char: minus (-1px) or dash (-moz-stuff)
+ return num();
+ }
+
+ if (isNameChar(ch)) {
+ return identifier();
+ }
+
+ if (isOp(ch)) {
+ return op();
+ }
+
+ if (ch === "\n") {
+ tokener("line");
+ walker.nextChar();
+ return;
+ }
+
+ throw error("Unrecognized character");
+ }
+
+ /**
+ * Returns newline character at specified position in content
+ * @param {String} content
+ * @param {Number} pos
+ * @return {String}
+ */
+ function getNewline(content, pos) {
+ return content.charAt(pos) == '\r' && content.charAt(pos + 1) == '\n'
+ ? '\r\n'
+ : content.charAt(pos);
+ }
+
+ return {
+ /**
+ * @param source
+ * @returns
+ * @memberOf emmet.cssParser
+ */
+ lex: function (source) {
+ walker.init(source);
+ tokens = [];
+ while (walker.ch !== false) {
+ tokenize();
+ }
+ return tokens;
+ },
+
+ /**
+ * Tokenizes CSS source
+ * @param {String} source
+ * @returns {Array}
+ */
+ parse: function(source) {
+ // transform tokens
+ var pos = 0;
+ return _.map(this.lex(source), function(token) {
+ if (token.type == 'line') {
+ token.value = getNewline(source, pos);
+ }
+
+ return {
+ type: token.type,
+ start: pos,
+ end: (pos += token.value.length)
+ };
+ });
+ },
+
+ toSource: function (toks) {
+ var i = 0, max = toks.length, t, src = '';
+ for (; i < max; i += 1) {
+ t = toks[i];
+ if (t.type === 'line') {
+ src += '\n';
+ } else {
+ src += t.value;
+ }
+ }
+ return src;
+ }
+ };
+});/**
+ * HTML tokenizer by Marijn Haverbeke
+ * http://codemirror.net/
+ * @constructor
+ * @memberOf __xmlParseDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('xmlParser', function(require, _) {
+ var Kludges = {
+ autoSelfClosers : {},
+ implicitlyClosed : {},
+ contextGrabbers : {},
+ doNotIndent : {},
+ allowUnquoted : true,
+ allowMissing : true
+ };
+
+ // Return variables for tokenizers
+ var tagName = null, type = null;
+
+ function inText(stream, state) {
+ function chain(parser) {
+ state.tokenize = parser;
+ return parser(stream, state);
+ }
+
+ var ch = stream.next();
+ if (ch == "<") {
+ if (stream.eat("!")) {
+ if (stream.eat("[")) {
+ if (stream.match("CDATA["))
+ return chain(inBlock("atom", "]]>"));
+ else
+ return null;
+ } else if (stream.match("--"))
+ return chain(inBlock("comment", "-->"));
+ else if (stream.match("DOCTYPE", true, true)) {
+ stream.eatWhile(/[\w\._\-]/);
+ return chain(doctype(1));
+ } else
+ return null;
+ } else if (stream.eat("?")) {
+ stream.eatWhile(/[\w\._\-]/);
+ state.tokenize = inBlock("meta", "?>");
+ return "meta";
+ } else {
+ type = stream.eat("/") ? "closeTag" : "openTag";
+ stream.eatSpace();
+ tagName = "";
+ var c;
+ while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/)))
+ tagName += c;
+ state.tokenize = inTag;
+ return "tag";
+ }
+ } else if (ch == "&") {
+ var ok;
+ if (stream.eat("#")) {
+ if (stream.eat("x")) {
+ ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
+ } else {
+ ok = stream.eatWhile(/[\d]/) && stream.eat(";");
+ }
+ } else {
+ ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
+ }
+ return ok ? "atom" : "error";
+ } else {
+ stream.eatWhile(/[^&<]/);
+ return "text";
+ }
+ }
+
+ function inTag(stream, state) {
+ var ch = stream.next();
+ if (ch == ">" || (ch == "/" && stream.eat(">"))) {
+ state.tokenize = inText;
+ type = ch == ">" ? "endTag" : "selfcloseTag";
+ return "tag";
+ } else if (ch == "=") {
+ type = "equals";
+ return null;
+ } else if (/[\'\"]/.test(ch)) {
+ state.tokenize = inAttribute(ch);
+ return state.tokenize(stream, state);
+ } else {
+ stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);
+ return "word";
+ }
+ }
+
+ function inAttribute(quote) {
+ return function(stream, state) {
+ while (!stream.eol()) {
+ if (stream.next() == quote) {
+ state.tokenize = inTag;
+ break;
+ }
+ }
+ return "string";
+ };
+ }
+
+ function inBlock(style, terminator) {
+ return function(stream, state) {
+ while (!stream.eol()) {
+ if (stream.match(terminator)) {
+ state.tokenize = inText;
+ break;
+ }
+ stream.next();
+ }
+ return style;
+ };
+ }
+
+ function doctype(depth) {
+ return function(stream, state) {
+ var ch;
+ while ((ch = stream.next()) != null) {
+ if (ch == "<") {
+ state.tokenize = doctype(depth + 1);
+ return state.tokenize(stream, state);
+ } else if (ch == ">") {
+ if (depth == 1) {
+ state.tokenize = inText;
+ break;
+ } else {
+ state.tokenize = doctype(depth - 1);
+ return state.tokenize(stream, state);
+ }
+ }
+ }
+ return "meta";
+ };
+ }
+
+ var curState = null, setStyle;
+ function pass() {
+ for (var i = arguments.length - 1; i >= 0; i--)
+ curState.cc.push(arguments[i]);
+ }
+
+ function cont() {
+ pass.apply(null, arguments);
+ return true;
+ }
+
+ function pushContext(tagName, startOfLine) {
+ var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName)
+ || (curState.context && curState.context.noIndent);
+ curState.context = {
+ prev : curState.context,
+ tagName : tagName,
+ indent : curState.indented,
+ startOfLine : startOfLine,
+ noIndent : noIndent
+ };
+ }
+
+ function popContext() {
+ if (curState.context)
+ curState.context = curState.context.prev;
+ }
+
+ function element(type) {
+ if (type == "openTag") {
+ curState.tagName = tagName;
+ return cont(attributes, endtag(curState.startOfLine));
+ } else if (type == "closeTag") {
+ var err = false;
+ if (curState.context) {
+ if (curState.context.tagName != tagName) {
+ if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
+ popContext();
+ }
+ err = !curState.context || curState.context.tagName != tagName;
+ }
+ } else {
+ err = true;
+ }
+
+ if (err)
+ setStyle = "error";
+ return cont(endclosetag(err));
+ }
+ return cont();
+ }
+
+ function endtag(startOfLine) {
+ return function(type) {
+ if (type == "selfcloseTag"
+ || (type == "endTag" && Kludges.autoSelfClosers
+ .hasOwnProperty(curState.tagName
+ .toLowerCase()))) {
+ maybePopContext(curState.tagName.toLowerCase());
+ return cont();
+ }
+ if (type == "endTag") {
+ maybePopContext(curState.tagName.toLowerCase());
+ pushContext(curState.tagName, startOfLine);
+ return cont();
+ }
+ return cont();
+ };
+ }
+
+ function endclosetag(err) {
+ return function(type) {
+ if (err)
+ setStyle = "error";
+ if (type == "endTag") {
+ popContext();
+ return cont();
+ }
+ setStyle = "error";
+ return cont(arguments.callee);
+ };
+ }
+
+ function maybePopContext(nextTagName) {
+ var parentTagName;
+ while (true) {
+ if (!curState.context) {
+ return;
+ }
+ parentTagName = curState.context.tagName.toLowerCase();
+ if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName)
+ || !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
+ return;
+ }
+ popContext();
+ }
+ }
+
+ function attributes(type) {
+ if (type == "word") {
+ setStyle = "attribute";
+ return cont(attribute, attributes);
+ }
+ if (type == "endTag" || type == "selfcloseTag")
+ return pass();
+ setStyle = "error";
+ return cont(attributes);
+ }
+
+ function attribute(type) {
+ if (type == "equals")
+ return cont(attvalue, attributes);
+ if (!Kludges.allowMissing)
+ setStyle = "error";
+ return (type == "endTag" || type == "selfcloseTag") ? pass()
+ : cont();
+ }
+
+ function attvalue(type) {
+ if (type == "string")
+ return cont(attvaluemaybe);
+ if (type == "word" && Kludges.allowUnquoted) {
+ setStyle = "string";
+ return cont();
+ }
+ setStyle = "error";
+ return (type == "endTag" || type == "selfCloseTag") ? pass()
+ : cont();
+ }
+
+ function attvaluemaybe(type) {
+ if (type == "string")
+ return cont(attvaluemaybe);
+ else
+ return pass();
+ }
+
+ function startState() {
+ return {
+ tokenize : inText,
+ cc : [],
+ indented : 0,
+ startOfLine : true,
+ tagName : null,
+ context : null
+ };
+ }
+
+ function token(stream, state) {
+ if (stream.sol()) {
+ state.startOfLine = true;
+ state.indented = 0;
+ }
+
+ if (stream.eatSpace())
+ return null;
+
+ setStyle = type = tagName = null;
+ var style = state.tokenize(stream, state);
+ state.type = type;
+ if ((style || type) && style != "comment") {
+ curState = state;
+ while (true) {
+ var comb = state.cc.pop() || element;
+ if (comb(type || style))
+ break;
+ }
+ }
+ state.startOfLine = false;
+ return setStyle || style;
+ }
+
+ return {
+ /**
+ * @memberOf emmet.xmlParser
+ * @returns
+ */
+ parse: function(data, offset) {
+ offset = offset || 0;
+ var state = startState();
+ var stream = require('stringStream').create(data);
+ var tokens = [];
+ while (!stream.eol()) {
+ tokens.push({
+ type: token(stream, state),
+ start: stream.start + offset,
+ end: stream.pos + offset
+ });
+ stream.start = stream.pos;
+ }
+
+ return tokens;
+ }
+ };
+});
+/*!
+ * string_score.js: String Scoring Algorithm 0.1.10
+ *
+ * http://joshaven.com/string_score
+ * https://github.com/joshaven/string_score
+ *
+ * Copyright (C) 2009-2011 Joshaven Potter
+ * Special thanks to all of the contributors listed here https://github.com/joshaven/string_score
+ * MIT license: http://www.opensource.org/licenses/mit-license.php
+ *
+ * Date: Tue Mar 1 2011
+*/
+
+/**
+ * Scores a string against another string.
+ * 'Hello World'.score('he'); //=> 0.5931818181818181
+ * 'Hello World'.score('Hello'); //=> 0.7318181818181818
+ */
+emmet.define('string-score', function(require, _) {
+ return {
+ score: function(string, abbreviation, fuzziness) {
+ // If the string is equal to the abbreviation, perfect match.
+ if (string == abbreviation) {return 1;}
+ //if it's not a perfect match and is empty return 0
+ if(abbreviation == "") {return 0;}
+
+ var total_character_score = 0,
+ abbreviation_length = abbreviation.length,
+ string_length = string.length,
+ start_of_string_bonus,
+ abbreviation_score,
+ fuzzies=1,
+ final_score;
+
+ // Walk through abbreviation and add up scores.
+ for (var i = 0,
+ character_score/* = 0*/,
+ index_in_string/* = 0*/,
+ c/* = ''*/,
+ index_c_lowercase/* = 0*/,
+ index_c_uppercase/* = 0*/,
+ min_index/* = 0*/;
+ i < abbreviation_length;
+ ++i) {
+
+ // Find the first case-insensitive match of a character.
+ c = abbreviation.charAt(i);
+
+ index_c_lowercase = string.indexOf(c.toLowerCase());
+ index_c_uppercase = string.indexOf(c.toUpperCase());
+ min_index = Math.min(index_c_lowercase, index_c_uppercase);
+ index_in_string = (min_index > -1) ? min_index : Math.max(index_c_lowercase, index_c_uppercase);
+
+ if (index_in_string === -1) {
+ if (fuzziness) {
+ fuzzies += 1-fuzziness;
+ continue;
+ } else {
+ return 0;
+ }
+ } else {
+ character_score = 0.1;
+ }
+
+ // Set base score for matching 'c'.
+
+ // Same case bonus.
+ if (string[index_in_string] === c) {
+ character_score += 0.1;
+ }
+
+ // Consecutive letter & start-of-string Bonus
+ if (index_in_string === 0) {
+ // Increase the score when matching first character of the remainder of the string
+ character_score += 0.6;
+ if (i === 0) {
+ // If match is the first character of the string
+ // & the first character of abbreviation, add a
+ // start-of-string match bonus.
+ start_of_string_bonus = 1; //true;
+ }
+ }
+ else {
+ // Acronym Bonus
+ // Weighing Logic: Typing the first character of an acronym is as if you
+ // preceded it with two perfect character matches.
+ if (string.charAt(index_in_string - 1) === ' ') {
+ character_score += 0.8; // * Math.min(index_in_string, 5); // Cap bonus at 0.4 * 5
+ }
+ }
+
+ // Left trim the already matched part of the string
+ // (forces sequential matching).
+ string = string.substring(index_in_string + 1, string_length);
+
+ total_character_score += character_score;
+ } // end of for loop
+
+ // Uncomment to weigh smaller words higher.
+ // return total_character_score / string_length;
+
+ abbreviation_score = total_character_score / abbreviation_length;
+ //percentage_of_matched_string = abbreviation_length / string_length;
+ //word_score = abbreviation_score * percentage_of_matched_string;
+
+ // Reduce penalty for longer strings.
+ //final_score = (word_score + abbreviation_score) / 2;
+ final_score = ((abbreviation_score * (abbreviation_length / string_length)) + abbreviation_score) / 2;
+
+ final_score = final_score / fuzzies;
+
+ if (start_of_string_bonus && (final_score + 0.15 < 1)) {
+ final_score += 0.15;
+ }
+
+ return final_score;
+ }
+ };
+});/**
+ * Utility module for Emmet
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('utils', function(require, _) {
+ /**
+ * Special token used as a placeholder for caret positions inside
+ * generated output
+ */
+ var caretPlaceholder = '${0}';
+
+ /**
+ * A simple string builder, optimized for faster text concatenation
+ * @param {String} value Initial value
+ */
+ function StringBuilder(value) {
+ this._data = [];
+ this.length = 0;
+
+ if (value)
+ this.append(value);
+ }
+
+ StringBuilder.prototype = {
+ /**
+ * Append string
+ * @param {String} text
+ */
+ append: function(text) {
+ this._data.push(text);
+ this.length += text.length;
+ },
+
+ /**
+ * @returns {String}
+ */
+ toString: function() {
+ return this._data.join('');
+ },
+
+ /**
+ * @returns {String}
+ */
+ valueOf: function() {
+ return this.toString();
+ }
+ };
+
+ return {
+ /** @memberOf utils */
+ reTag: /<\/?[\w:\-]+(?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*\s*(\/?)>$/,
+
+ /**
+ * Test if passed string ends with XHTML tag. This method is used for testing
+ * '>' character: it belongs to tag or it's a part of abbreviation?
+ * @param {String} str
+ * @return {Boolean}
+ */
+ endsWithTag: function(str) {
+ return this.reTag.test(str);
+ },
+
+ /**
+ * Check if passed symbol is a number
+ * @param {String} ch
+ * @returns {Boolean}
+ */
+ isNumeric: function(ch) {
+ if (typeof(ch) == 'string')
+ ch = ch.charCodeAt(0);
+
+ return (ch && ch > 47 && ch < 58);
+ },
+
+ /**
+ * Trim whitespace from string
+ * @param {String} text
+ * @return {String}
+ */
+ trim: function(text) {
+ return (text || "").replace(/^\s+|\s+$/g, "");
+ },
+
+ /**
+ * Returns newline character
+ * @returns {String}
+ */
+ getNewline: function() {
+ var res = require('resources');
+ if (!res) {
+ return '\n';
+ }
+
+ var nl = res.getVariable('newline');
+ return _.isString(nl) ? nl : '\n';
+ },
+
+ /**
+ * Sets new newline character that will be used in output
+ * @param {String} str
+ */
+ setNewline: function(str) {
+ var res = require('resources');
+ res.setVariable('newline', str);
+ res.setVariable('nl', str);
+ },
+
+ /**
+ * Split text into lines. Set remove_empty to true to filter
+ * empty lines
+ * @param {String} text Text to split
+ * @param {Boolean} removeEmpty Remove empty lines from result
+ * @return {Array}
+ */
+ splitByLines: function(text, removeEmpty) {
+ // IE fails to split string by regexp,
+ // need to normalize newlines first
+ // Also, Mozilla's Rhiho JS engine has a weird newline bug
+ var nl = this.getNewline();
+ var lines = (text || '')
+ .replace(/\r\n/g, '\n')
+ .replace(/\n\r/g, '\n')
+ .replace(/\r/g, '\n')
+ .replace(/\n/g, nl)
+ .split(nl);
+
+ if (removeEmpty) {
+ lines = _.filter(lines, function(line) {
+ return line.length && !!this.trim(line);
+ }, this);
+ }
+
+ return lines;
+ },
+
+ /**
+ * Normalizes newline character: replaces newlines in text
+ * with newline defined in preferences
+ * @param {String} text
+ * @returns {String}
+ */
+ normalizeNewline: function(text) {
+ return this.splitByLines(text).join(this.getNewline());
+ },
+
+ /**
+ * Repeats string howMany times
+ * @param {String} str
+ * @param {Number} how_many
+ * @return {String}
+ */
+ repeatString: function(str, howMany) {
+ var result = [];
+
+ for (var i = 0; i < howMany; i++)
+ result.push(str);
+
+ return result.join('');
+ },
+
+ /**
+ * Returns list of paddings that should be used to align passed string
+ * @param {Array} strings
+ * @returns {Array}
+ */
+ getStringsPads: function(strings) {
+ var lengths = _.map(strings, function(s) {
+ return _.isString(s) ? s.length : +s;
+ });
+
+ var max = _.max(lengths);
+ return _.map(lengths, function(l) {
+ var pad = max - l;
+ return pad ? this.repeatString(' ', pad) : '';
+ }, this);
+ },
+
+ /**
+ * Indents text with padding
+ * @param {String} text Text to indent
+ * @param {String} pad Padding size (number) or padding itself (string)
+ * @return {String}
+ */
+ padString: function(text, pad) {
+ var padStr = (_.isNumber(pad))
+ ? this.repeatString(require('resources').getVariable('indentation') || '\t', pad)
+ : pad;
+
+ var result = [];
+
+ var lines = this.splitByLines(text);
+ var nl = this.getNewline();
+
+ result.push(lines[0]);
+ for (var j = 1; j < lines.length; j++)
+ result.push(nl + padStr + lines[j]);
+
+ return result.join('');
+ },
+
+ /**
+ * Pad string with zeroes
+ * @param {String} str String to pad
+ * @param {Number} pad Desired string length
+ * @return {String}
+ */
+ zeroPadString: function(str, pad) {
+ var padding = '';
+ var il = str.length;
+
+ while (pad > il++) padding += '0';
+ return padding + str;
+ },
+
+ /**
+ * Removes padding at the beginning of each text's line
+ * @param {String} text
+ * @param {String} pad
+ */
+ unindentString: function(text, pad) {
+ var lines = this.splitByLines(text);
+ for (var i = 0; i < lines.length; i++) {
+ if (lines[i].search(pad) == 0)
+ lines[i] = lines[i].substr(pad.length);
+ }
+
+ return lines.join(this.getNewline());
+ },
+
+ /**
+ * Replaces unescaped symbols in str. For example, the '$' symbol
+ * will be replaced in 'item$count', but not in 'item\$count'.
+ * @param {String} str Original string
+ * @param {String} symbol Symbol to replace
+ * @param {String} replace Symbol replacement. Might be a function that
+ * returns new value
+ * @return {String}
+ */
+ replaceUnescapedSymbol: function(str, symbol, replace) {
+ var i = 0;
+ var il = str.length;
+ var sl = symbol.length;
+ var matchCount = 0;
+
+ while (i < il) {
+ if (str.charAt(i) == '\\') {
+ // escaped symbol, skip next character
+ i += sl + 1;
+ } else if (str.substr(i, sl) == symbol) {
+ // have match
+ var curSl = sl;
+ matchCount++;
+ var newValue = replace;
+ if (_.isFunction(replace)) {
+ var replaceData = replace(str, symbol, i, matchCount);
+ if (replaceData) {
+ curSl = replaceData[0].length;
+ newValue = replaceData[1];
+ } else {
+ newValue = false;
+ }
+ }
+
+ if (newValue === false) { // skip replacement
+ i++;
+ continue;
+ }
+
+ str = str.substring(0, i) + newValue + str.substring(i + curSl);
+ // adjust indexes
+ il = str.length;
+ i += newValue.length;
+ } else {
+ i++;
+ }
+ }
+
+ return str;
+ },
+
+ /**
+ * Replace variables like ${var} in string
+ * @param {String} str
+ * @param {Object} vars Variable set (defaults to variables defined in
+ * snippets.json) or variable resolver (Function)
+ * @return {String}
+ */
+ replaceVariables: function(str, vars) {
+ vars = vars || {};
+ var resolver = _.isFunction(vars) ? vars : function(str, p1) {
+ return p1 in vars ? vars[p1] : null;
+ };
+
+ var res = require('resources');
+ return require('tabStops').processText(str, {
+ variable: function(data) {
+ var newValue = resolver(data.token, data.name, data);
+ if (newValue === null) {
+ // try to find variable in resources
+ newValue = res.getVariable(data.name);
+ }
+
+ if (newValue === null || _.isUndefined(newValue))
+ // nothing found, return token itself
+ newValue = data.token;
+ return newValue;
+ }
+ });
+ },
+
+ /**
+ * Replaces '$' character in string assuming it might be escaped with '\'
+ * @param {String} str String where character should be replaced
+ * @param {String} value New value
+ * @return {String}
+ */
+ replaceCounter: function(str, value, total) {
+ var symbol = '$';
+ // in case we received strings from Java, convert the to native strings
+ str = String(str);
+ value = String(value);
+
+ if (/^\-?\d+$/.test(value)) {
+ value = +value;
+ }
+
+ var that = this;
+
+ return this.replaceUnescapedSymbol(str, symbol, function(str, symbol, pos, matchNum){
+ if (str.charAt(pos + 1) == '{' || that.isNumeric(str.charAt(pos + 1)) ) {
+ // it's a variable, skip it
+ return false;
+ }
+
+ // replace sequense of $ symbols with padded number
+ var j = pos + 1;
+ while(str.charAt(j) == '$' && str.charAt(j + 1) != '{') j++;
+ var pad = j - pos;
+
+ // get counter base
+ var base = 0, decrement = false, m;
+ if (m = str.substr(j).match(/^@(\-?)(\d*)/)) {
+ j += m[0].length;
+
+ if (m[1]) {
+ decrement = true;
+ }
+
+ base = parseInt(m[2] || 1) - 1;
+ }
+
+ if (decrement && total && _.isNumber(value)) {
+ value = total - value + 1;
+ }
+
+ value += base;
+
+ return [str.substring(pos, j), that.zeroPadString(value + '', pad)];
+ });
+ },
+
+ /**
+ * Check if string matches against reTag regexp. This
+ * function may be used to test if provided string contains HTML tags
+ * @param {String} str
+ * @returns {Boolean}
+ */
+ matchesTag: function(str) {
+ return this.reTag.test(str || '');
+ },
+
+ /**
+ * Escapes special characters used in Emmet, like '$', '|', etc.
+ * Use this method before passing to actions like "Wrap with Abbreviation"
+ * to make sure that existing special characters won't be altered
+ * @param {String} text
+ * @return {String}
+ */
+ escapeText: function(text) {
+ return text.replace(/([\$\\])/g, '\\$1');
+ },
+
+ /**
+ * Unescapes special characters used in Emmet, like '$', '|', etc.
+ * @param {String} text
+ * @return {String}
+ */
+ unescapeText: function(text) {
+ return text.replace(/\\(.)/g, '$1');
+ },
+
+ /**
+ * Returns caret placeholder
+ * @returns {String}
+ */
+ getCaretPlaceholder: function() {
+ return _.isFunction(caretPlaceholder)
+ ? caretPlaceholder.apply(this, arguments)
+ : caretPlaceholder;
+ },
+
+ /**
+ * Sets new representation for carets in generated output
+ * @param {String} value New caret placeholder. Might be a
+ * Function
+ */
+ setCaretPlaceholder: function(value) {
+ caretPlaceholder = value;
+ },
+
+ /**
+ * Returns line padding
+ * @param {String} line
+ * @return {String}
+ */
+ getLinePadding: function(line) {
+ return (line.match(/^(\s+)/) || [''])[0];
+ },
+
+ /**
+ * Helper function that returns padding of line of pos
+ * position in content
+ * @param {String} content
+ * @param {Number} pos
+ * @returns {String}
+ */
+ getLinePaddingFromPosition: function(content, pos) {
+ var lineRange = this.findNewlineBounds(content, pos);
+ return this.getLinePadding(lineRange.substring(content));
+ },
+
+ /**
+ * Escape special regexp chars in string, making it usable for creating dynamic
+ * regular expressions
+ * @param {String} str
+ * @return {String}
+ */
+ escapeForRegexp: function(str) {
+ var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
+ return str.replace(specials, "\\$&");
+ },
+
+ /**
+ * Make decimal number look good: convert it to fixed precision end remove
+ * traling zeroes
+ * @param {Number} num
+ * @param {Number} fracion Fraction numbers (default is 2)
+ * @return {String}
+ */
+ prettifyNumber: function(num, fraction) {
+ return num.toFixed(typeof fraction == 'undefined' ? 2 : fraction).replace(/\.?0+$/, '');
+ },
+
+ /**
+ * A simple mutable string shim, optimized for faster text concatenation
+ * @param {String} value Initial value
+ * @returns {StringBuilder}
+ */
+ stringBuilder: function(value) {
+ return new StringBuilder(value);
+ },
+
+ /**
+ * Replace substring of str with value
+ * @param {String} str String where to replace substring
+ * @param {String} value New substring value
+ * @param {Number} start Start index of substring to replace. May also
+ * be a Range object: in this case, the end
+ * argument is not required
+ * @param {Number} end End index of substring to replace. If ommited,
+ * start argument is used
+ */
+ replaceSubstring: function(str, value, start, end) {
+ if (_.isObject(start) && 'end' in start) {
+ end = start.end;
+ start = start.start;
+ }
+
+ if (_.isString(end))
+ end = start + end.length;
+
+ if (_.isUndefined(end))
+ end = start;
+
+ if (start < 0 || start > str.length)
+ return str;
+
+ return str.substring(0, start) + value + str.substring(end);
+ },
+
+ /**
+ * Narrows down text range, adjusting selection to non-space characters
+ * @param {String} text
+ * @param {Number} start Starting range in text where
+ * slection should be adjusted. Can also be any object that is accepted
+ * by Range class
+ * @return {Range}
+ */
+ narrowToNonSpace: function(text, start, end) {
+ var range = require('range').create(start, end);
+
+ var reSpace = /[\s\n\r\u00a0]/;
+ // narrow down selection until first non-space character
+ while (range.start < range.end) {
+ if (!reSpace.test(text.charAt(range.start)))
+ break;
+
+ range.start++;
+ }
+
+ while (range.end > range.start) {
+ range.end--;
+ if (!reSpace.test(text.charAt(range.end))) {
+ range.end++;
+ break;
+ }
+ }
+
+ return range;
+ },
+
+ /**
+ * Find start and end index of text line for from index
+ * @param {String} text
+ * @param {Number} from
+ */
+ findNewlineBounds: function(text, from) {
+ var len = text.length,
+ start = 0,
+ end = len - 1;
+
+ // search left
+ for (var i = from - 1; i > 0; i--) {
+ var ch = text.charAt(i);
+ if (ch == '\n' || ch == '\r') {
+ start = i + 1;
+ break;
+ }
+ }
+ // search right
+ for (var j = from; j < len; j++) {
+ var ch = text.charAt(j);
+ if (ch == '\n' || ch == '\r') {
+ end = j;
+ break;
+ }
+ }
+
+ return require('range').create(start, end - start);
+ },
+
+ /**
+ * Deep merge of two or more objects. Taken from jQuery.extend()
+ */
+ deepMerge: function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length;
+
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if (!_.isObject(target) && !_.isFunction(target)) {
+ target = {};
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( copy && ( _.isObject(copy) || (copyIsArray = _.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && _.isArray(src) ? src : [];
+
+ } else {
+ clone = src && _.isObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = this.deepMerge(clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+ }
+ };
+});
+/**
+ * Helper module to work with ranges
+ * @constructor
+ * @memberOf __rangeDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('range', function(require, _) {
+ function cmp(a, b, op) {
+ switch (op) {
+ case 'eq':
+ case '==':
+ return a === b;
+ case 'lt':
+ case '<':
+ return a < b;
+ case 'lte':
+ case '<=':
+ return a <= b;
+ case 'gt':
+ case '>':
+ return a > b;
+ case 'gte':
+ case '>=':
+ return a >= b;
+ }
+ }
+
+
+ /**
+ * @type Range
+ * @constructor
+ * @param {Object} start
+ * @param {Number} len
+ */
+ function Range(start, len) {
+ if (_.isObject(start) && 'start' in start) {
+ // create range from object stub
+ this.start = Math.min(start.start, start.end);
+ this.end = Math.max(start.start, start.end);
+ } else if (_.isArray(start)) {
+ this.start = start[0];
+ this.end = start[1];
+ } else {
+ len = _.isString(len) ? len.length : +len;
+ this.start = start;
+ this.end = start + len;
+ }
+ }
+
+ Range.prototype = {
+ length: function() {
+ return Math.abs(this.end - this.start);
+ },
+
+ /**
+ * Returns true if passed range is equals to current one
+ * @param {Range} range
+ * @returns {Boolean}
+ */
+ equal: function(range) {
+ return this.cmp(range, 'eq', 'eq');
+// return this.start === range.start && this.end === range.end;
+ },
+
+ /**
+ * Shifts indexes position with passed delat
+ * @param {Number} delta
+ * @returns {Range} range itself
+ */
+ shift: function(delta) {
+ this.start += delta;
+ this.end += delta;
+ return this;
+ },
+
+ /**
+ * Check if two ranges are overlapped
+ * @param {Range} range
+ * @returns {Boolean}
+ */
+ overlap: function(range) {
+ return range.start <= this.end && range.end >= this.start;
+ },
+
+ /**
+ * Finds intersection of two ranges
+ * @param {Range} range
+ * @returns {Range} null if ranges does not overlap
+ */
+ intersection: function(range) {
+ if (this.overlap(range)) {
+ var start = Math.max(range.start, this.start);
+ var end = Math.min(range.end, this.end);
+ return new Range(start, end - start);
+ }
+
+ return null;
+ },
+
+ /**
+ * Returns the union of the thow ranges.
+ * @param {Range} range
+ * @returns {Range} null if ranges are not overlapped
+ */
+ union: function(range) {
+ if (this.overlap(range)) {
+ var start = Math.min(range.start, this.start);
+ var end = Math.max(range.end, this.end);
+ return new Range(start, end - start);
+ }
+
+ return null;
+ },
+
+ /**
+ * Returns a Boolean value that indicates whether a specified position
+ * is in a given range.
+ * @param {Number} loc
+ */
+ inside: function(loc) {
+ return this.cmp(loc, 'lte', 'gt');
+// return this.start <= loc && this.end > loc;
+ },
+
+ /**
+ * Returns a Boolean value that indicates whether a specified position
+ * is in a given range, but not equals bounds.
+ * @param {Number} loc
+ */
+ contains: function(loc) {
+ return this.cmp(loc, 'lt', 'gt');
+ },
+
+ /**
+ * Check if current range completely includes specified one
+ * @param {Range} r
+ * @returns {Boolean}
+ */
+ include: function(r) {
+ return this.cmp(loc, 'lte', 'gte');
+// return this.start <= r.start && this.end >= r.end;
+ },
+
+ /**
+ * Low-level comparision method
+ * @param {Number} loc
+ * @param {String} left Left comparison operator
+ * @param {String} right Right comaprison operator
+ */
+ cmp: function(loc, left, right) {
+ var a, b;
+ if (loc instanceof Range) {
+ a = loc.start;
+ b = loc.end;
+ } else {
+ a = b = loc;
+ }
+
+ return cmp(this.start, a, left || '<=') && cmp(this.end, b, right || '>');
+ },
+
+ /**
+ * Returns substring of specified str for current range
+ * @param {String} str
+ * @returns {String}
+ */
+ substring: function(str) {
+ return this.length() > 0
+ ? str.substring(this.start, this.end)
+ : '';
+ },
+
+ /**
+ * Creates copy of current range
+ * @returns {Range}
+ */
+ clone: function() {
+ return new Range(this.start, this.length());
+ },
+
+ /**
+ * @returns {Array}
+ */
+ toArray: function() {
+ return [this.start, this.end];
+ },
+
+ toString: function() {
+ return '{' + this.start + ', ' + this.length() + '}';
+ }
+ };
+
+ return {
+ /**
+ * Creates new range object instance
+ * @param {Object} start Range start or array with 'start' and 'end'
+ * as two first indexes or object with 'start' and 'end' properties
+ * @param {Number} len Range length or string to produce range from
+ * @returns {Range}
+ * @memberOf emmet.range
+ */
+ create: function(start, len) {
+ if (_.isUndefined(start) || start === null)
+ return null;
+
+ if (start instanceof Range)
+ return start;
+
+ if (_.isObject(start) && 'start' in start && 'end' in start) {
+ len = start.end - start.start;
+ start = start.start;
+ }
+
+ return new Range(start, len);
+ },
+
+ /**
+ * Range object factory, the same as this.create()
+ * but last argument represents end of range, not length
+ * @returns {Range}
+ */
+ create2: function(start, end) {
+ if (_.isNumber(start) && _.isNumber(end)) {
+ end -= start;
+ }
+
+ return this.create(start, end);
+ }
+ };
+});/**
+ * Utility module that provides ordered storage of function handlers.
+ * Many Emmet modules' functionality can be extended/overridden by custom
+ * function. This modules provides unified storage of handler functions, their
+ * management and execution
+ *
+ * @constructor
+ * @memberOf __handlerListDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('handlerList', function(require, _) {
+ /**
+ * @type HandlerList
+ * @constructor
+ */
+ function HandlerList() {
+ this._list = [];
+ }
+
+ HandlerList.prototype = {
+ /**
+ * Adds function handler
+ * @param {Function} fn Handler
+ * @param {Object} options Handler options. Possible values are:
+ * order : (Number) – order in handler list. Handlers
+ * with higher order value will be executed earlier.
+ */
+ add: function(fn, options) {
+ this._list.push(_.extend({order: 0}, options || {}, {fn: fn}));
+ },
+
+ /**
+ * Removes handler from list
+ * @param {Function} fn
+ */
+ remove: function(fn) {
+ this._list = _.without(this._list, _.find(this._list, function(item) {
+ return item.fn === fn;
+ }));
+ },
+
+ /**
+ * Returns ordered list of handlers. By default, handlers
+ * with the same order option returned in reverse order,
+ * i.e. the latter function was added into the handlers list, the higher
+ * it will be in the returned array
+ * @returns {Array}
+ */
+ list: function() {
+ return _.sortBy(this._list, 'order').reverse();
+ },
+
+ /**
+ * Returns ordered list of handler functions
+ * @returns {Array}
+ */
+ listFn: function() {
+ return _.pluck(this.list(), 'fn');
+ },
+
+ /**
+ * Executes handler functions in their designated order. If function
+ * returns skipVal, meaning that function was unable to
+ * handle passed args, the next function will be executed
+ * and so on.
+ * @param {Object} skipValue If function returns this value, execute
+ * next handler.
+ * @param {Array} args Arguments to pass to handler function
+ * @returns {Boolean} Whether any of registered handlers performed
+ * successfully
+ */
+ exec: function(skipValue, args) {
+ args = args || [];
+ var result = null;
+ _.find(this.list(), function(h) {
+ result = h.fn.apply(h, args);
+ if (result !== skipValue)
+ return true;
+ });
+
+ return result;
+ }
+ };
+
+ return {
+ /**
+ * Factory method that produces HandlerList instance
+ * @returns {HandlerList}
+ * @memberOf handlerList
+ */
+ create: function() {
+ return new HandlerList();
+ }
+ };
+});/**
+ * Helper class for convenient token iteration
+ */
+emmet.define('tokenIterator', function(require, _) {
+ /**
+ * @type TokenIterator
+ * @param {Array} tokens
+ * @type TokenIterator
+ * @constructor
+ */
+ function TokenIterator(tokens) {
+ /** @type Array */
+ this.tokens = tokens;
+ this._position = 0;
+ this.reset();
+ }
+
+ TokenIterator.prototype = {
+ next: function() {
+ if (this.hasNext()) {
+ var token = this.tokens[++this._i];
+ this._position = token.start;
+ return token;
+ }
+
+ return null;
+ },
+
+ current: function() {
+ return this.tokens[this._i];
+ },
+
+ position: function() {
+ return this._position;
+ },
+
+ hasNext: function() {
+ return this._i < this._il - 1;
+ },
+
+ reset: function() {
+ this._i = -1;
+ this._il = this.tokens.length;
+ },
+
+ item: function() {
+ return this.tokens[this._i];
+ },
+
+ itemNext: function() {
+ return this.tokens[this._i + 1];
+ },
+
+ itemPrev: function() {
+ return this.tokens[this._i - 1];
+ },
+
+ nextUntil: function(type, callback) {
+ var token;
+ var test = _.isString(type)
+ ? function(t){return t.type == type;}
+ : type;
+
+ while (token = this.next()) {
+ if (callback)
+ callback.call(this, token);
+ if (test.call(this, token))
+ break;
+ }
+ }
+ };
+
+ return {
+ create: function(tokens) {
+ return new TokenIterator(tokens);
+ }
+ };
+});/**
+ * A trimmed version of CodeMirror's StringStream module for string parsing
+ */
+emmet.define('stringStream', function(require, _) {
+ /**
+ * @type StringStream
+ * @constructor
+ * @param {String} string
+ */
+ function StringStream(string) {
+ this.pos = this.start = 0;
+ this.string = string;
+ }
+
+ StringStream.prototype = {
+ /**
+ * Returns true only if the stream is at the end of the line.
+ * @returns {Boolean}
+ */
+ eol: function() {
+ return this.pos >= this.string.length;
+ },
+
+ /**
+ * Returns true only if the stream is at the start of the line
+ * @returns {Boolean}
+ */
+ sol: function() {
+ return this.pos == 0;
+ },
+
+ /**
+ * Returns the next character in the stream without advancing it.
+ * Will return undefined at the end of the line.
+ * @returns {String}
+ */
+ peek: function() {
+ return this.string.charAt(this.pos);
+ },
+
+ /**
+ * Returns the next character in the stream and advances it.
+ * Also returns undefined when no more characters are available.
+ * @returns {String}
+ */
+ next: function() {
+ if (this.pos < this.string.length)
+ return this.string.charAt(this.pos++);
+ },
+
+ /**
+ * match can be a character, a regular expression, or a function that
+ * takes a character and returns a boolean. If the next character in the
+ * stream 'matches' the given argument, it is consumed and returned.
+ * Otherwise, undefined is returned.
+ * @param {Object} match
+ * @returns {String}
+ */
+ eat: function(match) {
+ var ch = this.string.charAt(this.pos), ok;
+ if (typeof match == "string")
+ ok = ch == match;
+ else
+ ok = ch && (match.test ? match.test(ch) : match(ch));
+
+ if (ok) {
+ ++this.pos;
+ return ch;
+ }
+ },
+
+ /**
+ * Repeatedly calls eat with the given argument, until it
+ * fails. Returns true if any characters were eaten.
+ * @param {Object} match
+ * @returns {Boolean}
+ */
+ eatWhile: function(match) {
+ var start = this.pos;
+ while (this.eat(match)) {}
+ return this.pos > start;
+ },
+
+ /**
+ * Shortcut for eatWhile when matching white-space.
+ * @returns {Boolean}
+ */
+ eatSpace: function() {
+ var start = this.pos;
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos)))
+ ++this.pos;
+ return this.pos > start;
+ },
+
+ /**
+ * Moves the position to the end of the line.
+ */
+ skipToEnd: function() {
+ this.pos = this.string.length;
+ },
+
+ /**
+ * Skips to the next occurrence of the given character, if found on the
+ * current line (doesn't advance the stream if the character does not
+ * occur on the line). Returns true if the character was found.
+ * @param {String} ch
+ * @returns {Boolean}
+ */
+ skipTo: function(ch) {
+ var found = this.string.indexOf(ch, this.pos);
+ if (found > -1) {
+ this.pos = found;
+ return true;
+ }
+ },
+
+ /**
+ * Skips to close character which is pair to open
+ * character, considering possible pair nesting. This function is used
+ * to consume pair of characters, like opening and closing braces
+ * @param {String} open
+ * @param {String} close
+ * @returns {Boolean} Returns true if pair was successfully
+ * consumed
+ */
+ skipToPair: function(open, close) {
+ var braceCount = 0, ch;
+ var pos = this.pos, len = this.string.length;
+ while (pos < len) {
+ ch = this.string.charAt(pos++);
+ if (ch == open) {
+ braceCount++;
+ } else if (ch == close) {
+ braceCount--;
+ if (braceCount < 1) {
+ this.pos = pos;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ },
+
+ /**
+ * Backs up the stream n characters. Backing it up further than the
+ * start of the current token will cause things to break, so be careful.
+ * @param {Number} n
+ */
+ backUp : function(n) {
+ this.pos -= n;
+ },
+
+ /**
+ * Act like a multi-character eat—if consume is true or
+ * not given—or a look-ahead that doesn't update the stream position—if
+ * it is false. pattern can be either a string or a
+ * regular expression starting with ^. When it is a string,
+ * caseInsensitive can be set to true to make the match
+ * case-insensitive. When successfully matching a regular expression,
+ * the returned value will be the array returned by match,
+ * in case you need to extract matched groups.
+ *
+ * @param {RegExp} pattern
+ * @param {Boolean} consume
+ * @param {Boolean} caseInsensitive
+ * @returns
+ */
+ match: function(pattern, consume, caseInsensitive) {
+ if (typeof pattern == "string") {
+ var cased = caseInsensitive
+ ? function(str) {return str.toLowerCase();}
+ : function(str) {return str;};
+
+ if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
+ if (consume !== false)
+ this.pos += pattern.length;
+ return true;
+ }
+ } else {
+ var match = this.string.slice(this.pos).match(pattern);
+ if (match && consume !== false)
+ this.pos += match[0].length;
+ return match;
+ }
+ },
+
+ /**
+ * Get the string between the start of the current token and the
+ * current stream position.
+ * @returns {String}
+ */
+ current: function() {
+ return this.string.slice(this.start, this.pos);
+ }
+ };
+
+ return {
+ create: function(string) {
+ return new StringStream(string);
+ }
+ };
+});/**
+ * Parsed resources (snippets, abbreviations, variables, etc.) for Emmet.
+ * Contains convenient method to get access for snippets with respect of
+ * inheritance. Also provides ability to store data in different vocabularies
+ * ('system' and 'user') for fast and safe resource update
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ *
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('resources', function(require, _) {
+ var VOC_SYSTEM = 'system';
+ var VOC_USER = 'user';
+
+ var cache = {};
+
+ /** Regular expression for XML tag matching */
+ var reTag = /^<(\w+\:?[\w\-]*)((?:\s+[\w\:\-]+\s*=\s*(['"]).*?\3)*)\s*(\/?)>/;
+
+ var systemSettings = {};
+ var userSettings = {};
+
+ /** @type HandlerList List of registered abbreviation resolvers */
+ var resolvers = require('handlerList').create();
+
+ /**
+ * Normalizes caret plceholder in passed text: replaces | character with
+ * default caret placeholder
+ * @param {String} text
+ * @returns {String}
+ */
+ function normalizeCaretPlaceholder(text) {
+ var utils = require('utils');
+ return utils.replaceUnescapedSymbol(text, '|', utils.getCaretPlaceholder());
+ }
+
+ function parseItem(name, value, type) {
+ value = normalizeCaretPlaceholder(value);
+
+ if (type == 'snippets') {
+ return require('elements').create('snippet', value);
+ }
+
+ if (type == 'abbreviations') {
+ return parseAbbreviation(name, value);
+ }
+ }
+
+ /**
+ * Parses single abbreviation
+ * @param {String} key Abbreviation name
+ * @param {String} value Abbreviation value
+ * @return {Object}
+ */
+ function parseAbbreviation(key, value) {
+ key = require('utils').trim(key);
+ var elements = require('elements');
+ var m;
+ if (m = reTag.exec(value)) {
+ return elements.create('element', m[1], m[2], m[4] == '/');
+ } else {
+ // assume it's reference to another abbreviation
+ return elements.create('reference', value);
+ }
+ }
+
+ /**
+ * Normalizes snippet key name for better fuzzy search
+ * @param {String} str
+ * @returns {String}
+ */
+ function normalizeName(str) {
+ return str.replace(/:$/, '').replace(/:/g, '-');
+ }
+
+ return {
+ /**
+ * Sets new unparsed data for specified settings vocabulary
+ * @param {Object} data
+ * @param {String} type Vocabulary type ('system' or 'user')
+ * @memberOf resources
+ */
+ setVocabulary: function(data, type) {
+ cache = {};
+ if (type == VOC_SYSTEM)
+ systemSettings = data;
+ else
+ userSettings = data;
+ },
+
+ /**
+ * Returns resource vocabulary by its name
+ * @param {String} name Vocabulary name ('system' or 'user')
+ * @return {Object}
+ */
+ getVocabulary: function(name) {
+ return name == VOC_SYSTEM ? systemSettings : userSettings;
+ },
+
+ /**
+ * Returns resource (abbreviation, snippet, etc.) matched for passed
+ * abbreviation
+ * @param {TreeNode} node
+ * @param {String} syntax
+ * @returns {Object}
+ */
+ getMatchedResource: function(node, syntax) {
+ return resolvers.exec(null, _.toArray(arguments))
+ || this.findSnippet(syntax, node.name());
+ },
+
+ /**
+ * Returns variable value
+ * @return {String}
+ */
+ getVariable: function(name) {
+ return (this.getSection('variables') || {})[name];
+ },
+
+ /**
+ * Store runtime variable in user storage
+ * @param {String} name Variable name
+ * @param {String} value Variable value
+ */
+ setVariable: function(name, value){
+ var voc = this.getVocabulary('user') || {};
+ if (!('variables' in voc))
+ voc.variables = {};
+
+ voc.variables[name] = value;
+ this.setVocabulary(voc, 'user');
+ },
+
+ /**
+ * Check if there are resources for specified syntax
+ * @param {String} syntax
+ * @return {Boolean}
+ */
+ hasSyntax: function(syntax) {
+ return syntax in this.getVocabulary(VOC_USER)
+ || syntax in this.getVocabulary(VOC_SYSTEM);
+ },
+
+ /**
+ * Registers new abbreviation resolver.
+ * @param {Function} fn Abbreviation resolver which will receive
+ * abbreviation as first argument and should return parsed abbreviation
+ * object if abbreviation has handled successfully, null
+ * otherwise
+ * @param {Object} options Options list as described in
+ * {@link HandlerList#add()} method
+ */
+ addResolver: function(fn, options) {
+ resolvers.add(fn, options);
+ },
+
+ removeResolver: function(fn) {
+ resolvers.remove(fn);
+ },
+
+ /**
+ * Returns actual section data, merged from both
+ * system and user data
+ * @param {String} name Section name (syntax)
+ * @param {String} ...args Subsections
+ * @returns
+ */
+ getSection: function(name) {
+ if (!name)
+ return null;
+
+ if (!(name in cache)) {
+ cache[name] = require('utils').deepMerge({}, systemSettings[name], userSettings[name]);
+ }
+
+ var data = cache[name], subsections = _.rest(arguments), key;
+ while (data && (key = subsections.shift())) {
+ if (key in data) {
+ data = data[key];
+ } else {
+ return null;
+ }
+ }
+
+ return data;
+ },
+
+ /**
+ * Recursively searches for a item inside top level sections (syntaxes)
+ * with respect of `extends` attribute
+ * @param {String} topSection Top section name (syntax)
+ * @param {String} subsection Inner section name
+ * @returns {Object}
+ */
+ findItem: function(topSection, subsection) {
+ var data = this.getSection(topSection);
+ while (data) {
+ if (subsection in data)
+ return data[subsection];
+
+ data = this.getSection(data['extends']);
+ }
+ },
+
+ /**
+ * Recursively searches for a snippet definition inside syntax section.
+ * Definition is searched inside `snippets` and `abbreviations`
+ * subsections
+ * @param {String} syntax Top-level section name (syntax)
+ * @param {String} name Snippet name
+ * @returns {Object}
+ */
+ findSnippet: function(syntax, name, memo) {
+ if (!syntax || !name)
+ return null;
+
+ memo = memo || [];
+
+ var names = [name];
+ // create automatic aliases to properties with colons,
+ // e.g. pos-a == pos:a
+ if (~name.indexOf('-'))
+ names.push(name.replace(/\-/g, ':'));
+
+ var data = this.getSection(syntax), matchedItem = null;
+ _.find(['snippets', 'abbreviations'], function(sectionName) {
+ var data = this.getSection(syntax, sectionName);
+ if (data) {
+ return _.find(names, function(n) {
+ if (data[n])
+ return matchedItem = parseItem(n, data[n], sectionName);
+ });
+ }
+ }, this);
+
+ memo.push(syntax);
+ if (!matchedItem && data['extends'] && !_.include(memo, data['extends'])) {
+ // try to find item in parent syntax section
+ return this.findSnippet(data['extends'], name, memo);
+ }
+
+ return matchedItem;
+ },
+
+ /**
+ * Performs fuzzy search of snippet definition
+ * @param {String} syntax Top-level section name (syntax)
+ * @param {String} name Snippet name
+ * @returns
+ */
+ fuzzyFindSnippet: function(syntax, name, minScore) {
+ minScore = minScore || 0.3;
+
+ var payload = this.getAllSnippets(syntax);
+ var sc = require('string-score');
+
+ name = normalizeName(name);
+ var scores = _.map(payload, function(value, key) {
+ return {
+ key: key,
+ score: sc.score(value.nk, name, 0.1)
+ };
+ });
+
+ var result = _.last(_.sortBy(scores, 'score'));
+ if (result && result.score >= minScore) {
+ var k = result.key;
+ return payload[k].parsedValue;
+// return parseItem(k, payload[k].value, payload[k].type);
+ }
+ },
+
+ /**
+ * Returns plain dictionary of all available abbreviations and snippets
+ * for specified syntax with respect of inheritance
+ * @param {String} syntax
+ * @returns {Object}
+ */
+ getAllSnippets: function(syntax) {
+ var cacheKey = 'all-' + syntax;
+ if (!cache[cacheKey]) {
+ var stack = [], sectionKey = syntax;
+ var memo = [];
+
+ do {
+ var section = this.getSection(sectionKey);
+ if (!section)
+ break;
+
+ _.each(['snippets', 'abbreviations'], function(sectionName) {
+ var stackItem = {};
+ _.each(section[sectionName] || null, function(v, k) {
+ stackItem[k] = {
+ nk: normalizeName(k),
+ value: v,
+ parsedValue: parseItem(k, v, sectionName),
+ type: sectionName
+ };
+ });
+
+ stack.push(stackItem);
+ });
+
+ memo.push(sectionKey);
+ sectionKey = section['extends'];
+ } while (sectionKey && !_.include(memo, sectionKey));
+
+
+ cache[cacheKey] = _.extend.apply(_, stack.reverse());
+ }
+
+ return cache[cacheKey];
+ }
+ };
+});/**
+ * Module describes and performs Emmet actions. The actions themselves are
+ * defined in actions folder
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('actions', function(require, _, zc) {
+ var actions = {};
+
+ /**
+ * “Humanizes” action name, makes it more readable for people
+ * @param {String} name Action name (like 'expand_abbreviation')
+ * @return Humanized name (like 'Expand Abbreviation')
+ */
+ function humanizeActionName(name) {
+ return require('utils').trim(name.charAt(0).toUpperCase()
+ + name.substring(1).replace(/_[a-z]/g, function(str) {
+ return ' ' + str.charAt(1).toUpperCase();
+ }));
+ }
+
+ return {
+ /**
+ * Registers new action
+ * @param {String} name Action name
+ * @param {Function} fn Action function
+ * @param {Object} options Custom action options:
+ * label : (String) – Human-readable action name.
+ * May contain '/' symbols as submenu separators
+ * hidden : (Boolean) – Indicates whether action
+ * should be displayed in menu (getMenu() method)
+ *
+ * @memberOf actions
+ */
+ add: function(name, fn, options) {
+ name = name.toLowerCase();
+ options = options || {};
+ if (!options.label) {
+ options.label = humanizeActionName(name);
+ }
+
+ actions[name] = {
+ name: name,
+ fn: fn,
+ options: options
+ };
+ },
+
+ /**
+ * Returns action object
+ * @param {String} name Action name
+ * @returns {Object}
+ */
+ get: function(name) {
+ return actions[name.toLowerCase()];
+ },
+
+ /**
+ * Runs Emmet action. For list of available actions and their
+ * arguments see actions folder.
+ * @param {String} name Action name
+ * @param {Array} args Additional arguments. It may be array of arguments
+ * or inline arguments. The first argument should be IEmmetEditor instance
+ * @returns {Boolean} Status of performed operation, true
+ * means action was performed successfully.
+ * @example
+ * emmet.require('actions').run('expand_abbreviation', editor);
+ * emmet.require('actions').run('wrap_with_abbreviation', [editor, 'div']);
+ */
+ run: function(name, args) {
+ if (!_.isArray(args)) {
+ args = _.rest(arguments);
+ }
+
+ var action = this.get(name);
+ if (action) {
+ return action.fn.apply(emmet, args);
+ } else {
+ emmet.log('Action "%s" is not defined', name);
+ return false;
+ }
+ },
+
+ /**
+ * Returns all registered actions as object
+ * @returns {Object}
+ */
+ getAll: function() {
+ return actions;
+ },
+
+ /**
+ * Returns all registered actions as array
+ * @returns {Array}
+ */
+ getList: function() {
+ return _.values(this.getAll());
+ },
+
+ /**
+ * Returns actions list as structured menu. If action has label ,
+ * it will be splitted by '/' symbol into submenus (for example:
+ * CSS/Reflect Value) and grouped with other items
+ * @param {Array} skipActions List of action identifiers that should be
+ * skipped from menu
+ * @returns {Array}
+ */
+ getMenu: function(skipActions) {
+ var result = [];
+ skipActions = skipActions || [];
+ _.each(this.getList(), function(action) {
+ if (action.options.hidden || _.include(skipActions, action.name))
+ return;
+
+ var actionName = humanizeActionName(action.name);
+ var ctx = result;
+ if (action.options.label) {
+ var parts = action.options.label.split('/');
+ actionName = parts.pop();
+
+ // create submenus, if needed
+ var menuName, submenu;
+ while (menuName = parts.shift()) {
+ submenu = _.find(ctx, function(item) {
+ return item.type == 'submenu' && item.name == menuName;
+ });
+
+ if (!submenu) {
+ submenu = {
+ name: menuName,
+ type: 'submenu',
+ items: []
+ };
+ ctx.push(submenu);
+ }
+
+ ctx = submenu.items;
+ }
+ }
+
+ ctx.push({
+ type: 'action',
+ name: action.name,
+ label: actionName
+ });
+ });
+
+ return result;
+ },
+
+ /**
+ * Returns action name associated with menu item title
+ * @param {String} title
+ * @returns {String}
+ */
+ getActionNameForMenuTitle: function(title, menu) {
+ var item = null;
+ _.find(menu || this.getMenu(), function(val) {
+ if (val.type == 'action') {
+ if (val.label == title || val.name == title) {
+ return item = val.name;
+ }
+ } else {
+ return item = this.getActionNameForMenuTitle(title, val.items);
+ }
+ }, this);
+
+ return item || null;
+ }
+ };
+});/**
+ * Output profile module.
+ * Profile defines how XHTML output data should look like
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('profile', function(require, _) {
+ var profiles = {};
+
+ var defaultProfile = {
+ tag_case: 'asis',
+ attr_case: 'asis',
+ attr_quotes: 'double',
+
+ // each tag on new line
+ tag_nl: 'decide',
+
+ // with tag_nl === true, defines if leaf node (e.g. node with no children)
+ // should have formatted line breaks
+ tag_nl_leaf: false,
+
+ place_cursor: true,
+
+ // indent tags
+ indent: true,
+
+ // how many inline elements should be to force line break
+ // (set to 0 to disable)
+ inline_break: 3,
+
+ // use self-closing style for writing empty elements, e.g. or
+ self_closing_tag: 'xhtml',
+
+ // Profile-level output filters, re-defines syntax filters
+ filters: '',
+
+ // Additional filters applied to abbreviation.
+ // Unlike "filters", this preference doesn't override default filters
+ // but add the instead every time given profile is chosen
+ extraFilters: ''
+ };
+
+ /**
+ * @constructor
+ * @type OutputProfile
+ * @param {Object} options
+ */
+ function OutputProfile(options) {
+ _.extend(this, defaultProfile, options);
+ }
+
+ OutputProfile.prototype = {
+ /**
+ * Transforms tag name case depending on current profile settings
+ * @param {String} name String to transform
+ * @returns {String}
+ */
+ tagName: function(name) {
+ return stringCase(name, this.tag_case);
+ },
+
+ /**
+ * Transforms attribute name case depending on current profile settings
+ * @param {String} name String to transform
+ * @returns {String}
+ */
+ attributeName: function(name) {
+ return stringCase(name, this.attr_case);
+ },
+
+ /**
+ * Returns quote character for current profile
+ * @returns {String}
+ */
+ attributeQuote: function() {
+ return this.attr_quotes == 'single' ? "'" : '"';
+ },
+
+ /**
+ * Returns self-closing tag symbol for current profile
+ * @param {String} param
+ * @returns {String}
+ */
+ selfClosing: function(param) {
+ if (this.self_closing_tag == 'xhtml')
+ return ' /';
+
+ if (this.self_closing_tag === true)
+ return '/';
+
+ return '';
+ },
+
+ /**
+ * Returns cursor token based on current profile settings
+ * @returns {String}
+ */
+ cursor: function() {
+ return this.place_cursor ? require('utils').getCaretPlaceholder() : '';
+ }
+ };
+
+ /**
+ * Helper function that converts string case depending on
+ * caseValue
+ * @param {String} str String to transform
+ * @param {String} caseValue Case value: can be lower ,
+ * upper and leave
+ * @returns {String}
+ */
+ function stringCase(str, caseValue) {
+ switch (String(caseValue || '').toLowerCase()) {
+ case 'lower':
+ return str.toLowerCase();
+ case 'upper':
+ return str.toUpperCase();
+ }
+
+ return str;
+ }
+
+ /**
+ * Creates new output profile
+ * @param {String} name Profile name
+ * @param {Object} options Profile options
+ */
+ function createProfile(name, options) {
+ return profiles[name.toLowerCase()] = new OutputProfile(options);
+ }
+
+ function createDefaultProfiles() {
+ createProfile('xhtml');
+ createProfile('html', {self_closing_tag: false});
+ createProfile('xml', {self_closing_tag: true, tag_nl: true});
+ createProfile('plain', {tag_nl: false, indent: false, place_cursor: false});
+ createProfile('line', {tag_nl: false, indent: false, extraFilters: 's'});
+ }
+
+ createDefaultProfiles();
+
+ return {
+ /**
+ * Creates new output profile and adds it into internal dictionary
+ * @param {String} name Profile name
+ * @param {Object} options Profile options
+ * @memberOf emmet.profile
+ * @returns {Object} New profile
+ */
+ create: function(name, options) {
+ if (arguments.length == 2)
+ return createProfile(name, options);
+ else
+ // create profile object only
+ return new OutputProfile(_.defaults(name || {}, defaultProfile));
+ },
+
+ /**
+ * Returns profile by its name. If profile wasn't found, returns
+ * 'plain' profile
+ * @param {String} name Profile name. Might be profile itself
+ * @param {String} syntax. Optional. Current editor syntax. If defined,
+ * profile is searched in resources first, then in predefined profiles
+ * @returns {Object}
+ */
+ get: function(name, syntax) {
+ if (!name && syntax) {
+ // search in user resources first
+ var profile = require('resources').findItem(syntax, 'profile');
+ if (profile) {
+ name = profile;
+ }
+ }
+
+ if (!name) {
+ return profiles.plain;
+ }
+
+ if (name instanceof OutputProfile) {
+ return name;
+ }
+
+ if (_.isString(name) && name.toLowerCase() in profiles) {
+ return profiles[name.toLowerCase()];
+ }
+
+ return this.create(name);
+ },
+
+ /**
+ * Deletes profile with specified name
+ * @param {String} name Profile name
+ */
+ remove: function(name) {
+ name = (name || '').toLowerCase();
+ if (name in profiles)
+ delete profiles[name];
+ },
+
+ /**
+ * Resets all user-defined profiles
+ */
+ reset: function() {
+ profiles = {};
+ createDefaultProfiles();
+ },
+
+ /**
+ * Helper function that converts string case depending on
+ * caseValue
+ * @param {String} str String to transform
+ * @param {String} caseValue Case value: can be lower ,
+ * upper and leave
+ * @returns {String}
+ */
+ stringCase: stringCase
+ };
+});/**
+ * Utility module used to prepare text for pasting into back-end editor
+ * @param {Function} require
+ * @param {Underscore} _
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ */
+emmet.define('editorUtils', function(require, _) {
+ return {
+ /**
+ * Check if cursor is placed inside XHTML tag
+ * @param {String} html Contents of the document
+ * @param {Number} caretPos Current caret position inside tag
+ * @return {Boolean}
+ */
+ isInsideTag: function(html, caretPos) {
+ var reTag = /^<\/?\w[\w\:\-]*.*?>/;
+
+ // search left to find opening brace
+ var pos = caretPos;
+ while (pos > -1) {
+ if (html.charAt(pos) == '<')
+ break;
+ pos--;
+ }
+
+ if (pos != -1) {
+ var m = reTag.exec(html.substring(pos));
+ if (m && caretPos > pos && caretPos < pos + m[0].length)
+ return true;
+ }
+
+ return false;
+ },
+
+ /**
+ * Sanitizes incoming editor data and provides default values for
+ * output-specific info
+ * @param {IEmmetEditor} editor
+ * @param {String} syntax
+ * @param {String} profile
+ */
+ outputInfo: function(editor, syntax, profile) {
+ // most of this code makes sense for Java/Rhino environment
+ // because string that comes from Java are not actually JS string
+ // but Java String object so the have to be explicitly converted
+ // to native string
+ profile = profile || editor.getProfileName();
+ return {
+ /** @memberOf outputInfo */
+ syntax: String(syntax || editor.getSyntax()),
+ profile: profile ? String(profile) : null,
+ content: String(editor.getContent())
+ };
+ },
+
+ /**
+ * Unindent content, thus preparing text for tag wrapping
+ * @param {IEmmetEditor} editor Editor instance
+ * @param {String} text
+ * @return {String}
+ */
+ unindent: function(editor, text) {
+ return require('utils').unindentString(text, this.getCurrentLinePadding(editor));
+ },
+
+ /**
+ * Returns padding of current editor's line
+ * @param {IEmmetEditor} Editor instance
+ * @return {String}
+ */
+ getCurrentLinePadding: function(editor) {
+ return require('utils').getLinePadding(editor.getCurrentLine());
+ }
+ };
+});
+/**
+ * Utility methods for Emmet actions
+ * @param {Function} require
+ * @param {Underscore} _
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ */
+emmet.define('actionUtils', function(require, _) {
+ return {
+ mimeTypes: {
+ 'gif' : 'image/gif',
+ 'png' : 'image/png',
+ 'jpg' : 'image/jpeg',
+ 'jpeg': 'image/jpeg',
+ 'svg' : 'image/svg+xml',
+ 'html': 'text/html',
+ 'htm' : 'text/html'
+ },
+
+ /**
+ * Extracts abbreviations from text stream, starting from the end
+ * @param {String} str
+ * @return {String} Abbreviation or empty string
+ * @memberOf emmet.actionUtils
+ */
+ extractAbbreviation: function(str) {
+ var curOffset = str.length;
+ var startIndex = -1;
+ var groupCount = 0;
+ var braceCount = 0;
+ var textCount = 0;
+
+ var utils = require('utils');
+ var parser = require('abbreviationParser');
+
+ while (true) {
+ curOffset--;
+ if (curOffset < 0) {
+ // moved to the beginning of the line
+ startIndex = 0;
+ break;
+ }
+
+ var ch = str.charAt(curOffset);
+
+ if (ch == ']') {
+ braceCount++;
+ } else if (ch == '[') {
+ if (!braceCount) { // unexpected brace
+ startIndex = curOffset + 1;
+ break;
+ }
+ braceCount--;
+ } else if (ch == '}') {
+ textCount++;
+ } else if (ch == '{') {
+ if (!textCount) { // unexpected brace
+ startIndex = curOffset + 1;
+ break;
+ }
+ textCount--;
+ } else if (ch == ')') {
+ groupCount++;
+ } else if (ch == '(') {
+ if (!groupCount) { // unexpected brace
+ startIndex = curOffset + 1;
+ break;
+ }
+ groupCount--;
+ } else {
+ if (braceCount || textCount)
+ // respect all characters inside attribute sets or text nodes
+ continue;
+ else if (!parser.isAllowedChar(ch) || (ch == '>' && utils.endsWithTag(str.substring(0, curOffset + 1)))) {
+ // found stop symbol
+ startIndex = curOffset + 1;
+ break;
+ }
+ }
+ }
+
+ if (startIndex != -1 && !textCount && !braceCount && !groupCount)
+ // found something, remove some invalid symbols from the
+ // beginning and return abbreviation
+ return str.substring(startIndex).replace(/^[\*\+\>\^]+/, '');
+ else
+ return '';
+ },
+
+ /**
+ * Gets image size from image byte stream.
+ * @author http://romeda.org/rePublish/
+ * @param {String} stream Image byte stream (use IEmmetFile.read())
+ * @return {Object} Object with width and height properties
+ */
+ getImageSize: function(stream) {
+ var pngMagicNum = "\211PNG\r\n\032\n",
+ jpgMagicNum = "\377\330",
+ gifMagicNum = "GIF8",
+ nextByte = function() {
+ return stream.charCodeAt(pos++);
+ };
+
+ if (stream.substr(0, 8) === pngMagicNum) {
+ // PNG. Easy peasy.
+ var pos = stream.indexOf('IHDR') + 4;
+
+ return { width: (nextByte() << 24) | (nextByte() << 16) |
+ (nextByte() << 8) | nextByte(),
+ height: (nextByte() << 24) | (nextByte() << 16) |
+ (nextByte() << 8) | nextByte() };
+
+ } else if (stream.substr(0, 4) === gifMagicNum) {
+ pos = 6;
+
+ return {
+ width: nextByte() | (nextByte() << 8),
+ height: nextByte() | (nextByte() << 8)
+ };
+
+ } else if (stream.substr(0, 2) === jpgMagicNum) {
+ pos = 2;
+
+ var l = stream.length;
+ while (pos < l) {
+ if (nextByte() != 0xFF) return;
+
+ var marker = nextByte();
+ if (marker == 0xDA) break;
+
+ var size = (nextByte() << 8) | nextByte();
+
+ if (marker >= 0xC0 && marker <= 0xCF && !(marker & 0x4) && !(marker & 0x8)) {
+ pos += 1;
+ return { height: (nextByte() << 8) | nextByte(),
+ width: (nextByte() << 8) | nextByte() };
+
+ } else {
+ pos += size - 2;
+ }
+ }
+ }
+ },
+
+ /**
+ * Captures context XHTML element from editor under current caret position.
+ * This node can be used as a helper for abbreviation extraction
+ * @param {IEmmetEditor} editor
+ * @returns {Object}
+ */
+ captureContext: function(editor) {
+ var allowedSyntaxes = {'html': 1, 'xml': 1, 'xsl': 1};
+ var syntax = String(editor.getSyntax());
+ if (syntax in allowedSyntaxes) {
+ var content = String(editor.getContent());
+ var tag = require('htmlMatcher').find(content, editor.getCaretPos());
+
+ if (tag && tag.type == 'tag') {
+ var reAttr = /([\w\-:]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
+ var startTag = tag.open;
+ var tagAttrs = startTag.range.substring(content).replace(/^<[\w\-\:]+/, '');
+// var tagAttrs = startTag.full_tag.replace(/^<[\w\-\:]+/, '');
+ var contextNode = {
+ name: startTag.name,
+ attributes: []
+ };
+
+ // parse attributes
+ var m;
+ while (m = reAttr.exec(tagAttrs)) {
+ contextNode.attributes.push({
+ name: m[1],
+ value: m[2]
+ });
+ }
+
+ return contextNode;
+ }
+ }
+
+ return null;
+ },
+
+ /**
+ * Find expression bounds in current editor at caret position.
+ * On each character a fn function will be called and must
+ * return true if current character meets requirements,
+ * false otherwise
+ * @param {IEmmetEditor} editor
+ * @param {Function} fn Function to test each character of expression
+ * @return {Range}
+ */
+ findExpressionBounds: function(editor, fn) {
+ var content = String(editor.getContent());
+ var il = content.length;
+ var exprStart = editor.getCaretPos() - 1;
+ var exprEnd = exprStart + 1;
+
+ // start by searching left
+ while (exprStart >= 0 && fn(content.charAt(exprStart), exprStart, content)) exprStart--;
+
+ // then search right
+ while (exprEnd < il && fn(content.charAt(exprEnd), exprEnd, content)) exprEnd++;
+
+ if (exprEnd > exprStart) {
+ return require('range').create([++exprStart, exprEnd]);
+ }
+ },
+
+ /**
+ * @param {IEmmetEditor} editor
+ * @param {Object} data
+ * @returns {Boolean}
+ */
+ compoundUpdate: function(editor, data) {
+ if (data) {
+ var sel = editor.getSelectionRange();
+ editor.replaceContent(data.data, data.start, data.end, true);
+ editor.createSelection(data.caret, data.caret + sel.end - sel.start);
+ return true;
+ }
+
+ return false;
+ },
+
+ /**
+ * Common syntax detection method for editors that doesn’t provide any
+ * info about current syntax scope.
+ * @param {IEmmetEditor} editor Current editor
+ * @param {String} hint Any syntax hint that editor can provide
+ * for syntax detection. Default is 'html'
+ * @returns {String}
+ */
+ detectSyntax: function(editor, hint) {
+ var syntax = hint || 'html';
+
+ if (!require('resources').hasSyntax(syntax)) {
+ syntax = 'html';
+ }
+
+ if (syntax == 'html' && (this.isStyle(editor) || this.isInlineCSS(editor))) {
+ syntax = 'css';
+ }
+
+ return syntax;
+ },
+
+ /**
+ * Common method for detecting output profile
+ * @param {IEmmetEditor} editor
+ * @returns {String}
+ */
+ detectProfile: function(editor) {
+ var syntax = editor.getSyntax();
+
+ // get profile from syntax definition
+ var profile = require('resources').findItem(syntax, 'profile');
+ if (profile) {
+ return profile;
+ }
+
+ switch(syntax) {
+ case 'xml':
+ case 'xsl':
+ return 'xml';
+ case 'css':
+ if (this.isInlineCSS(editor)) {
+ return 'line';
+ }
+ break;
+ case 'html':
+ var profile = require('resources').getVariable('profile');
+ if (!profile) { // no forced profile, guess from content
+ // html or xhtml?
+ profile = this.isXHTML(editor) ? 'xhtml': 'html';
+ }
+
+ return profile;
+ }
+
+ return 'xhtml';
+ },
+
+ /**
+ * Tries to detect if current document is XHTML one.
+ * @param {IEmmetEditor} editor
+ * @returns {Boolean}
+ */
+ isXHTML: function(editor) {
+ return editor.getContent().search(/]+XHTML/i) != -1;
+ },
+
+ /**
+ * Check if current caret position is inside <style> tag
+ * @param {IEmmetEditor} editor
+ * @returns
+ */
+ isStyle: function(editor) {
+ var content = String(editor.getContent());
+ var caretPos = editor.getCaretPos();
+ var tag = require('htmlMatcher').tag(content, caretPos);
+ return tag && tag.open.name.toLowerCase() == 'style'
+ && tag.innerRange.cmp(caretPos, 'lte', 'gte');
+ },
+
+ /**
+ * Check if current caret position is inside "style" attribute of HTML
+ * element
+ * @param {IEmmetEditor} editor
+ * @returns {Boolean}
+ */
+ isInlineCSS: function(editor) {
+ var content = String(editor.getContent());
+ var caretPos = editor.getCaretPos();
+ var tree = require('xmlEditTree').parseFromPosition(content, caretPos, true);
+ if (tree) {
+ var attr = tree.itemFromPosition(caretPos, true);
+ return attr && attr.name().toLowerCase() == 'style'
+ && attr.valueRange(true).cmp(caretPos, 'lte', 'gte');
+ }
+
+ return false;
+ }
+ };
+});/**
+ * Utility functions to work with AbbreviationNode as HTML element
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('abbreviationUtils', function(require, _) {
+ return {
+ /**
+ * Check if passed abbreviation node has matched snippet resource
+ * @param {AbbreviationNode} node
+ * @returns {Boolean}
+ * @memberOf abbreviationUtils
+ */
+ isSnippet: function(node) {
+ return require('elements').is(node.matchedResource(), 'snippet');
+ },
+
+ /**
+ * Test if passed node is unary (no closing tag)
+ * @param {AbbreviationNode} node
+ * @return {Boolean}
+ */
+ isUnary: function(node) {
+ var r = node.matchedResource();
+ if (node.children.length || this.isSnippet(node))
+ return false;
+
+ return r && r.is_empty || require('tagName').isEmptyElement(node.name());
+ },
+
+ /**
+ * Test if passed node is inline-level (like <strong>, <img>)
+ * @param {AbbreviationNode} node
+ * @return {Boolean}
+ */
+ isInline: function(node) {
+ return node.isTextNode()
+ || !node.name()
+ || require('tagName').isInlineLevel(node.name());
+ },
+
+ /**
+ * Test if passed node is block-level
+ * @param {AbbreviationNode} node
+ * @return {Boolean}
+ */
+ isBlock: function(node) {
+ return this.isSnippet(node) || !this.isInline(node);
+ },
+
+ /**
+ * Test if given node is a snippet
+ * @param {AbbreviationNode} node
+ * @return {Boolean}
+ */
+ isSnippet: function(node) {
+ return require('elements').is(node.matchedResource(), 'snippet');
+ },
+
+ /**
+ * This function tests if passed node content contains HTML tags.
+ * This function is mostly used for output formatting
+ * @param {AbbreviationNode} node
+ * @returns {Boolean}
+ */
+ hasTagsInContent: function(node) {
+ return require('utils').matchesTag(node.content);
+ },
+
+ /**
+ * Test if current element contains block-level children
+ * @param {AbbreviationNode} node
+ * @return {Boolean}
+ */
+ hasBlockChildren: function(node) {
+ return (this.hasTagsInContent(node) && this.isBlock(node))
+ || _.any(node.children, function(child) {
+ return this.isBlock(child);
+ }, this);
+ },
+
+ /**
+ * Utility function that inserts content instead of ${child}
+ * variables on text
+ * @param {String} text Text where child content should be inserted
+ * @param {String} childContent Content to insert
+ * @param {Object} options
+ * @returns {String
+ */
+ insertChildContent: function(text, childContent, options) {
+ options = _.extend({
+ keepVariable: true,
+ appendIfNoChild: true
+ }, options || {});
+
+ var childVariableReplaced = false;
+ var utils = require('utils');
+ text = utils.replaceVariables(text, function(variable, name, data) {
+ var output = variable;
+ if (name == 'child') {
+ // add correct indentation
+ output = utils.padString(childContent, utils.getLinePaddingFromPosition(text, data.start));
+ childVariableReplaced = true;
+ if (options.keepVariable)
+ output += variable;
+ }
+
+ return output;
+ });
+
+ if (!childVariableReplaced && options.appendIfNoChild) {
+ text += childContent;
+ }
+
+ return text;
+ }
+ };
+});/**
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ */
+emmet.define('base64', function(require, _) {
+ var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+
+ return {
+ /**
+ * Encodes data using base64 algorithm
+ * @author Tyler Akins (http://rumkin.com)
+ * @param {String} input
+ * @returns {String}
+ * @memberOf emmet.base64
+ */
+ encode : function(input) {
+ var output = [];
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4, cdp1, cdp2, cdp3;
+ var i = 0, il = input.length, b64 = chars;
+
+ while (i < il) {
+
+ cdp1 = input.charCodeAt(i++);
+ cdp2 = input.charCodeAt(i++);
+ cdp3 = input.charCodeAt(i++);
+
+ chr1 = cdp1 & 0xff;
+ chr2 = cdp2 & 0xff;
+ chr3 = cdp3 & 0xff;
+
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+
+ if (isNaN(cdp2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(cdp3)) {
+ enc4 = 64;
+ }
+
+ output.push(b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4));
+ }
+
+ return output.join('');
+ },
+
+ /**
+ * Decodes string using MIME base64 algorithm
+ *
+ * @author Tyler Akins (http://rumkin.com)
+ * @param {String} data
+ * @return {String}
+ */
+ decode : function(data) {
+ var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, tmpArr = [];
+ var b64 = chars, il = data.length;
+
+ if (!data) {
+ return data;
+ }
+
+ data += '';
+
+ do { // unpack four hexets into three octets using index points in b64
+ h1 = b64.indexOf(data.charAt(i++));
+ h2 = b64.indexOf(data.charAt(i++));
+ h3 = b64.indexOf(data.charAt(i++));
+ h4 = b64.indexOf(data.charAt(i++));
+
+ bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
+
+ o1 = bits >> 16 & 0xff;
+ o2 = bits >> 8 & 0xff;
+ o3 = bits & 0xff;
+
+ if (h3 == 64) {
+ tmpArr[ac++] = String.fromCharCode(o1);
+ } else if (h4 == 64) {
+ tmpArr[ac++] = String.fromCharCode(o1, o2);
+ } else {
+ tmpArr[ac++] = String.fromCharCode(o1, o2, o3);
+ }
+ } while (i < il);
+
+ return tmpArr.join('');
+ }
+ };
+});/**
+ * HTML matcher: takes string and searches for HTML tag pairs for given position
+ *
+ * Unlike “classic” matchers, it parses content from the specified
+ * position, not from the start, so it may work even outside HTML documents
+ * (for example, inside strings of programming languages like JavaScript, Python
+ * etc.)
+ * @constructor
+ * @memberOf __htmlMatcherDefine
+ */
+emmet.define('htmlMatcher', function(require, _) {
+ // Regular Expressions for parsing tags and attributes
+ var reOpenTag = /^<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
+ var reCloseTag = /^<\/([\w\:\-]+)[^>]*>/;
+
+ function openTag(i, match) {
+ return {
+ name: match[1],
+ selfClose: !!match[3],
+ /** @type Range */
+ range: require('range').create(i, match[0]),
+ type: 'open'
+ };
+ }
+
+ function closeTag(i, match) {
+ return {
+ name: match[1],
+ /** @type Range */
+ range: require('range').create(i, match[0]),
+ type: 'close'
+ };
+ }
+
+ function comment(i, match) {
+ return {
+ /** @type Range */
+ range: require('range').create(i, _.isNumber(match) ? match - i : match[0]),
+ type: 'comment'
+ };
+ }
+
+ /**
+ * Creates new tag matcher session
+ * @param {String} text
+ */
+ function createMatcher(text) {
+ var memo = {}, m;
+ return {
+ /**
+ * Test if given position matches opening tag
+ * @param {Number} i
+ * @returns {Object} Matched tag object
+ */
+ open: function(i) {
+ var m = this.matches(i);
+ return m && m.type == 'open' ? m : null;
+ },
+
+ /**
+ * Test if given position matches closing tag
+ * @param {Number} i
+ * @returns {Object} Matched tag object
+ */
+ close: function(i) {
+ var m = this.matches(i);
+ return m && m.type == 'close' ? m : null;
+ },
+
+ /**
+ * Matches either opening or closing tag for given position
+ * @param i
+ * @returns
+ */
+ matches: function(i) {
+ var key = 'p' + i;
+
+ if (!(key in memo)) {
+ if (text.charAt(i) == '<') {
+ var substr = text.slice(i);
+ if (m = substr.match(reOpenTag)) {
+ memo[key] = openTag(i, m);
+ } else if (m = substr.match(reCloseTag)) {
+ memo[key] = closeTag(i, m);
+ } else {
+ // remember that given position contains no valid tag
+ memo[key] = false;
+ }
+ }
+ }
+
+ return memo[key];
+ },
+
+ /**
+ * Returns original text
+ * @returns {String}
+ */
+ text: function() {
+ return text;
+ }
+ };
+ }
+
+ function matches(text, pos, pattern) {
+ return text.substring(pos, pos + pattern.length) == pattern;
+ }
+
+ /**
+ * Search for closing pair of opening tag
+ * @param {Object} open Open tag instance
+ * @param {Object} matcher Matcher instance
+ */
+ function findClosingPair(open, matcher) {
+ var stack = [], tag = null;
+ var text = matcher.text();
+
+ for (var pos = open.range.end, len = text.length; pos < len; pos++) {
+ if (matches(text, pos, '')) {
+ pos = j + 3;
+ break;
+ }
+ }
+ }
+
+ if (tag = matcher.matches(pos)) {
+ if (tag.type == 'open' && !tag.selfClose) {
+ stack.push(tag.name);
+ } else if (tag.type == 'close') {
+ if (!stack.length) { // found valid pair?
+ return tag.name == open.name ? tag : null;
+ }
+
+ // check if current closing tag matches previously opened one
+ if (_.last(stack) == tag.name) {
+ stack.pop();
+ } else {
+ var found = false;
+ while (stack.length && !found) {
+ var last = stack.pop();
+ if (last == tag.name) {
+ found = true;
+ }
+ }
+
+ if (!stack.length && !found) {
+ return tag.name == open.name ? tag : null;
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ return {
+ /**
+ * Main function: search for tag pair in text for given
+ * position
+ * @memberOf htmlMatcher
+ * @param {String} text
+ * @param {Number} pos
+ * @returns {Object}
+ */
+ find: function(text, pos) {
+ var range = require('range');
+ var matcher = createMatcher(text);
+ var open = null, close = null;
+
+ for (var i = pos; i >= 0; i--) {
+ if (open = matcher.open(i)) {
+ // found opening tag
+ if (open.selfClose) {
+ if (open.range.cmp(pos, 'lt', 'gt')) {
+ // inside self-closing tag, found match
+ break;
+ }
+
+ // outside self-closing tag, continue
+ continue;
+ }
+
+ close = findClosingPair(open, matcher);
+ if (close) {
+ // found closing tag.
+ var r = range.create2(open.range.start, close.range.end);
+ if (r.contains(pos)) {
+ break;
+ }
+ } else if (open.range.contains(pos)) {
+ // we inside empty HTML tag like
+ break;
+ }
+
+ open = null;
+ } else if (matches(text, i, '-->')) {
+ // skip back to comment start
+ for (var j = i - 1; j >= 0; j--) {
+ if (matches(text, j, '-->')) {
+ // found another comment end, do nothing
+ break;
+ } else if (matches(text, j, '')) {
+ j += 3;
+ break;
+ }
+ }
+
+ open = comment(i, j);
+ break;
+ }
+ }
+
+ if (open) {
+ var outerRange = null;
+ var innerRange = null;
+
+ if (close) {
+ outerRange = range.create2(open.range.start, close.range.end);
+ innerRange = range.create2(open.range.end, close.range.start);
+ } else {
+ outerRange = innerRange = range.create2(open.range.start, open.range.end);
+ }
+
+ if (open.type == 'comment') {
+ // adjust positions of inner range for comment
+ var _c = outerRange.substring(text);
+ innerRange.start += _c.length - _c.replace(/^<\!--\s*/, '').length;
+ innerRange.end -= _c.length - _c.replace(/\s*-->$/, '').length;
+ }
+
+ return {
+ open: open,
+ close: close,
+ type: open.type == 'comment' ? 'comment' : 'tag',
+ innerRange: innerRange,
+ innerContent: function() {
+ return this.innerRange.substring(text);
+ },
+ outerRange: outerRange,
+ outerContent: function() {
+ return this.outerRange.substring(text);
+ },
+ range: !innerRange.length() || !innerRange.cmp(pos, 'lte', 'gte') ? outerRange : innerRange,
+ content: function() {
+ return this.range.substring(text);
+ },
+ source: text
+ };
+ }
+ },
+
+ /**
+ * The same as find() method, but restricts matched result
+ * to tag type
+ * @param {String} text
+ * @param {Number} pos
+ * @returns {Object}
+ */
+ tag: function(text, pos) {
+ var result = this.find(text, pos);
+ if (result && result.type == 'tag') {
+ return result;
+ }
+ }
+ };
+});/**
+ * Utility module for handling tabstops tokens generated by Emmet's
+ * "Expand Abbreviation" action. The main extract method will take
+ * raw text (for example: ${0} some ${1:text} ), find all tabstops
+ * occurrences, replace them with tokens suitable for your editor of choice and
+ * return object with processed text and list of found tabstops and their ranges.
+ * For sake of portability (Objective-C/Java) the tabstops list is a plain
+ * sorted array with plain objects.
+ *
+ * Placeholders with the same are meant to be linked in your editor.
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('tabStops', function(require, _) {
+ /**
+ * Global placeholder value, automatically incremented by
+ * variablesResolver() function
+ */
+ var startPlaceholderNum = 100;
+
+ var tabstopIndex = 0;
+
+ var defaultOptions = {
+ replaceCarets: false,
+ escape: function(ch) {
+ return '\\' + ch;
+ },
+ tabstop: function(data) {
+ return data.token;
+ },
+ variable: function(data) {
+ return data.token;
+ }
+ };
+
+ // XXX register output processor that will upgrade tabstops of parsed node
+ // in order to prevent tabstop index conflicts
+ require('abbreviationParser').addOutputProcessor(function(text, node, type) {
+ var maxNum = 0;
+ var tabstops = require('tabStops');
+ var utils = require('utils');
+
+ var tsOptions = {
+ tabstop: function(data) {
+ var group = parseInt(data.group);
+ if (group == 0)
+ return '${0}';
+
+ if (group > maxNum) maxNum = group;
+ if (data.placeholder) {
+ // respect nested placeholders
+ var ix = group + tabstopIndex;
+ var placeholder = tabstops.processText(data.placeholder, tsOptions);
+ return '${' + ix + ':' + placeholder + '}';
+ } else {
+ return '${' + (group + tabstopIndex) + '}';
+ }
+ }
+ };
+
+ // upgrade tabstops
+ text = tabstops.processText(text, tsOptions);
+
+ // resolve variables
+ text = utils.replaceVariables(text, tabstops.variablesResolver(node));
+
+ tabstopIndex += maxNum + 1;
+ return text;
+ });
+
+ return {
+ /**
+ * Main function that looks for a tabstops in provided text
+ * and returns a processed version of text with expanded
+ * placeholders and list of tabstops found.
+ * @param {String} text Text to process
+ * @param {Object} options List of processor options:
+ *
+ * replaceCarets : Boolean — replace all default
+ * caret placeholders (like {%::emmet-caret::%} ) with ${0:caret}
+ *
+ * escape : Function — function that handle escaped
+ * characters (mostly '$'). By default, it returns the character itself
+ * to be displayed as is in output, but sometimes you will use
+ * extract method as intermediate solution for further
+ * processing and want to keep character escaped. Thus, you should override
+ * escape method to return escaped symbol (e.g. '\\$')
+ *
+ * tabstop : Function – a tabstop handler. Receives
+ * a single argument – an object describing token: its position, number
+ * group, placeholder and token itself. Should return a replacement
+ * string that will appear in final output
+ *
+ * variable : Function – variable handler. Receives
+ * a single argument – an object describing token: its position, name
+ * and original token itself. Should return a replacement
+ * string that will appear in final output
+ *
+ * @returns {Object} Object with processed text property
+ * and array of tabstops found
+ * @memberOf tabStops
+ */
+ extract: function(text, options) {
+ // prepare defaults
+ var utils = require('utils');
+ var placeholders = {carets: ''};
+ var marks = [];
+
+ options = _.extend({}, defaultOptions, options, {
+ tabstop: function(data) {
+ var token = data.token;
+ var ret = '';
+ if (data.placeholder == 'cursor') {
+ marks.push({
+ start: data.start,
+ end: data.start + token.length,
+ group: 'carets',
+ value: ''
+ });
+ } else {
+ // unify placeholder value for single group
+ if ('placeholder' in data)
+ placeholders[data.group] = data.placeholder;
+
+ if (data.group in placeholders)
+ ret = placeholders[data.group];
+
+ marks.push({
+ start: data.start,
+ end: data.start + token.length,
+ group: data.group,
+ value: ret
+ });
+ }
+
+ return token;
+ }
+ });
+
+ if (options.replaceCarets) {
+ text = text.replace(new RegExp( utils.escapeForRegexp( utils.getCaretPlaceholder() ), 'g'), '${0:cursor}');
+ }
+
+ // locate tabstops and unify group's placeholders
+ text = this.processText(text, options);
+
+ // now, replace all tabstops with placeholders
+ var buf = utils.stringBuilder(), lastIx = 0;
+ var tabStops = _.map(marks, function(mark) {
+ buf.append(text.substring(lastIx, mark.start));
+
+ var pos = buf.length;
+ var ph = placeholders[mark.group] || '';
+
+ buf.append(ph);
+ lastIx = mark.end;
+
+ return {
+ group: mark.group,
+ start: pos,
+ end: pos + ph.length
+ };
+ });
+
+ buf.append(text.substring(lastIx));
+
+ return {
+ text: buf.toString(),
+ tabstops: _.sortBy(tabStops, 'start')
+ };
+ },
+
+ /**
+ * Text processing routine. Locates escaped characters and tabstops and
+ * replaces them with values returned by handlers defined in
+ * options
+ * @param {String} text
+ * @param {Object} options See extract method options
+ * description
+ * @returns {String}
+ */
+ processText: function(text, options) {
+ options = _.extend({}, defaultOptions, options);
+
+ var buf = require('utils').stringBuilder();
+ /** @type StringStream */
+ var stream = require('stringStream').create(text);
+ var ch, m, a;
+
+ while (ch = stream.next()) {
+ if (ch == '\\' && !stream.eol()) {
+ // handle escaped character
+ buf.append(options.escape(stream.next()));
+ continue;
+ }
+
+ a = ch;
+
+ if (ch == '$') {
+ // looks like a tabstop
+ stream.start = stream.pos - 1;
+
+ if (m = stream.match(/^[0-9]+/)) {
+ // it's $N
+ a = options.tabstop({
+ start: buf.length,
+ group: stream.current().substr(1),
+ token: stream.current()
+ });
+ } else if (m = stream.match(/^\{([a-z_\-][\w\-]*)\}/)) {
+ // ${variable}
+ a = options.variable({
+ start: buf.length,
+ name: m[1],
+ token: stream.current()
+ });
+ } else if (m = stream.match(/^\{([0-9]+)(:.+?)?\}/, false)) {
+ // ${N:value} or ${N} placeholder
+ // parse placeholder, including nested ones
+ stream.skipToPair('{', '}');
+
+ var obj = {
+ start: buf.length,
+ group: m[1],
+ token: stream.current()
+ };
+
+ var placeholder = obj.token.substring(obj.group.length + 2, obj.token.length - 1);
+
+ if (placeholder) {
+ obj.placeholder = placeholder.substr(1);
+ }
+
+ a = options.tabstop(obj);
+ }
+ }
+
+ buf.append(a);
+ }
+
+ return buf.toString();
+ },
+
+ /**
+ * Upgrades tabstops in output node in order to prevent naming conflicts
+ * @param {AbbreviationNode} node
+ * @param {Number} offset Tab index offset
+ * @returns {Number} Maximum tabstop index in element
+ */
+ upgrade: function(node, offset) {
+ var maxNum = 0;
+ var options = {
+ tabstop: function(data) {
+ var group = parseInt(data.group);
+ if (group > maxNum) maxNum = group;
+
+ if (data.placeholder)
+ return '${' + (group + offset) + ':' + data.placeholder + '}';
+ else
+ return '${' + (group + offset) + '}';
+ }
+ };
+
+ _.each(['start', 'end', 'content'], function(p) {
+ node[p] = this.processText(node[p], options);
+ }, this);
+
+ return maxNum;
+ },
+
+ /**
+ * Helper function that produces a callback function for
+ * replaceVariables() method from {@link utils}
+ * module. This callback will replace variable definitions (like
+ * ${var_name}) with their value defined in resource module,
+ * or outputs tabstop with variable name otherwise.
+ * @param {AbbreviationNode} node Context node
+ * @returns {Function}
+ */
+ variablesResolver: function(node) {
+ var placeholderMemo = {};
+ var res = require('resources');
+ return function(str, varName) {
+ // do not mark `child` variable as placeholder – it‘s a reserved
+ // variable name
+ if (varName == 'child')
+ return str;
+
+ if (varName == 'cursor')
+ return require('utils').getCaretPlaceholder();
+
+ var attr = node.attribute(varName);
+ if (!_.isUndefined(attr) && attr !== str) {
+ return attr;
+ }
+
+ var varValue = res.getVariable(varName);
+ if (varValue)
+ return varValue;
+
+ // output as placeholder
+ if (!placeholderMemo[varName])
+ placeholderMemo[varName] = startPlaceholderNum++;
+
+ return '${' + placeholderMemo[varName] + ':' + varName + '}';
+ };
+ },
+
+ /**
+ * Resets global tabstop index. When parsed tree is converted to output
+ * string (AbbreviationNode.toString()), all tabstops
+ * defined in snippets and elements are upgraded in order to prevent
+ * naming conflicts of nested. For example, ${1} of a node
+ * should not be linked with the same placehilder of the child node.
+ * By default, AbbreviationNode.toString() automatically
+ * upgrades tabstops of the same index for each node and writes maximum
+ * tabstop index into the tabstopIndex variable. To keep
+ * this variable at reasonable value, it is recommended to call
+ * resetTabstopIndex() method each time you expand variable
+ * @returns
+ */
+ resetTabstopIndex: function() {
+ tabstopIndex = 0;
+ startPlaceholderNum = 100;
+ }
+ };
+});/**
+ * Common module's preferences storage. This module
+ * provides general storage for all module preferences, their description and
+ * default values.
+ *
+ * This module can also be used to list all available properties to create
+ * UI for updating properties
+ *
+ * @memberOf __preferencesDefine
+ * @constructor
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('preferences', function(require, _) {
+ var preferences = {};
+ var defaults = {};
+ var _dbgDefaults = null;
+ var _dbgPreferences = null;
+
+ function toBoolean(val) {
+ if (_.isString(val)) {
+ val = val.toLowerCase();
+ return val == 'yes' || val == 'true' || val == '1';
+ }
+
+ return !!val;
+ }
+
+ function isValueObj(obj) {
+ return _.isObject(obj)
+ && 'value' in obj
+ && _.keys(obj).length < 3;
+ }
+
+ return {
+ /**
+ * Creates new preference item with default value
+ * @param {String} name Preference name. You can also pass object
+ * with many options
+ * @param {Object} value Preference default value
+ * @param {String} description Item textual description
+ * @memberOf preferences
+ */
+ define: function(name, value, description) {
+ var prefs = name;
+ if (_.isString(name)) {
+ prefs = {};
+ prefs[name] = {
+ value: value,
+ description: description
+ };
+ }
+
+ _.each(prefs, function(v, k) {
+ defaults[k] = isValueObj(v) ? v : {value: v};
+ });
+ },
+
+ /**
+ * Updates preference item value. Preference value should be defined
+ * first with define method.
+ * @param {String} name Preference name. You can also pass object
+ * with many options
+ * @param {Object} value Preference default value
+ * @memberOf preferences
+ */
+ set: function(name, value) {
+ var prefs = name;
+ if (_.isString(name)) {
+ prefs = {};
+ prefs[name] = value;
+ }
+
+ _.each(prefs, function(v, k) {
+ if (!(k in defaults)) {
+ throw 'Property "' + k + '" is not defined. You should define it first with `define` method of current module';
+ }
+
+ // do not set value if it equals to default value
+ if (v !== defaults[k].value) {
+ // make sure we have value of correct type
+ switch (typeof defaults[k].value) {
+ case 'boolean':
+ v = toBoolean(v);
+ break;
+ case 'number':
+ v = parseInt(v + '', 10) || 0;
+ break;
+ default: // convert to string
+ v += '';
+ }
+
+ preferences[k] = v;
+ } else if (k in preferences) {
+ delete preferences[k];
+ }
+ });
+ },
+
+ /**
+ * Returns preference value
+ * @param {String} name
+ * @returns {String} Returns undefined if preference is
+ * not defined
+ */
+ get: function(name) {
+ if (name in preferences)
+ return preferences[name];
+
+ if (name in defaults)
+ return defaults[name].value;
+
+ return void 0;
+ },
+
+ /**
+ * Returns comma-separated preference value as array of values
+ * @param {String} name
+ * @returns {Array} Returns undefined if preference is
+ * not defined, null if string cannot be converted to array
+ */
+ getArray: function(name) {
+ var val = this.get(name);
+ if (!_.isUndefined(val)) {
+ val = _.map(val.split(','), require('utils').trim);
+ if (!val.length)
+ val = null;
+ }
+
+ return val;
+ },
+
+ /**
+ * Returns comma and colon-separated preference value as dictionary
+ * @param {String} name
+ * @returns {Object}
+ */
+ getDict: function(name) {
+ var result = {};
+ _.each(this.getArray(name), function(val) {
+ var parts = val.split(':');
+ result[parts[0]] = parts[1];
+ });
+
+ return result;
+ },
+
+ /**
+ * Returns description of preference item
+ * @param {String} name Preference name
+ * @returns {Object}
+ */
+ description: function(name) {
+ return name in defaults ? defaults[name].description : void 0;
+ },
+
+ /**
+ * Completely removes specified preference(s)
+ * @param {String} name Preference name (or array of names)
+ */
+ remove: function(name) {
+ if (!_.isArray(name))
+ name = [name];
+
+ _.each(name, function(key) {
+ if (key in preferences)
+ delete preferences[key];
+
+ if (key in defaults)
+ delete defaults[key];
+ });
+ },
+
+ /**
+ * Returns sorted list of all available properties
+ * @returns {Array}
+ */
+ list: function() {
+ return _.map(_.keys(defaults).sort(), function(key) {
+ return {
+ name: key,
+ value: this.get(key),
+ type: typeof defaults[key].value,
+ description: defaults[key].description
+ };
+ }, this);
+ },
+
+ /**
+ * Loads user-defined preferences from JSON
+ * @param {Object} json
+ * @returns
+ */
+ load: function(json) {
+ _.each(json, function(value, key) {
+ this.set(key, value);
+ }, this);
+ },
+
+ /**
+ * Returns hash of user-modified preferences
+ * @returns {Object}
+ */
+ exportModified: function() {
+ return _.clone(preferences);
+ },
+
+ /**
+ * Reset to defaults
+ * @returns
+ */
+ reset: function() {
+ preferences = {};
+ },
+
+ /**
+ * For unit testing: use empty storage
+ */
+ _startTest: function() {
+ _dbgDefaults = defaults;
+ _dbgPreferences = preferences;
+ defaults = {};
+ preferences = {};
+ },
+
+ /**
+ * For unit testing: restore original storage
+ */
+ _stopTest: function() {
+ defaults = _dbgDefaults;
+ preferences = _dbgPreferences;
+ }
+ };
+});/**
+ * Module for handling filters
+ * @param {Function} require
+ * @param {Underscore} _
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ */
+emmet.define('filters', function(require, _) {
+ /** List of registered filters */
+ var registeredFilters = {};
+
+ /** Filters that will be applied for unknown syntax */
+ var basicFilters = 'html';
+
+ function list(filters) {
+ if (!filters)
+ return [];
+
+ if (_.isString(filters))
+ return filters.split(/[\|,]/g);
+
+ return filters;
+ }
+
+ return {
+ /**
+ * Register new filter
+ * @param {String} name Filter name
+ * @param {Function} fn Filter function
+ */
+ add: function(name, fn) {
+ registeredFilters[name] = fn;
+ },
+
+ /**
+ * Apply filters for final output tree
+ * @param {AbbreviationNode} tree Output tree
+ * @param {Array} filters List of filters to apply. Might be a
+ * String
+ * @param {Object} profile Output profile, defined in profile
+ * module. Filters defined it profile are not used, profile
+ * is passed to filter function
+ * @memberOf emmet.filters
+ * @returns {AbbreviationNode}
+ */
+ apply: function(tree, filters, profile) {
+ var utils = require('utils');
+ profile = require('profile').get(profile);
+
+ _.each(list(filters), function(filter) {
+ var name = utils.trim(filter.toLowerCase());
+ if (name && name in registeredFilters) {
+ tree = registeredFilters[name](tree, profile);
+ }
+ });
+
+ return tree;
+ },
+
+ /**
+ * Composes list of filters that should be applied to a tree, based on
+ * passed data
+ * @param {String} syntax Syntax name ('html', 'css', etc.)
+ * @param {Object} profile Output profile
+ * @param {String} additionalFilters List or pipe-separated
+ * string of additional filters to apply
+ * @returns {Array}
+ */
+ composeList: function(syntax, profile, additionalFilters) {
+ profile = require('profile').get(profile);
+ var filters = list(profile.filters || require('resources').findItem(syntax, 'filters') || basicFilters);
+
+ if (profile.extraFilters) {
+ filters = filters.concat(list(profile.extraFilters));
+ }
+
+ if (additionalFilters) {
+ filters = filters.concat(list(additionalFilters));
+ }
+
+ if (!filters || !filters.length) {
+ // looks like unknown syntax, apply basic filters
+ filters = list(basicFilters);
+ }
+
+ return filters;
+ },
+
+ /**
+ * Extracts filter list from abbreviation
+ * @param {String} abbr
+ * @returns {Array} Array with cleaned abbreviation and list of
+ * extracted filters
+ */
+ extractFromAbbreviation: function(abbr) {
+ var filters = '';
+ abbr = abbr.replace(/\|([\w\|\-]+)$/, function(str, p1){
+ filters = p1;
+ return '';
+ });
+
+ return [abbr, list(filters)];
+ }
+ };
+});/**
+ * Module that contains factories for element types used by Emmet
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('elements', function(require, _) {
+ var factories = {};
+ var reAttrs = /([\w\-]+)\s*=\s*(['"])(.*?)\2/g;
+
+ var result = {
+ /**
+ * Create new element factory
+ * @param {String} name Element identifier
+ * @param {Function} factory Function that produces element of specified
+ * type. The object generated by this factory is automatically
+ * augmented with type property pointing to element
+ * name
+ * @memberOf elements
+ */
+ add: function(name, factory) {
+ var that = this;
+ factories[name] = function() {
+ var elem = factory.apply(that, arguments);
+ if (elem)
+ elem.type = name;
+
+ return elem;
+ };
+ },
+
+ /**
+ * Returns factory for specified name
+ * @param {String} name
+ * @returns {Function}
+ */
+ get: function(name) {
+ return factories[name];
+ },
+
+ /**
+ * Creates new element with specified type
+ * @param {String} name
+ * @returns {Object}
+ */
+ create: function(name) {
+ var args = [].slice.call(arguments, 1);
+ var factory = this.get(name);
+ return factory ? factory.apply(this, args) : null;
+ },
+
+ /**
+ * Check if passed element is of specified type
+ * @param {Object} elem
+ * @param {String} type
+ * @returns {Boolean}
+ */
+ is: function(elem, type) {
+ return elem && elem.type === type;
+ }
+ };
+
+ // register resource references
+ function commonFactory(value) {
+ return {data: value};
+ }
+
+ /**
+ * Element factory
+ * @param {String} elementName Name of output element
+ * @param {String} attrs Attributes definition. You may also pass
+ * Array where each contains object with name
+ * and value properties, or Object
+ * @param {Boolean} isEmpty Is expanded element should be empty
+ */
+ result.add('element', function(elementName, attrs, isEmpty) {
+ var ret = {
+ /** @memberOf __emmetDataElement */
+ name: elementName,
+ is_empty: !!isEmpty
+ };
+
+ if (attrs) {
+ ret.attributes = [];
+ if (_.isArray(attrs)) {
+ ret.attributes = attrs;
+ } else if (_.isString(attrs)) {
+ var m;
+ while (m = reAttrs.exec(attrs)) {
+ ret.attributes.push({
+ name: m[1],
+ value: m[3]
+ });
+ }
+ } else {
+ _.each(attrs, function(value, name) {
+ ret.attributes.push({
+ name: name,
+ value: value
+ });
+ });
+ }
+ }
+
+ return ret;
+ });
+
+ result.add('snippet', commonFactory);
+ result.add('reference', commonFactory);
+ result.add('empty', function() {
+ return {};
+ });
+
+ return result;
+});/**
+ * Abstract implementation of edit tree interface.
+ * Edit tree is a named container of editable “name-value” child elements,
+ * parsed from source. This container provides convenient methods
+ * for editing/adding/removing child elements. All these update actions are
+ * instantly reflected in the source code with respect of formatting.
+ *
+ * For example, developer can create an edit tree from CSS rule and add or
+ * remove properties from it–all changes will be immediately reflected in the
+ * original source.
+ *
+ * All classes defined in this module should be extended the same way as in
+ * Backbone framework: using extend method to create new class and
+ * initialize method to define custom class constructor.
+ *
+ * @example
+ *
+ * var MyClass = require('editTree').EditElement.extend({
+ * initialize: function() {
+ * // constructor code here
+ * }
+ * });
+ *
+ * var elem = new MyClass();
+ *
+ *
+ *
+ * @param {Function} require
+ * @param {Underscore} _
+ * @constructor
+ * @memberOf __editTreeDefine
+ */
+emmet.define('editTree', function(require, _, core) {
+ var range = require('range').create;
+
+ /**
+ * Named container of edited source
+ * @type EditContainer
+ * @param {String} source
+ * @param {Object} options
+ */
+ function EditContainer(source, options) {
+ this.options = _.extend({offset: 0}, options);
+ /**
+ * Source code of edited structure. All changes in the structure are
+ * immediately reflected into this property
+ */
+ this.source = source;
+
+ /**
+ * List of all editable children
+ * @private
+ */
+ this._children = [];
+
+ /**
+ * Hash of all positions of container
+ * @private
+ */
+ this._positions = {
+ name: 0
+ };
+
+ this.initialize.apply(this, arguments);
+ }
+
+ /**
+ * The self-propagating extend function for classes.
+ * @type Function
+ */
+ EditContainer.extend = core.extend;
+
+ EditContainer.prototype = {
+ /**
+ * Child class constructor
+ */
+ initialize: function() {},
+
+ /**
+ * Replace substring of tag's source
+ * @param {String} value
+ * @param {Number} start
+ * @param {Number} end
+ * @private
+ */
+ _updateSource: function(value, start, end) {
+ // create modification range
+ var r = range(start, _.isUndefined(end) ? 0 : end - start);
+ var delta = value.length - r.length();
+
+ var update = function(obj) {
+ _.each(obj, function(v, k) {
+ if (v >= r.end)
+ obj[k] += delta;
+ });
+ };
+
+ // update affected positions of current container
+ update(this._positions);
+
+ // update affected positions of children
+ _.each(this.list(), function(item) {
+ update(item._positions);
+ });
+
+ this.source = require('utils').replaceSubstring(this.source, value, r);
+ },
+
+
+ /**
+ * Adds new attribute
+ * @param {String} name Property name
+ * @param {String} value Property value
+ * @param {Number} pos Position at which to insert new property. By
+ * default the property is inserted at the end of rule
+ * @returns {EditElement} Newly created element
+ */
+ add: function(name, value, pos) {
+ // this is abstract implementation
+ var item = new EditElement(name, value);
+ this._children.push(item);
+ return item;
+ },
+
+ /**
+ * Returns attribute object
+ * @param {String} name Attribute name or its index
+ * @returns {EditElement}
+ */
+ get: function(name) {
+ if (_.isNumber(name))
+ return this.list()[name];
+
+ if (_.isString(name))
+ return _.find(this.list(), function(prop) {
+ return prop.name() === name;
+ });
+
+ return name;
+ },
+
+ /**
+ * Returns all children by name or indexes
+ * @param {Object} name Element name(s) or indexes (String,
+ * Array, Number)
+ * @returns {Array}
+ */
+ getAll: function(name) {
+ if (!_.isArray(name))
+ name = [name];
+
+ // split names and indexes
+ var names = [], indexes = [];
+ _.each(name, function(item) {
+ if (_.isString(item))
+ names.push(item);
+ else if (_.isNumber(item))
+ indexes.push(item);
+ });
+
+ return _.filter(this.list(), function(attribute, i) {
+ return _.include(indexes, i) || _.include(names, attribute.name());
+ });
+ },
+
+ /**
+ * Returns or updates element value. If such element doesn't exists,
+ * it will be created automatically and added at the end of child list.
+ * @param {String} name Element name or its index
+ * @param {String} value New element value
+ * @returns {String}
+ */
+ value: function(name, value, pos) {
+ var element = this.get(name);
+ if (element)
+ return element.value(value);
+
+ if (!_.isUndefined(value)) {
+ // no such element — create it
+ return this.add(name, value, pos);
+ }
+ },
+
+ /**
+ * Returns all values of child elements found by getAll()
+ * method
+ * @param {Object} name Element name(s) or indexes (String,
+ * Array, Number)
+ * @returns {Array}
+ */
+ values: function(name) {
+ return _.map(this.getAll(name), function(element) {
+ return element.value();
+ });
+ },
+
+ /**
+ * Remove child element
+ * @param {String} name Property name or its index
+ */
+ remove: function(name) {
+ var element = this.get(name);
+ if (element) {
+ this._updateSource('', element.fullRange());
+ this._children = _.without(this._children, element);
+ }
+ },
+
+ /**
+ * Returns list of all editable child elements
+ * @returns {Array}
+ */
+ list: function() {
+ return this._children;
+ },
+
+ /**
+ * Returns index of editble child in list
+ * @param {Object} item
+ * @returns {Number}
+ */
+ indexOf: function(item) {
+ return _.indexOf(this.list(), this.get(item));
+ },
+
+ /**
+ * Sets or gets container name
+ * @param {String} val New name. If not passed, current
+ * name is returned
+ * @return {String}
+ */
+ name: function(val) {
+ if (!_.isUndefined(val) && this._name !== (val = String(val))) {
+ this._updateSource(val, this._positions.name, this._positions.name + this._name.length);
+ this._name = val;
+ }
+
+ return this._name;
+ },
+
+ /**
+ * Returns name range object
+ * @param {Boolean} isAbsolute Return absolute range (with respect of
+ * rule offset)
+ * @returns {Range}
+ */
+ nameRange: function(isAbsolute) {
+ return range(this._positions.name + (isAbsolute ? this.options.offset : 0), this.name());
+ },
+
+ /**
+ * Returns range of current source
+ * @param {Boolean} isAbsolute
+ */
+ range: function(isAbsolute) {
+ return range(isAbsolute ? this.options.offset : 0, this.toString());
+ },
+
+ /**
+ * Returns element that belongs to specified position
+ * @param {Number} pos
+ * @param {Boolean} isAbsolute
+ * @returns {EditElement}
+ */
+ itemFromPosition: function(pos, isAbsolute) {
+ return _.find(this.list(), function(elem) {
+ return elem.range(isAbsolute).inside(pos);
+ });
+ },
+
+ /**
+ * Returns source code of current container
+ * @returns {String}
+ */
+ toString: function() {
+ return this.source;
+ }
+ };
+
+ /**
+ * @param {EditContainer} parent
+ * @param {Object} nameToken
+ * @param {Object} valueToken
+ */
+ function EditElement(parent, nameToken, valueToken) {
+ /** @type EditContainer */
+ this.parent = parent;
+
+ this._name = nameToken.value;
+ this._value = valueToken ? valueToken.value : '';
+
+ this._positions = {
+ name: nameToken.start,
+ value: valueToken ? valueToken.start : -1
+ };
+
+ this.initialize.apply(this, arguments);
+ }
+
+ /**
+ * The self-propagating extend function for classes.
+ * @type Function
+ */
+ EditElement.extend = core.extend;
+
+ EditElement.prototype = {
+ /**
+ * Child class constructor
+ */
+ initialize: function() {},
+
+ /**
+ * Make position absolute
+ * @private
+ * @param {Number} num
+ * @param {Boolean} isAbsolute
+ * @returns {Boolean}
+ */
+ _pos: function(num, isAbsolute) {
+ return num + (isAbsolute ? this.parent.options.offset : 0);
+ },
+
+ /**
+ * Sets of gets element value
+ * @param {String} val New element value. If not passed, current
+ * value is returned
+ * @returns {String}
+ */
+ value: function(val) {
+ if (!_.isUndefined(val) && this._value !== (val = String(val))) {
+ this.parent._updateSource(val, this.valueRange());
+ this._value = val;
+ }
+
+ return this._value;
+ },
+
+ /**
+ * Sets of gets element name
+ * @param {String} val New element name. If not passed, current
+ * name is returned
+ * @returns {String}
+ */
+ name: function(val) {
+ if (!_.isUndefined(val) && this._name !== (val = String(val))) {
+ this.parent._updateSource(val, this.nameRange());
+ this._name = val;
+ }
+
+ return this._name;
+ },
+
+ /**
+ * Returns position of element name token
+ * @param {Boolean} isAbsolute Return absolute position
+ * @returns {Number}
+ */
+ namePosition: function(isAbsolute) {
+ return this._pos(this._positions.name, isAbsolute);
+ },
+
+ /**
+ * Returns position of element value token
+ * @param {Boolean} isAbsolute Return absolute position
+ * @returns {Number}
+ */
+ valuePosition: function(isAbsolute) {
+ return this._pos(this._positions.value, isAbsolute);
+ },
+
+ /**
+ * Returns element name
+ * @param {Boolean} isAbsolute Return absolute range
+ * @returns {Range}
+ */
+ range: function(isAbsolute) {
+ return range(this.namePosition(isAbsolute), this.toString());
+ },
+
+ /**
+ * Returns full element range, including possible indentation
+ * @param {Boolean} isAbsolute Return absolute range
+ * @returns {Range}
+ */
+ fullRange: function(isAbsolute) {
+ return this.range(isAbsolute);
+ },
+
+ /**
+ * Returns element name range
+ * @param {Boolean} isAbsolute Return absolute range
+ * @returns {Range}
+ */
+ nameRange: function(isAbsolute) {
+ return range(this.namePosition(isAbsolute), this.name());
+ },
+
+ /**
+ * Returns element value range
+ * @param {Boolean} isAbsolute Return absolute range
+ * @returns {Range}
+ */
+ valueRange: function(isAbsolute) {
+ return range(this.valuePosition(isAbsolute), this.value());
+ },
+
+ /**
+ * Returns current element string representation
+ * @returns {String}
+ */
+ toString: function() {
+ return this.name() + this.value();
+ },
+
+ valueOf: function() {
+ return this.toString();
+ }
+ };
+
+ return {
+ EditContainer: EditContainer,
+ EditElement: EditElement,
+
+ /**
+ * Creates token that can be fed to EditElement
+ * @param {Number} start
+ * @param {String} value
+ * @param {String} type
+ * @returns
+ */
+ createToken: function(start, value, type) {
+ var obj = {
+ start: start || 0,
+ value: value || '',
+ type: type
+ };
+
+ obj.end = obj.start + obj.value.length;
+ return obj;
+ }
+ };
+});/**
+ * CSS EditTree is a module that can parse a CSS rule into a tree with
+ * convenient methods for adding, modifying and removing CSS properties. These
+ * changes can be written back to string with respect of code formatting.
+ *
+ * @memberOf __cssEditTreeDefine
+ * @constructor
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('cssEditTree', function(require, _) {
+ var defaultOptions = {
+ styleBefore: '\n\t',
+ styleSeparator: ': ',
+ offset: 0
+ };
+
+ var WHITESPACE_REMOVE_FROM_START = 1;
+ var WHITESPACE_REMOVE_FROM_END = 2;
+
+ /**
+ * Returns range object
+ * @param {Number} start
+ * @param {Number} len
+ * @returns {Range}
+ */
+ function range(start, len) {
+ return require('range').create(start, len);
+ }
+
+ /**
+ * Removes whitespace tokens from the array ends
+ * @param {Array} tokens
+ * @param {Number} mask Mask indicating from which end whitespace should be
+ * removed
+ * @returns {Array}
+ */
+ function trimWhitespaceTokens(tokens, mask) {
+ mask = mask || (WHITESPACE_REMOVE_FROM_START | WHITESPACE_REMOVE_FROM_END);
+ var whitespace = ['white', 'line'];
+
+ if ((mask & WHITESPACE_REMOVE_FROM_END) == WHITESPACE_REMOVE_FROM_END)
+ while (tokens.length && _.include(whitespace, _.last(tokens).type)) {
+ tokens.pop();
+ }
+
+ if ((mask & WHITESPACE_REMOVE_FROM_START) == WHITESPACE_REMOVE_FROM_START)
+ while (tokens.length && _.include(whitespace, tokens[0].type)) {
+ tokens.shift();
+ }
+
+ return tokens;
+ }
+
+ /**
+ * Helper function that searches for selector range for CSSEditRule
+ * @param {TokenIterator} it
+ * @returns {Range}
+ */
+ function findSelectorRange(it) {
+ var tokens = [], token;
+ var start = it.position(), end;
+
+ while (token = it.next()) {
+ if (token.type == '{')
+ break;
+ tokens.push(token);
+ }
+
+ trimWhitespaceTokens(tokens);
+
+ if (tokens.length) {
+ start = tokens[0].start;
+ end = _.last(tokens).end;
+ } else {
+ end = start;
+ }
+
+ return range(start, end - start);
+ }
+
+ /**
+ * Helper function that searches for CSS property value range next to
+ * iterator's current position
+ * @param {TokenIterator} it
+ * @returns {Range}
+ */
+ function findValueRange(it) {
+ // find value start position
+ var skipTokens = ['white', 'line', ':'];
+ var tokens = [], token, start, end;
+
+ it.nextUntil(function(tok) {
+ return !_.include(skipTokens, this.itemNext().type);
+ });
+
+ start = it.current().end;
+ // consume value
+ while (token = it.next()) {
+ if (token.type == '}' || token.type == ';') {
+ // found value end
+ trimWhitespaceTokens(tokens, WHITESPACE_REMOVE_FROM_START
+ | (token.type == '}' ? WHITESPACE_REMOVE_FROM_END : 0));
+
+ if (tokens.length) {
+ start = tokens[0].start;
+ end = _.last(tokens).end;
+ } else {
+ end = start;
+ }
+
+ return range(start, end - start);
+ }
+
+ tokens.push(token);
+ }
+
+ // reached the end of tokens list
+ if (tokens.length) {
+ return range(tokens[0].start, _.last(tokens).end - tokens[0].start);
+ }
+ }
+
+ /**
+ * Finds parts of complex CSS value
+ * @param {String} str
+ * @returns {Array} Returns list of Range's
+ */
+ function findParts(str) {
+ /** @type StringStream */
+ var stream = require('stringStream').create(str);
+ var ch;
+ var result = [];
+ var sep = /[\s\u00a0,]/;
+
+ var add = function() {
+ stream.next();
+ result.push(range(stream.start, stream.current()));
+ stream.start = stream.pos;
+ };
+
+ // skip whitespace
+ stream.eatSpace();
+ stream.start = stream.pos;
+
+ while (ch = stream.next()) {
+ if (ch == '"' || ch == "'") {
+ stream.next();
+ if (!stream.skipTo(ch)) break;
+ add();
+ } else if (ch == '(') {
+ // function found, may have nested function
+ stream.backUp(1);
+ if (!stream.skipToPair('(', ')')) break;
+ stream.backUp(1);
+ add();
+ } else {
+ if (sep.test(ch)) {
+ result.push(range(stream.start, stream.current().length - 1));
+ stream.eatWhile(sep);
+ stream.start = stream.pos;
+ }
+ }
+ }
+
+ add();
+
+ return _.chain(result)
+ .filter(function(item) {
+ return !!item.length();
+ })
+ .uniq(false, function(item) {
+ return item.toString();
+ })
+ .value();
+ }
+
+ /**
+ * A bit hacky way to identify invalid CSS property definition: when user
+ * starts writing new abbreviation in CSS rule, he actually creates invalid
+ * CSS property definition and this method tries to identify such abbreviation
+ * and prevent it from being added to CSS edit tree
+ * @param {TokenIterator} it
+ */
+ function isValidIdentifier(it) {
+// return true;
+ var tokens = it.tokens;
+ for (var i = it._i + 1, il = tokens.length; i < il; i++) {
+ if (tokens[i].type == ':')
+ return true;
+
+ if (tokens[i].type == 'identifier' || tokens[i].type == 'line')
+ return false;
+ }
+
+ return false;
+ }
+
+ /**
+ * @class
+ * @extends EditContainer
+ */
+ var CSSEditContainer = require('editTree').EditContainer.extend({
+ initialize: function(source, options) {
+ _.defaults(this.options, defaultOptions);
+ var editTree = require('editTree');
+
+ /** @type TokenIterator */
+ var it = require('tokenIterator').create(
+ require('cssParser').parse(source));
+
+ var selectorRange = findSelectorRange(it);
+ this._positions.name = selectorRange.start;
+ this._name = selectorRange.substring(source);
+
+ if (!it.current() || it.current().type != '{')
+ throw 'Invalid CSS rule';
+
+ this._positions.contentStart = it.position() + 1;
+
+ // consume properties
+ var propertyRange, valueRange, token;
+ while (token = it.next()) {
+ if (token.type == 'identifier' && isValidIdentifier(it)) {
+ propertyRange = range(token);
+ valueRange = findValueRange(it);
+ var end = (it.current() && it.current().type == ';')
+ ? range(it.current())
+ : range(valueRange.end, 0);
+ this._children.push(new CSSEditElement(this,
+ editTree.createToken(propertyRange.start, propertyRange.substring(source)),
+ editTree.createToken(valueRange.start, valueRange.substring(source)),
+ editTree.createToken(end.start, end.substring(source))
+ ));
+ }
+ }
+
+ this._saveStyle();
+ },
+
+ /**
+ * Remembers all styles of properties
+ * @private
+ */
+ _saveStyle: function() {
+ var start = this._positions.contentStart;
+ var source = this.source;
+ var utils = require('utils');
+
+ _.each(this.list(), /** @param {CSSEditProperty} p */ function(p) {
+ p.styleBefore = source.substring(start, p.namePosition());
+ // a small hack here:
+ // Sometimes users add empty lines before properties to logically
+ // separate groups of properties. In this case, a blind copy of
+ // characters between rules may lead to undesired behavior,
+ // especially when current rule is duplicated or used as a donor
+ // to create new rule.
+ // To solve this issue, we‘ll take only last newline indentation
+ var lines = utils.splitByLines(p.styleBefore);
+ if (lines.length > 1) {
+ p.styleBefore = '\n' + _.last(lines);
+ }
+
+ p.styleSeparator = source.substring(p.nameRange().end, p.valuePosition());
+
+ // graceful and naive comments removal
+ p.styleBefore = _.last(p.styleBefore.split('*/'));
+ p.styleSeparator = p.styleSeparator.replace(/\/\*.*?\*\//g, '');
+
+ start = p.range().end;
+ });
+ },
+
+ /**
+ * Adds new CSS property
+ * @param {String} name Property name
+ * @param {String} value Property value
+ * @param {Number} pos Position at which to insert new property. By
+ * default the property is inserted at the end of rule
+ * @returns {CSSEditProperty}
+ */
+ add: function(name, value, pos) {
+ var list = this.list();
+ var start = this._positions.contentStart;
+ var styles = _.pick(this.options, 'styleBefore', 'styleSeparator');
+ var editTree = require('editTree');
+
+ if (_.isUndefined(pos))
+ pos = list.length;
+
+ /** @type CSSEditProperty */
+ var donor = list[pos];
+ if (donor) {
+ start = donor.fullRange().start;
+ } else if (donor = list[pos - 1]) {
+ // make sure that donor has terminating semicolon
+ donor.end(';');
+ start = donor.range().end;
+ }
+
+ if (donor) {
+ styles = _.pick(donor, 'styleBefore', 'styleSeparator');
+ }
+
+ var nameToken = editTree.createToken(start + styles.styleBefore.length, name);
+ var valueToken = editTree.createToken(nameToken.end + styles.styleSeparator.length, value);
+
+ var property = new CSSEditElement(this, nameToken, valueToken,
+ editTree.createToken(valueToken.end, ';'));
+
+ _.extend(property, styles);
+
+ // write new property into the source
+ this._updateSource(property.styleBefore + property.toString(), start);
+
+ // insert new property
+ this._children.splice(pos, 0, property);
+ return property;
+ }
+ });
+
+ /**
+ * @class
+ * @type CSSEditElement
+ * @constructor
+ */
+ var CSSEditElement = require('editTree').EditElement.extend({
+ initialize: function(rule, name, value, end) {
+ this.styleBefore = rule.options.styleBefore;
+ this.styleSeparator = rule.options.styleSeparator;
+
+ this._end = end.value;
+ this._positions.end = end.start;
+ },
+
+ /**
+ * Returns ranges of complex value parts
+ * @returns {Array} Returns null if value is not complex
+ */
+ valueParts: function(isAbsolute) {
+ var parts = findParts(this.value());
+ if (isAbsolute) {
+ var offset = this.valuePosition(true);
+ _.each(parts, function(p) {
+ p.shift(offset);
+ });
+ }
+
+ return parts;
+ },
+
+ /**
+ * Sets of gets property end value (basically, it's a semicolon)
+ * @param {String} val New end value. If not passed, current
+ * value is returned
+ */
+ end: function(val) {
+ if (!_.isUndefined(val) && this._end !== val) {
+ this.parent._updateSource(val, this._positions.end, this._positions.end + this._end.length);
+ this._end = val;
+ }
+
+ return this._end;
+ },
+
+ /**
+ * Returns full rule range, with indentation
+ * @param {Boolean} isAbsolute Return absolute range (with respect of
+ * rule offset)
+ * @returns {Range}
+ */
+ fullRange: function(isAbsolute) {
+ var r = this.range(isAbsolute);
+ r.start -= this.styleBefore.length;
+ return r;
+ },
+
+ /**
+ * Returns item string representation
+ * @returns {String}
+ */
+ toString: function() {
+ return this.name() + this.styleSeparator + this.value() + this.end();
+ }
+ });
+
+ return {
+ /**
+ * Parses CSS rule into editable tree
+ * @param {String} source
+ * @param {Object} options
+ * @memberOf emmet.cssEditTree
+ * @returns {EditContainer}
+ */
+ parse: function(source, options) {
+ return new CSSEditContainer(source, options);
+ },
+
+ /**
+ * Extract and parse CSS rule from specified position in content
+ * @param {String} content CSS source code
+ * @param {Number} pos Character position where to start source code extraction
+ * @returns {EditContainer}
+ */
+ parseFromPosition: function(content, pos, isBackward) {
+ var bounds = this.extractRule(content, pos, isBackward);
+ if (!bounds || !bounds.inside(pos))
+ // no matching CSS rule or caret outside rule bounds
+ return null;
+
+ return this.parse(bounds.substring(content), {
+ offset: bounds.start
+ });
+ },
+
+ /**
+ * Extracts single CSS selector definition from source code
+ * @param {String} content CSS source code
+ * @param {Number} pos Character position where to start source code extraction
+ * @returns {Range}
+ */
+ extractRule: function(content, pos, isBackward) {
+ var result = '';
+ var len = content.length;
+ var offset = pos;
+ var stopChars = '{}/\\<>\n\r';
+ var bracePos = -1, ch;
+
+ // search left until we find rule edge
+ while (offset >= 0) {
+ ch = content.charAt(offset);
+ if (ch == '{') {
+ bracePos = offset;
+ break;
+ }
+ else if (ch == '}' && !isBackward) {
+ offset++;
+ break;
+ }
+
+ offset--;
+ }
+
+ // search right for full rule set
+ while (offset < len) {
+ ch = content.charAt(offset);
+ if (ch == '{') {
+ bracePos = offset;
+ } else if (ch == '}') {
+ if (bracePos != -1)
+ result = content.substring(bracePos, offset + 1);
+ break;
+ }
+
+ offset++;
+ }
+
+ if (result) {
+ // find CSS selector
+ offset = bracePos - 1;
+ var selector = '';
+ while (offset >= 0) {
+ ch = content.charAt(offset);
+ if (stopChars.indexOf(ch) != -1) break;
+ offset--;
+ }
+
+ // also trim whitespace
+ selector = content.substring(offset + 1, bracePos).replace(/^[\s\n\r]+/m, '');
+ return require('range').create(bracePos - selector.length, result.length + selector.length);
+ }
+
+ return null;
+ },
+
+ /**
+ * Removes vendor prefix from CSS property
+ * @param {String} name CSS property
+ * @return {String}
+ */
+ baseName: function(name) {
+ return name.replace(/^\s*\-\w+\-/, '');
+ },
+
+ /**
+ * Finds parts of complex CSS value
+ * @param {String} str
+ * @returns {Array}
+ */
+ findParts: findParts
+ };
+});/**
+ * XML EditTree is a module that can parse an XML/HTML element into a tree with
+ * convenient methods for adding, modifying and removing attributes. These
+ * changes can be written back to string with respect of code formatting.
+ *
+ * @memberOf __xmlEditTreeDefine
+ * @constructor
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('xmlEditTree', function(require, _) {
+ var defaultOptions = {
+ styleBefore: ' ',
+ styleSeparator: '=',
+ styleQuote: '"',
+ offset: 0
+ };
+
+ var startTag = /^<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/m;
+
+ var XMLEditContainer = require('editTree').EditContainer.extend({
+ initialize: function(source, options) {
+ _.defaults(this.options, defaultOptions);
+ this._positions.name = 1;
+
+ var attrToken = null;
+ var tokens = require('xmlParser').parse(source);
+ var range = require('range');
+
+ _.each(tokens, function(token) {
+ token.value = range.create(token).substring(source);
+ switch (token.type) {
+ case 'tag':
+ if (/^<[^\/]+/.test(token.value)) {
+ this._name = token.value.substring(1);
+ }
+ break;
+
+ case 'attribute':
+ // add empty attribute
+ if (attrToken) {
+ this._children.push(new XMLEditElement(this, attrToken));
+ }
+
+ attrToken = token;
+ break;
+
+ case 'string':
+ this._children.push(new XMLEditElement(this, attrToken, token));
+ attrToken = null;
+ break;
+ }
+ }, this);
+
+ if (attrToken) {
+ this._children.push(new XMLEditElement(this, attrToken));
+ }
+
+ this._saveStyle();
+ },
+
+ /**
+ * Remembers all styles of properties
+ * @private
+ */
+ _saveStyle: function() {
+ var start = this.nameRange().end;
+ var source = this.source;
+
+ _.each(this.list(), /** @param {EditElement} p */ function(p) {
+ p.styleBefore = source.substring(start, p.namePosition());
+
+ if (p.valuePosition() !== -1) {
+ p.styleSeparator = source.substring(p.namePosition() + p.name().length, p.valuePosition() - p.styleQuote.length);
+ }
+
+ start = p.range().end;
+ });
+ },
+
+ /**
+ * Adds new attribute
+ * @param {String} name Property name
+ * @param {String} value Property value
+ * @param {Number} pos Position at which to insert new property. By
+ * default the property is inserted at the end of rule
+ */
+ add: function(name, value, pos) {
+ var list = this.list();
+ var start = this.nameRange().end;
+ var editTree = require('editTree');
+ var styles = _.pick(this.options, 'styleBefore', 'styleSeparator', 'styleQuote');
+
+ if (_.isUndefined(pos))
+ pos = list.length;
+
+
+ /** @type XMLEditAttribute */
+ var donor = list[pos];
+ if (donor) {
+ start = donor.fullRange().start;
+ } else if (donor = list[pos - 1]) {
+ start = donor.range().end;
+ }
+
+ if (donor) {
+ styles = _.pick(donor, 'styleBefore', 'styleSeparator', 'styleQuote');
+ }
+
+ value = styles.styleQuote + value + styles.styleQuote;
+
+ var attribute = new XMLEditElement(this,
+ editTree.createToken(start + styles.styleBefore.length, name),
+ editTree.createToken(start + styles.styleBefore.length + name.length
+ + styles.styleSeparator.length, value)
+ );
+
+ _.extend(attribute, styles);
+
+ // write new attribute into the source
+ this._updateSource(attribute.styleBefore + attribute.toString(), start);
+
+ // insert new attribute
+ this._children.splice(pos, 0, attribute);
+ return attribute;
+ }
+ });
+
+ var XMLEditElement = require('editTree').EditElement.extend({
+ initialize: function(parent, nameToken, valueToken) {
+ this.styleBefore = parent.options.styleBefore;
+ this.styleSeparator = parent.options.styleSeparator;
+
+ var value = '', quote = parent.options.styleQuote;
+ if (valueToken) {
+ value = valueToken.value;
+ quote = value.charAt(0);
+ if (quote == '"' || quote == "'") {
+ value = value.substring(1);
+ } else {
+ quote = '';
+ }
+
+ if (quote && value.charAt(value.length - 1) == quote) {
+ value = value.substring(0, value.length - 1);
+ }
+ }
+
+ this.styleQuote = quote;
+
+ this._value = value;
+ this._positions.value = valueToken ? valueToken.start + quote.length : -1;
+ },
+
+ /**
+ * Returns full rule range, with indentation
+ * @param {Boolean} isAbsolute Return absolute range (with respect of
+ * rule offset)
+ * @returns {Range}
+ */
+ fullRange: function(isAbsolute) {
+ var r = this.range(isAbsolute);
+ r.start -= this.styleBefore.length;
+ return r;
+ },
+
+ toString: function() {
+ return this.name() + this.styleSeparator
+ + this.styleQuote + this.value() + this.styleQuote;
+ }
+ });
+
+ return {
+ /**
+ * Parses HTML element into editable tree
+ * @param {String} source
+ * @param {Object} options
+ * @memberOf emmet.htmlEditTree
+ * @returns {EditContainer}
+ */
+ parse: function(source, options) {
+ return new XMLEditContainer(source, options);
+ },
+
+ /**
+ * Extract and parse HTML from specified position in content
+ * @param {String} content CSS source code
+ * @param {Number} pos Character position where to start source code extraction
+ * @returns {XMLEditElement}
+ */
+ parseFromPosition: function(content, pos, isBackward) {
+ var bounds = this.extractTag(content, pos, isBackward);
+ if (!bounds || !bounds.inside(pos))
+ // no matching HTML tag or caret outside tag bounds
+ return null;
+
+ return this.parse(bounds.substring(content), {
+ offset: bounds.start
+ });
+ },
+
+ /**
+ * Extracts nearest HTML tag range from content, starting at
+ * pos position
+ * @param {String} content
+ * @param {Number} pos
+ * @param {Boolean} isBackward
+ * @returns {Range}
+ */
+ extractTag: function(content, pos, isBackward) {
+ var len = content.length, i;
+ var range = require('range');
+
+ // max extraction length. I don't think there may be tags larger
+ // than 2000 characters length
+ var maxLen = Math.min(2000, len);
+
+ /** @type Range */
+ var r = null;
+
+ var match = function(pos) {
+ var m;
+ if (content.charAt(pos) == '<' && (m = content.substr(pos, maxLen).match(startTag)))
+ return range.create(pos, m[0]);
+ };
+
+ // lookup backward, in case we are inside tag already
+ for (i = pos; i >= 0; i--) {
+ if (r = match(i)) break;
+ }
+
+ if (r && (r.inside(pos) || isBackward))
+ return r;
+
+ if (!r && isBackward)
+ return null;
+
+ // search forward
+ for (i = pos; i < len; i++) {
+ if (r = match(i))
+ return r;
+ }
+ }
+ };
+});/**
+ * 'Expand abbreviation' editor action: extracts abbreviation from current caret
+ * position and replaces it with formatted output.
+ *
+ * This behavior can be overridden with custom handlers which can perform
+ * different actions when 'Expand Abbreviation' action is called.
+ * For example, a CSS gradient handler that produces vendor-prefixed gradient
+ * definitions registers its own expand abbreviation handler.
+ *
+ * @constructor
+ * @memberOf __expandAbbreviationActionDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('expandAbbreviation', function(require, _) {
+ /**
+ * @type HandlerList List of registered handlers
+ */
+ var handlers = require('handlerList').create();
+
+ /** Back-reference to module */
+ var module = null;
+
+ var actions = require('actions');
+ /**
+ * 'Expand abbreviation' editor action
+ * @param {IEmmetEditor} editor Editor instance
+ * @param {String} syntax Syntax type (html, css, etc.)
+ * @param {String} profile Output profile name (html, xml, xhtml)
+ * @return {Boolean} Returns true if abbreviation was expanded
+ * successfully
+ */
+ actions.add('expand_abbreviation', function(editor, syntax, profile) {
+ var args = _.toArray(arguments);
+
+ // normalize incoming arguments
+ var info = require('editorUtils').outputInfo(editor, syntax, profile);
+ args[1] = info.syntax;
+ args[2] = info.profile;
+
+ return handlers.exec(false, args);
+ });
+
+ /**
+ * A special version of expandAbbreviation function: if it can't
+ * find abbreviation, it will place Tab character at caret position
+ * @param {IEmmetEditor} editor Editor instance
+ * @param {String} syntax Syntax type (html, css, etc.)
+ * @param {String} profile Output profile name (html, xml, xhtml)
+ */
+ actions.add('expand_abbreviation_with_tab', function(editor, syntax, profile) {
+ var sel = editor.getSelection();
+ var indent = require('resources').getVariable('indentation');
+ if (sel) {
+ // indent selection
+ var utils = require('utils');
+ var selRange = require('range').create(editor.getSelectionRange());
+ var content = utils.padString(sel, indent);
+
+ editor.replaceContent(indent + '${0}', editor.getCaretPos());
+ var replaceRange = require('range').create(editor.getCaretPos(), selRange.length());
+ editor.replaceContent(content, replaceRange.start, replaceRange.end, true);
+ editor.createSelection(replaceRange.start, replaceRange.start + content.length);
+ return true;
+ }
+
+ if (!actions.run('expand_abbreviation', editor, syntax, profile)) {
+ editor.replaceContent(indent, editor.getCaretPos());
+ }
+
+ return true;
+ }, {hidden: true});
+
+ // XXX setup default handler
+ /**
+ * Extracts abbreviation from current caret
+ * position and replaces it with formatted output
+ * @param {IEmmetEditor} editor Editor instance
+ * @param {String} syntax Syntax type (html, css, etc.)
+ * @param {String} profile Output profile name (html, xml, xhtml)
+ * @return {Boolean} Returns true if abbreviation was expanded
+ * successfully
+ */
+ handlers.add(function(editor, syntax, profile) {
+ var caretPos = editor.getSelectionRange().end;
+ var abbr = module.findAbbreviation(editor);
+
+ if (abbr) {
+ var content = emmet.expandAbbreviation(abbr, syntax, profile,
+ require('actionUtils').captureContext(editor));
+ if (content) {
+ editor.replaceContent(content, caretPos - abbr.length, caretPos);
+ return true;
+ }
+ }
+
+ return false;
+ }, {order: -1});
+
+ return module = {
+ /**
+ * Adds custom expand abbreviation handler. The passed function should
+ * return true if it was performed successfully,
+ * false otherwise.
+ *
+ * Added handlers will be called when 'Expand Abbreviation' is called
+ * in order they were added
+ * @memberOf expandAbbreviation
+ * @param {Function} fn
+ * @param {Object} options
+ */
+ addHandler: function(fn, options) {
+ handlers.add(fn, options);
+ },
+
+ /**
+ * Removes registered handler
+ * @returns
+ */
+ removeHandler: function(fn) {
+ handlers.remove(fn, options);
+ },
+
+ /**
+ * Search for abbreviation in editor from current caret position
+ * @param {IEmmetEditor} editor Editor instance
+ * @return {String}
+ */
+ findAbbreviation: function(editor) {
+ /** @type Range */
+ var range = require('range').create(editor.getSelectionRange());
+ var content = String(editor.getContent());
+ if (range.length()) {
+ // abbreviation is selected by user
+ return range.substring(content);
+ }
+
+ // search for new abbreviation from current caret position
+ var curLine = editor.getCurrentLineRange();
+ return require('actionUtils').extractAbbreviation(content.substring(curLine.start, range.start));
+ }
+ };
+});/**
+ * Action that wraps content with abbreviation. For convenience, action is
+ * defined as reusable module
+ * @constructor
+ * @memberOf __wrapWithAbbreviationDefine
+ */
+emmet.define('wrapWithAbbreviation', function(require, _) {
+ /** Back-references to current module */
+ var module = null;
+
+ /**
+ * Wraps content with abbreviation
+ * @param {IEmmetEditor} Editor instance
+ * @param {String} abbr Abbreviation to wrap with
+ * @param {String} syntax Syntax type (html, css, etc.)
+ * @param {String} profile Output profile name (html, xml, xhtml)
+ */
+ require('actions').add('wrap_with_abbreviation', function (editor, abbr, syntax, profile) {
+ var info = require('editorUtils').outputInfo(editor, syntax, profile);
+ var utils = require('utils');
+ /** @type emmet.editorUtils */
+ var editorUtils = require('editorUtils');
+ abbr = abbr || editor.prompt("Enter abbreviation");
+
+ if (!abbr)
+ return null;
+
+ abbr = String(abbr);
+
+ var range = require('range').create(editor.getSelectionRange());
+
+ if (!range.length()) {
+ // no selection, find tag pair
+ var match = require('htmlMatcher').tag(info.content, range.start);
+ if (!match) { // nothing to wrap
+ return false;
+ }
+
+ range = utils.narrowToNonSpace(info.content, match.range);
+ }
+
+ var newContent = utils.escapeText(range.substring(info.content));
+ var result = module
+ .wrap(abbr, editorUtils.unindent(editor, newContent), info.syntax,
+ info.profile, require('actionUtils').captureContext(editor));
+
+ if (result) {
+ editor.replaceContent(result, range.start, range.end);
+ return true;
+ }
+
+ return false;
+ });
+
+ return module = {
+ /**
+ * Wraps passed text with abbreviation. Text will be placed inside last
+ * expanded element
+ * @memberOf wrapWithAbbreviation
+ * @param {String} abbr Abbreviation
+ * @param {String} text Text to wrap
+ * @param {String} syntax Document type (html, xml, etc.). Default is 'html'
+ * @param {String} profile Output profile's name. Default is 'plain'
+ * @param {Object} contextNode Context node inside which abbreviation
+ * is wrapped. It will be used as a reference for node name resolvers
+ * @return {String}
+ */
+ wrap: function(abbr, text, syntax, profile, contextNode) {
+ /** @type emmet.filters */
+ var filters = require('filters');
+ /** @type emmet.utils */
+ var utils = require('utils');
+
+ syntax = syntax || emmet.defaultSyntax();
+ profile = require('profile').get(profile, syntax);
+
+ require('tabStops').resetTabstopIndex();
+
+ var data = filters.extractFromAbbreviation(abbr);
+ var parsedTree = require('abbreviationParser').parse(data[0], {
+ syntax: syntax,
+ pastedContent: text,
+ contextNode: contextNode
+ });
+ if (parsedTree) {
+ var filtersList = filters.composeList(syntax, profile, data[1]);
+ filters.apply(parsedTree, filtersList, profile);
+ return utils.replaceVariables(parsedTree.toString());
+ }
+
+ return null;
+ }
+ };
+});/**
+ * Toggles HTML and CSS comments depending on current caret context. Unlike
+ * the same action in most editors, this action toggles comment on currently
+ * matched item—HTML tag or CSS selector—when nothing is selected.
+ *
+ * @param {Function} require
+ * @param {Underscore} _
+ * @memberOf __toggleCommentAction
+ * @constructor
+ */
+emmet.exec(function(require, _) {
+ /**
+ * Toggle HTML comment on current selection or tag
+ * @param {IEmmetEditor} editor
+ * @return {Boolean} Returns true if comment was toggled
+ */
+ function toggleHTMLComment(editor) {
+ /** @type Range */
+ var range = require('range').create(editor.getSelectionRange());
+ var info = require('editorUtils').outputInfo(editor);
+
+ if (!range.length()) {
+ // no selection, find matching tag
+ var tag = require('htmlMatcher').tag(info.content, editor.getCaretPos());
+ if (tag) { // found pair
+ range = tag.outerRange;
+ }
+ }
+
+ return genericCommentToggle(editor, '', range);
+ }
+
+ /**
+ * Simple CSS commenting
+ * @param {IEmmetEditor} editor
+ * @return {Boolean} Returns true if comment was toggled
+ */
+ function toggleCSSComment(editor) {
+ /** @type Range */
+ var range = require('range').create(editor.getSelectionRange());
+ var info = require('editorUtils').outputInfo(editor);
+
+ if (!range.length()) {
+ // no selection, try to get current rule
+ /** @type CSSRule */
+ var rule = require('cssEditTree').parseFromPosition(info.content, editor.getCaretPos());
+ if (rule) {
+ var property = cssItemFromPosition(rule, editor.getCaretPos());
+ range = property
+ ? property.range(true)
+ : require('range').create(rule.nameRange(true).start, rule.source);
+ }
+ }
+
+ if (!range.length()) {
+ // still no selection, get current line
+ range = require('range').create(editor.getCurrentLineRange());
+ require('utils').narrowToNonSpace(info.content, range);
+ }
+
+ return genericCommentToggle(editor, '/*', '*/', range);
+ }
+
+ /**
+ * Returns CSS property from rule that matches passed position
+ * @param {EditContainer} rule
+ * @param {Number} absPos
+ * @returns {EditElement}
+ */
+ function cssItemFromPosition(rule, absPos) {
+ // do not use default EditContainer.itemFromPosition() here, because
+ // we need to make a few assumptions to make CSS commenting more reliable
+ var relPos = absPos - (rule.options.offset || 0);
+ var reSafeChar = /^[\s\n\r]/;
+ return _.find(rule.list(), function(item) {
+ if (item.range().end === relPos) {
+ // at the end of property, but outside of it
+ // if there’s a space character at current position,
+ // use current property
+ return reSafeChar.test(rule.source.charAt(relPos));
+ }
+
+ return item.range().inside(relPos);
+ });
+ }
+
+ /**
+ * Search for nearest comment in str, starting from index from
+ * @param {String} text Where to search
+ * @param {Number} from Search start index
+ * @param {String} start_token Comment start string
+ * @param {String} end_token Comment end string
+ * @return {Range} Returns null if comment wasn't found
+ */
+ function searchComment(text, from, startToken, endToken) {
+ var commentStart = -1;
+ var commentEnd = -1;
+
+ var hasMatch = function(str, start) {
+ return text.substr(start, str.length) == str;
+ };
+
+ // search for comment start
+ while (from--) {
+ if (hasMatch(startToken, from)) {
+ commentStart = from;
+ break;
+ }
+ }
+
+ if (commentStart != -1) {
+ // search for comment end
+ from = commentStart;
+ var contentLen = text.length;
+ while (contentLen >= from++) {
+ if (hasMatch(endToken, from)) {
+ commentEnd = from + endToken.length;
+ break;
+ }
+ }
+ }
+
+ return (commentStart != -1 && commentEnd != -1)
+ ? require('range').create(commentStart, commentEnd - commentStart)
+ : null;
+ }
+
+ /**
+ * Generic comment toggling routine
+ * @param {IEmmetEditor} editor
+ * @param {String} commentStart Comment start token
+ * @param {String} commentEnd Comment end token
+ * @param {Range} range Selection range
+ * @return {Boolean}
+ */
+ function genericCommentToggle(editor, commentStart, commentEnd, range) {
+ var editorUtils = require('editorUtils');
+ var content = editorUtils.outputInfo(editor).content;
+ var caretPos = editor.getCaretPos();
+ var newContent = null;
+
+ var utils = require('utils');
+
+ /**
+ * Remove comment markers from string
+ * @param {Sting} str
+ * @return {String}
+ */
+ function removeComment(str) {
+ return str
+ .replace(new RegExp('^' + utils.escapeForRegexp(commentStart) + '\\s*'), function(str){
+ caretPos -= str.length;
+ return '';
+ }).replace(new RegExp('\\s*' + utils.escapeForRegexp(commentEnd) + '$'), '');
+ }
+
+ // first, we need to make sure that this substring is not inside
+ // comment
+ var commentRange = searchComment(content, caretPos, commentStart, commentEnd);
+ if (commentRange && commentRange.overlap(range)) {
+ // we're inside comment, remove it
+ range = commentRange;
+ newContent = removeComment(range.substring(content));
+ } else {
+ // should add comment
+ // make sure that there's no comment inside selection
+ newContent = commentStart + ' ' +
+ range.substring(content)
+ .replace(new RegExp(utils.escapeForRegexp(commentStart) + '\\s*|\\s*' + utils.escapeForRegexp(commentEnd), 'g'), '') +
+ ' ' + commentEnd;
+
+ // adjust caret position
+ caretPos += commentStart.length + 1;
+ }
+
+ // replace editor content
+ if (newContent !== null) {
+ newContent = utils.escapeText(newContent);
+ editor.setCaretPos(range.start);
+ editor.replaceContent(editorUtils.unindent(editor, newContent), range.start, range.end);
+ editor.setCaretPos(caretPos);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Toggle comment on current editor's selection or HTML tag/CSS rule
+ * @param {IEmmetEditor} editor
+ */
+ require('actions').add('toggle_comment', function(editor) {
+ var info = require('editorUtils').outputInfo(editor);
+ if (info.syntax == 'css') {
+ // in case our editor is good enough and can recognize syntax from
+ // current token, we have to make sure that cursor is not inside
+ // 'style' attribute of html element
+ var caretPos = editor.getCaretPos();
+ var tag = require('htmlMatcher').tag(info.content, caretPos);
+ if (tag && tag.open.range.inside(caretPos)) {
+ info.syntax = 'html';
+ }
+ }
+
+ if (info.syntax == 'html')
+ return toggleHTMLComment(editor);
+
+ return toggleCSSComment(editor);
+ });
+});/**
+ * Move between next/prev edit points. 'Edit points' are places between tags
+ * and quotes of empty attributes in html
+ * @constructor
+ *
+ * @memberOf __editPointActionDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ /**
+ * Search for new caret insertion point
+ * @param {IEmmetEditor} editor Editor instance
+ * @param {Number} inc Search increment: -1 — search left, 1 — search right
+ * @param {Number} offset Initial offset relative to current caret position
+ * @return {Number} Returns -1 if insertion point wasn't found
+ */
+ function findNewEditPoint(editor, inc, offset) {
+ inc = inc || 1;
+ offset = offset || 0;
+
+ var curPoint = editor.getCaretPos() + offset;
+ var content = String(editor.getContent());
+ var maxLen = content.length;
+ var nextPoint = -1;
+ var reEmptyLine = /^\s+$/;
+
+ function getLine(ix) {
+ var start = ix;
+ while (start >= 0) {
+ var c = content.charAt(start);
+ if (c == '\n' || c == '\r')
+ break;
+ start--;
+ }
+
+ return content.substring(start, ix);
+ }
+
+ while (curPoint <= maxLen && curPoint >= 0) {
+ curPoint += inc;
+ var curChar = content.charAt(curPoint);
+ var nextChar = content.charAt(curPoint + 1);
+ var prevChar = content.charAt(curPoint - 1);
+
+ switch (curChar) {
+ case '"':
+ case '\'':
+ if (nextChar == curChar && prevChar == '=') {
+ // empty attribute
+ nextPoint = curPoint + 1;
+ }
+ break;
+ case '>':
+ if (nextChar == '<') {
+ // between tags
+ nextPoint = curPoint + 1;
+ }
+ break;
+ case '\n':
+ case '\r':
+ // empty line
+ if (reEmptyLine.test(getLine(curPoint - 1))) {
+ nextPoint = curPoint;
+ }
+ break;
+ }
+
+ if (nextPoint != -1)
+ break;
+ }
+
+ return nextPoint;
+ }
+
+ /** @type emmet.actions */
+ var actions = require('actions');
+
+ /**
+ * Move caret to previous edit point
+ * @param {IEmmetEditor} editor Editor instance
+ */
+ actions.add('prev_edit_point', function(editor) {
+ var curPos = editor.getCaretPos();
+ var newPoint = findNewEditPoint(editor, -1);
+
+ if (newPoint == curPos)
+ // we're still in the same point, try searching from the other place
+ newPoint = findNewEditPoint(editor, -1, -2);
+
+ if (newPoint != -1) {
+ editor.setCaretPos(newPoint);
+ return true;
+ }
+
+ return false;
+ }, {label: 'Previous Edit Point'});
+
+ /**
+ * Move caret to next edit point
+ * @param {IEmmetEditor} editor Editor instance
+ */
+ actions.add('next_edit_point', function(editor) {
+ var newPoint = findNewEditPoint(editor, 1);
+ if (newPoint != -1) {
+ editor.setCaretPos(newPoint);
+ return true;
+ }
+
+ return false;
+ });
+});/**
+ * Actions that use stream parsers and tokenizers for traversing:
+ * -- Search for next/previous items in HTML
+ * -- Search for next/previous items in CSS
+ * @constructor
+ * @memberOf __selectItemActionDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ var startTag = /^<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
+
+ /**
+ * Generic function for searching for items to select
+ * @param {IEmmetEditor} editor
+ * @param {Boolean} isBackward Search backward (search forward otherwise)
+ * @param {Function} extractFn Function that extracts item content
+ * @param {Function} rangeFn Function that search for next token range
+ */
+ function findItem(editor, isBackward, extractFn, rangeFn) {
+ var range = require('range');
+ var content = require('editorUtils').outputInfo(editor).content;
+
+ var contentLength = content.length;
+ var itemRange, rng;
+ /** @type Range */
+ var prevRange = range.create(-1, 0);
+ /** @type Range */
+ var sel = range.create(editor.getSelectionRange());
+
+ var searchPos = sel.start, loop = 100000; // endless loop protection
+ while (searchPos >= 0 && searchPos < contentLength && --loop > 0) {
+ if ( (itemRange = extractFn(content, searchPos, isBackward)) ) {
+ if (prevRange.equal(itemRange)) {
+ break;
+ }
+
+ prevRange = itemRange.clone();
+ rng = rangeFn(itemRange.substring(content), itemRange.start, sel.clone());
+
+ if (rng) {
+ editor.createSelection(rng.start, rng.end);
+ return true;
+ } else {
+ searchPos = isBackward ? itemRange.start : itemRange.end - 1;
+ }
+ }
+
+ searchPos += isBackward ? -1 : 1;
+ }
+
+ return false;
+ }
+
+ // XXX HTML section
+
+ /**
+ * Find next HTML item
+ * @param {IEmmetEditor} editor
+ */
+ function findNextHTMLItem(editor) {
+ var isFirst = true;
+ return findItem(editor, false, function(content, searchPos){
+ if (isFirst) {
+ isFirst = false;
+ return findOpeningTagFromPosition(content, searchPos);
+ } else {
+ return getOpeningTagFromPosition(content, searchPos);
+ }
+ }, function(tag, offset, selRange) {
+ return getRangeForHTMLItem(tag, offset, selRange, false);
+ });
+ }
+
+ /**
+ * Find previous HTML item
+ * @param {IEmmetEditor} editor
+ */
+ function findPrevHTMLItem(editor) {
+ return findItem(editor, true, getOpeningTagFromPosition, function (tag, offset, selRange) {
+ return getRangeForHTMLItem(tag, offset, selRange, true);
+ });
+ }
+
+ /**
+ * Creates possible selection ranges for HTML tag
+ * @param {String} source Original HTML source for tokens
+ * @param {Array} tokens List of HTML tokens
+ * @returns {Array}
+ */
+ function makePossibleRangesHTML(source, tokens, offset) {
+ offset = offset || 0;
+ var range = require('range');
+ var result = [];
+ var attrStart = -1, attrName = '', attrValue = '', attrValueRange, tagName;
+ _.each(tokens, function(tok) {
+ switch (tok.type) {
+ case 'tag':
+ tagName = source.substring(tok.start, tok.end);
+ if (/^<[\w\:\-]/.test(tagName)) {
+ // add tag name
+ result.push(range.create({
+ start: tok.start + 1,
+ end: tok.end
+ }));
+ }
+ break;
+ case 'attribute':
+ attrStart = tok.start;
+ attrName = source.substring(tok.start, tok.end);
+ break;
+
+ case 'string':
+ // attribute value
+ // push full attribute first
+ result.push(range.create(attrStart, tok.end - attrStart));
+
+ attrValueRange = range.create(tok);
+ attrValue = attrValueRange.substring(source);
+
+ // is this a quoted attribute?
+ if (isQuote(attrValue.charAt(0)))
+ attrValueRange.start++;
+
+ if (isQuote(attrValue.charAt(attrValue.length - 1)))
+ attrValueRange.end--;
+
+ result.push(attrValueRange);
+
+ if (attrName == 'class') {
+ result = result.concat(classNameRanges(attrValueRange.substring(source), attrValueRange.start));
+ }
+
+ break;
+ }
+ });
+
+ // offset ranges
+ _.each(result, function(r) {
+ r.shift(offset);
+ });
+
+ return _.chain(result)
+ .filter(function(item) { // remove empty
+ return !!item.length();
+ })
+ .uniq(false, function(item) { // remove duplicates
+ return item.toString();
+ })
+ .value();
+ }
+
+ /**
+ * Returns ranges of class names in "class" attribute value
+ * @param {String} className
+ * @returns {Array}
+ */
+ function classNameRanges(className, offset) {
+ offset = offset || 0;
+ var result = [];
+ /** @type StringStream */
+ var stream = require('stringStream').create(className);
+ var range = require('range');
+
+ // skip whitespace
+ stream.eatSpace();
+ stream.start = stream.pos;
+
+ var ch;
+ while (ch = stream.next()) {
+ if (/[\s\u00a0]/.test(ch)) {
+ result.push(range.create(stream.start + offset, stream.pos - stream.start - 1));
+ stream.eatSpace();
+ stream.start = stream.pos;
+ }
+ }
+
+ result.push(range.create(stream.start + offset, stream.pos - stream.start));
+ return result;
+ }
+
+ /**
+ * Returns best HTML tag range match for current selection
+ * @param {String} tag Tag declaration
+ * @param {Number} offset Tag's position index inside content
+ * @param {Range} selRange Selection range
+ * @return {Range} Returns range if next item was found, null otherwise
+ */
+ function getRangeForHTMLItem(tag, offset, selRange, isBackward) {
+ var ranges = makePossibleRangesHTML(tag, require('xmlParser').parse(tag), offset);
+
+ if (isBackward)
+ ranges.reverse();
+
+ // try to find selected range
+ var curRange = _.find(ranges, function(r) {
+ return r.equal(selRange);
+ });
+
+ if (curRange) {
+ var ix = _.indexOf(ranges, curRange);
+ if (ix < ranges.length - 1)
+ return ranges[ix + 1];
+
+ return null;
+ }
+
+ // no selected range, find nearest one
+ if (isBackward)
+ // search backward
+ return _.find(ranges, function(r) {
+ return r.start < selRange.start;
+ });
+
+ // search forward
+ // to deal with overlapping ranges (like full attribute definition
+ // and attribute value) let's find range under caret first
+ if (!curRange) {
+ var matchedRanges = _.filter(ranges, function(r) {
+ return r.inside(selRange.end);
+ });
+
+ if (matchedRanges.length > 1)
+ return matchedRanges[1];
+ }
+
+
+ return _.find(ranges, function(r) {
+ return r.end > selRange.end;
+ });
+ }
+
+ /**
+ * Search for opening tag in content, starting at specified position
+ * @param {String} html Where to search tag
+ * @param {Number} pos Character index where to start searching
+ * @return {Range} Returns range if valid opening tag was found,
+ * null otherwise
+ */
+ function findOpeningTagFromPosition(html, pos) {
+ var tag;
+ while (pos >= 0) {
+ if (tag = getOpeningTagFromPosition(html, pos))
+ return tag;
+ pos--;
+ }
+
+ return null;
+ }
+
+ /**
+ * @param {String} html Where to search tag
+ * @param {Number} pos Character index where to start searching
+ * @return {Range} Returns range if valid opening tag was found,
+ * null otherwise
+ */
+ function getOpeningTagFromPosition(html, pos) {
+ var m;
+ if (html.charAt(pos) == '<' && (m = html.substring(pos, html.length).match(startTag))) {
+ return require('range').create(pos, m[0]);
+ }
+ }
+
+ function isQuote(ch) {
+ return ch == '"' || ch == "'";
+ }
+
+ /**
+ * Makes all possible selection ranges for specified CSS property
+ * @param {CSSProperty} property
+ * @returns {Array}
+ */
+ function makePossibleRangesCSS(property) {
+ // find all possible ranges, sorted by position and size
+ var valueRange = property.valueRange(true);
+ var result = [property.range(true), valueRange];
+ var stringStream = require('stringStream');
+ var cssEditTree = require('cssEditTree');
+ var range = require('range');
+
+ // locate parts of complex values.
+ // some examples:
+ // – 1px solid red: 3 parts
+ // – arial, sans-serif: enumeration, 2 parts
+ // – url(image.png): function value part
+ var value = property.value();
+ _.each(property.valueParts(), function(r) {
+ // add absolute range
+ var clone = r.clone();
+ result.push(clone.shift(valueRange.start));
+
+ /** @type StringStream */
+ var stream = stringStream.create(r.substring(value));
+ if (stream.match(/^[\w\-]+\(/, true)) {
+ // we have a function, find values in it.
+ // but first add function contents
+ stream.start = stream.pos;
+ stream.skipToPair('(', ')');
+ var fnBody = stream.current();
+ result.push(range.create(clone.start + stream.start, fnBody));
+
+ // find parts
+ _.each(cssEditTree.findParts(fnBody), function(part) {
+ result.push(range.create(clone.start + stream.start + part.start, part.substring(fnBody)));
+ });
+ }
+ });
+
+ // optimize result: remove empty ranges and duplicates
+ return _.chain(result)
+ .filter(function(item) {
+ return !!item.length();
+ })
+ .uniq(false, function(item) {
+ return item.toString();
+ })
+ .value();
+ }
+
+ /**
+ * Tries to find matched CSS property and nearest range for selection
+ * @param {CSSRule} rule
+ * @param {Range} selRange
+ * @param {Boolean} isBackward
+ * @returns {Range}
+ */
+ function matchedRangeForCSSProperty(rule, selRange, isBackward) {
+ /** @type CSSProperty */
+ var property = null;
+ var possibleRanges, curRange = null, ix;
+ var list = rule.list();
+ var searchFn, nearestItemFn;
+
+ if (isBackward) {
+ list.reverse();
+ searchFn = function(p) {
+ return p.range(true).start <= selRange.start;
+ };
+ nearestItemFn = function(r) {
+ return r.start < selRange.start;
+ };
+ } else {
+ searchFn = function(p) {
+ return p.range(true).end >= selRange.end;
+ };
+ nearestItemFn = function(r) {
+ return r.end > selRange.start;
+ };
+ }
+
+ // search for nearest to selection CSS property
+ while (property = _.find(list, searchFn)) {
+ possibleRanges = makePossibleRangesCSS(property);
+ if (isBackward)
+ possibleRanges.reverse();
+
+ // check if any possible range is already selected
+ curRange = _.find(possibleRanges, function(r) {
+ return r.equal(selRange);
+ });
+
+ if (!curRange) {
+ // no selection, select nearest item
+ var matchedRanges = _.filter(possibleRanges, function(r) {
+ return r.inside(selRange.end);
+ });
+
+ if (matchedRanges.length > 1) {
+ curRange = matchedRanges[1];
+ break;
+ }
+
+ if (curRange = _.find(possibleRanges, nearestItemFn))
+ break;
+ } else {
+ ix = _.indexOf(possibleRanges, curRange);
+ if (ix != possibleRanges.length - 1) {
+ curRange = possibleRanges[ix + 1];
+ break;
+ }
+ }
+
+ curRange = null;
+ selRange.start = selRange.end = isBackward
+ ? property.range(true).start - 1
+ : property.range(true).end + 1;
+ }
+
+ return curRange;
+ }
+
+ function findNextCSSItem(editor) {
+ return findItem(editor, false, require('cssEditTree').extractRule, getRangeForNextItemInCSS);
+ }
+
+ function findPrevCSSItem(editor) {
+ return findItem(editor, true, require('cssEditTree').extractRule, getRangeForPrevItemInCSS);
+ }
+
+ /**
+ * Returns range for item to be selected in CSS after current caret
+ * (selection) position
+ * @param {String} rule CSS rule declaration
+ * @param {Number} offset Rule's position index inside content
+ * @param {Range} selRange Selection range
+ * @return {Range} Returns range if next item was found, null otherwise
+ */
+ function getRangeForNextItemInCSS(rule, offset, selRange) {
+ var tree = require('cssEditTree').parse(rule, {
+ offset: offset
+ });
+
+ // check if selector is matched
+ var range = tree.nameRange(true);
+ if (selRange.end < range.end) {
+ return range;
+ }
+
+ return matchedRangeForCSSProperty(tree, selRange, false);
+ }
+
+ /**
+ * Returns range for item to be selected in CSS before current caret
+ * (selection) position
+ * @param {String} rule CSS rule declaration
+ * @param {Number} offset Rule's position index inside content
+ * @param {Range} selRange Selection range
+ * @return {Range} Returns range if previous item was found, null otherwise
+ */
+ function getRangeForPrevItemInCSS(rule, offset, selRange) {
+ var tree = require('cssEditTree').parse(rule, {
+ offset: offset
+ });
+
+ var curRange = matchedRangeForCSSProperty(tree, selRange, true);
+
+ if (!curRange) {
+ // no matched property, try to match selector
+ var range = tree.nameRange(true);
+ if (selRange.start > range.start) {
+ return range;
+ }
+ }
+
+ return curRange;
+ }
+
+ // XXX register actions
+ var actions = require('actions');
+ actions.add('select_next_item', function(editor){
+ if (editor.getSyntax() == 'css')
+ return findNextCSSItem(editor);
+ else
+ return findNextHTMLItem(editor);
+ });
+
+ actions.add('select_previous_item', function(editor){
+ if (editor.getSyntax() == 'css')
+ return findPrevCSSItem(editor);
+ else
+ return findPrevHTMLItem(editor);
+ });
+});/**
+ * HTML pair matching (balancing) actions
+ * @constructor
+ * @memberOf __matchPairActionDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ /** @type emmet.actions */
+ var actions = require('actions');
+ var matcher = require('htmlMatcher');
+ var lastMatch = null;
+
+ /**
+ * Find and select HTML tag pair
+ * @param {IEmmetEditor} editor Editor instance
+ * @param {String} direction Direction of pair matching: 'in' or 'out'.
+ * Default is 'out'
+ */
+ function matchPair(editor, direction) {
+ direction = String((direction || 'out').toLowerCase());
+ var info = require('editorUtils').outputInfo(editor);
+
+ var range = require('range');
+ /** @type Range */
+ var sel = range.create(editor.getSelectionRange());
+ var content = info.content;
+
+ // validate previous match
+ if (lastMatch && !lastMatch.range.equal(sel)) {
+ lastMatch = null;
+ }
+
+ if (lastMatch && sel.length()) {
+ if (direction == 'in') {
+ // user has previously selected tag and wants to move inward
+ if (lastMatch.type == 'tag' && !lastMatch.close) {
+ // unary tag was selected, can't move inward
+ return false;
+ } else {
+ if (lastMatch.range.equal(lastMatch.outerRange)) {
+ lastMatch.range = lastMatch.innerRange;
+ } else {
+ var narrowed = require('utils').narrowToNonSpace(content, lastMatch.innerRange);
+ lastMatch = matcher.find(content, narrowed.start + 1);
+ if (lastMatch && lastMatch.range.equal(sel) && lastMatch.outerRange.equal(sel)) {
+ lastMatch.range = lastMatch.innerRange;
+ }
+ }
+ }
+ } else {
+ if (
+ !lastMatch.innerRange.equal(lastMatch.outerRange)
+ && lastMatch.range.equal(lastMatch.innerRange)
+ && sel.equal(lastMatch.range)) {
+ lastMatch.range = lastMatch.outerRange;
+ } else {
+ lastMatch = matcher.find(content, sel.start);
+ if (lastMatch && lastMatch.range.equal(sel) && lastMatch.innerRange.equal(sel)) {
+ lastMatch.range = lastMatch.outerRange;
+ }
+ }
+ }
+ } else {
+ lastMatch = matcher.find(content, sel.start);
+ }
+
+ if (lastMatch && !lastMatch.range.equal(sel)) {
+ editor.createSelection(lastMatch.range.start, lastMatch.range.end);
+ return true;
+ }
+
+ lastMatch = null;
+ return false;
+ }
+
+ actions.add('match_pair', matchPair, {hidden: true});
+ actions.add('match_pair_inward', function(editor){
+ return matchPair(editor, 'in');
+ }, {label: 'HTML/Match Pair Tag (inward)'});
+
+ actions.add('match_pair_outward', function(editor){
+ return matchPair(editor, 'out');
+ }, {label: 'HTML/Match Pair Tag (outward)'});
+
+ /**
+ * Moves caret to matching opening or closing tag
+ * @param {IEmmetEditor} editor
+ */
+ actions.add('matching_pair', function(editor) {
+ var content = String(editor.getContent());
+ var caretPos = editor.getCaretPos();
+
+ if (content.charAt(caretPos) == '<')
+ // looks like caret is outside of tag pair
+ caretPos++;
+
+ var tag = matcher.tag(content, caretPos);
+ if (tag && tag.close) { // exclude unary tags
+ if (tag.open.range.inside(caretPos)) {
+ editor.setCaretPos(tag.close.range.start);
+ } else {
+ editor.setCaretPos(tag.open.range.start);
+ }
+
+ return true;
+ }
+
+ return false;
+ }, {label: 'HTML/Go To Matching Tag Pair'});
+});/**
+ * Gracefully removes tag under cursor
+ *
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ require('actions').add('remove_tag', function(editor) {
+ var utils = require('utils');
+ var info = require('editorUtils').outputInfo(editor);
+
+ // search for tag
+ var tag = require('htmlMatcher').tag(info.content, editor.getCaretPos());
+ if (tag) {
+ if (!tag.close) {
+ // simply remove unary tag
+ editor.replaceContent(utils.getCaretPlaceholder(), tag.range.start, tag.range.end);
+ } else {
+ // remove tag and its newlines
+ /** @type Range */
+ var tagContentRange = utils.narrowToNonSpace(info.content, tag.innerRange);
+ /** @type Range */
+ var startLineBounds = utils.findNewlineBounds(info.content, tagContentRange.start);
+ var startLinePad = utils.getLinePadding(startLineBounds.substring(info.content));
+ var tagContent = tagContentRange.substring(info.content);
+
+ tagContent = utils.unindentString(tagContent, startLinePad);
+ editor.replaceContent(utils.getCaretPlaceholder() + utils.escapeText(tagContent), tag.outerRange.start, tag.outerRange.end);
+ }
+
+ return true;
+ }
+
+ return false;
+ }, {label: 'HTML/Remove Tag'});
+});
+/**
+ * Splits or joins tag, e.g. transforms it into a short notation and vice versa:
+ * <div></div> → <div /> : join
+ * <div /> → <div></div> : split
+ * @param {Function} require
+ * @param {Underscore} _
+ * @memberOf __splitJoinTagAction
+ * @constructor
+ */
+emmet.exec(function(require, _) {
+ /**
+ * @param {IEmmetEditor} editor
+ * @param {Object} profile
+ * @param {Object} tag
+ */
+ function joinTag(editor, profile, tag) {
+ /** @type emmet.utils */
+ var utils = require('utils');
+
+ // empty closing slash is a nonsense for this action
+ var slash = profile.selfClosing() || ' /';
+ var content = tag.open.range.substring(tag.source).replace(/\s*>$/, slash + '>');
+
+ var caretPos = editor.getCaretPos();
+
+ // update caret position
+ if (content.length + tag.outerRange.start < caretPos) {
+ caretPos = content.length + tag.outerRange.start;
+ }
+
+ content = utils.escapeText(content);
+ editor.replaceContent(content, tag.outerRange.start, tag.outerRange.end);
+ editor.setCaretPos(caretPos);
+ return true;
+ }
+
+ function splitTag(editor, profile, tag) {
+ /** @type emmet.utils */
+ var utils = require('utils');
+
+ var nl = utils.getNewline();
+ var pad = require('resources').getVariable('indentation');
+ var caretPos = editor.getCaretPos();
+
+ // define tag content depending on profile
+ var tagContent = (profile.tag_nl === true) ? nl + pad + nl : '';
+ var content = tag.outerContent().replace(/\s*\/>$/, '>');
+ caretPos = tag.outerRange.start + content.length;
+ content += tagContent + '' + tag.open.name + '>';
+
+ content = utils.escapeText(content);
+ editor.replaceContent(content, tag.outerRange.start, tag.outerRange.end);
+ editor.setCaretPos(caretPos);
+ return true;
+ }
+
+ require('actions').add('split_join_tag', function(editor, profileName) {
+ var matcher = require('htmlMatcher');
+
+ var info = require('editorUtils').outputInfo(editor, null, profileName);
+ var profile = require('profile').get(info.profile);
+
+ // find tag at current position
+ var tag = matcher.tag(info.content, editor.getCaretPos());
+ if (tag) {
+ return tag.close
+ ? joinTag(editor, profile, tag)
+ : splitTag(editor, profile, tag);
+ }
+
+ return false;
+ }, {label: 'HTML/Split\\Join Tag Declaration'});
+});/**
+ * Reflect CSS value: takes rule's value under caret and pastes it for the same
+ * rules with vendor prefixes
+ * @constructor
+ * @memberOf __reflectCSSActionDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('reflectCSSValue', function(require, _) {
+ /**
+ * @type HandlerList List of registered handlers
+ */
+ var handlers = require('handlerList').create();
+
+ require('actions').add('reflect_css_value', function(editor) {
+ if (editor.getSyntax() != 'css') return false;
+
+ return require('actionUtils').compoundUpdate(editor, doCSSReflection(editor));
+ }, {label: 'CSS/Reflect Value'});
+
+ function doCSSReflection(editor) {
+ /** @type emmet.cssEditTree */
+ var cssEditTree = require('cssEditTree');
+ var outputInfo = require('editorUtils').outputInfo(editor);
+ var caretPos = editor.getCaretPos();
+
+ var cssRule = cssEditTree.parseFromPosition(outputInfo.content, caretPos);
+ if (!cssRule) return;
+
+ var property = cssRule.itemFromPosition(caretPos, true);
+ // no property under cursor, nothing to reflect
+ if (!property) return;
+
+ var oldRule = cssRule.source;
+ var offset = cssRule.options.offset;
+ var caretDelta = caretPos - offset - property.range().start;
+
+ handlers.exec(false, [property]);
+
+ if (oldRule !== cssRule.source) {
+ return {
+ data: cssRule.source,
+ start: offset,
+ end: offset + oldRule.length,
+ caret: offset + property.range().start + caretDelta
+ };
+ }
+ }
+
+ /**
+ * Returns regexp that should match reflected CSS property names
+ * @param {String} name Current CSS property name
+ * @return {RegExp}
+ */
+ function getReflectedCSSName(name) {
+ name = require('cssEditTree').baseName(name);
+ var vendorPrefix = '^(?:\\-\\w+\\-)?', m;
+
+ if (name == 'opacity' || name == 'filter') {
+ return new RegExp(vendorPrefix + '(?:opacity|filter)$');
+ } else if (m = name.match(/^border-radius-(top|bottom)(left|right)/)) {
+ // Mozilla-style border radius
+ return new RegExp(vendorPrefix + '(?:' + name + '|border-' + m[1] + '-' + m[2] + '-radius)$');
+ } else if (m = name.match(/^border-(top|bottom)-(left|right)-radius/)) {
+ return new RegExp(vendorPrefix + '(?:' + name + '|border-radius-' + m[1] + m[2] + ')$');
+ }
+
+ return new RegExp(vendorPrefix + name + '$');
+ }
+
+ /**
+ * Reflects value from donor into receiver
+ * @param {CSSProperty} donor Donor CSS property from which value should
+ * be reflected
+ * @param {CSSProperty} receiver Property that should receive reflected
+ * value from donor
+ */
+ function reflectValue(donor, receiver) {
+ var value = getReflectedValue(donor.name(), donor.value(),
+ receiver.name(), receiver.value());
+
+ receiver.value(value);
+ }
+
+ /**
+ * Returns value that should be reflected for refName CSS property
+ * from curName property. This function is used for special cases,
+ * when the same result must be achieved with different properties for different
+ * browsers. For example: opаcity:0.5; → filter:alpha(opacity=50);
+ *
+ * This function does value conversion between different CSS properties
+ *
+ * @param {String} curName Current CSS property name
+ * @param {String} curValue Current CSS property value
+ * @param {String} refName Receiver CSS property's name
+ * @param {String} refValue Receiver CSS property's value
+ * @return {String} New value for receiver property
+ */
+ function getReflectedValue(curName, curValue, refName, refValue) {
+ var cssEditTree = require('cssEditTree');
+ var utils = require('utils');
+ curName = cssEditTree.baseName(curName);
+ refName = cssEditTree.baseName(refName);
+
+ if (curName == 'opacity' && refName == 'filter') {
+ return refValue.replace(/opacity=[^)]*/i, 'opacity=' + Math.floor(parseFloat(curValue) * 100));
+ } else if (curName == 'filter' && refName == 'opacity') {
+ var m = curValue.match(/opacity=([^)]*)/i);
+ return m ? utils.prettifyNumber(parseInt(m[1]) / 100) : refValue;
+ }
+
+ return curValue;
+ }
+
+ // XXX add default handler
+ handlers.add(function(property) {
+ var reName = getReflectedCSSName(property.name());
+ _.each(property.parent.list(), function(p) {
+ if (reName.test(p.name())) {
+ reflectValue(property, p);
+ }
+ });
+ }, {order: -1});
+
+ return {
+ /**
+ * Adds custom reflect handler. The passed function will receive matched
+ * CSS property (as CSSEditElement object) and should
+ * return true if it was performed successfully (handled
+ * reflection), false otherwise.
+ * @param {Function} fn
+ * @param {Object} options
+ */
+ addHandler: function(fn, options) {
+ handlers.add(fn, options);
+ },
+
+ /**
+ * Removes registered handler
+ * @returns
+ */
+ removeHandler: function(fn) {
+ handlers.remove(fn, options);
+ }
+ };
+});/**
+ * Evaluates simple math expression under caret
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ require('actions').add('evaluate_math_expression', function(editor) {
+ var actionUtils = require('actionUtils');
+ var utils = require('utils');
+
+ var content = String(editor.getContent());
+ var chars = '.+-*/\\';
+
+ /** @type Range */
+ var sel = require('range').create(editor.getSelectionRange());
+ if (!sel.length()) {
+ sel = actionUtils.findExpressionBounds(editor, function(ch) {
+ return utils.isNumeric(ch) || chars.indexOf(ch) != -1;
+ });
+ }
+
+ if (sel && sel.length()) {
+ var expr = sel.substring(content);
+
+ // replace integral division: 11\2 => Math.round(11/2)
+ expr = expr.replace(/([\d\.\-]+)\\([\d\.\-]+)/g, 'Math.round($1/$2)');
+
+ try {
+ var result = utils.prettifyNumber(new Function('return ' + expr)());
+ editor.replaceContent(result, sel.start, sel.end);
+ editor.setCaretPos(sel.start + result.length);
+ return true;
+ } catch (e) {}
+ }
+
+ return false;
+ }, {label: 'Numbers/Evaluate Math Expression'});
+});
+/**
+ * Increment/decrement number under cursor
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ /**
+ * Extract number from current caret position of the editor and
+ * increment it by step
+ * @param {IEmmetEditor} editor
+ * @param {Number} step Increment step (may be negative)
+ */
+ function incrementNumber(editor, step) {
+ var utils = require('utils');
+ var actionUtils = require('actionUtils');
+
+ var hasSign = false;
+ var hasDecimal = false;
+
+ var r = actionUtils.findExpressionBounds(editor, function(ch, pos, content) {
+ if (utils.isNumeric(ch))
+ return true;
+ if (ch == '.') {
+ // make sure that next character is numeric too
+ if (!utils.isNumeric(content.charAt(pos + 1)))
+ return false;
+
+ return hasDecimal ? false : hasDecimal = true;
+ }
+ if (ch == '-')
+ return hasSign ? false : hasSign = true;
+
+ return false;
+ });
+
+ if (r && r.length()) {
+ var strNum = r.substring(String(editor.getContent()));
+ var num = parseFloat(strNum);
+ if (!_.isNaN(num)) {
+ num = utils.prettifyNumber(num + step);
+
+ // do we have zero-padded number?
+ if (/^(\-?)0+[1-9]/.test(strNum)) {
+ var minus = '';
+ if (RegExp.$1) {
+ minus = '-';
+ num = num.substring(1);
+ }
+
+ var parts = num.split('.');
+ parts[0] = utils.zeroPadString(parts[0], intLength(strNum));
+ num = minus + parts.join('.');
+ }
+
+ editor.replaceContent(num, r.start, r.end);
+ editor.createSelection(r.start, r.start + num.length);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns length of integer part of number
+ * @param {String} num
+ */
+ function intLength(num) {
+ num = num.replace(/^\-/, '');
+ if (~num.indexOf('.')) {
+ return num.split('.')[0].length;
+ }
+
+ return num.length;
+ }
+
+ var actions = require('actions');
+ _.each([1, -1, 10, -10, 0.1, -0.1], function(num) {
+ var prefix = num > 0 ? 'increment' : 'decrement';
+
+ actions.add(prefix + '_number_by_' + String(Math.abs(num)).replace('.', '').substring(0, 2), function(editor) {
+ return incrementNumber(editor, num);
+ }, {label: 'Numbers/' + prefix.charAt(0).toUpperCase() + prefix.substring(1) + ' number by ' + Math.abs(num)});
+ });
+});/**
+ * Actions to insert line breaks. Some simple editors (like browser's
+ * <textarea>, for example) do not provide such simple things
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ var actions = require('actions');
+ /** @type emmet.preferences */
+ var prefs = require('preferences');
+
+ // setup default preferences
+ prefs.define('css.closeBraceIndentation', '\n',
+ 'Indentation before closing brace of CSS rule. Some users prefere '
+ + 'indented closing brace of CSS rule for better readability. '
+ + 'This preference’s value will be automatically inserted before '
+ + 'closing brace when user adds newline in newly created CSS rule '
+ + '(e.g. when “Insert formatted linebreak” action will be performed '
+ + 'in CSS file). If you’re such user, you may want to write put a value '
+ + 'like \\n\\t in this preference.');
+
+ /**
+ * Inserts newline character with proper indentation in specific positions only.
+ * @param {IEmmetEditor} editor
+ * @return {Boolean} Returns true if line break was inserted
+ */
+ actions.add('insert_formatted_line_break_only', function(editor) {
+ var utils = require('utils');
+ /** @type emmet.resources */
+ var res = require('resources');
+
+ var info = require('editorUtils').outputInfo(editor);
+ var caretPos = editor.getCaretPos();
+ var nl = utils.getNewline();
+
+ if (_.include(['html', 'xml', 'xsl'], info.syntax)) {
+ var pad = res.getVariable('indentation');
+ // let's see if we're breaking newly created tag
+ var tag = require('htmlMatcher').tag(info.content, caretPos);
+ if (tag && !tag.innerRange.length()) {
+ editor.replaceContent(nl + pad + utils.getCaretPlaceholder() + nl, caretPos);
+ return true;
+ }
+ } else if (info.syntax == 'css') {
+ /** @type String */
+ var content = info.content;
+ if (caretPos && content.charAt(caretPos - 1) == '{') {
+ var append = prefs.get('css.closeBraceIndentation');
+ var pad = res.getVariable('indentation');
+
+ var hasCloseBrace = content.charAt(caretPos) == '}';
+ if (!hasCloseBrace) {
+ // do we really need special formatting here?
+ // check if this is really a newly created rule,
+ // look ahead for a closing brace
+ for (var i = caretPos, il = content.length, ch; i < il; i++) {
+ ch = content.charAt(i);
+ if (ch == '{') {
+ // ok, this is a new rule without closing brace
+ break;
+ }
+
+ if (ch == '}') {
+ // not a new rule, just add indentation
+ append = '';
+ hasCloseBrace = true;
+ break;
+ }
+ }
+ }
+
+ if (!hasCloseBrace) {
+ append += '}';
+ }
+
+ // defining rule set
+ var insValue = nl + pad + utils.getCaretPlaceholder() + append;
+ editor.replaceContent(insValue, caretPos);
+ return true;
+ }
+ }
+
+ return false;
+ }, {hidden: true});
+
+ /**
+ * Inserts newline character with proper indentation. This action is used in
+ * editors that doesn't have indentation control (like textarea element) to
+ * provide proper indentation
+ * @param {IEmmetEditor} editor Editor instance
+ */
+ actions.add('insert_formatted_line_break', function(editor) {
+ if (!actions.run('insert_formatted_line_break_only', editor)) {
+ var utils = require('utils');
+
+ var curPadding = require('editorUtils').getCurrentLinePadding(editor);
+ var content = String(editor.getContent());
+ var caretPos = editor.getCaretPos();
+ var len = content.length;
+ var nl = utils.getNewline();
+
+ // check out next line padding
+ var lineRange = editor.getCurrentLineRange();
+ var nextPadding = '';
+
+ for (var i = lineRange.end + 1, ch; i < len; i++) {
+ ch = content.charAt(i);
+ if (ch == ' ' || ch == '\t')
+ nextPadding += ch;
+ else
+ break;
+ }
+
+ if (nextPadding.length > curPadding.length)
+ editor.replaceContent(nl + nextPadding, caretPos, caretPos, true);
+ else
+ editor.replaceContent(nl, caretPos);
+ }
+
+ return true;
+ }, {hidden: true});
+});/**
+ * Merges selected lines or lines between XHTML tag pairs
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ require('actions').add('merge_lines', function(editor) {
+ var matcher = require('htmlMatcher');
+ var utils = require('utils');
+ var editorUtils = require('editorUtils');
+ var info = editorUtils.outputInfo(editor);
+
+ /** @type Range */
+ var selection = require('range').create(editor.getSelectionRange());
+ if (!selection.length()) {
+ // find matching tag
+ var pair = matcher.find(info.content, editor.getCaretPos());
+ if (pair) {
+ selection = pair.outerRange;
+ }
+ }
+
+ if (selection.length()) {
+ // got range, merge lines
+ var text = selection.substring(info.content);
+ var lines = utils.splitByLines(text);
+
+ for (var i = 1; i < lines.length; i++) {
+ lines[i] = lines[i].replace(/^\s+/, '');
+ }
+
+ text = lines.join('').replace(/\s{2,}/, ' ');
+ var textLen = text.length;
+ text = utils.escapeText(text);
+ editor.replaceContent(text, selection.start, selection.end);
+ editor.createSelection(selection.start, selection.start + textLen);
+
+ return true;
+ }
+
+ return false;
+ });
+});/**
+ * Encodes/decodes image under cursor to/from base64
+ * @param {IEmmetEditor} editor
+ * @since 0.65
+ *
+ * @memberOf __base64ActionDefine
+ * @constructor
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ require('actions').add('encode_decode_data_url', function(editor) {
+ var data = String(editor.getSelection());
+ var caretPos = editor.getCaretPos();
+
+ if (!data) {
+ // no selection, try to find image bounds from current caret position
+ var text = String(editor.getContent()), m;
+ while (caretPos-- >= 0) {
+ if (startsWith('src=', text, caretPos)) { // found
+ if (m = text.substr(caretPos).match(/^(src=(["'])?)([^'"<>\s]+)\1?/)) {
+ data = m[3];
+ caretPos += m[1].length;
+ }
+ break;
+ } else if (startsWith('url(', text, caretPos)) { // found CSS url() pattern
+ if (m = text.substr(caretPos).match(/^(url\((['"])?)([^'"\)\s]+)\1?/)) {
+ data = m[3];
+ caretPos += m[1].length;
+ }
+ break;
+ }
+ }
+ }
+
+ if (data) {
+ if (startsWith('data:', data))
+ return decodeFromBase64(editor, data, caretPos);
+ else
+ return encodeToBase64(editor, data, caretPos);
+ }
+
+ return false;
+ }, {label: 'Encode\\Decode data:URL image'});
+
+ /**
+ * Test if text starts with token at pos
+ * position. If pos is omitted, search from beginning of text
+ * @param {String} token Token to test
+ * @param {String} text Where to search
+ * @param {Number} pos Position where to start search
+ * @return {Boolean}
+ * @since 0.65
+ */
+ function startsWith(token, text, pos) {
+ pos = pos || 0;
+ return text.charAt(pos) == token.charAt(0) && text.substr(pos, token.length) == token;
+ }
+
+ /**
+ * Encodes image to base64
+ *
+ * @param {IEmmetEditor} editor
+ * @param {String} imgPath Path to image
+ * @param {Number} pos Caret position where image is located in the editor
+ * @return {Boolean}
+ */
+ function encodeToBase64(editor, imgPath, pos) {
+ var file = require('file');
+ var actionUtils = require('actionUtils');
+
+ var editorFile = editor.getFilePath();
+ var defaultMimeType = 'application/octet-stream';
+
+ if (editorFile === null) {
+ throw "You should save your file before using this action";
+ }
+
+ // locate real image path
+ var realImgPath = file.locateFile(editorFile, imgPath);
+ if (realImgPath === null) {
+ throw "Can't find " + imgPath + ' file';
+ }
+
+ file.read(realImgPath, function(err, content) {
+ if (err) {
+ throw 'Unable to read ' + realImgPath + ': ' + err;
+ }
+
+ var b64 = require('base64').encode(String(content));
+ if (!b64) {
+ throw "Can't encode file content to base64";
+ }
+
+ b64 = 'data:' + (actionUtils.mimeTypes[String(file.getExt(realImgPath))] || defaultMimeType) +
+ ';base64,' + b64;
+
+ editor.replaceContent('$0' + b64, pos, pos + imgPath.length);
+ });
+
+
+ return true;
+ }
+
+ /**
+ * Decodes base64 string back to file.
+ * @param {IEmmetEditor} editor
+ * @param {String} data Base64-encoded file content
+ * @param {Number} pos Caret position where image is located in the editor
+ */
+ function decodeFromBase64(editor, data, pos) {
+ // ask user to enter path to file
+ var filePath = String(editor.prompt('Enter path to file (absolute or relative)'));
+ if (!filePath)
+ return false;
+
+ var file = require('file');
+ var absPath = file.createPath(editor.getFilePath(), filePath);
+ if (!absPath) {
+ throw "Can't save file";
+ }
+
+ file.save(absPath, require('base64').decode( data.replace(/^data\:.+?;.+?,/, '') ));
+ editor.replaceContent('$0' + filePath, pos, pos + data.length);
+ return true;
+ }
+});
+/**
+ * Automatically updates image size attributes in HTML's <img> element or
+ * CSS rule
+ * @param {Function} require
+ * @param {Underscore} _
+ * @constructor
+ * @memberOf __updateImageSizeAction
+ */
+emmet.exec(function(require, _) {
+ /**
+ * Updates image size of <img src=""> tag
+ * @param {IEmmetEditor} editor
+ */
+ function updateImageSizeHTML(editor) {
+ var offset = editor.getCaretPos();
+
+ // find tag from current caret position
+ var info = require('editorUtils').outputInfo(editor);
+ var xmlElem = require('xmlEditTree').parseFromPosition(info.content, offset, true);
+ if (xmlElem && (xmlElem.name() || '').toLowerCase() == 'img') {
+ getImageSizeForSource(editor, xmlElem.value('src'), function(size) {
+ if (size) {
+ var compoundData = xmlElem.range(true);
+ xmlElem.value('width', size.width);
+ xmlElem.value('height', size.height, xmlElem.indexOf('width') + 1);
+
+ require('actionUtils').compoundUpdate(editor, _.extend(compoundData, {
+ data: xmlElem.toString(),
+ caret: offset
+ }));
+ }
+ });
+ }
+ }
+
+ /**
+ * Updates image size of CSS property
+ * @param {IEmmetEditor} editor
+ */
+ function updateImageSizeCSS(editor) {
+ var offset = editor.getCaretPos();
+
+ // find tag from current caret position
+ var info = require('editorUtils').outputInfo(editor);
+ var cssRule = require('cssEditTree').parseFromPosition(info.content, offset, true);
+ if (cssRule) {
+ // check if there is property with image under caret
+ var prop = cssRule.itemFromPosition(offset, true), m;
+ if (prop && (m = /url\((["']?)(.+?)\1\)/i.exec(prop.value() || ''))) {
+ getImageSizeForSource(editor, m[2], function(size) {
+ if (size) {
+ var compoundData = cssRule.range(true);
+ cssRule.value('width', size.width + 'px');
+ cssRule.value('height', size.height + 'px', cssRule.indexOf('width') + 1);
+
+ require('actionUtils').compoundUpdate(editor, _.extend(compoundData, {
+ data: cssRule.toString(),
+ caret: offset
+ }));
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Returns image dimensions for source
+ * @param {IEmmetEditor} editor
+ * @param {String} src Image source (path or data:url)
+ */
+ function getImageSizeForSource(editor, src, callback) {
+ var fileContent;
+ var au = require('actionUtils');
+ if (src) {
+ // check if it is data:url
+ if (/^data:/.test(src)) {
+ fileContent = require('base64').decode( src.replace(/^data\:.+?;.+?,/, '') );
+ return callback(au.getImageSize(fileContent));
+ }
+
+ var file = require('file');
+ var absPath = file.locateFile(editor.getFilePath(), src);
+ if (absPath === null) {
+ throw "Can't find " + src + ' file';
+ }
+
+ file.read(absPath, function(err, content) {
+ if (err) {
+ throw 'Unable to read ' + absPath + ': ' + err;
+ }
+
+ content = String(content);
+ callback(au.getImageSize(content));
+ });
+ }
+ }
+
+ require('actions').add('update_image_size', function(editor) {
+ // this action will definitely won’t work in SASS dialect,
+ // but may work in SCSS or LESS
+ if (_.include(['css', 'less', 'scss'], String(editor.getSyntax()))) {
+ updateImageSizeCSS(editor);
+ } else {
+ updateImageSizeHTML(editor);
+ }
+
+ return true;
+ });
+});/**
+ * Resolver for fast CSS typing. Handles abbreviations with the following
+ * notation:
+ *
+ * (-vendor prefix)?property(value)*(!)?
+ *
+ *
+ * Abbreviation handling
+ *
+ * By default, Emmet searches for matching snippet definition for provided abbreviation.
+ * If snippet wasn't found, Emmet automatically generates element with
+ * abbreviation's name. For example, foo abbreviation will generate
+ * <foo></foo> output.
+ *
+ * This module will capture all expanded properties and upgrade them with values,
+ * vendor prefixes and !important declarations. All unmatched abbreviations will
+ * be automatically transformed into property-name: ${1} snippets.
+ *
+ * Vendor prefixes
+ *
+ * If CSS-property is preceded with dash, resolver should output property with
+ * all known vendor prefixes. For example, if brad
+ * abbreviation generates border-radius: ${value}; snippet,
+ * the -brad abbreviation should generate:
+ *
+ * -webkit-border-radius: ${value};
+ * -moz-border-radius: ${value};
+ * border-radius: ${value};
+ *
+ * Note that o and ms prefixes are omitted since Opera and IE
+ * supports unprefixed property.
+ *
+ * Users can also provide an explicit list of one-character prefixes for any
+ * CSS property. For example, -wm-float will produce
+ *
+ *
+ * -webkit-float: ${1};
+ * -moz-float: ${1};
+ * float: ${1};
+ *
+ *
+ * Although this example looks pointless, users can use this feature to write
+ * cutting-edge properties implemented by browser vendors recently.
+ *
+ * @constructor
+ * @memberOf __cssResolverDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('cssResolver', function(require, _) {
+ /** Back-reference to module */
+ var module = null;
+
+ var prefixObj = {
+ /** Real vendor prefix name */
+ prefix: 'emmet',
+
+ /**
+ * Indicates this prefix is obsolete and should't be used when user
+ * wants to generate all-prefixed properties
+ */
+ obsolete: false,
+
+ /**
+ * Returns prefixed CSS property name
+ * @param {String} name Unprefixed CSS property
+ */
+ transformName: function(name) {
+ return '-' + this.prefix + '-' + name;
+ },
+
+ /**
+ * List of unprefixed CSS properties that supported by
+ * current prefix. This list is used to generate all-prefixed property
+ * @returns {Array}
+ */
+ properties: function() {
+ return getProperties('css.' + this.prefix + 'Properties') || [];
+ },
+
+ /**
+ * Check if given property is supported by current prefix
+ * @param name
+ */
+ supports: function(name) {
+ return _.include(this.properties(), name);
+ }
+ };
+
+
+ /**
+ * List of registered one-character prefixes. Key is a one-character prefix,
+ * value is an prefixObj object
+ */
+ var vendorPrefixes = {};
+
+ var defaultValue = '${1};';
+
+ // XXX module preferences
+ var prefs = require('preferences');
+ prefs.define('css.valueSeparator', ': ',
+ 'Defines a symbol that should be placed between CSS property and '
+ + 'value when expanding CSS abbreviations.');
+ prefs.define('css.propertyEnd', ';',
+ 'Defines a symbol that should be placed at the end of CSS property '
+ + 'when expanding CSS abbreviations.');
+
+ prefs.define('stylus.valueSeparator', ' ',
+ 'Defines a symbol that should be placed between CSS property and '
+ + 'value when expanding CSS abbreviations in Stylus dialect.');
+ prefs.define('stylus.propertyEnd', '',
+ 'Defines a symbol that should be placed at the end of CSS property '
+ + 'when expanding CSS abbreviations in Stylus dialect.');
+
+ prefs.define('sass.propertyEnd', '',
+ 'Defines a symbol that should be placed at the end of CSS property '
+ + 'when expanding CSS abbreviations in SASS dialect.');
+
+ prefs.define('css.autoInsertVendorPrefixes', true,
+ 'Automatically generate vendor-prefixed copies of expanded CSS '
+ + 'property. By default, Emmet will generate vendor-prefixed '
+ + 'properties only when you put dash before abbreviation '
+ + '(e.g. -bxsh). With this option enabled, you don’t '
+ + 'need dashes before abbreviations: Emmet will produce '
+ + 'vendor-prefixed properties for you.');
+
+ var descTemplate = _.template('A comma-separated list of CSS properties that may have '
+ + '<%= vendor %> vendor prefix. This list is used to generate '
+ + 'a list of prefixed properties when expanding -property '
+ + 'abbreviations. Empty list means that all possible CSS values may '
+ + 'have <%= vendor %> prefix.');
+
+ var descAddonTemplate = _.template('A comma-separated list of additional CSS properties '
+ + 'for css.<%= vendor %>Preperties preference. '
+ + 'You should use this list if you want to add or remove a few CSS '
+ + 'properties to original set. To add a new property, simply write its name, '
+ + 'to remove it, precede property with hyphen. '
+ + 'For example, to add foo property and remove border-radius one, '
+ + 'the preference value will look like this: foo, -border-radius.');
+
+ // properties list is created from cssFeatures.html file
+ var props = {
+ 'webkit': 'animation, animation-delay, animation-direction, animation-duration, animation-fill-mode, animation-iteration-count, animation-name, animation-play-state, animation-timing-function, appearance, backface-visibility, background-clip, background-composite, background-origin, background-size, border-fit, border-horizontal-spacing, border-image, border-vertical-spacing, box-align, box-direction, box-flex, box-flex-group, box-lines, box-ordinal-group, box-orient, box-pack, box-reflect, box-shadow, color-correction, column-break-after, column-break-before, column-break-inside, column-count, column-gap, column-rule-color, column-rule-style, column-rule-width, column-span, column-width, dashboard-region, font-smoothing, highlight, hyphenate-character, hyphenate-limit-after, hyphenate-limit-before, hyphens, line-box-contain, line-break, line-clamp, locale, margin-before-collapse, margin-after-collapse, marquee-direction, marquee-increment, marquee-repetition, marquee-style, mask-attachment, mask-box-image, mask-box-image-outset, mask-box-image-repeat, mask-box-image-slice, mask-box-image-source, mask-box-image-width, mask-clip, mask-composite, mask-image, mask-origin, mask-position, mask-repeat, mask-size, nbsp-mode, perspective, perspective-origin, rtl-ordering, text-combine, text-decorations-in-effect, text-emphasis-color, text-emphasis-position, text-emphasis-style, text-fill-color, text-orientation, text-security, text-stroke-color, text-stroke-width, transform, transition, transform-origin, transform-style, transition-delay, transition-duration, transition-property, transition-timing-function, user-drag, user-modify, user-select, writing-mode, svg-shadow, box-sizing, border-radius',
+ 'moz': 'animation-delay, animation-direction, animation-duration, animation-fill-mode, animation-iteration-count, animation-name, animation-play-state, animation-timing-function, appearance, backface-visibility, background-inline-policy, binding, border-bottom-colors, border-image, border-left-colors, border-right-colors, border-top-colors, box-align, box-direction, box-flex, box-ordinal-group, box-orient, box-pack, box-shadow, box-sizing, column-count, column-gap, column-rule-color, column-rule-style, column-rule-width, column-width, float-edge, font-feature-settings, font-language-override, force-broken-image-icon, hyphens, image-region, orient, outline-radius-bottomleft, outline-radius-bottomright, outline-radius-topleft, outline-radius-topright, perspective, perspective-origin, stack-sizing, tab-size, text-blink, text-decoration-color, text-decoration-line, text-decoration-style, text-size-adjust, transform, transform-origin, transform-style, transition, transition-delay, transition-duration, transition-property, transition-timing-function, user-focus, user-input, user-modify, user-select, window-shadow, background-clip, border-radius',
+ 'ms': 'accelerator, backface-visibility, background-position-x, background-position-y, behavior, block-progression, box-align, box-direction, box-flex, box-line-progression, box-lines, box-ordinal-group, box-orient, box-pack, content-zoom-boundary, content-zoom-boundary-max, content-zoom-boundary-min, content-zoom-chaining, content-zoom-snap, content-zoom-snap-points, content-zoom-snap-type, content-zooming, filter, flow-from, flow-into, font-feature-settings, grid-column, grid-column-align, grid-column-span, grid-columns, grid-layer, grid-row, grid-row-align, grid-row-span, grid-rows, high-contrast-adjust, hyphenate-limit-chars, hyphenate-limit-lines, hyphenate-limit-zone, hyphens, ime-mode, interpolation-mode, layout-flow, layout-grid, layout-grid-char, layout-grid-line, layout-grid-mode, layout-grid-type, line-break, overflow-style, perspective, perspective-origin, perspective-origin-x, perspective-origin-y, scroll-boundary, scroll-boundary-bottom, scroll-boundary-left, scroll-boundary-right, scroll-boundary-top, scroll-chaining, scroll-rails, scroll-snap-points-x, scroll-snap-points-y, scroll-snap-type, scroll-snap-x, scroll-snap-y, scrollbar-arrow-color, scrollbar-base-color, scrollbar-darkshadow-color, scrollbar-face-color, scrollbar-highlight-color, scrollbar-shadow-color, scrollbar-track-color, text-align-last, text-autospace, text-justify, text-kashida-space, text-overflow, text-size-adjust, text-underline-position, touch-action, transform, transform-origin, transform-origin-x, transform-origin-y, transform-origin-z, transform-style, transition, transition-delay, transition-duration, transition-property, transition-timing-function, user-select, word-break, word-wrap, wrap-flow, wrap-margin, wrap-through, writing-mode',
+ 'o': 'dashboard-region, animation, animation-delay, animation-direction, animation-duration, animation-fill-mode, animation-iteration-count, animation-name, animation-play-state, animation-timing-function, border-image, link, link-source, object-fit, object-position, tab-size, table-baseline, transform, transform-origin, transition, transition-delay, transition-duration, transition-property, transition-timing-function, accesskey, input-format, input-required, marquee-dir, marquee-loop, marquee-speed, marquee-style'
+ };
+
+ _.each(props, function(v, k) {
+ prefs.define('css.' + k + 'Properties', v, descTemplate({vendor: k}));
+ prefs.define('css.' + k + 'PropertiesAddon', '', descAddonTemplate({vendor: k}));
+ });
+
+ prefs.define('css.unitlessProperties', 'z-index, line-height, opacity, font-weight, zoom',
+ 'The list of properties whose values must not contain units.');
+
+ prefs.define('css.intUnit', 'px', 'Default unit for integer values');
+ prefs.define('css.floatUnit', 'em', 'Default unit for float values');
+
+ prefs.define('css.keywords', 'auto, inherit',
+ 'A comma-separated list of valid keywords that can be used in CSS abbreviations.');
+
+ prefs.define('css.keywordAliases', 'a:auto, i:inherit, s:solid, da:dashed, do:dotted, t:transparent',
+ 'A comma-separated list of keyword aliases, used in CSS abbreviation. '
+ + 'Each alias should be defined as alias:keyword_name.');
+
+ prefs.define('css.unitAliases', 'e:em, p:%, x:ex, r:rem',
+ 'A comma-separated list of unit aliases, used in CSS abbreviation. '
+ + 'Each alias should be defined as alias:unit_value.');
+
+ prefs.define('css.color.short', true,
+ 'Should color values like #ffffff be shortened to '
+ + '#fff after abbreviation with color was expanded.');
+
+ prefs.define('css.color.case', 'keep',
+ 'Letter case of color values generated by abbreviations with color '
+ + '(like c#0). Possible values are upper, '
+ + 'lower and keep.');
+
+ prefs.define('css.fuzzySearch', true,
+ 'Enable fuzzy search among CSS snippet names. When enabled, every '
+ + 'unknown snippet will be scored against available snippet '
+ + 'names (not values or CSS properties!). The match with best score '
+ + 'will be used to resolve snippet value. For example, with this '
+ + 'preference enabled, the following abbreviations are equal: '
+ + 'ov:h == ov-h == o-h == '
+ + 'oh');
+
+ prefs.define('css.fuzzySearchMinScore', 0.3,
+ 'The minium score (from 0 to 1) that fuzzy-matched abbreviation should '
+ + 'achive. Lower values may produce many false-positive matches, '
+ + 'higher values may reduce possible matches.');
+
+ prefs.define('css.alignVendor', false,
+ 'If set to true, all generated vendor-prefixed properties '
+ + 'will be aligned by real property name.');
+
+
+ function isNumeric(ch) {
+ var code = ch && ch.charCodeAt(0);
+ return (ch && ch == '.' || (code > 47 && code < 58));
+ }
+
+ /**
+ * Check if provided snippet contains only one CSS property and value.
+ * @param {String} snippet
+ * @returns {Boolean}
+ */
+ function isSingleProperty(snippet) {
+ var utils = require('utils');
+ snippet = utils.trim(snippet);
+
+ // check if it doesn't contain a comment and a newline
+ if (~snippet.indexOf('/*') || /[\n\r]/.test(snippet)) {
+ return false;
+ }
+
+ // check if it's a valid snippet definition
+ if (!/^[a-z0-9\-]+\s*\:/i.test(snippet)) {
+ return false;
+ }
+
+ snippet = require('tabStops').processText(snippet, {
+ replaceCarets: true,
+ tabstop: function() {
+ return 'value';
+ }
+ });
+
+ return snippet.split(':').length == 2;
+ }
+
+ /**
+ * Normalizes abbreviated value to final CSS one
+ * @param {String} value
+ * @returns {String}
+ */
+ function normalizeValue(value) {
+ if (value.charAt(0) == '-' && !/^\-[\.\d]/.test(value)) {
+ value = value.replace(/^\-+/, '');
+ }
+
+ if (value.charAt(0) == '#') {
+ return normalizeHexColor(value);
+ }
+
+ return getKeyword(value);
+ }
+
+ function normalizeHexColor(value) {
+ var hex = value.replace(/^#+/, '') || '0';
+ if (hex.toLowerCase() == 't') {
+ return 'transparent';
+ }
+
+ var repeat = require('utils').repeatString;
+ var color = null;
+ switch (hex.length) {
+ case 1:
+ color = repeat(hex, 6);
+ break;
+ case 2:
+ color = repeat(hex, 3);
+ break;
+ case 3:
+ color = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
+ break;
+ case 4:
+ color = hex + hex.substr(0, 2);
+ break;
+ case 5:
+ color = hex + hex.charAt(0);
+ break;
+ default:
+ color = hex.substr(0, 6);
+ }
+
+ // color must be shortened?
+ if (prefs.get('css.color.short')) {
+ var p = color.split('');
+ if (p[0] == p[1] && p[2] == p[3] && p[4] == p[5]) {
+ color = p[0] + p[2] + p[4];
+ }
+ }
+
+ // should transform case?
+ switch (prefs.get('css.color.case')) {
+ case 'upper':
+ color = color.toUpperCase();
+ break;
+ case 'lower':
+ color = color.toLowerCase();
+ break;
+ }
+
+ return '#' + color;
+ }
+
+ function getKeyword(name) {
+ var aliases = prefs.getDict('css.keywordAliases');
+ return name in aliases ? aliases[name] : name;
+ }
+
+ function getUnit(name) {
+ var aliases = prefs.getDict('css.unitAliases');
+ return name in aliases ? aliases[name] : name;
+ }
+
+ function isValidKeyword(keyword) {
+ return _.include(prefs.getArray('css.keywords'), getKeyword(keyword));
+ }
+
+ /**
+ * Check if passed CSS property support specified vendor prefix
+ * @param {String} property
+ * @param {String} prefix
+ */
+ function hasPrefix(property, prefix) {
+ var info = vendorPrefixes[prefix];
+
+ if (!info)
+ info = _.find(vendorPrefixes, function(data) {
+ return data.prefix == prefix;
+ });
+
+ return info && info.supports(property);
+ }
+
+ /**
+ * Search for a list of supported prefixes for CSS property. This list
+ * is used to generate all-prefixed snippet
+ * @param {String} property CSS property name
+ * @returns {Array}
+ */
+ function findPrefixes(property, noAutofill) {
+ var result = [];
+ _.each(vendorPrefixes, function(obj, prefix) {
+ if (hasPrefix(property, prefix)) {
+ result.push(prefix);
+ }
+ });
+
+ if (!result.length && !noAutofill) {
+ // add all non-obsolete prefixes
+ _.each(vendorPrefixes, function(obj, prefix) {
+ if (!obj.obsolete)
+ result.push(prefix);
+ });
+ }
+
+ return result;
+ }
+
+ function addPrefix(name, obj) {
+ if (_.isString(obj))
+ obj = {prefix: obj};
+
+ vendorPrefixes[name] = _.extend({}, prefixObj, obj);
+ }
+
+ function getSyntaxPreference(name, syntax) {
+ if (syntax) {
+ var val = prefs.get(syntax + '.' + name);
+ if (!_.isUndefined(val))
+ return val;
+ }
+
+ return prefs.get('css.' + name);
+ }
+
+ /**
+ * Format CSS property according to current syntax dialect
+ * @param {String} property
+ * @param {String} syntax
+ * @returns {String}
+ */
+ function formatProperty(property, syntax) {
+ var ix = property.indexOf(':');
+ property = property.substring(0, ix).replace(/\s+$/, '')
+ + getSyntaxPreference('valueSeparator', syntax)
+ + require('utils').trim(property.substring(ix + 1));
+
+ return property.replace(/\s*;\s*$/, getSyntaxPreference('propertyEnd', syntax));
+ }
+
+ /**
+ * Transforms snippet value if required. For example, this transformation
+ * may add !important declaration to CSS property
+ * @param {String} snippet
+ * @param {Boolean} isImportant
+ * @returns {String}
+ */
+ function transformSnippet(snippet, isImportant, syntax) {
+ if (!_.isString(snippet))
+ snippet = snippet.data;
+
+ if (!isSingleProperty(snippet))
+ return snippet;
+
+ if (isImportant) {
+ if (~snippet.indexOf(';')) {
+ snippet = snippet.split(';').join(' !important;');
+ } else {
+ snippet += ' !important';
+ }
+ }
+
+ return formatProperty(snippet, syntax);
+ }
+
+ /**
+ * Helper function that parses comma-separated list of elements into array
+ * @param {String} list
+ * @returns {Array}
+ */
+ function parseList(list) {
+ var result = _.map((list || '').split(','), require('utils').trim);
+ return result.length ? result : null;
+ }
+
+ function getProperties(key) {
+ var list = prefs.getArray(key);
+ _.each(prefs.getArray(key + 'Addon'), function(prop) {
+ if (prop.charAt(0) == '-') {
+ list = _.without(list, prop.substr(1));
+ } else {
+ if (prop.charAt(0) == '+')
+ prop = prop.substr(1);
+
+ list.push(prop);
+ }
+ });
+
+ return list;
+ }
+
+
+ // TODO refactor, this looks awkward now
+ addPrefix('w', {
+ prefix: 'webkit'
+ });
+ addPrefix('m', {
+ prefix: 'moz'
+ });
+ addPrefix('s', {
+ prefix: 'ms'
+ });
+ addPrefix('o', {
+ prefix: 'o'
+ });
+
+ // I think nobody uses it
+// addPrefix('k', {
+// prefix: 'khtml',
+// obsolete: true
+// });
+
+ var cssSyntaxes = ['css', 'less', 'sass', 'scss', 'stylus'];
+
+ /**
+ * XXX register resolver
+ * @param {TreeNode} node
+ * @param {String} syntax
+ */
+ require('resources').addResolver(function(node, syntax) {
+ if (_.include(cssSyntaxes, syntax) && node.isElement()) {
+ return module.expandToSnippet(node.abbreviation, syntax);
+ }
+
+ return null;
+ });
+
+ var ea = require('expandAbbreviation');
+ /**
+ * For CSS-like syntaxes, we need to handle a special use case. Some editors
+ * (like Sublime Text 2) may insert semicolons automatically when user types
+ * abbreviation. After expansion, user receives a double semicolon. This
+ * handler automatically removes semicolon from generated content in such cases.
+ * @param {IEmmetEditor} editor
+ * @param {String} syntax
+ * @param {String} profile
+ */
+ ea.addHandler(function(editor, syntax, profile) {
+ if (!_.include(cssSyntaxes, syntax)) {
+ return false;
+ }
+
+ var caretPos = editor.getSelectionRange().end;
+ var abbr = ea.findAbbreviation(editor);
+
+ if (abbr) {
+ var content = emmet.expandAbbreviation(abbr, syntax, profile);
+ if (content) {
+ var replaceFrom = caretPos - abbr.length;
+ var replaceTo = caretPos;
+ if (editor.getContent().charAt(caretPos) == ';' && content.charAt(content.length - 1) == ';') {
+ replaceTo++;
+ }
+
+ editor.replaceContent(content, replaceFrom, replaceTo);
+ return true;
+ }
+ }
+
+ return false;
+ });
+
+ return module = {
+ /**
+ * Adds vendor prefix
+ * @param {String} name One-character prefix name
+ * @param {Object} obj Object describing vendor prefix
+ * @memberOf cssResolver
+ */
+ addPrefix: addPrefix,
+
+ /**
+ * Check if passed CSS property supports specified vendor prefix
+ * @param {String} property
+ * @param {String} prefix
+ */
+ supportsPrefix: hasPrefix,
+
+ /**
+ * Returns prefixed version of passed CSS property, only if this
+ * property supports such prefix
+ * @param {String} property
+ * @param {String} prefix
+ * @returns
+ */
+ prefixed: function(property, prefix) {
+ return hasPrefix(property, prefix)
+ ? '-' + prefix + '-' + property
+ : property;
+ },
+
+ /**
+ * Returns list of all registered vendor prefixes
+ * @returns {Array}
+ */
+ listPrefixes: function() {
+ return _.map(vendorPrefixes, function(obj) {
+ return obj.prefix;
+ });
+ },
+
+ /**
+ * Returns object describing vendor prefix
+ * @param {String} name
+ * @returns {Object}
+ */
+ getPrefix: function(name) {
+ return vendorPrefixes[name];
+ },
+
+ /**
+ * Removes prefix object
+ * @param {String} name
+ */
+ removePrefix: function(name) {
+ if (name in vendorPrefixes)
+ delete vendorPrefixes[name];
+ },
+
+ /**
+ * Extract vendor prefixes from abbreviation
+ * @param {String} abbr
+ * @returns {Object} Object containing array of prefixes and clean
+ * abbreviation name
+ */
+ extractPrefixes: function(abbr) {
+ if (abbr.charAt(0) != '-') {
+ return {
+ property: abbr,
+ prefixes: null
+ };
+ }
+
+ // abbreviation may either contain sequence of one-character prefixes
+ // or just dash, meaning that user wants to produce all possible
+ // prefixed properties
+ var i = 1, il = abbr.length, ch;
+ var prefixes = [];
+
+ while (i < il) {
+ ch = abbr.charAt(i);
+ if (ch == '-') {
+ // end-sequence character found, stop searching
+ i++;
+ break;
+ }
+
+ if (ch in vendorPrefixes) {
+ prefixes.push(ch);
+ } else {
+ // no prefix found, meaning user want to produce all
+ // vendor-prefixed properties
+ prefixes.length = 0;
+ i = 1;
+ break;
+ }
+
+ i++;
+ }
+
+ // reached end of abbreviation and no property name left
+ if (i == il -1) {
+ i = 1;
+ prefixes.length = 1;
+ }
+
+ return {
+ property: abbr.substring(i),
+ prefixes: prefixes.length ? prefixes : 'all'
+ };
+ },
+
+ /**
+ * Search for value substring in abbreviation
+ * @param {String} abbr
+ * @returns {String} Value substring
+ */
+ findValuesInAbbreviation: function(abbr, syntax) {
+ syntax = syntax || 'css';
+
+ var i = 0, il = abbr.length, value = '', ch;
+ while (i < il) {
+ ch = abbr.charAt(i);
+ if (isNumeric(ch) || ch == '#' || (ch == '-' && isNumeric(abbr.charAt(i + 1)))) {
+ value = abbr.substring(i);
+ break;
+ }
+
+ i++;
+ }
+
+ // try to find keywords in abbreviation
+ var property = abbr.substring(0, abbr.length - value.length);
+ var res = require('resources');
+ var keywords = [];
+ // try to extract some commonly-used properties
+ while (~property.indexOf('-') && !res.findSnippet(syntax, property)) {
+ var parts = property.split('-');
+ var lastPart = parts.pop();
+ if (!isValidKeyword(lastPart)) {
+ break;
+ }
+
+ keywords.unshift(lastPart);
+ property = parts.join('-');
+ }
+
+ return keywords.join('-') + value;
+ },
+
+ parseValues: function(str) {
+ /** @type StringStream */
+ var stream = require('stringStream').create(str);
+ var values = [];
+ var ch = null;
+
+ while (ch = stream.next()) {
+ if (ch == '#') {
+ stream.match(/^t|[0-9a-f]+/i, true);
+ values.push(stream.current());
+ } else if (ch == '-') {
+ if (isValidKeyword(_.last(values)) ||
+ ( stream.start && isNumeric(str.charAt(stream.start - 1)) )
+ ) {
+ stream.start = stream.pos;
+ }
+
+ stream.match(/^\-?[0-9]*(\.[0-9]+)?[a-z%\.]*/, true);
+ values.push(stream.current());
+ } else {
+ stream.match(/^[0-9]*(\.[0-9]*)?[a-z%]*/, true);
+ values.push(stream.current());
+ }
+
+ stream.start = stream.pos;
+ }
+
+ return _.map(_.compact(values), normalizeValue);
+ },
+
+ /**
+ * Extracts values from abbreviation
+ * @param {String} abbr
+ * @returns {Object} Object containing array of values and clean
+ * abbreviation name
+ */
+ extractValues: function(abbr) {
+ // search for value start
+ var abbrValues = this.findValuesInAbbreviation(abbr);
+ if (!abbrValues) {
+ return {
+ property: abbr,
+ values: null
+ };
+ }
+
+ return {
+ property: abbr.substring(0, abbr.length - abbrValues.length).replace(/-$/, ''),
+ values: this.parseValues(abbrValues)
+ };
+ },
+
+ /**
+ * Normalizes value, defined in abbreviation.
+ * @param {String} value
+ * @param {String} property
+ * @returns {String}
+ */
+ normalizeValue: function(value, property) {
+ property = (property || '').toLowerCase();
+ var unitlessProps = prefs.getArray('css.unitlessProperties');
+ return value.replace(/^(\-?[0-9\.]+)([a-z]*)$/, function(str, val, unit) {
+ if (!unit && (val == '0' || _.include(unitlessProps, property)))
+ return val;
+
+ if (!unit)
+ return val.replace(/\.$/, '') + prefs.get(~val.indexOf('.') ? 'css.floatUnit' : 'css.intUnit');
+
+ return val + getUnit(unit);
+ });
+ },
+
+ /**
+ * Expands abbreviation into a snippet
+ * @param {String} abbr Abbreviation name to expand
+ * @param {String} value Abbreviation value
+ * @param {String} syntax Currect syntax or dialect. Default is 'css'
+ * @returns {Object} Array of CSS properties and values or predefined
+ * snippet (string or element)
+ */
+ expand: function(abbr, value, syntax) {
+ syntax = syntax || 'css';
+ var resources = require('resources');
+ var autoInsertPrefixes = prefs.get('css.autoInsertVendorPrefixes');
+
+ // check if snippet should be transformed to !important
+ var isImportant;
+ if (isImportant = /^(.+)\!$/.test(abbr)) {
+ abbr = RegExp.$1;
+ }
+
+ // check if we have abbreviated resource
+ var snippet = resources.findSnippet(syntax, abbr);
+ if (snippet && !autoInsertPrefixes) {
+ return transformSnippet(snippet, isImportant, syntax);
+ }
+
+ // no abbreviated resource, parse abbreviation
+ var prefixData = this.extractPrefixes(abbr);
+ var valuesData = this.extractValues(prefixData.property);
+ var abbrData = _.extend(prefixData, valuesData);
+
+ if (!snippet) {
+ snippet = resources.findSnippet(syntax, abbrData.property);
+ } else {
+ abbrData.values = null;
+ }
+
+ if (!snippet && prefs.get('css.fuzzySearch')) {
+ // let’s try fuzzy search
+ snippet = resources.fuzzyFindSnippet(syntax, abbrData.property, parseFloat(prefs.get('css.fuzzySearchMinScore')));
+ }
+
+ if (!snippet) {
+ snippet = abbrData.property + ':' + defaultValue;
+ } else if (!_.isString(snippet)) {
+ snippet = snippet.data;
+ }
+
+ if (!isSingleProperty(snippet)) {
+ return snippet;
+ }
+
+ var snippetObj = this.splitSnippet(snippet);
+ var result = [];
+ if (!value && abbrData.values) {
+ value = _.map(abbrData.values, function(val) {
+ return this.normalizeValue(val, snippetObj.name);
+ }, this).join(' ') + ';';
+ }
+
+ snippetObj.value = value || snippetObj.value;
+
+ var prefixes = abbrData.prefixes == 'all' || (!abbrData.prefixes && autoInsertPrefixes)
+ ? findPrefixes(snippetObj.name, autoInsertPrefixes && abbrData.prefixes != 'all')
+ : abbrData.prefixes;
+
+
+ var names = [], propName;
+ _.each(prefixes, function(p) {
+ if (p in vendorPrefixes) {
+ propName = vendorPrefixes[p].transformName(snippetObj.name);
+ names.push(propName);
+ result.push(transformSnippet(propName + ':' + snippetObj.value,
+ isImportant, syntax));
+ }
+ });
+
+ // put the original property
+ result.push(transformSnippet(snippetObj.name + ':' + snippetObj.value, isImportant, syntax));
+ names.push(snippetObj.name);
+
+ if (prefs.get('css.alignVendor')) {
+ var pads = require('utils').getStringsPads(names);
+ result = _.map(result, function(prop, i) {
+ return pads[i] + prop;
+ });
+ }
+
+ return result;
+ },
+
+ /**
+ * Same as expand method but transforms output into
+ * Emmet snippet
+ * @param {String} abbr
+ * @param {String} syntax
+ * @returns {String}
+ */
+ expandToSnippet: function(abbr, syntax) {
+ var snippet = this.expand(abbr, null, syntax);
+ if (_.isArray(snippet)) {
+ return snippet.join('\n');
+ }
+
+ if (!_.isString(snippet))
+ return snippet.data;
+
+ return String(snippet);
+ },
+
+ /**
+ * Split snippet into a CSS property-value pair
+ * @param {String} snippet
+ */
+ splitSnippet: function(snippet) {
+ var utils = require('utils');
+ snippet = utils.trim(snippet);
+ if (snippet.indexOf(':') == -1) {
+ return {
+ name: snippet,
+ value: defaultValue
+ };
+ }
+
+ var pair = snippet.split(':');
+
+ return {
+ name: utils.trim(pair.shift()),
+ // replace ${0} tabstop to produce valid vendor-prefixed values
+ // where possible
+ value: utils.trim(pair.join(':')).replace(/^(\$\{0\}|\$0)(\s*;?)$/, '${1}$2')
+ };
+ },
+
+ getSyntaxPreference: getSyntaxPreference,
+ transformSnippet: transformSnippet
+ };
+});
+/**
+ * 'Expand Abbreviation' handler that parses gradient definition from under
+ * cursor and updates CSS rule with vendor-prefixed values.
+ *
+ * @memberOf __cssGradientHandlerDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('cssGradient', function(require, _) {
+ var defaultLinearDirections = ['top', 'to bottom', '0deg'];
+ /** Back-reference to current module */
+ var module = null;
+
+ var cssSyntaxes = ['css', 'less', 'sass', 'scss', 'stylus', 'styl'];
+
+ var reDeg = /\d+deg/i;
+ var reKeyword = /top|bottom|left|right/i;
+
+ // XXX define preferences
+ /** @type preferences */
+ var prefs = require('preferences');
+ prefs.define('css.gradient.prefixes', 'webkit, moz, o',
+ 'A comma-separated list of vendor-prefixes for which values should '
+ + 'be generated.');
+
+ prefs.define('css.gradient.oldWebkit', true,
+ 'Generate gradient definition for old Webkit implementations');
+
+ prefs.define('css.gradient.omitDefaultDirection', true,
+ 'Do not output default direction definition in generated gradients.');
+
+ prefs.define('css.gradient.defaultProperty', 'background-image',
+ 'When gradient expanded outside CSS value context, it will produce '
+ + 'properties with this name.');
+
+ prefs.define('css.gradient.fallback', false,
+ 'With this option enabled, CSS gradient generator will produce '
+ + 'background-color property with gradient first color '
+ + 'as fallback for old browsers.');
+
+ function normalizeSpace(str) {
+ return require('utils').trim(str).replace(/\s+/g, ' ');
+ }
+
+ /**
+ * Parses linear gradient definition
+ * @param {String}
+ */
+ function parseLinearGradient(gradient) {
+ var direction = defaultLinearDirections[0];
+
+ // extract tokens
+ /** @type StringStream */
+ var stream = require('stringStream').create(require('utils').trim(gradient));
+ var colorStops = [], ch;
+ while (ch = stream.next()) {
+ if (stream.peek() == ',') {
+ colorStops.push(stream.current());
+ stream.next();
+ stream.eatSpace();
+ stream.start = stream.pos;
+ } else if (ch == '(') { // color definition, like 'rgb(0,0,0)'
+ stream.skipTo(')');
+ }
+ }
+
+ // add last token
+ colorStops.push(stream.current());
+ colorStops = _.compact(_.map(colorStops, normalizeSpace));
+
+ if (!colorStops.length)
+ return null;
+
+ // let's see if the first color stop is actually a direction
+ if (reDeg.test(colorStops[0]) || reKeyword.test(colorStops[0])) {
+ direction = colorStops.shift();
+ }
+
+ return {
+ type: 'linear',
+ direction: direction,
+ colorStops: _.map(colorStops, parseColorStop)
+ };
+ }
+
+ /**
+ * Parses color stop definition
+ * @param {String} colorStop
+ * @returns {Object}
+ */
+ function parseColorStop(colorStop) {
+ colorStop = normalizeSpace(colorStop);
+
+ // find color declaration
+ // first, try complex color declaration, like rgb(0,0,0)
+ var color = null;
+ colorStop = colorStop.replace(/^(\w+\(.+?\))\s*/, function(str, c) {
+ color = c;
+ return '';
+ });
+
+ if (!color) {
+ // try simple declaration, like yellow, #fco, #ffffff, etc.
+ var parts = colorStop.split(' ');
+ color = parts[0];
+ colorStop = parts[1] || '';
+ }
+
+ var result = {
+ color: color
+ };
+
+ if (colorStop) {
+ // there's position in color stop definition
+ colorStop.replace(/^(\-?[\d\.]+)([a-z%]+)?$/, function(str, pos, unit) {
+ result.position = pos;
+ if (~pos.indexOf('.')) {
+ unit = '';
+ } else if (!unit) {
+ unit = '%';
+ }
+
+ if (unit)
+ result.unit = unit;
+ });
+ }
+
+ return result;
+ }
+
+ /**
+ * Resolves property name (abbreviation): searches for snippet definition in
+ * 'resources' and returns new name of matched property
+ */
+ function resolvePropertyName(name, syntax) {
+ var res = require('resources');
+ var prefs = require('preferences');
+ var snippet = res.findSnippet(syntax, name);
+
+ if (!snippet && prefs.get('css.fuzzySearch')) {
+ snippet = res.fuzzyFindSnippet(syntax, name,
+ parseFloat(prefs.get('css.fuzzySearchMinScore')));
+ }
+
+ if (snippet) {
+ if (!_.isString(snippet)) {
+ snippet = snippet.data;
+ }
+
+ return require('cssResolver').splitSnippet(snippet).name;
+ }
+ }
+
+ /**
+ * Fills-out implied positions in color-stops. This function is useful for
+ * old Webkit gradient definitions
+ */
+ function fillImpliedPositions(colorStops) {
+ var from = 0;
+
+ _.each(colorStops, function(cs, i) {
+ // make sure that first and last positions are defined
+ if (!i)
+ return cs.position = cs.position || 0;
+
+ if (i == colorStops.length - 1 && !('position' in cs))
+ cs.position = 1;
+
+ if ('position' in cs) {
+ var start = colorStops[from].position || 0;
+ var step = (cs.position - start) / (i - from);
+ _.each(colorStops.slice(from, i), function(cs2, j) {
+ cs2.position = start + step * j;
+ });
+
+ from = i;
+ }
+ });
+ }
+
+ /**
+ * Returns textual version of direction expressed in degrees
+ * @param {String} direction
+ * @returns {String}
+ */
+ function textualDirection(direction) {
+ var angle = parseFloat(direction);
+
+ if(!_.isNaN(angle)) {
+ switch(angle % 360) {
+ case 0: return 'left';
+ case 90: return 'bottom';
+ case 180: return 'right';
+ case 240: return 'top';
+ }
+ }
+
+ return direction;
+ }
+
+ /**
+ * Creates direction definition for old Webkit gradients
+ * @param {String} direction
+ * @returns {String}
+ */
+ function oldWebkitDirection(direction) {
+ direction = textualDirection(direction);
+
+ if(reDeg.test(direction))
+ throw "The direction is an angle that can’t be converted.";
+
+ var v = function(pos) {
+ return ~direction.indexOf(pos) ? '100%' : '0';
+ };
+
+ return v('right') + ' ' + v('bottom') + ', ' + v('left') + ' ' + v('top');
+ }
+
+ function getPrefixedNames(name) {
+ var prefixes = prefs.getArray('css.gradient.prefixes');
+ var names = _.map(prefixes, function(p) {
+ return '-' + p + '-' + name;
+ });
+ names.push(name);
+
+ return names;
+ }
+
+ /**
+ * Returns list of CSS properties with gradient
+ * @param {Object} gradient
+ * @param {String} propertyName Original CSS property name
+ * @returns {Array}
+ */
+ function getPropertiesForGradient(gradient, propertyName) {
+ var props = [];
+ var css = require('cssResolver');
+
+ if (prefs.get('css.gradient.fallback') && ~propertyName.toLowerCase().indexOf('background')) {
+ props.push({
+ name: 'background-color',
+ value: '${1:' + gradient.colorStops[0].color + '}'
+ });
+ }
+
+ _.each(prefs.getArray('css.gradient.prefixes'), function(prefix) {
+ var name = css.prefixed(propertyName, prefix);
+ if (prefix == 'webkit' && prefs.get('css.gradient.oldWebkit')) {
+ try {
+ props.push({
+ name: name,
+ value: module.oldWebkitLinearGradient(gradient)
+ });
+ } catch(e) {}
+ }
+
+ props.push({
+ name: name,
+ value: module.toString(gradient, prefix)
+ });
+ });
+
+ return props.sort(function(a, b) {
+ return b.name.length - a.name.length;
+ });
+ }
+
+ /**
+ * Pastes gradient definition into CSS rule with correct vendor-prefixes
+ * @param {EditElement} property Matched CSS property
+ * @param {Object} gradient Parsed gradient
+ * @param {Range} valueRange If passed, only this range within property
+ * value will be replaced with gradient. Otherwise, full value will be
+ * replaced
+ */
+ function pasteGradient(property, gradient, valueRange) {
+ var rule = property.parent;
+ var utils = require('utils');
+ var alignVendor = require('preferences').get('css.alignVendor');
+
+ // we may have aligned gradient definitions: find the smallest value
+ // separator
+ var sep = property.styleSeparator;
+ var before = property.styleBefore;
+
+ // first, remove all properties within CSS rule with the same name and
+ // gradient definition
+ _.each(rule.getAll(getPrefixedNames(property.name())), function(item) {
+ if (item != property && /gradient/i.test(item.value())) {
+ if (item.styleSeparator.length < sep.length) {
+ sep = item.styleSeparator;
+ }
+ if (item.styleBefore.length < before.length) {
+ before = item.styleBefore;
+ }
+ rule.remove(item);
+ }
+ });
+
+ if (alignVendor) {
+ // update prefix
+ if (before != property.styleBefore) {
+ var fullRange = property.fullRange();
+ rule._updateSource(before, fullRange.start, fullRange.start + property.styleBefore.length);
+ property.styleBefore = before;
+ }
+
+ // update separator value
+ if (sep != property.styleSeparator) {
+ rule._updateSource(sep, property.nameRange().end, property.valueRange().start);
+ property.styleSeparator = sep;
+ }
+ }
+
+ var value = property.value();
+ if (!valueRange)
+ valueRange = require('range').create(0, property.value());
+
+ var val = function(v) {
+ return utils.replaceSubstring(value, v, valueRange);
+ };
+
+ // put vanilla-clean gradient definition into current rule
+ property.value(val(module.toString(gradient)) + '${2}');
+
+ // create list of properties to insert
+ var propsToInsert = getPropertiesForGradient(gradient, property.name());
+
+ // align prefixed values
+ if (alignVendor) {
+ var values = _.pluck(propsToInsert, 'value');
+ var names = _.pluck(propsToInsert, 'name');
+ values.push(property.value());
+ names.push(property.name());
+
+ var valuePads = utils.getStringsPads(_.map(values, function(v) {
+ return v.substring(0, v.indexOf('('));
+ }));
+
+ var namePads = utils.getStringsPads(names);
+ property.name(_.last(namePads) + property.name());
+
+ _.each(propsToInsert, function(prop, i) {
+ prop.name = namePads[i] + prop.name;
+ prop.value = valuePads[i] + prop.value;
+ });
+
+ property.value(_.last(valuePads) + property.value());
+ }
+
+ // put vendor-prefixed definitions before current rule
+ _.each(propsToInsert, function(prop) {
+ rule.add(prop.name, prop.value, rule.indexOf(property));
+ });
+ }
+
+ /**
+ * Search for gradient definition inside CSS property value
+ */
+ function findGradient(cssProp) {
+ var value = cssProp.value();
+ var gradient = null;
+ var matchedPart = _.find(cssProp.valueParts(), function(part) {
+ return gradient = module.parse(part.substring(value));
+ });
+
+ if (matchedPart && gradient) {
+ return {
+ gradient: gradient,
+ valueRange: matchedPart
+ };
+ }
+
+ return null;
+ }
+
+ /**
+ * Tries to expand gradient outside CSS value
+ * @param {IEmmetEditor} editor
+ * @param {String} syntax
+ */
+ function expandGradientOutsideValue(editor, syntax) {
+ var propertyName = prefs.get('css.gradient.defaultProperty');
+
+ if (!propertyName)
+ return false;
+
+ // assuming that gradient definition is written on new line,
+ // do a simplified parsing
+ var content = String(editor.getContent());
+ /** @type Range */
+ var lineRange = require('range').create(editor.getCurrentLineRange());
+
+ // get line content and adjust range with padding
+ var line = lineRange.substring(content)
+ .replace(/^\s+/, function(pad) {
+ lineRange.start += pad.length;
+ return '';
+ })
+ .replace(/\s+$/, function(pad) {
+ lineRange.end -= pad.length;
+ return '';
+ });
+
+ var css = require('cssResolver');
+ var gradient = module.parse(line);
+ if (gradient) {
+ var props = getPropertiesForGradient(gradient, propertyName);
+ props.push({
+ name: propertyName,
+ value: module.toString(gradient) + '${2}'
+ });
+
+ var sep = css.getSyntaxPreference('valueSeparator', syntax);
+ var end = css.getSyntaxPreference('propertyEnd', syntax);
+
+ if (require('preferences').get('css.alignVendor')) {
+ var pads = require('utils').getStringsPads(_.map(props, function(prop) {
+ return prop.value.substring(0, prop.value.indexOf('('));
+ }));
+ _.each(props, function(prop, i) {
+ prop.value = pads[i] + prop.value;
+ });
+ }
+
+ props = _.map(props, function(item) {
+ return item.name + sep + item.value + end;
+ });
+
+ editor.replaceContent(props.join('\n'), lineRange.start, lineRange.end);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Search for gradient definition inside CSS value under cursor
+ * @param {String} content
+ * @param {Number} pos
+ * @returns {Object}
+ */
+ function findGradientFromPosition(content, pos) {
+ var cssProp = null;
+ /** @type EditContainer */
+ var cssRule = require('cssEditTree').parseFromPosition(content, pos, true);
+
+ if (cssRule) {
+ cssProp = cssRule.itemFromPosition(pos, true);
+ if (!cssProp) {
+ // in case user just started writing CSS property
+ // and didn't include semicolon–try another approach
+ cssProp = _.find(cssRule.list(), function(elem) {
+ return elem.range(true).end == pos;
+ });
+ }
+ }
+
+ return {
+ rule: cssRule,
+ property: cssProp
+ };
+ }
+
+ // XXX register expand abbreviation handler
+ /**
+ * @param {IEmmetEditor} editor
+ * @param {String} syntax
+ * @param {String} profile
+ */
+ require('expandAbbreviation').addHandler(function(editor, syntax, profile) {
+ var info = require('editorUtils').outputInfo(editor, syntax, profile);
+ if (!_.include(cssSyntaxes, info.syntax))
+ return false;
+
+ // let's see if we are expanding gradient definition
+ var caret = editor.getCaretPos();
+ var content = info.content;
+ var css = findGradientFromPosition(content, caret);
+
+ if (css.property) {
+ // make sure that caret is inside property value with gradient
+ // definition
+ var g = findGradient(css.property);
+ if (g) {
+ var ruleStart = css.rule.options.offset || 0;
+ var ruleEnd = ruleStart + css.rule.toString().length;
+
+ // Handle special case:
+ // user wrote gradient definition between existing CSS
+ // properties and did not finished it with semicolon.
+ // In this case, we have semicolon right after gradient
+ // definition and re-parse rule again
+ if (/[\n\r]/.test(css.property.value())) {
+ // insert semicolon at the end of gradient definition
+ var insertPos = css.property.valueRange(true).start + g.valueRange.end;
+ content = require('utils').replaceSubstring(content, ';', insertPos);
+ var newCss = findGradientFromPosition(content, caret);
+ if (newCss.property) {
+ g = findGradient(newCss.property);
+ css = newCss;
+ }
+ }
+
+ // make sure current property has terminating semicolon
+ css.property.end(';');
+
+ // resolve CSS property name
+ var resolvedName = resolvePropertyName(css.property.name(), syntax);
+ if (resolvedName) {
+ css.property.name(resolvedName);
+ }
+
+ pasteGradient(css.property, g.gradient, g.valueRange);
+ editor.replaceContent(css.rule.toString(), ruleStart, ruleEnd, true);
+ return true;
+ }
+ }
+
+ return expandGradientOutsideValue(editor, syntax);
+ });
+
+ // XXX register "Reflect CSS Value" action delegate
+ /**
+ * @param {EditElement} property
+ */
+ require('reflectCSSValue').addHandler(function(property) {
+ var utils = require('utils');
+
+ var g = findGradient(property);
+ if (!g)
+ return false;
+
+ var value = property.value();
+ var val = function(v) {
+ return utils.replaceSubstring(value, v, g.valueRange);
+ };
+
+ // reflect value for properties with the same name
+ _.each(property.parent.getAll(getPrefixedNames(property.name())), function(prop) {
+ if (prop === property)
+ return;
+
+ // check if property value starts with gradient definition
+ var m = prop.value().match(/^\s*(\-([a-z]+)\-)?linear\-gradient/);
+ if (m) {
+ prop.value(val(module.toString(g.gradient, m[2] || '')));
+ } else if (m = prop.value().match(/\s*\-webkit\-gradient/)) {
+ // old webkit gradient definition
+ prop.value(val(module.oldWebkitLinearGradient(g.gradient)));
+ }
+ });
+
+ return true;
+ });
+
+ return module = {
+ /**
+ * Parses gradient definition
+ * @param {String} gradient
+ * @returns {Object}
+ */
+ parse: function(gradient) {
+ var result = null;
+ require('utils').trim(gradient).replace(/^([\w\-]+)\((.+?)\)$/, function(str, type, definition) {
+ // remove vendor prefix
+ type = type.toLowerCase().replace(/^\-[a-z]+\-/, '');
+ if (type == 'linear-gradient' || type == 'lg') {
+ result = parseLinearGradient(definition);
+ return '';
+ }
+
+ return str;
+ });
+
+ return result;
+ },
+
+ /**
+ * Produces linear gradient definition used in early Webkit
+ * implementations
+ * @param {Object} gradient Parsed gradient
+ * @returns {String}
+ */
+ oldWebkitLinearGradient: function(gradient) {
+ if (_.isString(gradient))
+ gradient = this.parse(gradient);
+
+ if (!gradient)
+ return null;
+
+ var colorStops = _.map(gradient.colorStops, _.clone);
+
+ // normalize color-stops position
+ _.each(colorStops, function(cs) {
+ if (!('position' in cs)) // implied position
+ return;
+
+ if (~cs.position.indexOf('.') || cs.unit == '%') {
+ cs.position = parseFloat(cs.position) / (cs.unit == '%' ? 100 : 1);
+ } else {
+ throw "Can't convert color stop '" + (cs.position + (cs.unit || '')) + "'";
+ }
+ });
+
+ fillImpliedPositions(colorStops);
+
+ // transform color-stops into string representation
+ colorStops = _.map(colorStops, function(cs, i) {
+ if (!cs.position && !i)
+ return 'from(' + cs.color + ')';
+
+ if (cs.position == 1 && i == colorStops.length - 1)
+ return 'to(' + cs.color + ')';
+
+ return 'color-stop(' + (cs.position.toFixed(2).replace(/\.?0+$/, '')) + ', ' + cs.color + ')';
+ });
+
+ return '-webkit-gradient(linear, '
+ + oldWebkitDirection(gradient.direction)
+ + ', '
+ + colorStops.join(', ')
+ + ')';
+ },
+
+ /**
+ * Returns string representation of parsed gradient
+ * @param {Object} gradient Parsed gradient
+ * @param {String} prefix Vendor prefix
+ * @returns {String}
+ */
+ toString: function(gradient, prefix) {
+ if (gradient.type == 'linear') {
+ var fn = (prefix ? '-' + prefix + '-' : '') + 'linear-gradient';
+
+ // transform color-stops
+ var colorStops = _.map(gradient.colorStops, function(cs) {
+ return cs.color + ('position' in cs
+ ? ' ' + cs.position + (cs.unit || '')
+ : '');
+ });
+
+ if (gradient.direction
+ && (!prefs.get('css.gradient.omitDefaultDirection')
+ || !_.include(defaultLinearDirections, gradient.direction))) {
+ colorStops.unshift(gradient.direction);
+ }
+
+ return fn + '(' + colorStops.join(', ') + ')';
+ }
+ }
+ };
+});/**
+ * Module adds support for generators: a regexp-based abbreviation resolver
+ * that can produce custom output.
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ /** @type HandlerList */
+ var generators = require('handlerList').create();
+ var resources = require('resources');
+
+ _.extend(resources, {
+ /**
+ * Add generator. A generator function fn will be called
+ * only if current abbreviation matches regexp regular
+ * expression and this function should return null if
+ * abbreviation cannot be resolved
+ * @param {RegExp} regexp Regular expression for abbreviation element name
+ * @param {Function} fn Resolver function
+ * @param {Object} options Options list as described in
+ * {@link HandlerList#add()} method
+ */
+ addGenerator: function(regexp, fn, options) {
+ if (_.isString(regexp))
+ regexp = new RegExp(regexp);
+
+ generators.add(function(node, syntax) {
+ var m;
+ if ((m = regexp.exec(node.name()))) {
+ return fn(m, node, syntax);
+ }
+
+ return null;
+ }, options);
+ }
+ });
+
+ resources.addResolver(function(node, syntax) {
+ return generators.exec(null, _.toArray(arguments));
+ });
+});/**
+ * Module for resolving tag names: returns best matched tag name for child
+ * element based on passed parent's tag name. Also provides utility function
+ * for element type detection (inline, block-level, empty)
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.define('tagName', function(require, _) {
+ var elementTypes = {
+ empty: 'area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,keygen,command'.split(','),
+ blockLevel: 'address,applet,blockquote,button,center,dd,del,dir,div,dl,dt,fieldset,form,frameset,hr,iframe,ins,isindex,li,link,map,menu,noframes,noscript,object,ol,p,pre,script,table,tbody,td,tfoot,th,thead,tr,ul,h1,h2,h3,h4,h5,h6'.split(','),
+ inlineLevel: 'a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'.split(',')
+ };
+
+ var elementMap = {
+ 'p': 'span',
+ 'ul': 'li',
+ 'ol': 'li',
+ 'table': 'tr',
+ 'tr': 'td',
+ 'tbody': 'tr',
+ 'thead': 'tr',
+ 'tfoot': 'tr',
+ 'colgroup': 'col',
+ 'select': 'option',
+ 'optgroup': 'option',
+ 'audio': 'source',
+ 'video': 'source',
+ 'object': 'param',
+ 'map': 'area'
+ };
+
+ return {
+ /**
+ * Returns best matched child element name for passed parent's
+ * tag name
+ * @param {String} name
+ * @returns {String}
+ * @memberOf tagName
+ */
+ resolve: function(name) {
+ name = (name || '').toLowerCase();
+
+ if (name in elementMap)
+ return this.getMapping(name);
+
+ if (this.isInlineLevel(name))
+ return 'span';
+
+ return 'div';
+ },
+
+ /**
+ * Returns mapped child element name for passed parent's name
+ * @param {String} name
+ * @returns {String}
+ */
+ getMapping: function(name) {
+ return elementMap[name.toLowerCase()];
+ },
+
+ /**
+ * Check if passed element name belongs to inline-level element
+ * @param {String} name
+ * @returns {Boolean}
+ */
+ isInlineLevel: function(name) {
+ return this.isTypeOf(name, 'inlineLevel');
+ },
+
+ /**
+ * Check if passed element belongs to block-level element.
+ * For better matching of unknown elements (for XML, for example),
+ * you should use !this.isInlineLevel(name)
+ * @returns {Boolean}
+ */
+ isBlockLevel: function(name) {
+ return this.isTypeOf(name, 'blockLevel');
+ },
+
+ /**
+ * Check if passed element is void (i.e. should not have closing tag).
+ * @returns {Boolean}
+ */
+ isEmptyElement: function(name) {
+ return this.isTypeOf(name, 'empty');
+ },
+
+ /**
+ * Generic function for testing if element name belongs to specified
+ * elements collection
+ * @param {String} name Element name
+ * @param {String} type Collection name
+ * @returns {Boolean}
+ */
+ isTypeOf: function(name, type) {
+ return _.include(elementTypes[type], name);
+ },
+
+ /**
+ * Adds new parent–child mapping
+ * @param {String} parent
+ * @param {String} child
+ */
+ addMapping: function(parent, child) {
+ elementMap[parent] = child;
+ },
+
+ /**
+ * Removes parent-child mapping
+ */
+ removeMapping: function(parent) {
+ if (parent in elementMap)
+ delete elementMap[parent];
+ },
+
+ /**
+ * Adds new element into collection
+ * @param {String} name Element name
+ * @param {String} collection Collection name
+ */
+ addElementToCollection: function(name, collection) {
+ if (!elementTypes[collection])
+ elementTypes[collection] = [];
+
+ var col = this.getCollection(collection);
+ if (!_.include(col, name))
+ col.push(name);
+ },
+
+ /**
+ * Removes element name from specified collection
+ * @param {String} name Element name
+ * @param {String} collection Collection name
+ * @returns
+ */
+ removeElementFromCollection: function(name, collection) {
+ if (collection in elementTypes) {
+ elementTypes[collection] = _.without(this.getCollection(collection), name);
+ }
+ },
+
+ /**
+ * Returns elements name collection
+ * @param {String} name Collection name
+ * @returns {Array}
+ */
+ getCollection: function(name) {
+ return elementTypes[name];
+ }
+ };
+});/**
+ * Filter for aiding of writing elements with complex class names as described
+ * in Yandex's BEM (Block, Element, Modifier) methodology. This filter will
+ * automatically inherit block and element names from parent elements and insert
+ * them into child element classes
+ * @memberOf __bemFilterDefine
+ * @constructor
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ var prefs = require('preferences');
+ prefs.define('bem.elementSeparator', '__', 'Class name’s element separator.');
+ prefs.define('bem.modifierSeparator', '_', 'Class name’s modifier separator.');
+ prefs.define('bem.shortElementPrefix', '-',
+ 'Symbol for describing short “block-element” notation. Class names '
+ + 'prefixed with this symbol will be treated as element name for parent‘s '
+ + 'block name. Each symbol instance traverses one level up in parsed '
+ + 'tree for block name lookup. Empty value will disable short notation.');
+
+ var shouldRunHtmlFilter = false;
+
+ function getSeparators() {
+ return {
+ element: prefs.get('bem.elementSeparator'),
+ modifier: prefs.get('bem.modifierSeparator')
+ };
+ }
+
+ /**
+ * @param {AbbreviationNode} item
+ */
+ function bemParse(item) {
+ if (require('abbreviationUtils').isSnippet(item))
+ return item;
+
+ // save BEM stuff in cache for faster lookups
+ item.__bem = {
+ block: '',
+ element: '',
+ modifier: ''
+ };
+
+ var classNames = normalizeClassName(item.attribute('class')).split(' ');
+
+ // guess best match for block name
+ var reBlockName = /^[a-z]\-/i;
+ item.__bem.block = _.find(classNames, function(name) {
+ return reBlockName.test(name);
+ });
+
+ // guessing doesn't worked, pick first class name as block name
+ if (!item.__bem.block) {
+ reBlockName = /^[a-z]/i;
+ item.__bem.block = _.find(classNames, function(name) {
+ return reBlockName.test(name);
+ }) || '';
+ }
+
+ classNames = _.chain(classNames)
+ .map(function(name) {return processClassName(name, item);})
+ .flatten()
+ .uniq()
+ .value()
+ .join(' ');
+
+ if (classNames)
+ item.attribute('class', classNames);
+
+ return item;
+ }
+
+ /**
+ * @param {String} className
+ * @returns {String}
+ */
+ function normalizeClassName(className) {
+ var utils = require('utils');
+ className = (' ' + (className || '') + ' ').replace(/\s+/g, ' ');
+
+ var shortSymbol = prefs.get('bem.shortElementPrefix');
+ if (shortSymbol) {
+ var re = new RegExp('\\s(' + utils.escapeForRegexp(shortSymbol) + '+)', 'g');
+ className = className.replace(re, function(str, p1) {
+ return ' ' + utils.repeatString(getSeparators().element, p1.length);
+ });
+ }
+
+ return utils.trim(className);
+ }
+
+ /**
+ * Processes class name
+ * @param {String} name Class name item to process
+ * @param {AbbreviationNode} item Host node for provided class name
+ * @returns Processed class name. May return Array of
+ * class names
+ */
+ function processClassName(name, item) {
+ name = transformClassName(name, item, 'element');
+ name = transformClassName(name, item, 'modifier');
+
+ // expand class name
+ // possible values:
+ // * block__element
+ // * block__element_modifier
+ // * block__element_modifier1_modifier2
+ // * block_modifier
+ var block = '', element = '', modifier = '';
+ var separators = getSeparators();
+ if (~name.indexOf(separators.element)) {
+ var blockElem = name.split(separators.element);
+ var elemModifiers = blockElem[1].split(separators.modifier);
+
+ block = blockElem[0];
+ element = elemModifiers.shift();
+ modifier = elemModifiers.join(separators.modifier);
+ } else if (~name.indexOf(separators.modifier)) {
+ var blockModifiers = name.split(separators.modifier);
+
+ block = blockModifiers.shift();
+ modifier = blockModifiers.join(separators.modifier);
+ }
+
+ if (block || element || modifier) {
+ if (!block) {
+ block = item.__bem.block;
+ }
+
+ // inherit parent bem element, if exists
+// if (item.parent && item.parent.__bem && item.parent.__bem.element)
+// element = item.parent.__bem.element + separators.element + element;
+
+ // produce multiple classes
+ var prefix = block;
+ var result = [];
+
+ if (element) {
+ prefix += separators.element + element;
+ result.push(prefix);
+ } else {
+ result.push(prefix);
+ }
+
+ if (modifier) {
+ result.push(prefix + separators.modifier + modifier);
+ }
+
+ item.__bem.block = block;
+ item.__bem.element = element;
+ item.__bem.modifier = modifier;
+
+ return result;
+ }
+
+ // ...otherwise, return processed or original class name
+ return name;
+ }
+
+ /**
+ * Low-level function to transform user-typed class name into full BEM class
+ * @param {String} name Class name item to process
+ * @param {AbbreviationNode} item Host node for provided class name
+ * @param {String} entityType Type of entity to be tried to transform
+ * ('element' or 'modifier')
+ * @returns {String} Processed class name or original one if it can't be
+ * transformed
+ */
+ function transformClassName(name, item, entityType) {
+ var separators = getSeparators();
+ var reSep = new RegExp('^(' + separators[entityType] + ')+', 'g');
+ if (reSep.test(name)) {
+ var depth = 0; // parent lookup depth
+ var cleanName = name.replace(reSep, function(str, p1) {
+ depth = str.length / separators[entityType].length;
+ return '';
+ });
+
+ // find donor element
+ var donor = item;
+ while (donor.parent && depth--) {
+ donor = donor.parent;
+ }
+
+ if (!donor || !donor.__bem)
+ donor = item;
+
+ if (donor && donor.__bem) {
+ var prefix = donor.__bem.block;
+
+ // decide if we should inherit element name
+// if (entityType == 'element') {
+// var curElem = cleanName.split(separators.modifier, 1)[0];
+// if (donor.__bem.element && donor.__bem.element != curElem)
+// prefix += separators.element + donor.__bem.element;
+// }
+
+ if (entityType == 'modifier' && donor.__bem.element)
+ prefix += separators.element + donor.__bem.element;
+
+ return prefix + separators[entityType] + cleanName;
+ }
+ }
+
+ return name;
+ }
+
+ /**
+ * Recursive function for processing tags, which extends class names
+ * according to BEM specs: http://bem.github.com/bem-method/pages/beginning/beginning.ru.html
+ *
+ * It does several things:
+ *
+ * Expands complex class name (according to BEM symbol semantics):
+ * .block__elem_modifier → .block.block__elem.block__elem_modifier
+ *
+ * Inherits block name on child elements:
+ * .b-block > .__el > .__el → .b-block > .b-block__el > .b-block__el__el
+ *
+ * Treats first dash symbol as '__'
+ * Double underscore (or typographic '–') is also treated as an element
+ * level lookup, e.g. ____el will search for element definition in parent’s
+ * parent element:
+ * .b-block > .__el1 > .____el2 → .b-block > .b-block__el1 > .b-block__el2
+ *
+ *
+ *
+ * @param {AbbreviationNode} tree
+ * @param {Object} profile
+ */
+ function process(tree, profile) {
+ if (tree.name)
+ bemParse(tree, profile);
+
+ var abbrUtils = require('abbreviationUtils');
+ _.each(tree.children, function(item) {
+ process(item, profile);
+ if (!abbrUtils.isSnippet(item) && item.start)
+ shouldRunHtmlFilter = true;
+ });
+
+ return tree;
+ };
+
+ require('filters').add('bem', function(tree, profile) {
+ shouldRunHtmlFilter = false;
+ tree = process(tree, profile);
+ // in case 'bem' filter is applied after 'html' filter: run it again
+ // to update output
+ if (shouldRunHtmlFilter) {
+ tree = require('filters').apply(tree, 'html', profile);
+ }
+
+ return tree;
+ });
+});
+
+/**
+ * Comment important tags (with 'id' and 'class' attributes)
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ * @constructor
+ * @memberOf __commentFilterDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ // define some preferences
+ /** @type emmet.preferences */
+ var prefs = require('preferences');
+
+ prefs.define('filter.commentAfter',
+ '\n',
+ 'A definition of comment that should be placed after matched '
+ + 'element when comment filter is applied. This definition '
+ + 'is an ERB-style template passed to _.template() '
+ + 'function (see Underscore.js docs for details). In template context, '
+ + 'the following properties and functions are availabe:\n'
+ + ''
+
+ + 'attr(name, before, after) – a function that outputs'
+ + 'specified attribute value concatenated with before '
+ + 'and after strings. If attribute doesn\'t exists, the '
+ + 'empty string will be returned. '
+
+ + 'node – current node (instance of AbbreviationNode) '
+
+ + 'name – name of current tag '
+
+ + 'padding – current string padding, can be used '
+ + 'for formatting '
+
+ +' ');
+
+ prefs.define('filter.commentBefore',
+ '',
+ 'A definition of comment that should be placed before matched '
+ + 'element when comment filter is applied. '
+ + 'For more info, read description of filter.commentAfter '
+ + 'property');
+
+ prefs.define('filter.commentTrigger', 'id, class',
+ 'A comma-separated list of attribute names that should exist in abbreviatoin '
+ + 'where comment should be added. If you wish to add comment for '
+ + 'every element, set this option to *');
+
+ /**
+ * Add comments to tag
+ * @param {AbbreviationNode} node
+ */
+ function addComments(node, templateBefore, templateAfter) {
+ var utils = require('utils');
+
+ // check if comments should be added
+ var trigger = prefs.get('filter.commentTrigger');
+ if (trigger != '*') {
+ var shouldAdd = _.find(trigger.split(','), function(name) {
+ return !!node.attribute(utils.trim(name));
+ });
+ if (!shouldAdd) return;
+ }
+
+ var ctx = {
+ node: node,
+ name: node.name(),
+ padding: node.parent ? node.parent.padding : '',
+ attr: function(name, before, after) {
+ var attr = node.attribute(name);
+ if (attr) {
+ return (before || '') + attr + (after || '');
+ }
+
+ return '';
+ }
+ };
+
+ var nodeBefore = utils.normalizeNewline(templateBefore ? templateBefore(ctx) : '');
+ var nodeAfter = utils.normalizeNewline(templateAfter ? templateAfter(ctx) : '');
+
+ node.start = node.start.replace(/, nodeBefore + '<');
+ node.end = node.end.replace(/>/, '>' + nodeAfter);
+ }
+
+ function process(tree, before, after) {
+ var abbrUtils = require('abbreviationUtils');
+ _.each(tree.children, function(item) {
+ if (abbrUtils.isBlock(item))
+ addComments(item, before, after);
+
+ process(item, before, after);
+ });
+
+ return tree;
+ }
+
+ require('filters').add('c', function(tree) {
+ var templateBefore = _.template(prefs.get('filter.commentBefore'));
+ var templateAfter = _.template(prefs.get('filter.commentAfter'));
+
+ return process(tree, templateBefore, templateAfter);
+ });
+});
+/**
+ * Filter for escaping unsafe XML characters: <, >, &
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ */
+emmet.exec(function(require, _) {
+ var charMap = {
+ '<': '<',
+ '>': '>',
+ '&': '&'
+ };
+
+ function escapeChars(str) {
+ return str.replace(/([<>&])/g, function(str, p1){
+ return charMap[p1];
+ });
+ }
+
+ require('filters').add('e', function process(tree) {
+ _.each(tree.children, function(item) {
+ item.start = escapeChars(item.start);
+ item.end = escapeChars(item.end);
+ item.content = escapeChars(item.content);
+ process(item);
+ });
+
+ return tree;
+ });
+});/**
+ * Generic formatting filter: creates proper indentation for each tree node,
+ * placing "%s" placeholder where the actual output should be. You can use
+ * this filter to preformat tree and then replace %s placeholder to whatever you
+ * need. This filter should't be called directly from editor as a part
+ * of abbreviation.
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ * @constructor
+ * @memberOf __formatFilterDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _){
+ var placeholder = '%s';
+
+ /** @type preferences */
+ var prefs = require('preferences');
+ prefs.define('format.noIndentTags', 'html',
+ 'A comma-separated list of tag names that should not get inner indentation.');
+
+ prefs.define('format.forceIndentationForTags', 'body',
+ 'A comma-separated list of tag names that should always get inner indentation.');
+
+ /**
+ * Get indentation for given node
+ * @param {AbbreviationNode} node
+ * @returns {String}
+ */
+ function getIndentation(node) {
+ if (_.include(prefs.getArray('format.noIndentTags') || [], node.name())) {
+ return '';
+ }
+
+ return require('resources').getVariable('indentation');
+ }
+
+ /**
+ * Test if passed node has block-level sibling element
+ * @param {AbbreviationNode} item
+ * @return {Boolean}
+ */
+ function hasBlockSibling(item) {
+ return item.parent && require('abbreviationUtils').hasBlockChildren(item.parent);
+ }
+
+ /**
+ * Test if passed item is very first child in parsed tree
+ * @param {AbbreviationNode} item
+ */
+ function isVeryFirstChild(item) {
+ return item.parent && !item.parent.parent && !item.index();
+ }
+
+ /**
+ * Check if a newline should be added before element
+ * @param {AbbreviationNode} node
+ * @param {OutputProfile} profile
+ * @return {Boolean}
+ */
+ function shouldAddLineBreak(node, profile) {
+ var abbrUtils = require('abbreviationUtils');
+ if (profile.tag_nl === true || abbrUtils.isBlock(node))
+ return true;
+
+ if (!node.parent || !profile.inline_break)
+ return false;
+
+ // check if there are required amount of adjacent inline element
+ return shouldFormatInline(node.parent, profile);
+}
+
+ /**
+ * Need to add newline because item has too many inline children
+ * @param {AbbreviationNode} node
+ * @param {OutputProfile} profile
+ */
+ function shouldBreakChild(node, profile) {
+ // we need to test only one child element, because
+ // hasBlockChildren() method will do the rest
+ return node.children.length && shouldAddLineBreak(node.children[0], profile);
+ }
+
+ function shouldFormatInline(node, profile) {
+ var nodeCount = 0;
+ var abbrUtils = require('abbreviationUtils');
+ return !!_.find(node.children, function(child) {
+ if (child.isTextNode() || !abbrUtils.isInline(child))
+ nodeCount = 0;
+ else if (abbrUtils.isInline(child))
+ nodeCount++;
+
+ if (nodeCount >= profile.inline_break)
+ return true;
+ });
+ }
+
+ function isRoot(item) {
+ return !item.parent;
+ }
+
+ /**
+ * Processes element with matched resource of type snippet
+ * @param {AbbreviationNode} item
+ * @param {OutputProfile} profile
+ * @param {Number} level Depth level
+ */
+ function processSnippet(item, profile, level) {
+ item.start = item.end = '';
+ if (!isVeryFirstChild(item) && profile.tag_nl !== false && shouldAddLineBreak(item, profile)) {
+ // check if we’re not inside inline element
+ if (isRoot(item.parent) || !require('abbreviationUtils').isInline(item.parent)) {
+ item.start = require('utils').getNewline() + item.start;
+ }
+ }
+
+ return item;
+ }
+
+ /**
+ * Check if we should add line breaks inside inline element
+ * @param {AbbreviationNode} node
+ * @param {OutputProfile} profile
+ * @return {Boolean}
+ */
+ function shouldBreakInsideInline(node, profile) {
+ var abbrUtils = require('abbreviationUtils');
+ var hasBlockElems = _.any(node.children, function(child) {
+ if (abbrUtils.isSnippet(child))
+ return false;
+
+ return !abbrUtils.isInline(child);
+ });
+
+ if (!hasBlockElems) {
+ return shouldFormatInline(node, profile);
+ }
+
+ return true;
+ }
+
+ /**
+ * Processes element with tag type
+ * @param {AbbreviationNode} item
+ * @param {OutputProfile} profile
+ * @param {Number} level Depth level
+ */
+ function processTag(item, profile, level) {
+ item.start = item.end = placeholder;
+ var utils = require('utils');
+ var abbrUtils = require('abbreviationUtils');
+ var isUnary = abbrUtils.isUnary(item);
+ var nl = utils.getNewline();
+ var indent = getIndentation(item);
+
+ // formatting output
+ if (profile.tag_nl !== false) {
+ var forceNl = profile.tag_nl === true && (profile.tag_nl_leaf || item.children.length);
+ if (!forceNl) {
+ forceNl = _.include(prefs.getArray('format.forceIndentationForTags') || [], item.name());
+ }
+
+ // formatting block-level elements
+ if (!item.isTextNode()) {
+ if (shouldAddLineBreak(item, profile)) {
+ // - do not indent the very first element
+ // - do not indent first child of a snippet
+ if (!isVeryFirstChild(item) && (!abbrUtils.isSnippet(item.parent) || item.index()))
+ item.start = nl + item.start;
+
+ if (abbrUtils.hasBlockChildren(item) || shouldBreakChild(item, profile) || (forceNl && !isUnary))
+ item.end = nl + item.end;
+
+ if (abbrUtils.hasTagsInContent(item) || (forceNl && !item.children.length && !isUnary))
+ item.start += nl + indent;
+ } else if (abbrUtils.isInline(item) && hasBlockSibling(item) && !isVeryFirstChild(item)) {
+ item.start = nl + item.start;
+ } else if (abbrUtils.isInline(item) && shouldBreakInsideInline(item, profile)) {
+ item.end = nl + item.end;
+ }
+
+ item.padding = indent;
+ }
+ }
+
+ return item;
+ }
+
+ /**
+ * Processes simplified tree, making it suitable for output as HTML structure
+ * @param {AbbreviationNode} tree
+ * @param {OutputProfile} profile
+ * @param {Number} level Depth level
+ */
+ require('filters').add('_format', function process(tree, profile, level) {
+ level = level || 0;
+ var abbrUtils = require('abbreviationUtils');
+
+ _.each(tree.children, function(item) {
+ if (abbrUtils.isSnippet(item))
+ processSnippet(item, profile, level);
+ else
+ processTag(item, profile, level);
+
+ process(item, profile, level + 1);
+ });
+
+ return tree;
+ });
+});/**
+ * Filter for producing HAML code from abbreviation.
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ * @constructor
+ * @memberOf __hamlFilterDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ var childToken = '${child}';
+
+ function transformClassName(className) {
+ return require('utils').trim(className).replace(/\s+/g, '.');
+ }
+
+ /**
+ * Creates HAML attributes string from tag according to profile settings
+ * @param {AbbreviationNode} tag
+ * @param {Object} profile
+ */
+ function makeAttributesString(tag, profile) {
+ var attrs = '';
+ var otherAttrs = [];
+ var attrQuote = profile.attributeQuote();
+ var cursor = profile.cursor();
+
+ _.each(tag.attributeList(), function(a) {
+ var attrName = profile.attributeName(a.name);
+ switch (attrName.toLowerCase()) {
+ // use short notation for ID and CLASS attributes
+ case 'id':
+ attrs += '#' + (a.value || cursor);
+ break;
+ case 'class':
+ attrs += '.' + transformClassName(a.value || cursor);
+ break;
+ // process other attributes
+ default:
+ otherAttrs.push(':' +attrName + ' => ' + attrQuote + (a.value || cursor) + attrQuote);
+ }
+ });
+
+ if (otherAttrs.length)
+ attrs += '{' + otherAttrs.join(', ') + '}';
+
+ return attrs;
+ }
+
+ /**
+ * Test if passed node has block-level sibling element
+ * @param {AbbreviationNode} item
+ * @return {Boolean}
+ */
+ function hasBlockSibling(item) {
+ return item.parent && item.parent.hasBlockChildren();
+ }
+
+ /**
+ * Processes element with tag type
+ * @param {AbbreviationNode} item
+ * @param {OutputProfile} profile
+ * @param {Number} level Depth level
+ */
+ function processTag(item, profile, level) {
+ if (!item.parent)
+ // looks like it's root element
+ return item;
+
+ var abbrUtils = require('abbreviationUtils');
+ var utils = require('utils');
+
+ var attrs = makeAttributesString(item, profile);
+ var cursor = profile.cursor();
+ var isUnary = abbrUtils.isUnary(item);
+ var selfClosing = profile.self_closing_tag && isUnary ? '/' : '';
+ var start= '';
+
+ // define tag name
+ var tagName = '%' + profile.tagName(item.name());
+ if (tagName.toLowerCase() == '%div' && attrs && attrs.indexOf('{') == -1)
+ // omit div tag
+ tagName = '';
+
+ item.end = '';
+ start = tagName + attrs + selfClosing + ' ';
+
+ var placeholder = '%s';
+ // We can't just replace placeholder with new value because
+ // JavaScript will treat double $ character as a single one, assuming
+ // we're using RegExp literal.
+ item.start = utils.replaceSubstring(item.start, start, item.start.indexOf(placeholder), placeholder);
+
+ if (!item.children.length && !isUnary)
+ item.start += cursor;
+
+ return item;
+ }
+
+ /**
+ * Processes simplified tree, making it suitable for output as HTML structure
+ * @param {AbbreviationNode} tree
+ * @param {Object} profile
+ * @param {Number} level Depth level
+ */
+ require('filters').add('haml', function process(tree, profile, level) {
+ level = level || 0;
+ var abbrUtils = require('abbreviationUtils');
+
+ if (!level) {
+ tree = require('filters').apply(tree, '_format', profile);
+ }
+
+ _.each(tree.children, function(item) {
+ if (!abbrUtils.isSnippet(item))
+ processTag(item, profile, level);
+
+ process(item, profile, level + 1);
+ });
+
+ return tree;
+ });
+});/**
+ * Filter that produces HTML tree
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ * @constructor
+ * @memberOf __htmlFilterDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ /**
+ * Creates HTML attributes string from tag according to profile settings
+ * @param {AbbreviationNode} node
+ * @param {OutputProfile} profile
+ */
+ function makeAttributesString(node, profile) {
+ var attrQuote = profile.attributeQuote();
+ var cursor = profile.cursor();
+
+ return _.map(node.attributeList(), function(a) {
+ var attrName = profile.attributeName(a.name);
+ return ' ' + attrName + '=' + attrQuote + (a.value || cursor) + attrQuote;
+ }).join('');
+ }
+
+ /**
+ * Processes element with tag type
+ * @param {AbbreviationNode} item
+ * @param {OutputProfile} profile
+ * @param {Number} level Depth level
+ */
+ function processTag(item, profile, level) {
+ if (!item.parent) // looks like it's root element
+ return item;
+
+ var abbrUtils = require('abbreviationUtils');
+ var utils = require('utils');
+
+ var attrs = makeAttributesString(item, profile);
+ var cursor = profile.cursor();
+ var isUnary = abbrUtils.isUnary(item);
+ var start= '';
+ var end = '';
+
+ // define opening and closing tags
+ if (!item.isTextNode()) {
+ var tagName = profile.tagName(item.name());
+ if (isUnary) {
+ start = '<' + tagName + attrs + profile.selfClosing() + '>';
+ item.end = '';
+ } else {
+ start = '<' + tagName + attrs + '>';
+ end = '' + tagName + '>';
+ }
+ }
+
+ var placeholder = '%s';
+ // We can't just replace placeholder with new value because
+ // JavaScript will treat double $ character as a single one, assuming
+ // we're using RegExp literal.
+ item.start = utils.replaceSubstring(item.start, start, item.start.indexOf(placeholder), placeholder);
+ item.end = utils.replaceSubstring(item.end, end, item.end.indexOf(placeholder), placeholder);
+
+ // should we put caret placeholder after opening tag?
+ if (
+ !item.children.length
+ && !isUnary
+ && !~item.content.indexOf(cursor)
+ && !require('tabStops').extract(item.content).tabstops.length
+ ) {
+ item.start += cursor;
+ }
+
+ return item;
+ }
+
+ /**
+ * Processes simplified tree, making it suitable for output as HTML structure
+ * @param {AbbreviationNode} tree
+ * @param {Object} profile
+ * @param {Number} level Depth level
+ */
+ require('filters').add('html', function process(tree, profile, level) {
+ level = level || 0;
+ var abbrUtils = require('abbreviationUtils');
+
+ if (!level) {
+ tree = require('filters').apply(tree, '_format', profile);
+ }
+
+ _.each(tree.children, function(item) {
+ if (!abbrUtils.isSnippet(item))
+ processTag(item, profile, level);
+
+ process(item, profile, level + 1);
+ });
+
+ return tree;
+ });
+});/**
+ * Output abbreviation on a single line (i.e. no line breaks)
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ * @constructor
+ * @memberOf __singleLineFilterDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ var rePad = /^\s+/;
+ var reNl = /[\n\r]/g;
+
+ require('filters').add('s', function process(tree, profile, level) {
+ var abbrUtils = require('abbreviationUtils');
+
+ _.each(tree.children, function(item) {
+ if (!abbrUtils.isSnippet(item)) {
+ // remove padding from item
+ item.start = item.start.replace(rePad, '');
+ item.end = item.end.replace(rePad, '');
+ }
+
+ // remove newlines
+ item.start = item.start.replace(reNl, '');
+ item.end = item.end.replace(reNl, '');
+ item.content = item.content.replace(reNl, '');
+
+ process(item);
+ });
+
+ return tree;
+ });
+});
+/**
+ * Trim filter: removes characters at the beginning of the text
+ * content that indicates lists: numbers, #, *, -, etc.
+ *
+ * Useful for wrapping lists with abbreviation.
+ *
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ *
+ * @constructor
+ * @memberOf __trimFilterDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ require('preferences').define('filter.trimRegexp', '[\\s|\\u00a0]*[\\d|#|\\-|\*|\\u2022]+\\.?\\s*',
+ 'Regular expression used to remove list markers (numbers, dashes, '
+ + 'bullets, etc.) in t (trim) filter. The trim filter '
+ + 'is useful for wrapping with abbreviation lists, pased from other '
+ + 'documents (for example, Word documents).');
+
+ function process(tree, re) {
+ _.each(tree.children, function(item) {
+ if (item.content)
+ item.content = item.content.replace(re, '');
+
+ process(item, re);
+ });
+
+ return tree;
+ }
+
+ require('filters').add('t', function(tree) {
+ var re = new RegExp(require('preferences').get('filter.trimRegexp'));
+ return process(tree, re);
+ });
+});
+/**
+ * Filter for trimming "select" attributes from some tags that contains
+ * child elements
+ * @author Sergey Chikuyonok (serge.che@gmail.com)
+ * @link http://chikuyonok.ru
+ *
+ * @constructor
+ * @memberOf __xslFilterDefine
+ * @param {Function} require
+ * @param {Underscore} _
+ */
+emmet.exec(function(require, _) {
+ var tags = {
+ 'xsl:variable': 1,
+ 'xsl:with-param': 1
+ };
+
+ /**
+ * Removes "select" attribute from node
+ * @param {AbbreviationNode} node
+ */
+ function trimAttribute(node) {
+ node.start = node.start.replace(/\s+select\s*=\s*(['"]).*?\1/, '');
+ }
+
+ require('filters').add('xsl', function process(tree) {
+ var abbrUtils = require('abbreviationUtils');
+ _.each(tree.children, function(item) {
+ if (!abbrUtils.isSnippet(item)
+ && (item.name() || '').toLowerCase() in tags
+ && item.children.length)
+ trimAttribute(item);
+ process(item);
+ });
+
+ return tree;
+ });
+});/**
+ * "Lorem ipsum" text generator. Matches lipsum(num)? or
+ * lorem(num)? abbreviation.
+ * This code is based on Django's contribution:
+ * https://code.djangoproject.com/browser/django/trunk/django/contrib/webdesign/lorem_ipsum.py
+ *
+ * Examples to test:
+ * lipsum – generates 30 words text.
+ * lipsum*6 – generates 6 paragraphs (autowrapped with <p> element) of text.
+ * ol>lipsum10*5 — generates ordered list with 5 list items (autowrapped with <li> tag)
+ * with text of 10 words on each line
+ * span*3>lipsum20 – generates 3 paragraphs of 20-words text, each wrapped with <span> element .
+ * Each paragraph phrase is unique
+ * @param {Function} require
+ * @param {Underscore} _
+ * @constructor
+ * @memberOf __loremIpsumGeneratorDefine
+ */
+emmet.exec(function(require, _) {
+ /**
+ * @param {AbbreviationNode} tree
+ * @param {Object} options
+ */
+ require('abbreviationParser').addPreprocessor(function(tree, options) {
+ var re = /^(?:lorem|lipsum)(\d*)$/i, match;
+
+ /** @param {AbbreviationNode} node */
+ tree.findAll(function(node) {
+ if (node._name && (match = node._name.match(re))) {
+ var wordCound = match[1] || 30;
+
+ // force node name resolving if node should be repeated
+ // or contains attributes. In this case, node should be outputed
+ // as tag, otherwise as text-only node
+ node._name = '';
+ node.data('forceNameResolving', node.isRepeating() || node.attributeList().length);
+ node.data('pasteOverwrites', true);
+ node.data('paste', function(i, content) {
+ return paragraph(wordCound, !i);
+ });
+ }
+ });
+ });
+
+ var COMMON_P = 'lorem ipsum dolor sit amet consectetur adipisicing elit'.split(' ');
+
+ var WORDS = ['exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet',
+ 'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi',
+ 'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi',
+ 'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos',
+ 'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum',
+ 'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus',
+ 'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus',
+ 'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum',
+ 'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem',
+ 'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus',
+ 'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente',
+ 'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet',
+ 'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta',
+ 'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima',
+ 'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim',
+ 'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores',
+ 'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias',
+ 'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea',
+ 'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt',
+ 'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate',
+ 'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius',
+ 'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos',
+ 'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore',
+ 'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo',
+ 'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi',
+ 'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam',
+ 'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique',
+ 'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere',
+ 'maxime', 'corrupti'];
+
+ /**
+ * Returns random integer between from and to values
+ * @param {Number} from
+ * @param {Number} to
+ * @returns {Number}
+ */
+ function randint(from, to) {
+ return Math.round(Math.random() * (to - from) + from);
+ }
+
+ /**
+ * @param {Array} arr
+ * @param {Number} count
+ * @returns {Array}
+ */
+ function sample(arr, count) {
+ var len = arr.length;
+ var iterations = Math.min(len, count);
+ var result = [];
+ while (result.length < iterations) {
+ var randIx = randint(0, len - 1);
+ if (!_.include(result, randIx))
+ result.push(randIx);
+ }
+
+ return _.map(result, function(ix) {
+ return arr[ix];
+ });
+ }
+
+ function choice(val) {
+ if (_.isString(val))
+ return val.charAt(randint(0, val.length - 1));
+
+ return val[randint(0, val.length - 1)];
+ }
+
+ function sentence(words, end) {
+ if (words.length) {
+ words[0] = words[0].charAt(0).toUpperCase() + words[0].substring(1);
+ }
+
+ return words.join(' ') + (end || choice('?!...')); // more dots that question marks
+ }
+
+ /**
+ * Insert commas at randomly selected words. This function modifies values
+ * inside words array
+ * @param {Array} words
+ */
+ function insertCommas(words) {
+ var len = words.length;
+ var totalCommas = 0;
+
+ if (len > 3 && len <= 6) {
+ totalCommas = randint(0, 1);
+ } else if (len > 6 && len <= 12) {
+ totalCommas = randint(0, 2);
+ } else {
+ totalCommas = randint(1, 4);
+ }
+
+ _.each(sample(_.range(totalCommas)), function(ix) {
+ words[ix] += ',';
+ });
+ }
+
+ /**
+ * Generate a paragraph of "Lorem ipsum" text
+ * @param {Number} wordCount Words count in paragraph
+ * @param {Boolean} startWithCommon Should paragraph start with common
+ * "lorem ipsum" sentence.
+ * @returns {String}
+ */
+ function paragraph(wordCount, startWithCommon) {
+ var result = [];
+ var totalWords = 0;
+ var words;
+
+ wordCount = parseInt(wordCount, 10);
+
+ if (startWithCommon) {
+ words = COMMON_P.slice(0, wordCount);
+ if (words.length > 5)
+ words[4] += ',';
+ totalWords += words.length;
+ result.push(sentence(words, '.'));
+ }
+
+ while (totalWords < wordCount) {
+ words = sample(WORDS, Math.min(randint(3, 12) * randint(1, 5), wordCount - totalWords));
+ totalWords += words.length;
+ insertCommas(words);
+ result.push(sentence(words));
+ }
+
+ return result.join(' ');
+ }
+});/**
+ * Select current line (for simple editors like browser's <textarea>)
+ */
+emmet.exec(function(require, _) {
+ require('actions').add('select_line', function(editor) {
+ var range = editor.getCurrentLineRange();
+ editor.createSelection(range.start, range.end);
+ return true;
+ });
+});emmet.exec(function(require, _){require('resources').setVocabulary({
+ "variables": {
+ "lang": "en",
+ "locale": "en-US",
+ "charset": "UTF-8",
+ "indentation": "\t",
+ "newline": "\n"
+ },
+
+ "css": {
+ "filters": "html",
+ "snippets": {
+ "@i": "@import url(|);",
+ "@import": "@import url(|);",
+ "@m": "@media ${1:screen} {\n\t|\n}",
+ "@media": "@media ${1:screen} {\n\t|\n}",
+ "@f": "@font-face {\n\tfont-family:|;\n\tsrc:url(|);\n}",
+ "@f+": "@font-face {\n\tfont-family: '${1:FontName}';\n\tsrc: url('${2:FileName}.eot');\n\tsrc: url('${2:FileName}.eot?#iefix') format('embedded-opentype'),\n\t\t url('${2:FileName}.woff') format('woff'),\n\t\t url('${2:FileName}.ttf') format('truetype'),\n\t\t url('${2:FileName}.svg#${1:FontName}') format('svg');\n\tfont-style: ${3:normal};\n\tfont-weight: ${4:normal};\n}",
+
+ "@kf": "@-webkit-keyframes ${1:identifier} {\n\t${2:from} { ${3} }${6}\n\t${4:to} { ${5} }\n}\n@-o-keyframes ${1:identifier} {\n\t${2:from} { ${3} }${6}\n\t${4:to} { ${5} }\n}\n@-moz-keyframes ${1:identifier} {\n\t${2:from} { ${3} }${6}\n\t${4:to} { ${5} }\n}\n@keyframes ${1:identifier} {\n\t${2:from} { ${3} }${6}\n\t${4:to} { ${5} }\n}",
+
+
+ "anim": "animation:|;",
+ "anim-": "animation:${1:name} ${2:duration} ${3:timing-function} ${4:delay} ${5:iteration-count} ${6:direction} ${7:fill-mode};",
+ "animdel": "animation-delay:${1:time};",
+
+ "animdir": "animation-direction:${1:normal};",
+ "animdir:n": "animation-direction:normal;",
+ "animdir:r": "animation-direction:reverse;",
+ "animdir:a": "animation-direction:alternate;",
+ "animdir:ar": "animation-direction:alternate-reverse;",
+
+ "animdur": "animation-duration:${1:0}s;",
+
+ "animfm": "animation-fill-mode:${1:both};",
+ "animfm:f": "animation-fill-mode:forwards;",
+ "animfm:b": "animation-fill-mode:backwards;",
+ "animfm:bt": "animation-fill-mode:both;",
+ "animfm:bh": "animation-fill-mode:both;",
+
+ "animic": "animation-iteration-count:${1:1};",
+ "animic:i": "animation-iteration-count:infinite;",
+
+ "animn": "animation-name:${1:none};",
+
+ "animps": "animation-play-state:${1:running};",
+ "animps:p": "animation-play-state:paused;",
+ "animps:r": "animation-play-state:running;",
+
+ "animtf": "animation-timing-function:${1:linear};",
+ "animtf:e": "animation-timing-function:ease;",
+ "animtf:ei": "animation-timing-function:ease-in;",
+ "animtf:eo": "animation-timing-function:ease-out;",
+ "animtf:eio": "animation-timing-function:ease-in-out;",
+ "animtf:l": "animation-timing-function:linear;",
+ "animtf:cb": "animation-timing-function:cubic-bezier(${1:0.1}, ${2:0.7}, ${3:1.0}, ${3:0.1});",
+
+ "ap": "appearance:${none}",
+
+ "!": "!important",
+ "pos": "position:${1:relative};",
+ "pos:s": "position:static;",
+ "pos:a": "position:absolute;",
+ "pos:r": "position:relative;",
+ "pos:f": "position:fixed;",
+ "t": "top:|;",
+ "t:a": "top:auto;",
+ "r": "right:|;",
+ "r:a": "right:auto;",
+ "b": "bottom:|;",
+ "b:a": "bottom:auto;",
+ "l": "left:|;",
+ "l:a": "left:auto;",
+ "z": "z-index:|;",
+ "z:a": "z-index:auto;",
+ "fl": "float:${1:left};",
+ "fl:n": "float:none;",
+ "fl:l": "float:left;",
+ "fl:r": "float:right;",
+ "cl": "clear:${1:both};",
+ "cl:n": "clear:none;",
+ "cl:l": "clear:left;",
+ "cl:r": "clear:right;",
+ "cl:b": "clear:both;",
+
+ "colm": "columns:|;",
+ "colmc": "column-count:|;",
+ "colmf": "column-fill:|;",
+ "colmg": "column-gap:|;",
+ "colmr": "column-rule:|;",
+ "colmrc": "column-rule-color:|;",
+ "colmrs": "column-rule-style:|;",
+ "colmrw": "column-rule-width:|;",
+ "colms": "column-span:|;",
+ "colmw": "column-width:|;",
+
+ "d": "display:${1:block};",
+ "d:n": "display:none;",
+ "d:b": "display:block;",
+ "d:i": "display:inline;",
+ "d:ib": "display:inline-block;",
+ "d:li": "display:list-item;",
+ "d:ri": "display:run-in;",
+ "d:cp": "display:compact;",
+ "d:tb": "display:table;",
+ "d:itb": "display:inline-table;",
+ "d:tbcp": "display:table-caption;",
+ "d:tbcl": "display:table-column;",
+ "d:tbclg": "display:table-column-group;",
+ "d:tbhg": "display:table-header-group;",
+ "d:tbfg": "display:table-footer-group;",
+ "d:tbr": "display:table-row;",
+ "d:tbrg": "display:table-row-group;",
+ "d:tbc": "display:table-cell;",
+ "d:rb": "display:ruby;",
+ "d:rbb": "display:ruby-base;",
+ "d:rbbg": "display:ruby-base-group;",
+ "d:rbt": "display:ruby-text;",
+ "d:rbtg": "display:ruby-text-group;",
+ "v": "visibility:${1:hidden};",
+ "v:v": "visibility:visible;",
+ "v:h": "visibility:hidden;",
+ "v:c": "visibility:collapse;",
+ "ov": "overflow:${1:hidden};",
+ "ov:v": "overflow:visible;",
+ "ov:h": "overflow:hidden;",
+ "ov:s": "overflow:scroll;",
+ "ov:a": "overflow:auto;",
+ "ovx": "overflow-x:${1:hidden};",
+ "ovx:v": "overflow-x:visible;",
+ "ovx:h": "overflow-x:hidden;",
+ "ovx:s": "overflow-x:scroll;",
+ "ovx:a": "overflow-x:auto;",
+ "ovy": "overflow-y:${1:hidden};",
+ "ovy:v": "overflow-y:visible;",
+ "ovy:h": "overflow-y:hidden;",
+ "ovy:s": "overflow-y:scroll;",
+ "ovy:a": "overflow-y:auto;",
+ "ovs": "overflow-style:${1:scrollbar};",
+ "ovs:a": "overflow-style:auto;",
+ "ovs:s": "overflow-style:scrollbar;",
+ "ovs:p": "overflow-style:panner;",
+ "ovs:m": "overflow-style:move;",
+ "ovs:mq": "overflow-style:marquee;",
+ "zoo": "zoom:1;",
+ "zm": "zoom:1;",
+ "cp": "clip:|;",
+ "cp:a": "clip:auto;",
+ "cp:r": "clip:rect(${1:top} ${2:right} ${3:bottom} ${4:left});",
+ "bxz": "box-sizing:${1:border-box};",
+ "bxz:cb": "box-sizing:content-box;",
+ "bxz:bb": "box-sizing:border-box;",
+ "bxsh": "box-shadow:${1:inset }${2:hoff} ${3:voff} ${4:blur} ${5:color};",
+ "bxsh:r": "box-shadow:${1:inset }${2:hoff} ${3:voff} ${4:blur} ${5:spread }rgb(${6:0}, ${7:0}, ${8:0});",
+ "bxsh:ra": "box-shadow:${1:inset }${2:h} ${3:v} ${4:blur} ${5:spread }rgba(${6:0}, ${7:0}, ${8:0}, .${9:5});",
+ "bxsh:n": "box-shadow:none;",
+ "m": "margin:|;",
+ "m:a": "margin:auto;",
+ "mt": "margin-top:|;",
+ "mt:a": "margin-top:auto;",
+ "mr": "margin-right:|;",
+ "mr:a": "margin-right:auto;",
+ "mb": "margin-bottom:|;",
+ "mb:a": "margin-bottom:auto;",
+ "ml": "margin-left:|;",
+ "ml:a": "margin-left:auto;",
+ "p": "padding:|;",
+ "pt": "padding-top:|;",
+ "pr": "padding-right:|;",
+ "pb": "padding-bottom:|;",
+ "pl": "padding-left:|;",
+ "w": "width:|;",
+ "w:a": "width:auto;",
+ "h": "height:|;",
+ "h:a": "height:auto;",
+ "maw": "max-width:|;",
+ "maw:n": "max-width:none;",
+ "mah": "max-height:|;",
+ "mah:n": "max-height:none;",
+ "miw": "min-width:|;",
+ "mih": "min-height:|;",
+ "mar": "max-resolution:${1:res};",
+ "mir": "min-resolution:${1:res};",
+ "ori": "orientation:|;",
+ "ori:l": "orientation:landscape;",
+ "ori:p": "orientation:portrait;",
+ "ol": "outline:|;",
+ "ol:n": "outline:none;",
+ "olo": "outline-offset:|;",
+ "olw": "outline-width:|;",
+ "ols": "outline-style:|;",
+ "olc": "outline-color:#${1:000};",
+ "olc:i": "outline-color:invert;",
+ "bd": "border:|;",
+ "bd+": "border:${1:1px} ${2:solid} ${3:#000};",
+ "bd:n": "border:none;",
+ "bdbk": "border-break:${1:close};",
+ "bdbk:c": "border-break:close;",
+ "bdcl": "border-collapse:|;",
+ "bdcl:c": "border-collapse:collapse;",
+ "bdcl:s": "border-collapse:separate;",
+ "bdc": "border-color:#${1:000};",
+ "bdc:t": "border-color:transparent;",
+ "bdi": "border-image:url(|);",
+ "bdi:n": "border-image:none;",
+ "bdti": "border-top-image:url(|);",
+ "bdti:n": "border-top-image:none;",
+ "bdri": "border-right-image:url(|);",
+ "bdri:n": "border-right-image:none;",
+ "bdbi": "border-bottom-image:url(|);",
+ "bdbi:n": "border-bottom-image:none;",
+ "bdli": "border-left-image:url(|);",
+ "bdli:n": "border-left-image:none;",
+ "bdci": "border-corner-image:url(|);",
+ "bdci:n": "border-corner-image:none;",
+ "bdci:c": "border-corner-image:continue;",
+ "bdtli": "border-top-left-image:url(|);",
+ "bdtli:n": "border-top-left-image:none;",
+ "bdtli:c": "border-top-left-image:continue;",
+ "bdtri": "border-top-right-image:url(|);",
+ "bdtri:n": "border-top-right-image:none;",
+ "bdtri:c": "border-top-right-image:continue;",
+ "bdbri": "border-bottom-right-image:url(|);",
+ "bdbri:n": "border-bottom-right-image:none;",
+ "bdbri:c": "border-bottom-right-image:continue;",
+ "bdbli": "border-bottom-left-image:url(|);",
+ "bdbli:n": "border-bottom-left-image:none;",
+ "bdbli:c": "border-bottom-left-image:continue;",
+ "bdf": "border-fit:${1:repeat};",
+ "bdf:c": "border-fit:clip;",
+ "bdf:r": "border-fit:repeat;",
+ "bdf:sc": "border-fit:scale;",
+ "bdf:st": "border-fit:stretch;",
+ "bdf:ow": "border-fit:overwrite;",
+ "bdf:of": "border-fit:overflow;",
+ "bdf:sp": "border-fit:space;",
+ "bdlen": "border-length:|;",
+ "bdlen:a": "border-length:auto;",
+ "bdsp": "border-spacing:|;",
+ "bds": "border-style:|;",
+ "bds:n": "border-style:none;",
+ "bds:h": "border-style:hidden;",
+ "bds:dt": "border-style:dotted;",
+ "bds:ds": "border-style:dashed;",
+ "bds:s": "border-style:solid;",
+ "bds:db": "border-style:double;",
+ "bds:dtds": "border-style:dot-dash;",
+ "bds:dtdtds": "border-style:dot-dot-dash;",
+ "bds:w": "border-style:wave;",
+ "bds:g": "border-style:groove;",
+ "bds:r": "border-style:ridge;",
+ "bds:i": "border-style:inset;",
+ "bds:o": "border-style:outset;",
+ "bdw": "border-width:|;",
+ "bdtw": "border-top-width:|;",
+ "bdrw": "border-right-width:|;",
+ "bdbw": "border-bottom-width:|;",
+ "bdlw": "border-left-width:|;",
+ "bdt": "border-top:|;",
+ "bt": "border-top:|;",
+ "bdt+": "border-top:${1:1px} ${2:solid} ${3:#000};",
+ "bdt:n": "border-top:none;",
+ "bdts": "border-top-style:|;",
+ "bdts:n": "border-top-style:none;",
+ "bdtc": "border-top-color:#${1:000};",
+ "bdtc:t": "border-top-color:transparent;",
+ "bdr": "border-right:|;",
+ "br": "border-right:|;",
+ "bdr+": "border-right:${1:1px} ${2:solid} ${3:#000};",
+ "bdr:n": "border-right:none;",
+ "bdrst": "border-right-style:|;",
+ "bdrst:n": "border-right-style:none;",
+ "bdrc": "border-right-color:#${1:000};",
+ "bdrc:t": "border-right-color:transparent;",
+ "bdb": "border-bottom:|;",
+ "bb": "border-bottom:|;",
+ "bdb+": "border-bottom:${1:1px} ${2:solid} ${3:#000};",
+ "bdb:n": "border-bottom:none;",
+ "bdbs": "border-bottom-style:|;",
+ "bdbs:n": "border-bottom-style:none;",
+ "bdbc": "border-bottom-color:#${1:000};",
+ "bdbc:t": "border-bottom-color:transparent;",
+ "bdl": "border-left:|;",
+ "bl": "border-left:|;",
+ "bdl+": "border-left:${1:1px} ${2:solid} ${3:#000};",
+ "bdl:n": "border-left:none;",
+ "bdls": "border-left-style:|;",
+ "bdls:n": "border-left-style:none;",
+ "bdlc": "border-left-color:#${1:000};",
+ "bdlc:t": "border-left-color:transparent;",
+ "bdrs": "border-radius:|;",
+ "bdtrrs": "border-top-right-radius:|;",
+ "bdtlrs": "border-top-left-radius:|;",
+ "bdbrrs": "border-bottom-right-radius:|;",
+ "bdblrs": "border-bottom-left-radius:|;",
+ "bg": "background:|;",
+ "bg+": "background:${1:#fff} url(${2}) ${3:0} ${4:0} ${5:no-repeat};",
+ "bg:n": "background:none;",
+ "bg:ie": "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='${1:x}.png',sizingMethod='${2:crop}');",
+ "bgc": "background-color:#${1:fff};",
+ "bgc:t": "background-color:transparent;",
+ "bgi": "background-image:url(|);",
+ "bgi:n": "background-image:none;",
+ "bgr": "background-repeat:|;",
+ "bgr:n": "background-repeat:no-repeat;",
+ "bgr:x": "background-repeat:repeat-x;",
+ "bgr:y": "background-repeat:repeat-y;",
+ "bgr:sp": "background-repeat:space;",
+ "bgr:rd": "background-repeat:round;",
+ "bga": "background-attachment:|;",
+ "bga:f": "background-attachment:fixed;",
+ "bga:s": "background-attachment:scroll;",
+ "bgp": "background-position:${1:0} ${2:0};",
+ "bgpx": "background-position-x:|;",
+ "bgpy": "background-position-y:|;",
+ "bgbk": "background-break:|;",
+ "bgbk:bb": "background-break:bounding-box;",
+ "bgbk:eb": "background-break:each-box;",
+ "bgbk:c": "background-break:continuous;",
+ "bgcp": "background-clip:${1:padding-box};",
+ "bgcp:bb": "background-clip:border-box;",
+ "bgcp:pb": "background-clip:padding-box;",
+ "bgcp:cb": "background-clip:content-box;",
+ "bgcp:nc": "background-clip:no-clip;",
+ "bgo": "background-origin:|;",
+ "bgo:pb": "background-origin:padding-box;",
+ "bgo:bb": "background-origin:border-box;",
+ "bgo:cb": "background-origin:content-box;",
+ "bgsz": "background-size:|;",
+ "bgsz:a": "background-size:auto;",
+ "bgsz:ct": "background-size:contain;",
+ "bgsz:cv": "background-size:cover;",
+ "c": "color:#${1:000};",
+ "c:r": "color:rgb(${1:0}, ${2:0}, ${3:0});",
+ "c:ra": "color:rgba(${1:0}, ${2:0}, ${3:0}, .${4:5});",
+ "cm": "/* |${child} */",
+ "cnt": "content:'|';",
+ "cnt:n": "content:normal;",
+ "cnt:oq": "content:open-quote;",
+ "cnt:noq": "content:no-open-quote;",
+ "cnt:cq": "content:close-quote;",
+ "cnt:ncq": "content:no-close-quote;",
+ "cnt:a": "content:attr(|);",
+ "cnt:c": "content:counter(|);",
+ "cnt:cs": "content:counters(|);",
+
+
+ "tbl": "table-layout:|;",
+ "tbl:a": "table-layout:auto;",
+ "tbl:f": "table-layout:fixed;",
+ "cps": "caption-side:|;",
+ "cps:t": "caption-side:top;",
+ "cps:b": "caption-side:bottom;",
+ "ec": "empty-cells:|;",
+ "ec:s": "empty-cells:show;",
+ "ec:h": "empty-cells:hide;",
+ "lis": "list-style:|;",
+ "lis:n": "list-style:none;",
+ "lisp": "list-style-position:|;",
+ "lisp:i": "list-style-position:inside;",
+ "lisp:o": "list-style-position:outside;",
+ "list": "list-style-type:|;",
+ "list:n": "list-style-type:none;",
+ "list:d": "list-style-type:disc;",
+ "list:c": "list-style-type:circle;",
+ "list:s": "list-style-type:square;",
+ "list:dc": "list-style-type:decimal;",
+ "list:dclz": "list-style-type:decimal-leading-zero;",
+ "list:lr": "list-style-type:lower-roman;",
+ "list:ur": "list-style-type:upper-roman;",
+ "lisi": "list-style-image:|;",
+ "lisi:n": "list-style-image:none;",
+ "q": "quotes:|;",
+ "q:n": "quotes:none;",
+ "q:ru": "quotes:'\\00AB' '\\00BB' '\\201E' '\\201C';",
+ "q:en": "quotes:'\\201C' '\\201D' '\\2018' '\\2019';",
+ "ct": "content:|;",
+ "ct:n": "content:normal;",
+ "ct:oq": "content:open-quote;",
+ "ct:noq": "content:no-open-quote;",
+ "ct:cq": "content:close-quote;",
+ "ct:ncq": "content:no-close-quote;",
+ "ct:a": "content:attr(|);",
+ "ct:c": "content:counter(|);",
+ "ct:cs": "content:counters(|);",
+ "coi": "counter-increment:|;",
+ "cor": "counter-reset:|;",
+ "va": "vertical-align:${1:top};",
+ "va:sup": "vertical-align:super;",
+ "va:t": "vertical-align:top;",
+ "va:tt": "vertical-align:text-top;",
+ "va:m": "vertical-align:middle;",
+ "va:bl": "vertical-align:baseline;",
+ "va:b": "vertical-align:bottom;",
+ "va:tb": "vertical-align:text-bottom;",
+ "va:sub": "vertical-align:sub;",
+ "ta": "text-align:${1:left};",
+ "ta:l": "text-align:left;",
+ "ta:c": "text-align:center;",
+ "ta:r": "text-align:right;",
+ "ta:j": "text-align:justify;",
+ "ta-lst": "text-align-last:|;",
+ "tal:a": "text-align-last:auto;",
+ "tal:l": "text-align-last:left;",
+ "tal:c": "text-align-last:center;",
+ "tal:r": "text-align-last:right;",
+ "td": "text-decoration:${1:none};",
+ "td:n": "text-decoration:none;",
+ "td:u": "text-decoration:underline;",
+ "td:o": "text-decoration:overline;",
+ "td:l": "text-decoration:line-through;",
+ "te": "text-emphasis:|;",
+ "te:n": "text-emphasis:none;",
+ "te:ac": "text-emphasis:accent;",
+ "te:dt": "text-emphasis:dot;",
+ "te:c": "text-emphasis:circle;",
+ "te:ds": "text-emphasis:disc;",
+ "te:b": "text-emphasis:before;",
+ "te:a": "text-emphasis:after;",
+ "th": "text-height:|;",
+ "th:a": "text-height:auto;",
+ "th:f": "text-height:font-size;",
+ "th:t": "text-height:text-size;",
+ "th:m": "text-height:max-size;",
+ "ti": "text-indent:|;",
+ "ti:-": "text-indent:-9999px;",
+ "tj": "text-justify:|;",
+ "tj:a": "text-justify:auto;",
+ "tj:iw": "text-justify:inter-word;",
+ "tj:ii": "text-justify:inter-ideograph;",
+ "tj:ic": "text-justify:inter-cluster;",
+ "tj:d": "text-justify:distribute;",
+ "tj:k": "text-justify:kashida;",
+ "tj:t": "text-justify:tibetan;",
+ "tov": "text-overflow:${ellipsis};",
+ "tov:e": "text-overflow:ellipsis;",
+ "tov:c": "text-overflow:clip;",
+ "to": "text-outline:|;",
+ "to+": "text-outline:${1:0} ${2:0} ${3:#000};",
+ "to:n": "text-outline:none;",
+ "tr": "text-replace:|;",
+ "tr:n": "text-replace:none;",
+ "tt": "text-transform:${1:uppercase};",
+ "tt:n": "text-transform:none;",
+ "tt:c": "text-transform:capitalize;",
+ "tt:u": "text-transform:uppercase;",
+ "tt:l": "text-transform:lowercase;",
+ "tw": "text-wrap:|;",
+ "tw:n": "text-wrap:normal;",
+ "tw:no": "text-wrap:none;",
+ "tw:u": "text-wrap:unrestricted;",
+ "tw:s": "text-wrap:suppress;",
+ "tsh": "text-shadow:${1:hoff} ${2:voff} ${3:blur} ${4:#000};",
+ "tsh:r": "text-shadow:${1:h} ${2:v} ${3:blur} rgb(${4:0}, ${5:0}, ${6:0});",
+ "tsh:ra": "text-shadow:${1:h} ${2:v} ${3:blur} rgba(${4:0}, ${5:0}, ${6:0}, .${7:5});",
+ "tsh+": "text-shadow:${1:0} ${2:0} ${3:0} ${4:#000};",
+ "tsh:n": "text-shadow:none;",
+ "trf": "transform:|;",
+ "trf:skx": "transform: skewX(${1:angle});",
+ "trf:sky": "transform: skewY(${1:angle});",
+ "trf:sc": "transform: scale(${1:x}, ${2:y});",
+ "trf:scx": "transform: scaleX(${1:x});",
+ "trf:scy": "transform: scaleY(${1:y});",
+ "trf:r": "transform: rotate(${1:angle});",
+ "trf:t": "transform: translate(${1:x}, ${2:y});",
+ "trf:tx": "transform: translateX(${1:x});",
+ "trf:ty": "transform: translateY(${1:y});",
+ "trfo": "transform-origin:|;",
+ "trfs": "transform-style:${1:preserve-3d};",
+ "trs": "transition:${1:prop} ${2:time};",
+ "trsde": "transition-delay:${1:time};",
+ "trsdu": "transition-duration:${1:time};",
+ "trsp": "transition-property:${1:prop};",
+ "trstf": "transition-timing-function:${1:tfunc};",
+ "lh": "line-height:|;",
+ "whs": "white-space:|;",
+ "whs:n": "white-space:normal;",
+ "whs:p": "white-space:pre;",
+ "whs:nw": "white-space:nowrap;",
+ "whs:pw": "white-space:pre-wrap;",
+ "whs:pl": "white-space:pre-line;",
+ "whsc": "white-space-collapse:|;",
+ "whsc:n": "white-space-collapse:normal;",
+ "whsc:k": "white-space-collapse:keep-all;",
+ "whsc:l": "white-space-collapse:loose;",
+ "whsc:bs": "white-space-collapse:break-strict;",
+ "whsc:ba": "white-space-collapse:break-all;",
+ "wob": "word-break:|;",
+ "wob:n": "word-break:normal;",
+ "wob:k": "word-break:keep-all;",
+ "wob:l": "word-break:loose;",
+ "wob:bs": "word-break:break-strict;",
+ "wob:ba": "word-break:break-all;",
+ "wos": "word-spacing:|;",
+ "wow": "word-wrap:|;",
+ "wow:nm": "word-wrap:normal;",
+ "wow:n": "word-wrap:none;",
+ "wow:u": "word-wrap:unrestricted;",
+ "wow:s": "word-wrap:suppress;",
+ "lts": "letter-spacing:|;",
+ "f": "font:|;",
+ "f+": "font:${1:1em} ${2:Arial,sans-serif};",
+ "fw": "font-weight:|;",
+ "fw:n": "font-weight:normal;",
+ "fw:b": "font-weight:bold;",
+ "fw:br": "font-weight:bolder;",
+ "fw:lr": "font-weight:lighter;",
+ "fs": "font-style:${italic};",
+ "fs:n": "font-style:normal;",
+ "fs:i": "font-style:italic;",
+ "fs:o": "font-style:oblique;",
+ "fv": "font-variant:|;",
+ "fv:n": "font-variant:normal;",
+ "fv:sc": "font-variant:small-caps;",
+ "fz": "font-size:|;",
+ "fza": "font-size-adjust:|;",
+ "fza:n": "font-size-adjust:none;",
+ "ff": "font-family:|;",
+ "ff:s": "font-family:serif;",
+ "ff:ss": "font-family:sans-serif;",
+ "ff:c": "font-family:cursive;",
+ "ff:f": "font-family:fantasy;",
+ "ff:m": "font-family:monospace;",
+ "fef": "font-effect:|;",
+ "fef:n": "font-effect:none;",
+ "fef:eg": "font-effect:engrave;",
+ "fef:eb": "font-effect:emboss;",
+ "fef:o": "font-effect:outline;",
+ "fem": "font-emphasize:|;",
+ "femp": "font-emphasize-position:|;",
+ "femp:b": "font-emphasize-position:before;",
+ "femp:a": "font-emphasize-position:after;",
+ "fems": "font-emphasize-style:|;",
+ "fems:n": "font-emphasize-style:none;",
+ "fems:ac": "font-emphasize-style:accent;",
+ "fems:dt": "font-emphasize-style:dot;",
+ "fems:c": "font-emphasize-style:circle;",
+ "fems:ds": "font-emphasize-style:disc;",
+ "fsm": "font-smooth:|;",
+ "fsm:a": "font-smooth:auto;",
+ "fsm:n": "font-smooth:never;",
+ "fsm:aw": "font-smooth:always;",
+ "fst": "font-stretch:|;",
+ "fst:n": "font-stretch:normal;",
+ "fst:uc": "font-stretch:ultra-condensed;",
+ "fst:ec": "font-stretch:extra-condensed;",
+ "fst:c": "font-stretch:condensed;",
+ "fst:sc": "font-stretch:semi-condensed;",
+ "fst:se": "font-stretch:semi-expanded;",
+ "fst:e": "font-stretch:expanded;",
+ "fst:ee": "font-stretch:extra-expanded;",
+ "fst:ue": "font-stretch:ultra-expanded;",
+ "op": "opacity:|;",
+ "op:ie": "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);",
+ "op:ms": "-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)';",
+ "rsz": "resize:|;",
+ "rsz:n": "resize:none;",
+ "rsz:b": "resize:both;",
+ "rsz:h": "resize:horizontal;",
+ "rsz:v": "resize:vertical;",
+ "cur": "cursor:${pointer};",
+ "cur:a": "cursor:auto;",
+ "cur:d": "cursor:default;",
+ "cur:c": "cursor:crosshair;",
+ "cur:ha": "cursor:hand;",
+ "cur:he": "cursor:help;",
+ "cur:m": "cursor:move;",
+ "cur:p": "cursor:pointer;",
+ "cur:t": "cursor:text;",
+ "pgbb": "page-break-before:|;",
+ "pgbb:au": "page-break-before:auto;",
+ "pgbb:al": "page-break-before:always;",
+ "pgbb:l": "page-break-before:left;",
+ "pgbb:r": "page-break-before:right;",
+ "pgbi": "page-break-inside:|;",
+ "pgbi:au": "page-break-inside:auto;",
+ "pgbi:av": "page-break-inside:avoid;",
+ "pgba": "page-break-after:|;",
+ "pgba:au": "page-break-after:auto;",
+ "pgba:al": "page-break-after:always;",
+ "pgba:l": "page-break-after:left;",
+ "pgba:r": "page-break-after:right;",
+ "orp": "orphans:|;",
+ "us": "user-select:${none};",
+ "wid": "widows:|;",
+ "wfsm": "-webkit-font-smoothing:${antialiased};",
+ "wfsm:a": "-webkit-font-smoothing:antialiased;",
+ "wfsm:s": "-webkit-font-smoothing:subpixel-antialiased;",
+ "wfsm:sa": "-webkit-font-smoothing:subpixel-antialiased;",
+ "wfsm:n": "-webkit-font-smoothing:none;"
+ }
+ },
+
+ "html": {
+ "filters": "html",
+ "profile": "html",
+ "snippets": {
+ "!!!": "",
+ "!!!4t": "",
+ "!!!4s": "",
+ "!!!xt": "",
+ "!!!xs": "",
+ "!!!xxs": "",
+
+ "c": "",
+ "cc:ie6": "",
+ "cc:ie": "",
+ "cc:noie": "\n\t${child}|\n"
+ },
+
+ "abbreviations": {
+ "!": "html:5",
+ "a": "",
+ "a:link": " ",
+ "a:mail": " ",
+ "abbr": "",
+ "acronym": "",
+ "base": " ",
+ "bdo": "",
+ "bdo:r": "",
+ "bdo:l": "",
+ "link": " ",
+ "link:css": " ",
+ "link:print": " ",
+ "link:favicon": " ",
+ "link:touch": " ",
+ "link:rss": " ",
+ "link:atom": " ",
+ "meta:utf": " ",
+ "meta:win": " ",
+ "meta:vp": " ",
+ "meta:compat": " ",
+ "style": "\n' + close;
+ }
+
+ // Add defer to all inline script tags in IE.
+ // This is because IE runs scripts as it loads them, so variables that
+ // scripts like jQuery add to the global scope are undefined.
+ // See http://jsbin.com/ijapom/5
+ if (jsbin.ie && re.scriptopen.test(source)) {
+ source = source.replace(/'
+ },
+ {
+ 'url': [
+ 'http://jashkenas.github.io/underscore/underscore-min.js',
+ 'http://jashkenas.github.io/backbone/backbone-min.js'
+ ],
+ 'label': 'Backbone latest'
+ },
+ {
+ 'url': [
+ 'http://jashkenas.github.io/underscore/underscore-min.js',
+ 'http://jashkenas.github.io/backbone/backbone-min.js',
+ 'http://marionettejs.com/downloads/backbone.marionette.min.js'
+ ],
+ 'label': 'MarionetteJS latest'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/bonsai/0.4/bonsai.min.js',
+ 'label': 'Bonsai 0.4.latest'
+ },
+ {
+ 'url': 'http://jashkenas.github.io/coffee-script/extras/coffee-script.js',
+ 'label': 'CoffeeScript'
+ },
+ {
+ 'url': [
+ 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js',
+ 'http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js',
+ 'http://builds.emberjs.com.s3.amazonaws.com/tags/v1.0.0/ember.js'
+ ],
+ 'label': 'Ember.js 1.0.0'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/es5-shim/2.0.8/es5-shim.min.js',
+ 'label': 'ES5 shim 2.0.8'
+ },
+ {
+ 'url': [
+ 'http://extjs.cachefly.net/ext-3.1.0/resources/css/ext-all.css',
+ 'http://cdnjs.cloudflare.com/ajax/libs/ext-core/3.1.0/ext-core.min.js'
+ ],
+ 'label': 'ext-core 3.1.0'
+ },
+ {
+ 'url': [
+ 'http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/css/normalize.min.css',
+ 'http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/css/foundation.min.css',
+ 'http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/js/vendor/jquery.min.js',
+ 'http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/js/foundation.min.js'
+ ],
+ 'label': 'Foundation 5.0.3'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js',
+ 'label': 'Handlebars.js 1.0.0'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js',
+ 'label': 'Knockout 3.0.0'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/less.js/1.3.3/less.min.js',
+ 'label': 'Less 1.3.3'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js',
+ 'label': 'Lo-Dash 2.4.1'
+ },
+ {
+ 'url': 'http://modernizr.com/downloads/modernizr-latest.js',
+ 'label': 'Modernizr Development latest'
+ },
+ {
+ 'url': [
+ 'http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js',
+ 'http://cdnjs.cloudflare.com/ajax/libs/detectizr/1.5.0/detectizr.min.js'
+ ],
+ 'label': 'Detectizr 1.5.0'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js',
+ 'label': 'Prefixfree 1.0.7'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/processing.js/1.4.1/processing-api.min.js',
+ 'label': 'Processing 1.4.1'
+ },
+ {
+ 'url': 'http://d3js.org/d3.v3.min.js',
+ 'label': 'D3 3.x'
+ },
+ {
+ 'url': '//code.highcharts.com/highcharts.js',
+ 'label': 'Highcharts latest'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js',
+ 'label': 'Raphaël 2.1.0'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/sammy.js/0.7.4/sammy.min.js',
+ 'label': 'Sammy 0.7.4'
+ },
+ {
+ 'url': [
+ 'http://cdn.sencha.io/touch/1.1.0/resources/css/sencha-touch.css',
+ 'http://cdn.sencha.io/touch/1.1.0/sencha-touch.js'
+ ],
+ 'label': 'Sencha Touch'
+ },
+ {
+ 'url': [
+ jsbin.static + '/js/vendor/traceur.js'
+ ],
+ 'label': 'Traceur'
+ },
+ {
+ 'url': 'http://remy.github.io/twitterlib/twitterlib.min.js',
+ 'label': 'TwitterLib'
+ },
+ {
+ 'url': 'http://jashkenas.github.io/underscore/underscore-min.js',
+ 'label': 'underscore'
+ },
+ {
+ 'url':[
+ 'http://code.jquery.com/jquery.min.js',
+ '//canjs.com/release/2.0.3/can.jquery.min.js'
+ ],
+ 'label': 'CanJS 2.0.3'
+ },
+ {
+ 'url':[
+ 'http://cdnjs.cloudflare.com/ajax/libs/three.js/r61/three.min.js'
+ ],
+ 'label': 'Three.js r61'
+ },
+ {
+ 'url':[
+ 'http://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.2/html5shiv.js'
+ ],
+ 'label': 'HTML5 shiv'
+ },
+ {
+ 'url': [
+ 'http://lungo.tapquo.com/demo/components/lungo/lungo.css',
+ 'http://lungo.tapquo.com/demo/components/lungo/lungo.theme.css',
+ 'http://lungo.tapquo.com/demo/components/lungo/lungo.icon.css',
+ 'http://lungo.tapquo.com/demo/components/quojs/quo.js',
+ 'http://lungo.tapquo.com/demo/components/lungo/lungo.js'
+ ],
+ 'label': 'Lungo'
+ },
+ {
+ 'url': [
+ '//cdnjs.cloudflare.com/ajax/libs/polymer/0.3.3/platform.js',
+ '//cdnjs.cloudflare.com/ajax/libs/polymer/0.3.3/polymer.js'
+ ],
+ 'label': 'Polymer 0.3.3'
+ },
+ {
+ 'url': '//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css',
+ 'label': 'Font Awesome 4.0.3'
+ },
+ {
+ 'url': '//cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.12/paper.js',
+ 'label': 'Paper.js 0.9.12'
+ },
+ {
+ 'url': {
+ 'url': 'https://openui5.hana.ondemand.com/resources/sap-ui-core.js',
+ 'id': 'sap-ui-bootstrap',
+ 'data-sap-ui-theme': 'sap_bluecrystal',
+ 'data-sap-ui-libs': 'sap.m'
+ },
+ 'label': 'OpenUI5 1.18.8 Mobile BlueCrystal'
+ },
+ {
+ 'url': 'http://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.7/TweenMax.min.js',
+ 'label': 'GSAP 1.11.7'
+ },
+ {
+ 'url': '//cdnjs.cloudflare.com/ajax/libs/phaser/2.0.5/phaser.min.js',
+ 'label': 'Phaser 2.0.5'
+ }
+];
+
+window.libraries = libraries; // expose a command line API
+
+libraries.userSpecified = JSON.parse(localStorage.getItem('libraries') || '[]');
+for (var i = 0; i < libraries.userSpecified.length; i++) {
+ libraries.push(libraries.userSpecified[i]);
+}
+
+libraries.add = function (lib) {
+ // Extract each script from a list (as documented) or use the default way
+ if (lib.scripts) {
+ lib.scripts.forEach(function (script) {
+ script.group = lib.text;
+ script.label = script.text;
+ libraries.userSpecified.push(script);
+ libraries.push(script);
+ });
+ } else {
+ // Adding a lib according to the above schema
+ lib.group = 'Custom';
+ libraries.userSpecified.push(lib);
+ libraries.push(lib);
+ }
+ try {
+ localStorage.setItem('libraries', JSON.stringify(this.userSpecified));
+ } catch (e) {} // just in case of DOM_22 error, makes me so sad to use this :(
+ $('#library').trigger('init');
+};
+
+libraries.clear = function () {
+ libraries.userSpecified = [];
+ localStorage.removeItem('libraries');
+ var length = libraries.length;
+ for (var i = 0; i < length; i++) {
+ if (libraries[i].group === 'Custom') {
+ libraries.splice(i, 1);
+ length--;
+ }
+ }
+ // force a refresh?
+ $('#library').trigger('init');
+};
+;/*global $:true, editors:true, libraries:true, analytics:true */
+// 'use strict'; // this causes bigger issues :-\
+
+var $library = $('#library'),
+ groups = {};
+
+$library.bind('init', function () {
+ var i = 0,
+ j = 0,
+ k = 0,
+ library = {},
+ groupOrder = [],
+ group = {},
+ groupLabel = '',
+ lcGroup = '';
+
+ // reset
+ groups = {};
+ $library.empty();
+
+ for (i = 0; i < libraries.length; i++) {
+ library = libraries[i];
+ groupLabel = library.group || 'Other';
+ lcGroup = groupLabel.toLowerCase().replace(/[^a-z0-9]/ig, '');
+ if (groupOrder.indexOf(lcGroup) === -1) {
+ group = { label: groupLabel, libraries: [], key: lcGroup };
+ groups[lcGroup] = group;
+ groupOrder.push(lcGroup);
+ } else {
+ group = groups[lcGroup];
+ }
+
+ group.libraries.push(library);
+ }
+
+ var html = ['None '];
+
+ for (i = 0; i < groupOrder.length; i++) {
+ group = groups[groupOrder[i]];
+ html.push('------------- ');
+
+ for (j = 0; j < group.libraries.length; j++) {
+ library = group.libraries[j];
+ html.push('' + library.label + ' ');
+ }
+ }
+
+ $library.html( html.join('') );
+}).trigger('init');
+
+
+$library.bind('change', function () {
+ if (!this.value) { return; }
+
+ var selected = this.value.split(':'),
+ group = groups[selected[0]],
+ library = group.libraries[selected[1]];
+
+ analytics.library('select', group.libraries[selected[1]].label);
+ insertResources(library.url);
+ if (library.snippet) {
+ insertSnippet(library.snippet);
+ }
+}).on('click', function () {
+ analytics.library('open');
+});
+
+function insertResources(urls) {
+ if (!$.isArray(urls)) {
+ urls = [urls];
+ }
+
+ var i = 0,
+ length = urls.length,
+ url = '',
+ code = editors.html.getCode(),
+ state = { line: editors.html.editor.currentLine(),
+ character: editors.html.editor.getCursor().ch,
+ add: 0
+ },
+ html = [],
+ file = '',
+ resource,
+ attrList,
+ attrs,
+ scriptDefaultAttrs = {},
+ cssDefaultAttrs = { 'rel': 'stylesheet', 'type': 'text/css' };
+
+ for (i = 0; i < length; i++) {
+ url = urls[i];
+
+ // URLs can be objects carrying desired attributes
+ // The main resource (src, href) property is always 'url'
+ if ($.isPlainObject(url)) {
+ attrs = url;
+ url = url.url;
+ delete attrs.url;
+ } else {
+ attrs = {};
+ }
+
+ file = url.split('/').pop();
+
+ // Introduce any default attrs and flatten into a list for insertion
+ attrs = $.extend({}, (isCssFile(file) ? cssDefaultAttrs : scriptDefaultAttrs), attrs);
+ attrList = '';
+ for (var attr in attrs) {
+ attrList += ' ' + attr + '="' + attrs[attr] + '"';
+ }
+
+ if (file && code.indexOf(file + '"')) {
+ // attempt to lift out similar scripts
+ if (isCssFile(file)) {
+ code = code.replace(new RegExp(' \n?'), '');
+ } else {
+ code = code.replace(new RegExp('<' + '/script>\n?'), '');
+ }
+ state.add--;
+ }
+
+ if (isCssFile(url)) {
+ resource = '<' + 'link href="' + url + '"' + attrList + ' />';
+ } else {
+ resource = '<' + 'script src="' + url + '"' + attrList + '><' + '/script>';
+ }
+
+ if (isJadeActive()) {
+ resource = isCssFile(url) ? htmlLinkToJade(resource) : htmlScriptToJade(resource);
+ }
+
+ html.push(resource);
+
+ state.add++;
+ }
+
+ if (isJadeActive()) {
+ // always append Jade at the end, it's just easier that way...okay?
+ var indent = (code.match(/html.*\n(\s*)\S?/i) || [,])[1];
+ code = code.trim() + '\n' + indent + html.join('\n' + indent).trim();
+ } else {
+ if (code.indexOf('/i, '\n' + html.join('\n'));
+ } else { // add to the start of the doc
+ code = html.join('\n') + code;
+ }
+ }
+
+ editors.html.setCode(code);
+ editors.html.editor.setCursor({ line: state.line + state.add, ch: state.character });
+
+}
+
+function insertSnippet(snippet) {
+ var code = editors.html.getCode(),
+ state = { line: editors.html.editor.currentLine(),
+ character: editors.html.editor.getCursor().ch,
+ add: 0
+ };
+
+ if (code.indexOf('/i, snippet + '\n');
+ } else { // add to the start of the doc
+ code = snippet + '\n' + code;
+ }
+
+ editors.html.setCode(code);
+ editors.html.editor.setCursor({ line: state.line + state.add, ch: state.character });
+}
+
+function createHTMLToJadeTagConverter(tagName, attribute, suffix){
+ var regExToGrabResource = new RegExp(attribute+'=(\'|").+.'+suffix+'\\1');
+ return function(html){
+ var resource = html.match(regExToGrabResource);
+ return tagName+'('+resource[0]+')';
+ };
+}
+
+var htmlScriptToJade = createHTMLToJadeTagConverter('script', 'src', 'js');
+// Dirty, but good enough for now, parse the link and add commas between attributes;
+var htmlLinkToJade = (function(){
+ var parseLink = createHTMLToJadeTagConverter('link', 'href', 'css');
+ return function(html){
+ var jadeLink = parseLink(html);
+ return jadeLink.split('" ').join('",');
+ };
+}());
+
+function isJadeActive(){
+ return jsbin.state.processors.html === 'jade';
+}
+
+function isCssFile(url) {
+ return (url.length - (url.lastIndexOf('.css') + 4) === 0);
+}
+;(function () {
+ 'use strict';
+ /*globals $, jsbin, CodeMirror*/
+
+ var defaults = {
+ closebrackets: true,
+ highlight: false,
+ vim: false,
+ emacs: false,
+ trailingspace: false,
+ fold: false,
+ sublime: false,
+ tern: false,
+ activeline: true,
+ matchbrackets: false
+ };
+
+ if (!jsbin.settings.addons) {
+ jsbin.settings.addons = defaults;
+ }
+
+ var detailsSupport = 'open' in document.createElement('details');
+
+ var settingsHints = {};
+ var settingsHintShow = {};
+ var hintShow = {
+ console: true,
+ line: false,
+ under: false,
+ gutter: false
+ };
+ // css must go last for the moment due to CSSLint creating the
+ // global variable 'exports'
+ ['js', 'html', 'coffeescript', 'css'].forEach(function (val) {
+ var h = val + 'hint';
+ var d = false;
+ if (val === 'js') {
+ d = true;
+ }
+ settingsHints[h] = (jsbin.settings[h] !== undefined) ? jsbin.settings[h] : d;
+ });
+
+ settingsHintShow = $.extend({}, hintShow, jsbin.settings.hintShow);
+ settingsHintShow.tooltip = settingsHintShow.gutter;
+ var settingsAddons = $.extend({}, jsbin.settings.addons, settingsHints);
+
+ var addons = {
+ closebrackets: {
+ url: '/js/vendor/codemirror4/addon/edit/closebrackets.js',
+ test: defaultTest('autoCloseBrackets'),
+ done: function (cm) {
+ setOption(cm, 'autoCloseBrackets', true);
+ }
+ },
+ highlight: {
+ url: '/js/vendor/codemirror4/addon/search/match-highlighter.js',
+ test: defaultTest('highlightSelectionMatches'),
+ done: function (cm) {
+ setOption(cm, 'highlightSelectionMatches', true);
+ }
+ },
+ vim: {
+ url: [
+ '/js/vendor/codemirror4/addon/dialog/dialog.css',
+ '/js/vendor/codemirror4/keymap/vim.js',
+ '/js/vendor/codemirror4/addon/dialog/dialog.js'
+ ],
+ test: defaultTest('vimMode'),
+ done: function (cm) {
+ setOption(cm, 'vimMode', true);
+ setOption(cm, 'showCursorWhenSelecting', true);
+ }
+ },
+ emacs: {
+ url: [
+ '/js/vendor/codemirror4/addon/dialog/dialog.css',
+ '/js/vendor/codemirror4/keymap/emacs.js',
+ '/js/vendor/codemirror4/addon/dialog/dialog.js',
+ '/js/vendor/codemirror4/addon/search/search.js'
+ ],
+ test: function () {
+ return jsbin.panels.panels.javascript.editor.openDialog &&
+ CodeMirror.commands.find &&
+ CodeMirror.keyMap.emacs;
+ },
+ done: function (cm) {
+ setOption(cm, 'keyMap', 'emacs');
+ }
+ },
+ matchtags: {
+ url: [
+ '/js/vendor/codemirror4/addon/fold/xml-fold.js',
+ '/js/vendor/codemirror4/addon/edit/matchtags.js'
+ ],
+ test: function () {
+ return CodeMirror.scanForClosingTag &&
+ CodeMirror.optionHandlers.matchTags;
+ },
+ done: function (cm) {
+ setOption(cm, 'matchTags', { bothTags: true });
+ cm.addKeyMap({'Ctrl-J': 'toMatchingTag' });
+ }
+ },
+ trailingspace: {
+ url: '/js/vendor/codemirror4/addon/edit/trailingspace.js',
+ test: defaultTest('showTrailingSpace'),
+ done: function (cm) {
+ setOption(cm, 'showTrailingSpace', true);
+ }
+ },
+ fold: {
+ url: [
+ '/js/vendor/codemirror4/addon/fold/foldgutter.css',
+ '/js/vendor/codemirror4/addon/fold/foldcode.js',
+ '/js/vendor/codemirror4/addon/fold/foldgutter.js',
+ '/js/vendor/codemirror4/addon/fold/brace-fold.js',
+ '/js/vendor/codemirror4/addon/fold/xml-fold.js',
+ '/js/vendor/codemirror4/addon/fold/comment-fold.js'
+ ],
+ test: function () {
+ return CodeMirror.helpers.fold &&
+ CodeMirror.optionHandlers.foldGutter &&
+ CodeMirror.optionHandlers.gutters;
+ },
+ done: function (cm) {
+ $body.addClass('code-fold');
+ cm.addKeyMap({'Ctrl-Q': function (cm) {
+ cm.foldCode(cm.getCursor());
+ }});
+ setOption(cm, 'foldGutter', true);
+ var gutters = cm.getOption('gutters');
+ gutters.push('CodeMirror-linenumbers');
+ gutters.push('CodeMirror-foldgutter');
+ setOption(cm, 'gutters', gutters);
+ }
+ },
+ sublime: {
+ url: [
+ '/js/vendor/codemirror4/addon/dialog/dialog.css',
+ '/js/vendor/codemirror4/keymap/sublime.js',
+ '/js/vendor/codemirror4/addon/dialog/dialog.js',
+ '/js/vendor/codemirror4/addon/search/search.js'
+ ],
+ test: function () {
+ return jsbin.panels.panels.javascript.editor.openDialog &&
+ CodeMirror.commands.find &&
+ CodeMirror.keyMap.sublime;
+ },
+ done: function (cm) {
+ setOption(cm, 'keyMap', 'sublime');
+ // Keys that CodeMirror should never take over
+ var cmd = $.browser.platform === 'mac' ? 'Cmd' : 'Ctrl';
+ delete CodeMirror.keyMap['sublime'][cmd + '-L'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-T'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-W'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-J'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-R'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-Enter'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-Up'];
+ delete CodeMirror.keyMap['sublime'][cmd + '-Down'];
+ cm.removeKeyMap('noEmmet');
+ }
+ },
+ tern: {
+ url: [
+ '/js/vendor/codemirror4/addon/dialog/dialog.css',
+ '/js/vendor/codemirror4/addon/hint/show-hint.css',
+ '/js/vendor/codemirror4/addon/tern/tern.css',
+ '/js/vendor/codemirror4/addon/hint/show-hint.js',
+ '/js/vendor/codemirror4/addon/dialog/dialog.js',
+ '/js/prod/addon-tern-' + jsbin.version + '.min.js'
+ ],
+ test: function () {
+ return jsbin.panels.panels.javascript.editor.openDialog &&
+ (typeof window.ternBasicDefs !== 'undefined') &&
+ CodeMirror.showHint &&
+ CodeMirror.TernServer &&
+ CodeMirror.startTern;
+ },
+ done: function () {
+ CodeMirror.startTern();
+ }
+ },
+ activeline: {
+ url: [
+ '/js/vendor/codemirror4/addon/selection/active-line.js'
+ ],
+ test: function() {
+ return (typeof CodeMirror.defaults.styleActiveLine !== 'undefined');
+ },
+ done: function(cm) {
+ setOption(cm, 'styleActiveLine', true);
+ }
+ },
+ matchbrackets: {
+ url: [],
+ test: function() {
+ return (typeof CodeMirror.defaults.matchBrackets !== 'undefined');
+ },
+ done: function(cm) {
+ setOption(cm, 'matchBrackets', true);
+ }
+ },
+ csshint: {
+ url: [
+ '/js/vendor/csslint/csslint.min.js',
+ '/js/vendor/cm_addons/lint/css-lint.js'
+ ],
+ test: function() {
+ return hintingTest('css') &&
+ (typeof CSSLint !== 'undefined');
+ },
+ done: function(cm) {
+ if (cm.getOption('mode') !== 'css') {
+ return;
+ }
+ hintingDone(cm);
+ }
+ },
+ jshint: {
+ url: [],
+ test: function() {
+ return hintingTest('javascript') &&
+ (typeof JSHINT !== 'undefined');
+ },
+ done: function(cm) {
+ if (cm.getOption('mode') !== 'javascript') {
+ return;
+ }
+ hintingDone(cm, {
+ 'eqnull': true
+ });
+ }
+ },
+ htmlhint: {
+ url: [
+ '/js/vendor/htmlhint/htmlhint.js',
+ '/js/vendor/cm_addons/lint/html-lint.js'
+ ],
+ test: function() {
+ return hintingTest('htmlmixed') &&
+ (typeof HTMLHint !== 'undefined');
+ },
+ done: function(cm) {
+ if (cm.getOption('mode') !== 'htmlmixed') {
+ return;
+ }
+ hintingDone(cm);
+ }
+ },
+ coffeescripthint: {
+ url: [
+ '/js/vendor/coffeelint/coffeelint.min.js',
+ '/js/vendor/cm_addons/lint/coffeescript-lint.js'
+ ],
+ test: function() {
+ return hintingTest('coffeescript') &&
+ (typeof coffeelint !== 'undefined');
+ },
+ done: function(cm) {
+ if (cm.getOption('mode') !== 'coffeescript') {
+ return;
+ }
+ hintingDone(cm);
+ }
+ }
+ };
+
+ // begin loading user addons
+
+
+ var $body = $('body');
+
+ function load(url) {
+ if (url.indexOf('http') !== 0) {
+ url = jsbin.static + url;
+ }
+
+ if (url.slice(-3) === '.js') {
+ return $.ajax({
+ url: url + '?' + jsbin.version, // manual cache busting
+ dataType: 'script',
+ cache: true
+ });
+ } else if (url.slice(-4) === '.css') {
+ var d = $.Deferred();
+ setTimeout(function () {
+ $body.append(' ');
+ d.resolve();
+ }, 0);
+ return d;
+ }
+ }
+
+ function ready(test) {
+ var d = $.Deferred();
+ var timer = null;
+
+ if (test()) {
+ d.resolve();
+ } else {
+ timer = setInterval(function () {
+ if (test()) {
+ clearInterval(timer);
+ d.resolve();
+ }
+ }, 100);
+ }
+
+ return d;
+ }
+
+ function setOption(cm, option, value) {
+ cm.setOption(option, value);
+ }
+
+ function defaultTest(prop) {
+ return function () {
+ return (typeof CodeMirror.optionHandlers[prop] !== 'undefined');
+ };
+ }
+
+ function hintingTest(mode) {
+ return (typeof CodeMirror.defaults.lint !== 'undefined') &&
+ CodeMirror.helpers.lint &&
+ CodeMirror.helpers.lint[mode] &&
+ CodeMirror.optionHandlers.lint;
+ }
+
+ window.hintingDone = function(cm, defhintOptions) {
+ var mode = cm.getOption('mode');
+ if (mode === 'javascript') {
+ mode = 'js';
+ }
+ if (mode === 'htmlmixed') {
+ mode = 'html';
+ }
+ var opt = $.extend({}, settingsHintShow);
+ opt.consoleParent = cm.getWrapperElement().parentNode.parentNode;
+ setOption(cm, 'lintOpt', opt);
+ setOption(cm, 'lintRules', $.extend({}, defhintOptions, jsbin.settings[mode + 'hintOptions']));
+ if (opt.gutter) {
+ var gutters = cm.getOption('gutters');
+ if (gutters.indexOf('CodeMirror-lint-markers') === -1) {
+ gutters.push('CodeMirror-lint-markers');
+ setOption(cm, 'gutters', gutters);
+ }
+ setOption(cm, 'lint', true);
+ var ln = cm.getOption('lineNumbers');
+ setOption(cm, 'lineNumbers', !ln);
+ setOption(cm, 'lineNumbers', ln);
+ } else {
+ setOption(cm, 'lint', true);
+ }
+ if (opt.console) {
+ $document.trigger('sizeeditors');
+ $(cm.consolelint.head).on('click', function() {
+ if (!detailsSupport) {
+ $(this).nextAll().toggle();
+ }
+ // trigger a resize after the click has completed and the details is close
+ setTimeout(function () {
+ $document.trigger('sizeeditors');
+ }, 10);
+ });
+ }
+ }
+
+ var options = Object.keys(settingsAddons);
+
+ function loadAddon(key) {
+ var addon = addons[key];
+ if (addon && settingsAddons[key]) {
+ if (typeof addon.url === 'string') {
+ addon.url = [addon.url];
+ }
+
+ // dirty jQuery way of doing .done on an array of promises
+ $.when.call($, addon.url.map(load)).done(function () {
+ if (addon.done) {
+ ready(addon.test).then(function () {
+ jsbin.panels.allEditors(function (panel) {
+ if (panel.editor) {
+ addon.done(panel.editor);
+ }
+ });
+ });
+ }
+ });
+ }
+ }
+
+ options.forEach(loadAddon);
+
+ // External method to realod all the addons
+ window.reloadAddons = function(arr) {
+ if (arr) {
+ arr.forEach(loadAddon);
+ } else {
+ options.forEach(loadAddon);
+ }
+ };
+
+ // External method to realod the selected addon
+ // may be useful in the future
+ // window.reloadSelectedAddon = function(addon) {
+ // if (options.indexOf(addon) !== -1) {
+ // loadAddon(addon);
+ // }
+ // };
+
+})();;(function () {
+ 'use strict';
+
+ /*globals $, jsbin, CodeMirror, template, ternDefinitions, ternBasicDefs */
+ if (!jsbin.settings.addons.tern) {
+ return;
+ }
+
+ var ternServer;
+ var ternLoaded = {};
+
+ var initTern = function(editor, defs){
+ var keyMap = {
+ 'Ctrl-Q': function(cm) { ternServer.selectName(cm); },
+ 'Ctrl-I': function(cm) { ternServer.showType(cm); },
+ 'Ctrl-Space': function(cm) { ternServer.complete(cm); }
+ };
+ if (typeof defs === 'undefined') {
+ defs = [];
+ }
+ ternServer = new CodeMirror.TernServer({
+ defs: defs,
+ useWorker: false,
+ cm: editor
+ });
+ editor.addKeyMap(keyMap);
+ editor.on('cursorActivity', function(cm) { ternServer.updateArgHints(cm); });
+ };
+
+ var addTernDefinition = function(def) {
+ if (typeof ternServer === 'object') {
+ ternServer.options.defs.push(def);
+ ternServer = new CodeMirror.TernServer({
+ defs: ternServer.options.defs,
+ useWorker: ternServer.options.useWorker,
+ tooltipType: ternServer.options.tooltipType,
+ cm: ternServer.options.cm
+ });
+ }
+ };
+
+ // Load the json defition of the library
+ var loadTernDefinition = function(name, file) {
+ if (!ternLoaded[name]) {
+ $.ajax({
+ url: file,
+ dataType: 'json',
+ success: function(data) {
+ addTernDefinition(data);
+ ternLoaded[name] = true;
+ }
+ });
+ }
+ };
+
+ // Load the actual js library
+ var loadTernFile = function(name, file) {
+ if (!ternLoaded[name]) {
+ $.ajax({
+ url: file,
+ dataType: 'script',
+ success: function(data) {
+ ternServer.server.addFile(name, data);
+ ternLoaded[name] = true;
+ }
+ });
+ }
+ };
+
+ var loadTern = function(editor) {
+ initTern(editor, ternBasicDefs);
+ ternLoaded.ecma5 = true;
+ ternLoaded.browser = true;
+ };
+
+ var searchTernDefinition = function(htmlCode) {
+ for (var i = 0; i < ternDefinitions.length; i++) {
+ if (ternDefinitions[i].match.test(htmlCode)) {
+ if (ternDefinitions[i].type === 'def') {
+ loadTernDefinition(ternDefinitions[i].name, ternDefinitions[i].file);
+ } else {
+ loadTernFile(ternDefinitions[i].name, ternDefinitions[i].file);
+ }
+ }
+ }
+ };
+
+ // Overwrite the autocomplete function to use tern
+ CodeMirror.commands.autocomplete = function(cm) {
+ if (CodeMirror.snippets(cm) === CodeMirror.Pass) {
+ var pos = cm.getCursor();
+ var tok = cm.getTokenAt(pos);
+ var indent = '';
+ if (cm.options.indentWithTabs) {
+ indent = '\t';
+ } else {
+ indent = new Array(cm.options.indentUnit * 1 + 1).join(' ');
+ }
+
+ if (tok.string === ';') {
+ return cm.replaceRange(indent, pos);
+ }
+ if (tok.string.trim() !== '') {
+ return ternServer.complete(cm);
+ }
+ return cm.replaceRange(indent, pos);
+ }
+ };
+
+ CodeMirror.startTern = function() {
+ loadTern(jsbin.panels.panels.javascript.editor);
+ searchTernDefinition(template.html);
+
+ $('#library').bind('change', function () {
+ searchTernDefinition(jsbin.panels.panels.html.getCode());
+ });
+ };
+
+})();;;(function () {
+ var $body = $('body'),
+ loaded = false,
+ $history; // set in hookUserHistory()
+
+ $document.on('history:open', function () {
+ if ($history && jsbin.panels.getVisible().length === 0) {
+ $history.appendTo('body');
+ }
+ }).on('history:close', function () {
+ if ($history === null) {
+ $history = $('#history').detach();
+ }
+ });
+
+ var loadList = function () {
+ if (loaded) return;
+
+ if ($('html').hasClass('public-listing')) {
+ hookUserHistory();
+ } else {
+ $.ajax({
+ dataType: 'html',
+ url: jsbin.root + '/list',
+ error: function () {
+ $('#history').remove();
+ setTimeout(loadList, 500);
+ },
+ success: function (html) {
+ $('#history').remove();
+ $body.append(html);
+ hookUserHistory();
+ loaded = true;
+ }
+ });
+ }
+ };
+
+ var updatePreview = function(url, $iframe) {
+ $iframe.attr('src', url + '/quiet');
+ $iframe.removeAttr('hidden');
+ };
+
+ var updateViewing = function (url, $viewing) {
+ $viewing.text(url);
+ };
+
+ var updateLayout = function ($tbodys, archiveMode) {
+ var $parent = $tbodys.parent();
+ $tbodys
+ .detach()
+ .each(function () {
+ var $tbody = $(this),
+ filter = archiveMode ? '.archived' : ':not(.archived)',
+ $trs = $('tr' + filter, $tbody).filter(':not(.spacer)');
+ if ($trs.length > 0) {
+ $trs.filter('.first').removeClass('first');
+ $tbody.removeClass('hidden');
+ $trs.first().addClass('first');
+ } else {
+ $tbody.addClass('hidden');
+ }
+ })
+ .appendTo($parent);
+ };
+
+ var hookUserHistory = function () {
+ // Loading the HTML from the server may have failed
+ $history = $('#history').detach();
+ if (!$history.length) return $history;
+
+ // Cache some useful elements
+ var $iframe = $('iframe', $history),
+ $viewing = $('#viewing', $history),
+ $bins = $history,
+ $tbodys = $('tbody', $history),
+ $trs = $('tr', $history),
+ $created = $('td.created a', $history),
+ $toggle = $('.toggle_archive', $history),
+ current = null,
+ hoverTimer = null,
+ layoutTimer = null;
+
+ // Load bin from data-edit-url attribute when user clicks on a row
+ $bins.delegate('tr:not(.spacer)', 'click', function () {
+ if (event.shiftKey || event.metaKey) return;
+ window.location = this.getAttribute('data-edit-url');
+ });
+
+ // Archive & un-archive click handlers
+ $bins.delegate('.archive, .unarchive', 'click', function (e) {
+ var $this = $(this),
+ $row = $this.parents('tr');
+ // Instantly update this row and the page layout
+ $row.toggleClass('archived');
+
+ analytics[this.pathname.indexOf('unarchive') === -1 ? 'archive' : 'unarchive'](jsbin.root + $row.data('url'));
+
+ updateLayout($tbodys, $history.hasClass('archive_mode'));
+ // Then send the update to the server
+ $.ajax({
+ type: 'POST',
+ url: $this.attr('href'),
+ error: function () {
+ // Undo if something went wrong
+ alert("Something went wrong, please try again");
+ $row.toggleClass('archived');
+ updateLayout($tbodys, $history.hasClass('archive_mode'));
+ },
+ success: function () {}
+ });
+ return false;
+ });
+
+ // Handle toggling of archive view
+ $toggle.change(function () {
+ $history.toggleClass('archive_mode');
+ var archive = $history.hasClass('archive_mode');
+ analytics.archiveView(archive);
+ updateLayout($tbodys, archive);
+ });
+
+
+ // Load a preview on tr mouseover (delayed by 400ms)
+ $bins.delegate('tr', 'mouseover', function (event) {
+ var $this = $(this),
+ url = $this.attr('data-url');
+ clearTimeout(hoverTimer);
+ if (!$this.hasClass('spacer') && current !== url) {
+ hoverTimer = setTimeout(function () {
+ $trs.removeClass('selected');
+ $this.addClass('selected');
+ current = url;
+ updatePreview(url, $iframe);
+ updateViewing(url, $viewing);
+ }, 400);
+ }
+ return false;
+ });
+
+ // Update the time every 30 secs
+ // Need to replace Z in ISO8601 timestamp with +0000 so prettyDate() doesn't
+ // completely remove it (and parse the date using the local timezone).
+ $('a[pubdate]', $history).attr('pubdate', function (i, val) {
+ return val.replace('Z', '+0000');
+ }).prettyDate();
+ setInterval(function(){
+ $created.prettyDate();
+ }, 30 * 1000);
+
+ // Update the layout straign away
+ setTimeout(function () {
+ updateLayout($tbodys, false);
+ }, 0);
+
+ $document.trigger('history:open');
+
+ return $history;
+ };
+
+ // inside a ready call because history DOM is rendered *after* our JS to improve load times.
+ $(document).on('jsbinReady', function () {
+ if (jsbin.embed) return;
+
+ var $panelButtons = $('#panels a'),
+ $homebtn = $('.homebtn'),
+ panelsVisible = $body.hasClass('panelsVisible');
+
+ var panelCloseIntent = function() {
+ var activeCount = $panelButtons.filter('.active').length;
+ if (activeCount === 1 && $(this).hasClass('active')) {
+ loadList();
+ }
+ };
+
+ // this code attempts to only call the list ajax request only if
+ // the user should want to see the list page - most users will
+ // jump in and jump out of jsbin, and never see this page,
+ // so let's not send this ajax request.
+ //
+ // The list should be loaded when:
+ // - user hovers the home button
+ // - they close all the panels
+ // - they arrive at the page with no panels open
+
+ $homebtn.on('click', loadList);
+ $panelButtons.on('mousedown', panelCloseIntent);
+
+ if (!panelsVisible) {
+ loadList();
+ }
+
+ });
+
+}());
+;var loginVisible = false,
+ dropdownOpen = false,
+ keyboardHelpVisible = false,
+ urlHelpVisible = false;
+
+$document.keydown(function (event) {
+ if (event.which == 27) {//} || (keyboardHelpVisible && event.which == 191 && event.shiftKey && event.metaKey)) {
+ hideOpen();
+ }
+});
+
+function hideOpen() {
+ if (urlHelpVisible) {
+ $body.removeClass('urlHelp');
+ urlHelpVisible = false;
+ analytics.closeMenu('help');
+ } else if (keyboardHelpVisible) {
+ $body.removeClass('keyboardHelp');
+ keyboardHelpVisible = false;
+ analytics.closeMenu('keyboardHelp');
+ } else if (dropdownOpen) {
+ var open = $('.menu.open').removeClass('open');
+ analytics.closeMenu(open.find('.button')[0].hash.substring(1));
+ dropdownOpen = false;
+ } else if (loginVisible) {
+ $('#login').hide();
+ analytics.closeMenu('login');
+ loginVisible = false;
+ }
+}
+
+$document.delegate('.modal', 'click', function (event) {
+ if ($(event.target).is('.modal')) {
+ hideOpen();
+ }
+});;var githubIssue = (function () {
+/*global $:true, jsbin:true */
+ 'use strict';
+
+ function githubIssue() {
+ var url = 'http://github.com/jsbin/jsbin/issues/new';
+ var body = ['Please provide any additional information, record a screencast ',
+ 'with http://quickcast.io or http://screenr.com and attach a screenshot ',
+ 'if possible.\n\n**JS Bin info**\n\n* [%url%](%url%)\n* ',
+ window.navigator.userAgent + '\n',
+ (jsbin.user && jsbin.user.name ? '* ' + jsbin.user.name : ''),
+ '\n'].join('');
+
+ return url + '?body=' + encodeURIComponent(body.replace(/%url%/g, jsbin.getURL()));
+ }
+
+ var $newissue = $('#newissue');
+
+ $('#help').parent().on('open', function () {
+ $newissue.attr('href', githubIssue());
+ });
+
+ return githubIssue;
+})();;$('#download').click(function (event) {
+ event.preventDefault();
+ window.location = jsbin.getURL() + '/download';
+ analytics.download();
+});
+;/* global $ */
+
+$('form.login').submit(function (event) {
+ 'use strict';
+ event.preventDefault();
+
+ var form = $(this),
+ name = form.find('input[name=username]').val(),
+ key = form.find('input[name=password]').val(),
+ email = form.find('input[name=email]').val(),
+ $loginFeedback = form.find('.loginFeedback');
+
+
+ // jsbin.settings.home = name; // will save later
+ $loginFeedback.show().text('Checking...');
+
+ $.ajax({
+ url: form.attr('action'),
+ data: { username: name, key: key, email: email },
+ type: 'POST',
+ dataType: 'json',
+ complete: function (jqXHR) {
+ var data = $.parseJSON(jqXHR.responseText) || {};
+ // cookie is required to share with the server so we can do a redirect on new bin
+ if (jqXHR.status === 200) {
+ if (data.avatar) {
+ $('a.avatar').find('img').remove().end().prepend(' ');
+ }
+ if (data.message) {
+ $loginFeedback.text(data.message);
+ } else {
+ window.location = window.location.pathname + window.location.search;
+ }
+ } else {
+ analytics.login(false);
+ $loginFeedback.text(data.message || ('"' + name + '" has already been taken. Please either double check the password, or choose another username.'));
+ }
+ }
+ });
+});
+;(function () {
+
+ var $html = $(document.documentElement),
+ $tip = $('#tip'),
+ $tipContent = $('p', $tip),
+ tipTimeout;
+
+ var removeTip = function (cb) {
+ $html.removeClass('showtip');
+ $tip.removeClass();
+ $tipContent.html('');
+ $(window).resize();
+ cb && setTimeout(cb, 0);
+ };
+
+ var setTip = function (data) {
+ clearTimeout(tipTimeout);
+ $tipContent.html(data.content);
+ $tip.removeClass().addClass(data.type || 'info');
+ $html.addClass('showtip');
+ if (!data.autohide) return;
+ tipTimeout = setTimeout(function () {
+ removeTip();
+ }, parseInt(data.autohide, 10) || 5 * 1000);
+ };
+
+ /**
+ * Trigger a tip to be shown.
+ *
+ * $document.trigger('tip', 'You have an infinite loop in your HTML.');
+ *
+ * $document.trigger('tip', {
+ * type: 'error',
+ * content: 'Do you even Javascript?',
+ * autohide: 8000
+ * });
+ */
+ $document.on('tip', function (event, data) {
+ var tipData = data;
+ if (typeof data === 'string') {
+ tipData = {};
+ tipData.content = data;
+ tipData.type = 'info';
+ }
+ // If the content and the type haven't changed, just set it again.
+ if ($tipContent.html() === tipData.content &&
+ $tip.hasClass(tipData.type)) return setTip(data);
+ removeTip(function () {
+ setTip(tipData);
+ });
+ });
+
+ $('#tip').on('click', 'a.dismiss', function () {
+ removeTip();
+ return false;
+ });
+
+ // Escape
+ $document.keydown(function (event) {
+ if (event.which == 27) {
+ removeTip();
+ }
+ });
+
+}());;var saving = {
+ todo: {
+ html: false,
+ css: false,
+ javascript: false
+ },
+ _inprogress: false,
+ inprogress: function (inprogress) {
+ if (typeof inprogress === 'undefined') {
+ return saving._inprogress;
+ }
+
+ saving._inprogress = inprogress;
+ if (inprogress === false) {
+ var panels = ['html','css','javascript'],
+ todo;
+
+ var save = function () {
+ var todo = panels.pop();
+ if (todo && saving.todo[todo]) {
+ saving._inprogress = true;
+ updateCode(todo, save);
+ saving.todo[todo] = false;
+ } else if (todo) {
+ save();
+ }
+ };
+
+ save();
+ }
+ }
+};
+
+// to allow for download button to be introduced via beta feature
+$('a.save').click(function (event) {
+ event.preventDefault();
+
+ analytics.milestone();
+ // if save is disabled, hitting save will trigger a reload
+ var ajax = true;
+ if (jsbin.saveDisabled === true) {
+ ajax = false;
+ }
+ saveCode('save', ajax);
+
+ return false;
+});
+
+var $shareLinks = $('#share .link');
+
+$panelCheckboxes = $('#sharemenu #sharepanels input');
+
+function updateSavedState() {
+ 'use strict';
+ var mapping = {
+ live: 'output',
+ javascript: 'js',
+ css: 'css',
+ html: 'html',
+ console: 'console'
+ };
+ var query = $panelCheckboxes.filter(':checked').map(function () {
+ return mapping[this.getAttribute('data-panel')];
+ }).get().join(',');
+ $shareLinks.each(function () {
+ var path = this.getAttribute('data-path');
+ var url = jsbin.getURL(false, path === '/') + path + (query && this.id !== 'livepreview' ? '?' + query : ''),
+ nodeName = this.nodeName;
+ var hash = panels.getHighlightLines();
+
+ if (hash) {
+ hash = '#' + hash;
+ }
+
+ if (nodeName === 'A') {
+ this.href = url;
+ } else if (nodeName === 'INPUT') {
+ this.value = url;
+ if (path === '/edit') {
+ this.value += hash;
+ }
+ } else if (nodeName === 'TEXTAREA') {
+ this.value = ('' + documentTitle + ' <' + 'script src="' + jsbin.static + '/js/embed.js"><' + '/script>').replace(/<>"&/g, function (m) {
+ return {
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ '&': '&'
+ }[m];
+ });
+ }
+ });
+}
+
+$('#sharemenu').bind('open', function () {
+ updateSavedState();
+});
+
+$document.on('saved', function () {
+ updateSavedState();
+ $shareLinks.closest('.menu').removeClass('hidden');
+
+ $('#jsbinurl').attr('href', jsbin.getURL()).removeClass('hidden');
+ $('#clone').removeClass('hidden');
+});
+
+var saveChecksum = jsbin.state.checksum || sessionStorage.getItem('checksum') || false;
+
+// store it back on state
+jsbin.state.checksum = saveChecksum;
+
+if (saveChecksum) {
+ // remove the disabled class, but also remove the cancelling event handlers
+ $('#share div.disabled').removeClass('disabled').unbind('click mousedown mouseup');
+} else {
+ $('#share div.disabled').one('click', function (event) {
+ event.preventDefault();
+ $('a.save').click();
+ });
+}
+
+$document.one('saved', function () {
+ $('#share div.disabled').removeClass('disabled').unbind('click mousedown mouseup');
+});
+
+function onSaveError(jqXHR, panelId) {
+ if (jqXHR.status === 413) {
+ // Hijack the tip label to show an error message.
+ $('#tip p').html('Sorry this bin is too large for us to save');
+ $(document.documentElement).addClass('showtip');
+ } else if (jqXHR.status === 403) {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'I think there\'s something wrong with your session and I\'m unable to save. Refresh to fix this , you will not lose your code.'
+ });
+ } else if (panelId) {
+ if (panelId) savingLabels[panelId].text('Saving...').animate({ opacity: 1 }, 100);
+ window._console.error({message: 'Warning: Something went wrong while saving. Your most recent work is not saved.'});
+ }
+}
+
+
+
+// only start live saving it they're allowed to (whereas save is disabled if they're following)
+if (!jsbin.saveDisabled) {
+ $('.code.panel .label .name').append('Saved ');
+
+ var savingLabels = {
+ html: $('.panel.html .name span'),
+ javascript: $('.panel.javascript .name span'),
+ css: $('.panel.css .name span')
+ };
+
+ $document.bind('jsbinReady', function () {
+ jsbin.panels.allEditors(function (panel) {
+ panel.on('processor', function () {
+ // if the url doesn't match the root - i.e. they've actually saved something then save on processor change
+ if (jsbin.root !== jsbin.getURL()) {
+ $document.trigger('codeChange', [{ panelId: panel.id }]);
+ }
+ });
+ });
+
+ $document.bind('codeChange', function (event, data) {
+ // savingLabels[data.panelId].text('Saving');
+ if (savingLabels[data.panelId]) {
+ savingLabels[data.panelId].css({ 'opacity': 0 }).stop(true, true);
+ }
+ });
+
+ $document.bind('saveComplete', throttle(function (event, data) {
+ // show saved, then revert out animation
+ savingLabels[data.panelId]
+ .text('Saved')
+ .stop(true, true)
+ .animate({ opacity: 1 }, 100)
+ .delay(1200)
+ .animate({ opacity: 0 }, 500);
+ }, 500));
+
+ $document.bind('codeChange', throttle(function (event, data) {
+ if (!data.panelId) {
+ return;
+ }
+
+ if (jsbin.state.deleted) {
+ return;
+ }
+
+ var panelId = data.panelId;
+
+ jsbin.panels.savecontent();
+
+ if (saving.inprogress()) {
+ // queue up the request and wait
+ saving.todo[panelId] = true;
+ return;
+ }
+
+ saving.inprogress(true);
+
+ // We force a full save if there's no checksum OR if there's no bin code/url
+ if (!saveChecksum || !jsbin.state.code) {
+ // create the bin and when the response comes back update the url
+ saveCode('save', true);
+ } else {
+ updateCode(panelId);
+ }
+ }, 250));
+ });
+} else {
+ $document.one('jsbinReady', function () {
+ var shown = false;
+ if (!jsbin.embed && !jsbin.sandbox) {
+ $document.on('codeChange', function (event, data) {
+ if (!data.onload && !shown && data.origin !== 'setValue') {
+ shown = true;
+ var ismac = navigator.userAgent.indexOf(' Mac ') !== -1;
+ var cmd = ismac ? '⌘' : 'ctrl';
+ var shift = ismac ? '⇧' : 'shift';
+ var plus = ismac ? '' : '+';
+
+ $document.trigger('tip', {
+ type: 'notification',
+ content: 'You\'re currently viewing someone else\'s live stream, but you can clone your own copy (' + cmd + plus + shift + plus + 'S) at any time to save your edits'
+ });
+ }
+ });
+ }
+ });
+}
+
+function compressKeys(keys, obj) {
+ obj.compressed = keys;
+ keys.split(',').forEach(function (key) {
+ obj[key] = LZString.compressToUTF16(obj[key]);
+ });
+}
+
+function updateCode(panelId, callback) {
+ var panelSettings = {};
+
+ if (jsbin.state.processors) {
+ panelSettings.processors = jsbin.state.processors;
+ }
+
+ var data = {
+ code: jsbin.state.code,
+ revision: jsbin.state.revision,
+ method: 'update',
+ panel: panelId,
+ content: editors[panelId].getCode(),
+ checksum: saveChecksum,
+ settings: JSON.stringify(panelSettings),
+ };
+
+ if (jsbin.settings.useCompression) {
+ compressKeys('content', data);
+ }
+
+ $.ajax({
+ url: jsbin.getURL() + '/save',
+ data: data,
+ type: 'post',
+ dataType: 'json',
+ headers: {'Accept': 'application/json'},
+ success: function (data) {
+ $document.trigger('saveComplete', { panelId: panelId });
+ if (data.error) {
+ saveCode('save', true, function (data) {
+ // savedAlready = data.checksum;
+ });
+ }
+ },
+ error: function (jqXHR) {
+ onSaveError(jqXHR, panelId);
+ },
+ complete: function () {
+ saving.inprogress(false);
+ callback && callback();
+ }
+ });
+}
+
+$('a.clone').click(function (event) {
+ event.preventDefault();
+
+ // save our panel layout - assumes our user is happy with this layout
+ jsbin.panels.save();
+ analytics.clone();
+
+ var $form = setupform('save,new');
+ $form.submit();
+
+ return false;
+});
+
+function setupform(method) {
+var $form = $('form#saveform').empty()
+ .append(' ')
+ .append(' ')
+ .append(' ')
+ .append(' ')
+ .append(' ')
+ .append(' ');
+
+ var settings = {};
+
+ if (jsbin.state.processors) {
+ settings.processors = jsbin.state.processors;
+ }
+
+ // this prevents new revisions forking off the welcome bin
+ // because it's looking silly!
+ if (jsbin.state.code === 'welcome') {
+ $form.attr('action', '/save');
+ }
+
+ $form.find('input[name=settings]').val(JSON.stringify(settings));
+ $form.find('input[name=javascript]').val(editors.javascript.getCode());
+ $form.find('input[name=css]').val(editors.css.getCode());
+ $form.find('input[name=html]').val(editors.html.getCode());
+ $form.find('input[name=method]').val(method);
+
+ return $form;
+}
+
+function pad(n){
+ return n<10 ? '0'+n : n
+}
+
+function ISODateString(d){
+ return d.getFullYear()+'-'
+ + pad(d.getMonth()+1)+'-'
+ + pad(d.getDate())+'T'
+ + pad(d.getHours())+':'
+ + pad(d.getMinutes())+':'
+ + pad(d.getSeconds())+'Z'
+}
+
+function saveCode(method, ajax, ajaxCallback) {
+ // create form and post to it
+ var $form = setupform(method);
+ // save our panel layout - assumes our user is happy with this layout
+ jsbin.panels.save();
+ jsbin.panels.saveOnExit = true;
+
+ var data = $form.serializeArray().reduce(function(obj, data) {
+ obj[data.name] = data.value;
+ return obj;
+ }, {});
+
+ if (jsbin.settings.useCompression) {
+ compressKeys('html,css,javascript', data);
+ }
+
+ if (ajax) {
+ $.ajax({
+ url: $form.attr('action'),
+ data: data,
+ dataType: 'json',
+ type: 'post',
+ headers: {'Accept': 'application/json'},
+ success: function (data) {
+ var $binGroup,
+ edit;
+
+ $form.attr('action', data.url + '/save');
+ if (ajaxCallback) {
+ ajaxCallback(data);
+ }
+
+ sessionStorage.setItem('checksum', data.checksum);
+ saveChecksum = data.checksum;
+
+ jsbin.state.checksum = saveChecksum;
+ jsbin.state.code = data.code;
+ jsbin.state.revision = data.revision;
+ jsbin.state.metadata = { name: jsbin.user.name };
+
+ // getURL(true) gets the jsbin without the root attached
+ // $binGroup = $('#history tr[data-url="' + jsbin.getURL(true) + '"]');
+ // edit = data.edit.replace(location.protocol + '//' + window.location.host, '') + window.location.search;
+ // $binGroup.find('td.url a span.first').removeClass('first');
+ // $binGroup.before('' + data.code + '/ ' + data.revision + '/Just now ' + data.title + ' ');
+
+
+ if (window.history && window.history.pushState) {
+ // updateURL(edit);
+ var hash = panels.getHighlightLines();
+ if (hash) hash = '#' + hash;
+ window.history.pushState(null, '', jsbin.getURL() + '/edit' + hash);
+ sessionStorage.setItem('url', jsbin.getURL());
+ } else {
+ window.location.hash = data.edit;
+ }
+
+ $document.trigger('saved');
+ },
+ error: function (jqXHR) {
+ onSaveError(jqXHR, null);
+ },
+ complete: function () {
+ saving.inprogress(false);
+ }
+ });
+ } else {
+ $form.submit();
+ }
+}
+
+/**
+ * Returns the similar part of two strings
+ * @param {String} a first string
+ * @param {String} b second string
+ * @return {String} common substring
+ */
+function sameStart(a, b) {
+ if (a == b) return a;
+
+ var tmp = b.slice(0, 1);
+ while (a.indexOf(b.slice(0, tmp.length + 1)) === 0) {
+ tmp = b.slice(0, tmp.length + 1);
+ }
+
+ return tmp;
+}
+
+/*
+
+// refresh the window when we popstate, because for now we don't do an xhr to
+// inject the panel content...yet.
+window.onpopstate = function onpopstate(event) {
+ // ignore the first popstate event, because that comes from the browser...
+ if (!onpopstate.first) window.location.reload();
+ else onpopstate.first = false;
+};
+
+onpopstate.first = true;
+
+function updateURL(path) {
+ var old = location.pathname,
+ back = true,
+ same = sameStart(old, path);
+ sameAt = same.length;
+
+ if (updateURL.timer) window.cancelAnimationFrame(updateURL.timer);
+
+ var run = function () {
+ if (location.pathname !== path) {
+ updateURL.timer = window.requestAnimationFrame(run);
+ }
+
+ if (location.pathname !== same) {
+ if (back) {
+ history.replaceState({ path: path }, '', location.pathname.slice(0, -1));
+ } else {
+ history.replaceState({ path: path }, '', path.slice(0, location.pathname.length + 1));
+ }
+ } else {
+ back = false;
+ history.replaceState({ path: path }, '', path.slice(0, sameAt + 2));
+ }
+ };
+
+ history.pushState({ path: path }, '', location.pathname.slice(0, -1));
+
+ run();
+}
+
+*/
+;var $startingpoint = $('a.startingpoint').click(function (event) {
+ event.preventDefault();
+ if (localStorage) {
+ analytics.saveTemplate();
+ localStorage.setItem('saved-javascript', editors.javascript.getCode());
+ localStorage.setItem('saved-html', editors.html.getCode());
+ localStorage.setItem('saved-css', editors.css.getCode());
+
+ $document.trigger('tip', {
+ type: 'notification',
+ content: 'Starting template updated and saved',
+ autohide: 3000
+ });
+ } else {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'Saving templates isn\'t supported in this browser I\'m afraid. Sorry'
+ });
+ }
+ return false;
+});
+
+// if (localStorage && localStorage['saved-html']) {
+ // $startingpoint.append('')
+// }
+
+$('a.disabled').on('click mousedown mouseup', function (event) {
+ event.stopImmediatePropagation();
+ return false;
+});
+
+$('#loginbtn').click(function () {
+ analytics.login();
+ $(this).toggleClass('open');
+ // $('#login').show();
+ // loginVisible = true;
+ // return false;
+});
+
+$('a.logout').click(function (event) {
+ event.preventDefault();
+
+ // We submit a form here because I can't work out how to style the button
+ // element in the form to look the same as the anchor. Ideally we would
+ // remove that and just let the form submit itself...
+ $(this.hash).submit();
+ // Clear session storage so private bins wont be cached.
+ for (i = 0; i < sessionStorage.length; i++) {
+ key = sessionStorage.key(i);
+ if (key.indexOf('jsbin.content.') === 0) {
+ sessionStorage.removeItem(key);
+ }
+ }
+});
+
+$('.homebtn').click(function (event, data) {
+ if (this.id === 'avatar') {
+ analytics.openFromAvatar();
+ } else if (this.id === 'profile') {
+ analytics.openFromAvatar();
+ $(this).closest('.open').removeClass('open');
+ } else {
+ analytics.open(data);
+ }
+
+ jsbin.panels.hideAll();
+ return false;
+});
+
+var $lockrevision = $('.lockrevision').on('click', function (event) {
+ event.preventDefault();
+ if (!$lockrevision.data('lock')) {
+ analytics.lock();
+ $lockrevision.removeClass('icon-unlocked').addClass('icon-lock');
+ $lockrevision.html('This bin is now locked from further changes ');
+ $lockrevision.data('locked', true);
+ saveChecksum = false;
+ $document.trigger('locked');
+ }
+ return false;
+}).on('mouseup', function () {
+ return false;
+});
+
+$document.on('saved', function () {
+ $lockrevision.removeClass('icon-lock').addClass('icon-unlocked').data('locked', false);
+ $lockrevision.html('Click to lock and prevent further changes ');
+});
+
+$('#share input[type=text], #share textarea').on('beforecopy', function (event) {
+ analytics.share('copy', this.getAttribute('data-path').substring(1) || 'output');
+});
+
+var $panelCheckboxes = $('#sharepanels input').on('change click', updateSavedState);
+$('#sharemenu').bind('open', function () {
+ // analytics.openShare();
+ // $lockrevision.removeClass('icon-unlock').addClass('icon-lock');
+
+ $panelCheckboxes.attr('checked', false);
+ jsbin.panels.getVisible().forEach(function (panel) {
+ $panelCheckboxes.filter('[data-panel="' + panel.id + '"]').attr('checked', true).change();
+ });
+
+});
+
+var dropdownOpen = false,
+ onhover = false,
+ menuDown = false;
+
+function opendropdown(el) {
+ var menu;
+ if (!dropdownOpen) {
+ menu = $(el).closest('.menu').addClass('open').trigger('open');
+ // $body.addClass('menuinfo');
+ analytics.openMenu(el.hash.substring(1));
+ var input = menu.find(':text:visible:first').focus()[0];
+ if (input) setTimeout(function () {
+ input.select();
+ }, 0);
+ dropdownOpen = el;
+ }
+}
+
+function closedropdown() {
+ menuDown = false;
+ if (dropdownOpen) {
+ dropdownButtons.closest('.menu').removeClass('open').trigger('close');
+ // $body.removeClass('menuinfo');
+ dropdownOpen = false;
+ onhover = false;
+ }
+}
+
+var dropdownButtons = $('.button-dropdown, .button-open').mousedown(function (e) {
+ $dropdownLinks.removeClass('hover');
+ if (dropdownOpen && dropdownOpen !== this) {
+ closedropdown();
+ }
+ if (!dropdownOpen) {
+ menuDown = true;
+ opendropdown(this);
+ }
+ e.preventDefault();
+ return false;
+}).mouseup(function () {
+ if (menuDown) return false;
+}).click(function () {
+ if (!menuDown) {
+ analytics.closeMenu(this.hash.substring(1));
+ closedropdown();
+ }
+ menuDown = false;
+ return false;
+});
+
+$('#actionmenu').click(function () {
+ dropdownOpen = true;
+});
+
+var ignoreUp = false;
+$body.bind('mousedown', function (event) {
+ if (dropdownOpen) {
+ if ($(event.target).closest('.menu').length) {
+ ignoreUp = true;
+ }
+ }
+}).bind('click mouseup', function (event) {
+ if (dropdownOpen && !ignoreUp) {
+ if (!$(event.target).closest('.menu').length) {
+ closedropdown();
+ return false;
+ }
+ }
+ ignoreUp = false;
+});
+
+var fromClick = false;
+var $dropdownLinks = $('.dropdownmenu a, .dropdownmenu .button').mouseup(function () {
+ setTimeout(closedropdown, 0);
+ analytics.selectMenu(this.getAttribute('data-label') || this.hash.substring(1) || this.href);
+ if (!fromClick) {
+ if (this.hostname === window.location.hostname) {
+ if ($(this).triggerHandler('click') !== false) {
+ window.location = this.href;
+ }
+ } else {
+ if (this.getAttribute('target')) {
+ window.open(this.href);
+ } else {
+ window.location = this.href;
+ }
+ }
+ }
+ fromClick = false;
+}).mouseover(function () {
+ $dropdownLinks.removeClass('hover');
+ $(this).addClass('hover');
+}).mousedown(function () {
+ fromClick = true;
+});
+
+$('#jsbinurl').click(function (e) {
+ setTimeout(function () {
+ jsbin.panels.panels.live.hide();
+ }, 0);
+});
+
+$('#runwithalerts').click(function (event, data) {
+ analytics.run(data);
+ if (editors.console.visible) {
+ editors.console.render(true);
+ } else {
+ renderLivePreview(true);
+ }
+ return false;
+});
+
+$('#runconsole').click(function () {
+ analytics.runconsole();
+ editors.console.render(true);
+ return false;
+});
+
+$('#clearconsole').click(function () {
+ jsconsole.clear();
+ return false;
+});
+
+$('#showhelp').click(function () {
+ $body.toggleClass('keyboardHelp');
+ keyboardHelpVisible = $body.is('.keyboardHelp');
+ if (keyboardHelpVisible) {
+ // analytics.help('keyboard');
+ }
+ return false;
+});
+
+$('#showurls').click(function () {
+ $body.toggleClass('urlHelp');
+ urlHelpVisible = $body.is('.urlHelp');
+ if (urlHelpVisible) {
+ // analytics.urls();
+ }
+ return false;
+});
+
+$('.code.panel > .label > span.name').dblclick(function () {
+ jsbin.panels.allEditors(function (panel) {
+ var lineNumbers = !panel.editor.getOption('lineNumbers');
+ panel.editor.setOption('lineNumbers', lineNumbers);
+ jsbin.settings.editor.lineNumbers = lineNumbers;
+ });
+});
+
+$('#createnew').click(function (event) {
+ event.preventDefault();
+ var i, key;
+ analytics.createNew();
+ // FIXME this is out and out [cr]lazy....
+ jsbin.panels.savecontent = function(){};
+ for (i = 0; i < sessionStorage.length; i++) {
+ key = sessionStorage.key(i);
+ if (key.indexOf('jsbin.content.') === 0) {
+ sessionStorage.removeItem(key);
+ }
+ }
+
+ // clear out the write checksum too
+ sessionStorage.removeItem('checksum');
+
+ jsbin.panels.saveOnExit = true;
+
+ // first try to restore their default panels
+ jsbin.panels.restore();
+
+ // if nothing was shown, show html & live
+ setTimeout(function () {
+ if (jsbin.panels.getVisible().length === 0) {
+ jsbin.panels.panels.html.show();
+ jsbin.panels.panels.live.show();
+ }
+ window.location = jsbin.root;
+ }, 0);
+});
+
+var $privateButton = $('#control a.visibilityToggle#private');
+var $publicButton = $('#control a.visibilityToggle#public');
+
+var $visibilityButtons = $('#control a.visibilityToggle').click(function(event) {
+ event.preventDefault();
+
+ var visibility = $(this).data('vis');
+
+ $.ajax({
+ url: jsbin.getURL() + '/' + visibility,
+ type: 'post',
+ success: function (data) {
+
+ $document.trigger('tip', {
+ type: 'notification',
+ content: 'This bin is now ' + visibility,
+ autohide: 6000
+ });
+
+ $visibilityButtons.css('display', 'none');
+
+ if (visibility === 'public') {
+ $privateButton.css('display', 'block');
+ } else {
+ $publicButton.css('display', 'block');
+ }
+
+ }
+ });
+});
+
+$('form.login').closest('.menu').bind('close', function () {
+ $(this).find('.loginFeedback').empty().hide();
+ $('#login').removeClass('forgot');
+});
+
+$('#lostpass').click(function (e) {
+ $('#login').addClass('forgot').find('input[name=email]').focus();
+ return false;
+});
+
+jsbin.settings.includejs = jsbin.settings.includejs === undefined ? true : jsbin.settings.includejs;
+
+$('#enablejs').change(function () {
+ jsbin.settings.includejs = this.checked;
+ analytics.enableLiveJS(jsbin.settings.includejs);
+ editors.live.render();
+}).attr('checked', jsbin.settings.includejs);
+
+if (jsbin.settings.hideheader) {
+ $body.addClass('hideheader');
+}
+
+var cancelUp = false;
+$('form input, form textarea').focus(function () {
+ this.select();
+ cancelUp = true;
+}).mouseup(function () {
+ if (cancelUp) {
+ cancelUp = false;
+ return false;
+ }
+});
+
+if (window.location.hash) {
+ $('a[href$="' + window.location.hash + '"]').mousedown();
+}
+
+var ismac = navigator.userAgent.indexOf(' Mac ') !== -1,
+ mackeys = {
+ 'ctrl': '⌘',
+ 'shift': '⇧',
+ 'del': '⌫'
+ };
+
+$('#control').find('a[data-shortcut]').each(function () {
+ var $this = $(this),
+ data = $this.data();
+
+ var key = data.shortcut;
+ if (ismac) {
+ key = key.replace(/ctrl/i, mackeys.ctrl).replace(/shift/, mackeys.shift).replace(/del/, mackeys.del).replace(/\+/g, '').toUpperCase();
+ }
+
+ $this.append('' + key + ' ');
+});
+
+(function () {
+
+var re = {
+ head: //i,
+ metaContent: /content=".*?"/i
+};
+
+var metatag = ' \n';
+
+$('#addmeta').click(function () {
+ // if not - insert
+ //
+ // if meta description is in the HTML, highlight it
+ var editor = jsbin.panels.panels.html,
+ cm = editor.editor,
+ html = editor.getCode();
+
+ if (!re.meta.test(html)) {
+ if (re.head.test(html)) {
+ html = html.replace(re.head, '' + jsbin.shareRoot + ' '
+ });
+ },
+ error: function (xhr) {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'There was a problem publishing to your vanity URL. Can you try again or file a new issue ?'
+ });
+ }
+ })
+});
+
+$('a.deletebin').on('click', function (e) {
+ e.preventDefault();
+ if (confirm('Delete this bin?')) {
+ analytics['delete']();
+ $.ajax({
+ type: 'post',
+ url: jsbin.getURL() + '/delete',
+ data: { checksum: jsbin.state.checksum },
+ success: function () {
+ jsbin.state.deleted = true;
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'This bin is now deleted. You can continue to edit, but once you leave the bin can\'t be retrieved'
+ });
+ },
+ error: function (xhr) {
+ if (xhr.status === 403) {
+ $document.trigger('tip', {
+ content: 'You don\'t own this bin, so you can\'t delete it.',
+ autohide: 5000
+ });
+ }
+ }
+ });
+
+ }
+});
+
+$('a.archivebin').on('click', function (e) {
+ e.preventDefault();
+ archive();
+});
+
+$('a.unarchivebin').on('click', function (e) {
+ e.preventDefault();
+ archive(false);
+});
+
+}());
+;function allowDrop(holder) {
+ holder.ondragover = function () {
+ return false;
+ };
+
+ holder.ondragend = function () {
+ return false;
+ };
+
+ var jstypes = {
+ 'javascript': 1,
+ 'coffeescript': 1,
+ 'coffee': 1,
+ 'js' :1
+ },
+ csstypes = {
+ 'css': 1,
+ 'less': 1,
+ 'sass': 1
+ };
+
+ holder.ondrop = function (e) {
+ e.preventDefault();
+
+ var file = e.dataTransfer.files[0],
+ reader = new FileReader();
+ reader.onload = function (event) {
+ // put JS in the JavaScript panel
+ var type = file.type ? file.type.toLowerCase().replace(/^(text|application)\//, '') : file.name.toLowerCase().replace(/.*\./g, ''),
+ panelId = 'html',
+ panel = editors[panelId],
+ syncCode = event.target.result,
+ scroller = null;
+
+ if (jstypes[type]) {
+ panelId = 'javascript';
+ } else if (csstypes[type]) {
+ panelId = 'css';
+ }
+
+ panel = editors[panelId];
+ scroller = panel.editor.scroller;
+
+ panel.setCode(event.target.result);
+ panel.show();
+
+ try {
+ // now kick off - basically just doing a copy and paste job from @wookiehangover - thanks man! :)
+ var worker = new Worker(jsbin.root + '/js/editors/sync-worker.js');
+
+ // pass the worker the file object
+ worker.postMessage(file);
+
+ panel.$el.find('> .label').append(' (live: edit & save in your fav editor) ');
+
+ // bind onmessage handler
+ worker.onmessage = function (event) {
+ var top = scroller.scrollTop;
+ panel.setCode(event.data.body);
+ scroller.scrollTop = top;
+ syncCode = event.data.body;
+ };
+
+ /* FIXME for now, there's a bug in CodeMirror 2 whereby binding the
+ onKeyEvent causes all cursor keys to be ate :( */
+ // panel.editor.setOption('onKeyEvent', function (event) {
+ // if (syncCode !== panel.editor.getCode()) {
+ // worker.terminate();
+ // console.log('terminate');
+ // panel.$el.find('> .label small').remove();
+ // panel.editor.setOption('onKeyEvent', function () { return true });
+ // }
+ // return event;
+ // });
+ } catch (e) {
+ // fail on the awesomeness...oh well
+ }
+ };
+
+ reader.readAsText(file);
+
+ return false;
+ };
+}
+
+// test for dnd and file api first
+if (!!(window.File && window.FileList && window.FileReader)) allowDrop(document.body);
+;var Gist = (function () { // jshint ignore:line
+ /*global $:true, jsbin:true, processors:true, $document*/
+ 'use strict';
+
+ // Only allow gist import/export if CORS is supported
+ var CORS = !!('withCredentials' in new XMLHttpRequest() ||
+ typeof XDomainRequest !== 'undefined');
+ if (!CORS) {
+ return $(function () {
+ $('#export-as-gist').remove();
+ });
+ }
+
+ var Gist = function (id) {
+ var gist = this,
+ token = '';
+ gist.code = {};
+ if (jsbin.user && jsbin.user.github_token) { // jshint ignore:line
+ token = '?access_token=' + jsbin.user.github_token; // jshint ignore:line
+ }
+ $.get('https://api.github.com/gists/' + id + token, function (data) {
+ if (!data) {return;}
+ $.each(data.files, function (fileName, fileData) {
+ var ext = fileName.split('.').slice(-1).join('');
+ gist.code[ext] = fileData.content;
+ });
+ gist.setCode();
+ });
+ return this;
+ };
+
+ Gist.prototype.setCode = function () {
+ var gist = this;
+ $.each(gist.code, function (ext, data) {
+ var processorInit = jsbin.processors.findByExtension(ext),
+ target = processorInit.target || processorInit.id,
+ panel = jsbin.panels.panels[target];
+ if (!panel) {return;}
+ processors.set(target, processorInit.id);
+ jsbin.saveDisabled = true;
+ panel.setCode(data);
+ jsbin.saveDisabled = false;
+ });
+ };
+
+ /**
+ * Export as gist
+ */
+
+ $('a.export-as-gist').click(function () {
+ var gist = {
+ public: true,
+ files: {}
+ };
+ var panels = [
+ { panel: 'html' },
+ { panel: 'css' },
+ { panel: 'javascript', extension: 'js' }
+ ];
+
+ // Add files to gist for each panel
+ panels.forEach(function (data) {
+ var code;
+ try {
+ code = jsbin.panels.panels[data.panel].getCode();
+ } catch(e) {}
+ if (!code || !code.length) {return;}
+ // Figure out what the file extension should be according to the processor
+ var ext = data.extension || data.panel,
+ processor = jsbin.panels.panels[data.panel].processor;
+ if (processor && processor.extensions) {
+ ext = processor.extensions[0] || processor.name;
+ }
+ // Build a file name
+ var file = ['jsbin', (jsbin.state.code || 'untitled'), ext].join('.');
+ gist.files[file] = {
+ content: code
+ };
+ });
+
+ var token = '';
+ if (jsbin.user && jsbin.user.github_token) { // jshint ignore:line
+ token = '?access_token=' + jsbin.user.github_token; // jshint ignore:line
+ }
+
+ $.ajax({
+ type: 'POST',
+ url: 'https://api.github.com/gists' + token,
+ data: JSON.stringify(gist),
+ dataType: 'json',
+ crossDomain: true,
+ success: function (data) {
+ $document.trigger('tip', {
+ type: 'notification',
+ content: 'Gist created! Open in new tab. ' // jshint ignore:line
+ });
+ },
+ error: function (xhr, status) {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'Error: ' + status
+ });
+ }
+ });
+ // return false becuase there's weird even stuff going on. ask @rem.
+ return false;
+ });
+
+ return Gist;
+
+}());
+;function spinner(element) {
+ 'use strict';
+ var c = element || document.createElement('canvas');
+ if (!c.getContext) {
+ return false;
+ }
+ var ctx = c.getContext('2d');
+
+ var rafID = null;
+
+ c.height = c.width = 11;
+
+ var TORADIAN = Math.PI / 180;
+ var w = c.width;
+ var h = c.height;
+ var deg = 0;
+ var r = 4;
+ var speed = 4;
+ var tailspeed = 1/7;
+
+ ctx.strokeStyle = 'rgba(0,0,0,.5)';
+ ctx.lineWidth = 1.5;
+
+ var last = true;
+ function draw() {
+ rafID = window.requestAnimationFrame(draw);
+
+ deg += speed;
+
+ var start = ((deg * tailspeed)) % 360; // A / TAIL
+ var end = deg % 360; // B / HEAD
+ var flip = end === start;
+
+ if (flip) {
+ last = !last;
+ // this prevents a single blank frame when
+ // the start and end have the same value
+ start -= 1;
+ }
+
+ ctx.fillStyle = 'white';
+ ctx.strokeStyle = '#111';
+ ctx.fillRect(w/2 - r*2, h/2 - r*2, r * 4, r * 4);
+ ctx.beginPath();
+ ctx.arc(w/2 + 0.5, h/2 + 0.5, r, start * TORADIAN, end * TORADIAN, last);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#999';
+ ctx.beginPath();
+ ctx.arc(w/2 + 0.5, h/2 + 0.5, r, end * TORADIAN, start * TORADIAN, last);
+ ctx.stroke();
+
+ ctx.closePath();
+
+ }
+
+ return {
+ element: c,
+ start: draw,
+ stop: function () {
+ window.cancelAnimationFrame(rafID);
+ }
+ };
+};(function () {
+ /*global $:true, jsbin:true, prettyDate:true, EventSource:true, throttle:true, $document:true*/
+ 'use strict';
+
+ // don't insert this on embeded views
+ if (jsbin.embed) {
+ return;
+ }
+
+ var $template = $('#infocard'); // donkey way of cloning from template
+ var $header = $template.find('header');
+ var canvas = $header.find('canvas')[0];
+ var s = spinner(canvas);
+
+ if ($template.length === 0) {
+ return;
+ }
+
+ function updateInfoCard(event) {
+ var meta = jsbin.state.metadata || {};
+ var classes = [];
+ var es = null;
+ var owner = false;
+
+ if (meta.name) {
+ $header.find('.name b').html(meta.name);
+ $header.find('img').attr('src', meta.avatar);
+ classes.push(meta.name);
+ }
+
+ if (jsbin.state.checksum || (jsbin.user && (meta.name === jsbin.user.name))) {
+ owner = true;
+ classes.push('author');
+ }
+
+ if (s) {
+ s.stop();
+ }
+
+ if (!jsbin.state.streaming || owner === true) {
+ $header.find('time').html(event ? 'just now' : prettyDate(meta.last_updated));
+ } else if (owner === false) {
+ $header.find('time').html('Streaming');
+ classes.push('streaming');
+ if (s) {
+ s.start();
+ }
+ }
+
+ if (!jsbin.checksum) {
+ classes.push('meta');
+ }
+
+ if (meta.pro) {
+ classes.push('pro');
+ }
+
+ $header.find('.visibility').text(meta.visibility);
+
+ if (meta.visibility === 'private') {
+ classes.push('private');
+ } else if (meta.visibility === 'public') {
+ classes.push('public');
+ } // TODO handle team
+
+ if (jsbin.state.code) {
+ $template.addClass(classes.join(' ')).parent().removeAttr('hidden');
+
+ $header.click(function (e) {
+ e.preventDefault();
+ $template.toggleClass('open');
+ });
+
+ var viewers = 0;
+
+ if (jsbin.state.streaming) {
+ if (window.EventSource && owner) {
+ listenStats();
+ var url = jsbin.getURL();
+ $document.on('saved', function () {
+ var newurl = window.location.toString();
+ if (url !== newurl) {
+ es.close();
+ listenStats();
+ }
+ });
+ } else if (jsbin.saveDisabled === true && window.location.pathname.slice(-5) === '/edit') {
+ $.getScript(jsbin.static + '/js/spike.js?' + jsbin.version);
+ $document.on('stats', throttle(updateStats, 1000));
+ }
+ }
+ }
+
+ function updateStats(event, _data) {
+ var data = _data ? JSON.parse(_data) : JSON.parse(event.data);
+
+ if (data.connections > 0 && viewers === 0) {
+ $template.addClass('viewers');
+ }
+
+ if (viewers !== data.connections) {
+ var $b = $header.find('.viewers b').removeClass('up down').html('' + data.connections + ' ' + viewers + ' ' + data.connections + ' '),
+ c = viewers > data.connections ? 'down' : 'up';
+ setTimeout(function () {
+ $b.addClass(c);
+ }, 0);
+ }
+
+ viewers = data.connections;
+
+ if (viewers === 0) {
+ setTimeout(function () {
+ $template.removeClass('viewers');
+ }, 250);
+ }
+
+ }
+
+ function listenStats() {
+ es = new EventSource(jsbin.getURL() + '/stats?checksum=' + jsbin.state.checksum);
+ es.addEventListener('stats', throttle(updateStats, 1000));
+ }
+ }
+
+ updateInfoCard();
+ $document.bind('saved', updateInfoCard);
+})();
+;(function () {
+ 'use strict';
+
+ function getExpires() {
+ var d = new Date();
+
+ // expires in 1 hour from now
+ d.setTime(+d + 1000 * 60 * 60);
+ return d.toUTCString();
+ }
+
+ function save() {
+ var url = jsbin.getURL(true) + '/edit';
+ if (url) {
+ document.cookie = 'last=' + encodeURIComponent(url) + '; expires=' + getExpires() + '; path=/';
+ } else {
+ // expire cookie
+ document.cookie = 'last=""; expires=-1; path=/';
+ }
+ }
+
+ function readCookie(name) {
+ var nameEQ = name + '=';
+ var ca = document.cookie.split(';');
+ for(var i=0;i < ca.length;i++) {
+ var c = ca[i];
+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
+ }
+ return null;
+ }
+
+ function updateBackButton() {
+ var el = document.getElementById('back');
+ var back = readCookie('last');
+
+ if (el && back !== null && back !== '%2Fedit') {
+ el.href = decodeURIComponent(back);
+ }
+ }
+
+ // save the bin url when the bin is saved, changed and when we load first time
+ if (jsbin && jsbin.getURL) {
+ $document.on('saved', save);
+ save();
+ } else {
+ updateBackButton();
+ }
+})();;function archive(unarchive) {
+ /*global jsbin, $, $document, analytics*/
+ 'use strict';
+ var type = unarchive === false ? 'unarchive' : 'archive';
+ var text = unarchive === false ? 'restore from archive' : 'archiving';
+ analytics[type](jsbin.getURL());
+ if (!jsbin.user.name) {
+ $document.trigger('tip', {
+ type: 'notication',
+ content: 'You must be logged in and the owner of the bin to archive.'
+ });
+ } else if (jsbin.owner()) {
+ $.ajax({
+ type: 'POST',
+ url: jsbin.getURL() + '/' + type,
+ error: function () {
+ $document.trigger('tip', {
+ type: 'error',
+ content: 'The ' + text + ' failed. If this continues, please can you file an issue?'
+ });
+ },
+ success: function () {
+ jsbin.state.metadata.archive = unarchive !== false;
+ updateArchiveMenu();
+ $document.trigger('tip', {
+ type: 'notication',
+ autohide: 5000,
+ content: 'This bin is now ' + (unarchive === false ? 'restored from the archive.' : 'archived.')
+ });
+ }
+ });
+ } else {
+ $document.trigger('tip', {
+ type: 'notication',
+ content: 'The ' + text + ' failed. You can only archive bins that you own.'
+ });
+ }
+}
+
+function updateArchiveMenu() {
+ if (jsbin.state.metadata && jsbin.state.metadata.archive) {
+ $('a.archivebin').hide();
+ $('a.unarchivebin').show();
+ } else {
+ $('a.archivebin').show();
+ $('a.unarchivebin').hide();
+ }
+}
+
+updateArchiveMenu();
+
+var unarchive = archive.bind(null, false);;(function () {
+ /*global jsbin, $, $body, $document, analytics, settings*/
+ 'use strict';
+
+ if (!$('#toppanel').length) {
+ return;
+ }
+
+ if (jsbin.settings.gui === undefined) {
+ jsbin.settings.gui = {};
+ }
+ if (jsbin.settings.gui.toppanel === undefined) {
+ jsbin.settings.gui.toppanel = true;
+ localStorage.setItem('settings', JSON.stringify(jsbin.settings));
+ }
+
+ if ($body.hasClass('toppanel') && jsbin.settings.gui.toppanel === false) {
+ $body.addClass('toppanel-close');
+ $body.removeClass('toppanel');
+ }
+
+ // analytics for panel state
+ analytics.welcomePanelState(jsbin.settings.gui.toppanel);
+
+ var removeToppanel = function() {
+ jsbin.settings.gui.toppanel = false;
+ settings.save();
+ $body.addClass('toppanel-close');
+ $body.removeClass('toppanel');
+ };
+
+ var showToppanel = function() {
+ jsbin.settings.gui.toppanel = true;
+ settings.save();
+ $body.removeClass('toppanel-close');
+ $body.addClass('toppanel');
+ };
+
+ // to remove
+ var goSlow = function(e) {
+ $body.removeClass('toppanel-slow');
+ if (e.shiftKey) {
+ $body.addClass('toppanel-slow');
+ }
+ };
+
+ $('.toppanel-hide').click(function(event) {
+ event.preventDefault();
+ goSlow(event);
+ removeToppanel();
+ });
+ $('.toppanel-logo').click(function(event) {
+ event.preventDefault();
+ goSlow(event);
+ showToppanel();
+ });
+ $document.keydown(function (event) {
+ if (event.which === 27) {
+ if ($body.hasClass('toppanel')) {
+ removeToppanel();
+ }
+ }
+ });
+
+ // analytics for links
+ $('#toppanel').find('.toppanel-link').mousedown(function() {
+ analytics.welcomePanelLink(this.href);
+ });
+
+}());;// if a gist has been requested, lazy load the gist library and plug it in
+if (/gist\/.*/.test(window.location.pathname)) {
+ window.editors = editors; // needs to be global when the callback triggers to set the content
+ loadGist = function () {
+ window.gist = new Gist(window.location.pathname.replace(/.*\/([^/]+)$/, "$1"));
+ };
+
+ if (editors.ready) {
+ loadGist();
+ } else {
+ $document.on('jsbinReady', loadGist);
+ }
+}
+
+// prevent the app from accidently getting scrolled out of view
+if (!jsbin.mobile) document.body.onscroll = window.onscroll = function () {
+ if (document.body.scrollTop !== 0) {
+ window.scrollTo(0,0);
+ }
+ return false;
+};
+
+window.CodeMirror = CodeMirror; // fix to allow code mirror to break naturally
+
+// These are keys that CodeMirror (and Emmet) should never take over
+// ref: https://gist.github.com/rodneyrehm/5213304
+if (CodeMirror.keyMap && CodeMirror.keyMap['default']) {
+ var cmd = $.browser.platform === 'mac' ? 'Cmd' : 'Ctrl';
+ delete CodeMirror.keyMap['default'][cmd + '-L'];
+ delete CodeMirror.keyMap['default'][cmd + '-T'];
+ delete CodeMirror.keyMap['default'][cmd + '-W'];
+ delete CodeMirror.keyMap['default'][cmd + '-J'];
+ delete CodeMirror.keyMap['default'][cmd + '-R'];
+}
+
+var link = document.createElement('link');
+link.rel = 'stylesheet';
+link.href = jsbin['static'] + '/css/font.css?' + jsbin.version;
+link.type = 'text/css';
+document.getElementsByTagName('head')[0].appendChild(link);
+
+if (jsbin.embed) {
+ analytics.embed();
+};}
\ No newline at end of file
diff --git a/public/js/prod/jsbin-3.15.4.min.js b/public/js/prod/jsbin-3.15.4.min.js
new file mode 100644
index 00000000..c7453419
--- /dev/null
+++ b/public/js/prod/jsbin-3.15.4.min.js
@@ -0,0 +1,20 @@
+/*! jsbin - v3.15.4 - 2014-07-03 */
+function start(template,jsbin,window,document,undefined){function prettyDate(a){var b=new Date((a||"").replace(/-/g,"/").replace(/[TZ]/g," ")),c=((new Date).getTime()-b.getTime())/1e3,d=Math.floor(c/86400);if(!(isNaN(d)||0>d||d>=31))return 0==d&&(60>c&&"just now"||120>c&&"1 minute ago"||3600>c&&Math.floor(c/60)+" minutes ago"||7200>c&&"1 hour ago"||86400>c&&Math.floor(c/3600)+" hours ago")||1==d&&"Yesterday"||7>d&&d+" days ago"||31>d&&Math.ceil(d/7)+" weeks ago"}function hasStore(a){try{return a in window&&null!==window[a]}catch(b){return!1}}function throttle(a,b){var c=function(){var d=this,e=arguments;c.cancel(),c.timer=setTimeout(function(){a.apply(d,e)},b)};return c.cancel=function(){clearTimeout(c.timer)},c}function escapeHTML(a){return String(a).replace(/&(?!\w+;)/g,"&").replace(//g,">").replace(/"/g,""")}function dedupe(a){var b,c,d,e={},f=[],g=Object.prototype.hasOwnProperty;for(b=0,d=a.length;d>b;b+=1)c=a[b],g.call(e,c)||(e[c]=1,f.push(c));return f}function exposeSettings(){"use strict";if(window.jsbin instanceof Node||!window.jsbin){if(window.jsbin={"static":jsbin["static"]},jsbin.state.metadata&&jsbin.user&&jsbin.state.metadata.name===jsbin.user.name&&jsbin.user.name)return window.jsbin.settings=jsbin.settings,void 0;var a="o"+(1*Math.random()).toString(32).slice(2);Object.defineProperty(window,a,{get:function(){window.jsbin.settings=jsbin.settings,console.log("jsbin.settings can how be modified on the console")}}),console.log("To edit settings, type this string into the console: "+a)}}function objectValue(a,b){var c=a.split("."),d=c.length,e=1,f=b||window,g=f[a];try{if(f[c[0]]!==undefined)for(f=f[c[0]];d>e&&f[c[e]]!==undefined;e++)e===d-1&&(g=f[c[e]]),f=f[c[e]]}catch(h){g=undefined}return g}function sendReload(){saveChecksum&&$.ajax({url:jsbin.getURL()+"/reload",data:{code:jsbin.state.code,revision:jsbin.state.revision,checksum:saveChecksum},type:"post"})}function codeChangeLive(a,b){clearTimeout(deferredLiveRender);var c,d,e=jsbin.panels.panels.live;jsbin.panels.ready&&(jsbin.settings.includejs===!1&&"javascript"===b.panelId||e.visible&&(!jsbin.lameEditor&&jsbin.panels.focused&&"javascript"===jsbin.panels.focused.id?(c=jsbin.panels.focused.editor,d=c.getLine(c.getCursor().line),ignoreDuringLive.test(d)===!0?(throttledPreview.cancel(),deferredLiveRender=setTimeout(function(){codeChangeLive(a,b)},1e3)):throttledPreview()):throttledPreview()))}function enableAltUse(){jsbin.settings.keys||(jsbin.settings.keys={}),jsbin.settings.keys.useAlt=this.checked}function keycontrol(a){a=normalise(a);var b={};jsbin.panels.focused&&jsbin.panels.focused.editor?b=jsbin.panels.focused.editor:jsbin.panels.focused&&(b=jsbin.panels.focused);var c={css:1,javascript:1,html:1}[b.id],d=!1,e=customKeys.useAlt?a.altKey:!a.altKey;if("keydown"===a.type){if(c&&a.metaKey&&13===a.which&&(editors.console.visible&&!editors.live.visible?(d=!0,$("#runconsole").trigger("click","keyboard")):editors.live.visible?($("#runwithalerts").trigger("click","keyboard"),d=!0):($("#runwithalerts").trigger("click","keyboard"),d=!0),d?a.stop():sendReload()),panelShortcuts[a.which]!==undefined&&a.metaKey&&e)if(jsbin.panels.focused.id===panelShortcuts[a.which])jsbin.panels.hide(panelShortcuts[a.which]),a.stop();else if(jsbin.panels.show(panelShortcuts[a.which]),a.stop(),!(customKeys.useAlt||jsbin.settings.keys&&jsbin.settings.keys.seenWarning)){var f="mac"===$.browser.platform?"cmd":"ctrl";jsbin.settings.keys||(jsbin.settings.keys={}),jsbin.settings.keys.seenWarning=!0,$document.trigger("tip",{type:"notification",content:' Turn this off . Reserve '+f+"+[n] for switching browser tabs and use "+f+"+alt +[n] to switch JS Bin panels. You can access this any time in Help→Keyboard "}),$("#tip").delegate("input.enablealt","click",function(){enableAltUse.call(this),window.location.reload()})}if(191===a.which&&a.metaKey&&a.shiftKey)$body.toggleClass("keyboardHelp"),keyboardHelpVisible=$body.is(".keyboardHelp"),keyboardHelpVisible&&analytics.track("keyboard","select","help"),a.stop();else if(27===a.which&&keyboardHelpVisible)$body.removeClass("keyboardHelp"),keyboardHelpVisible=!1,a.stop();else if(27===a.which&&jsbin.panels.focused&&c);else if(190===a.which&&e&&a.metaKey&&"html"===b.id){if(b.somethingSelected())return;var g=b.getCursor(!1),h=b.getTokenAt(g),i=h;/^[\w$_]*$/.test(h.string)||(h=i={start:g.ch,end:g.ch,string:"",state:h.state,className:"."===h.string?"js-property":null}),b.replaceRange(""+h.state.htmlState.context.tagName+">",{line:g.line,ch:h.end},{line:g.line,ch:h.end}),a.stop()}else if(188===a.which&&a.ctrlKey&&a.shiftKey&&c)return a.stop(),startTagComplete(b)}return a.stopping?!1:void 0}function normalise(a){var b={type:a.type,which:a.which,metaKey:a.metaKey,shiftKey:a.shiftKey,ctrlKey:a.ctrlKey,altKey:a.altKey,orig:a};null!==a.which||null===a.charCode&&null===a.keyCode||(b.which=null!==a.charCode?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(b.metaKey=a.ctrlKey),0===a.which&&a.ctrlKey===!0&&a.shiftKey===!0&&"keydown"===a.type&&(b.which=191);var c=a.stop;return b.stop=function(){b.stopping=!0,c&&c.call(a)},b}function upgradeConsolePanel(a){a.$el.click(function(a){$(a.target).closest("#output").length||jsconsole.focus()}),a.reset=function(){jsconsole.reset()},a.settings.render=function(a){var b=editors.html.render().trim();if(""===b){var c=editors.javascript.render().trim(),d=getPreparedCode().replace(//,"").replace(/<\/pre>/,"");renderer.postMessage("render",{source:""}),setTimeout(function(){jsconsole.run({echo:c,cmd:d})},0)}else renderLivePreview(a||!1)},a.settings.show=function(){jsconsole.clear(),setTimeout(function(){editors.console.ready&&!jsbin.embed&&jsconsole.focus()},0)},a.settings.hide=function(){!editors.live.visible},$document.one("jsbinReady",function(){var a=function(){$("#runconsole")[this.visible?"hide":"show"]()};jsbin.panels.panels.live.on("show",a).on("hide",a),jsbin.panels.panels.live.visible&&$("#runconsole").hide()})}function populateEditor(a,b){if(a.codeSet)f=!0;else{var c=sessionStorage.getItem("jsbin.content."+b),d=localStorage.getItem("saved-"+b),e=sessionStorage.getItem("url"),f=!1;e===jsbin.getURL()||jsbin.state.checksum||(sessionStorage.removeItem("checksum"),saveChecksum=!1),template&&c==template[b]?a.setCode(c):c&&e==jsbin.getURL()?(a.setCode(c),f=c!=d&&c!=template[b]):template.post||null===d||/edit/.test(window.location)||window.location.search?a.setCode(template[b]):a.setCode(d)}f&&$document.trigger("codeChange",[{revert:!1,onload:!0}])}function getQuery(a){var b="&",c="=",d={},e=/\+/g;a=a.split(b);var f=1e3,g=a.length;f>0&&g>f&&(g=f);for(var h=0;g>h;++h){var i,j,k,l,m=a[h].replace(e,"%20"),n=m.indexOf(c);n>=0?(i=m.substr(0,n),j=m.substr(n+1)):(i=m,j="");try{k=decodeURIComponent(i),l=decodeURIComponent(j)}catch(o){k=i,l=j}(window.hasOwnProperty?window.hasOwnProperty(d,k):d.hasOwnProperty(k))?$.isArray(d[k])?d[k].push(l):d[k]=[d[k],l]:d[k]=l}return d}function insertResources(a){$.isArray(a)||(a=[a]);var b,c,d,e=0,f=a.length,g="",h=editors.html.getCode(),i={line:editors.html.editor.currentLine(),character:editors.html.editor.getCursor().ch,add:0},j=[],k="",l={},m={rel:"stylesheet",type:"text/css"};for(e=0;f>e;e++){g=a[e],$.isPlainObject(g)?(d=g,g=g.url,delete d.url):d={},k=g.split("/").pop(),d=$.extend({},isCssFile(k)?m:l,d),c="";for(var n in d)c+=" "+n+'="'+d[n]+'"';k&&h.indexOf(k+'"')&&(h=isCssFile(k)?h.replace(new RegExp(' \n?'),""):h.replace(new RegExp('<'+"/script>\n?"),""),i.add--),b=isCssFile(g)?' ":'\n"+g}if(a.console.test(d)){var m="window.runnerWindow.proxyConsole.";d=d.replace(a.console,function(a,b,c,e){var f=d.lastIndexOf("'},{url:["http://jashkenas.github.io/underscore/underscore-min.js","http://jashkenas.github.io/backbone/backbone-min.js"],label:"Backbone latest"},{url:["http://jashkenas.github.io/underscore/underscore-min.js","http://jashkenas.github.io/backbone/backbone-min.js","http://marionettejs.com/downloads/backbone.marionette.min.js"],label:"MarionetteJS latest"},{url:"http://cdnjs.cloudflare.com/ajax/libs/bonsai/0.4/bonsai.min.js",label:"Bonsai 0.4.latest"},{url:"http://jashkenas.github.io/coffee-script/extras/coffee-script.js",label:"CoffeeScript"},{url:["http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js","http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js","http://builds.emberjs.com.s3.amazonaws.com/tags/v1.0.0/ember.js"],label:"Ember.js 1.0.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/es5-shim/2.0.8/es5-shim.min.js",label:"ES5 shim 2.0.8"},{url:["http://extjs.cachefly.net/ext-3.1.0/resources/css/ext-all.css","http://cdnjs.cloudflare.com/ajax/libs/ext-core/3.1.0/ext-core.min.js"],label:"ext-core 3.1.0"},{url:["http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/css/normalize.min.css","http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/css/foundation.min.css","http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/js/vendor/jquery.min.js","http://cdnjs.cloudflare.com/ajax/libs/foundation/5.0.3/js/foundation.min.js"],label:"Foundation 5.0.3"},{url:"http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js",label:"Handlebars.js 1.0.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js",label:"Knockout 3.0.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/less.js/1.3.3/less.min.js",label:"Less 1.3.3"},{url:"http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js",label:"Lo-Dash 2.4.1"},{url:"http://modernizr.com/downloads/modernizr-latest.js",label:"Modernizr Development latest"},{url:["http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js","http://cdnjs.cloudflare.com/ajax/libs/detectizr/1.5.0/detectizr.min.js"],label:"Detectizr 1.5.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js",label:"Prefixfree 1.0.7"},{url:"http://cdnjs.cloudflare.com/ajax/libs/processing.js/1.4.1/processing-api.min.js",label:"Processing 1.4.1"},{url:"http://d3js.org/d3.v3.min.js",label:"D3 3.x"},{url:"//code.highcharts.com/highcharts.js",label:"Highcharts latest"},{url:"http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js",label:"Raphaël 2.1.0"},{url:"http://cdnjs.cloudflare.com/ajax/libs/sammy.js/0.7.4/sammy.min.js",label:"Sammy 0.7.4"},{url:["http://cdn.sencha.io/touch/1.1.0/resources/css/sencha-touch.css","http://cdn.sencha.io/touch/1.1.0/sencha-touch.js"],label:"Sencha Touch"},{url:[jsbin.static+"/js/vendor/traceur.js"],label:"Traceur"},{url:"http://remy.github.io/twitterlib/twitterlib.min.js",label:"TwitterLib"},{url:"http://jashkenas.github.io/underscore/underscore-min.js",label:"underscore"},{url:["http://code.jquery.com/jquery.min.js","//canjs.com/release/2.0.3/can.jquery.min.js"],label:"CanJS 2.0.3"},{url:["http://cdnjs.cloudflare.com/ajax/libs/three.js/r61/three.min.js"],label:"Three.js r61"},{url:["http://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.2/html5shiv.js"],label:"HTML5 shiv"},{url:["http://lungo.tapquo.com/demo/components/lungo/lungo.css","http://lungo.tapquo.com/demo/components/lungo/lungo.theme.css","http://lungo.tapquo.com/demo/components/lungo/lungo.icon.css","http://lungo.tapquo.com/demo/components/quojs/quo.js","http://lungo.tapquo.com/demo/components/lungo/lungo.js"],label:"Lungo"},{url:["//cdnjs.cloudflare.com/ajax/libs/polymer/0.3.3/platform.js","//cdnjs.cloudflare.com/ajax/libs/polymer/0.3.3/polymer.js"],label:"Polymer 0.3.3"},{url:"//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css",label:"Font Awesome 4.0.3"},{url:"//cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.12/paper.js",label:"Paper.js 0.9.12"},{url:{url:"https://openui5.hana.ondemand.com/resources/sap-ui-core.js",id:"sap-ui-bootstrap","data-sap-ui-theme":"sap_bluecrystal","data-sap-ui-libs":"sap.m"},label:"OpenUI5 1.18.8 Mobile BlueCrystal"},{url:"http://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.7/TweenMax.min.js",label:"GSAP 1.11.7"},{url:"//cdnjs.cloudflare.com/ajax/libs/phaser/2.0.5/phaser.min.js",label:"Phaser 2.0.5"}];window.libraries=libraries,libraries.userSpecified=JSON.parse(localStorage.getItem("libraries")||"[]");for(var i=0;ib;b++)"Custom"===libraries[b].group&&(libraries.splice(b,1),a--);$("#library").trigger("init")};var $library=$("#library"),groups={};$library.bind("init",function(){var a=0,b=0,c={},d=[],e={},f="",g="";for(groups={},$library.empty(),a=0;aNone'];for(a=0;a-------------'),b=0;b'+c.label+"");$library.html(h.join(""))}).trigger("init"),$library.bind("change",function(){if(this.value){var a=this.value.split(":"),b=groups[a[0]],c=b.libraries[a[1]];analytics.library("select",b.libraries[a[1]].label),insertResources(c.url),c.snippet&&insertSnippet(c.snippet)}}).on("click",function(){analytics.library("open")});var htmlScriptToJade=createHTMLToJadeTagConverter("script","src","js"),htmlLinkToJade=function(){var a=createHTMLToJadeTagConverter("link","href","css");return function(b){var c=a(b);return c.split('" ').join('",')}}();!function(){"use strict";function a(a){if(0!==a.indexOf("http")&&(a=jsbin.static+a),".js"===a.slice(-3))return $.ajax({url:a+"?"+jsbin.version,dataType:"script",cache:!0});if(".css"===a.slice(-4)){var b=$.Deferred();return setTimeout(function(){n.append(' '),b.resolve()},0),b}}function b(a){var b=$.Deferred(),c=null;return a()?b.resolve():c=setInterval(function(){a()&&(clearInterval(c),b.resolve())},100),b}function c(a,b,c){a.setOption(b,c)}function d(a){return function(){return"undefined"!=typeof CodeMirror.optionHandlers[a]}}function e(a){return"undefined"!=typeof CodeMirror.defaults.lint&&CodeMirror.helpers.lint&&CodeMirror.helpers.lint[a]&&CodeMirror.optionHandlers.lint}function f(c){var d=m[c];d&&l[c]&&("string"==typeof d.url&&(d.url=[d.url]),$.when.call($,d.url.map(a)).done(function(){d.done&&b(d.test).then(function(){jsbin.panels.allEditors(function(a){a.editor&&d.done(a.editor)})})}))}var g={closebrackets:!0,highlight:!1,vim:!1,emacs:!1,trailingspace:!1,fold:!1,sublime:!1,tern:!1,activeline:!0,matchbrackets:!1};jsbin.settings.addons||(jsbin.settings.addons=g);var h="open"in document.createElement("details"),i={},j={},k={console:!0,line:!1,under:!1,gutter:!1};["js","html","coffeescript","css"].forEach(function(a){var b=a+"hint",c=!1;"js"===a&&(c=!0),i[b]=jsbin.settings[b]!==undefined?jsbin.settings[b]:c}),j=$.extend({},k,jsbin.settings.hintShow),j.tooltip=j.gutter;var l=$.extend({},jsbin.settings.addons,i),m={closebrackets:{url:"/js/vendor/codemirror4/addon/edit/closebrackets.js",test:d("autoCloseBrackets"),done:function(a){c(a,"autoCloseBrackets",!0)}},highlight:{url:"/js/vendor/codemirror4/addon/search/match-highlighter.js",test:d("highlightSelectionMatches"),done:function(a){c(a,"highlightSelectionMatches",!0)}},vim:{url:["/js/vendor/codemirror4/addon/dialog/dialog.css","/js/vendor/codemirror4/keymap/vim.js","/js/vendor/codemirror4/addon/dialog/dialog.js"],test:d("vimMode"),done:function(a){c(a,"vimMode",!0),c(a,"showCursorWhenSelecting",!0)}},emacs:{url:["/js/vendor/codemirror4/addon/dialog/dialog.css","/js/vendor/codemirror4/keymap/emacs.js","/js/vendor/codemirror4/addon/dialog/dialog.js","/js/vendor/codemirror4/addon/search/search.js"],test:function(){return jsbin.panels.panels.javascript.editor.openDialog&&CodeMirror.commands.find&&CodeMirror.keyMap.emacs},done:function(a){c(a,"keyMap","emacs")}},matchtags:{url:["/js/vendor/codemirror4/addon/fold/xml-fold.js","/js/vendor/codemirror4/addon/edit/matchtags.js"],test:function(){return CodeMirror.scanForClosingTag&&CodeMirror.optionHandlers.matchTags},done:function(a){c(a,"matchTags",{bothTags:!0}),a.addKeyMap({"Ctrl-J":"toMatchingTag"})}},trailingspace:{url:"/js/vendor/codemirror4/addon/edit/trailingspace.js",test:d("showTrailingSpace"),done:function(a){c(a,"showTrailingSpace",!0)}},fold:{url:["/js/vendor/codemirror4/addon/fold/foldgutter.css","/js/vendor/codemirror4/addon/fold/foldcode.js","/js/vendor/codemirror4/addon/fold/foldgutter.js","/js/vendor/codemirror4/addon/fold/brace-fold.js","/js/vendor/codemirror4/addon/fold/xml-fold.js","/js/vendor/codemirror4/addon/fold/comment-fold.js"],test:function(){return CodeMirror.helpers.fold&&CodeMirror.optionHandlers.foldGutter&&CodeMirror.optionHandlers.gutters},done:function(a){n.addClass("code-fold"),a.addKeyMap({"Ctrl-Q":function(a){a.foldCode(a.getCursor())}}),c(a,"foldGutter",!0);var b=a.getOption("gutters");b.push("CodeMirror-linenumbers"),b.push("CodeMirror-foldgutter"),c(a,"gutters",b)}},sublime:{url:["/js/vendor/codemirror4/addon/dialog/dialog.css","/js/vendor/codemirror4/keymap/sublime.js","/js/vendor/codemirror4/addon/dialog/dialog.js","/js/vendor/codemirror4/addon/search/search.js"],test:function(){return jsbin.panels.panels.javascript.editor.openDialog&&CodeMirror.commands.find&&CodeMirror.keyMap.sublime},done:function(a){c(a,"keyMap","sublime");var b="mac"===$.browser.platform?"Cmd":"Ctrl";delete CodeMirror.keyMap.sublime[b+"-L"],delete CodeMirror.keyMap.sublime[b+"-T"],delete CodeMirror.keyMap.sublime[b+"-W"],delete CodeMirror.keyMap.sublime[b+"-J"],delete CodeMirror.keyMap.sublime[b+"-R"],delete CodeMirror.keyMap.sublime[b+"-Enter"],delete CodeMirror.keyMap.sublime[b+"-Up"],delete CodeMirror.keyMap.sublime[b+"-Down"],a.removeKeyMap("noEmmet")}},tern:{url:["/js/vendor/codemirror4/addon/dialog/dialog.css","/js/vendor/codemirror4/addon/hint/show-hint.css","/js/vendor/codemirror4/addon/tern/tern.css","/js/vendor/codemirror4/addon/hint/show-hint.js","/js/vendor/codemirror4/addon/dialog/dialog.js","/js/prod/addon-tern-"+jsbin.version+".min.js"],test:function(){return jsbin.panels.panels.javascript.editor.openDialog&&"undefined"!=typeof window.ternBasicDefs&&CodeMirror.showHint&&CodeMirror.TernServer&&CodeMirror.startTern},done:function(){CodeMirror.startTern()}},activeline:{url:["/js/vendor/codemirror4/addon/selection/active-line.js"],test:function(){return"undefined"!=typeof CodeMirror.defaults.styleActiveLine},done:function(a){c(a,"styleActiveLine",!0)}},matchbrackets:{url:[],test:function(){return"undefined"!=typeof CodeMirror.defaults.matchBrackets},done:function(a){c(a,"matchBrackets",!0)}},csshint:{url:["/js/vendor/csslint/csslint.min.js","/js/vendor/cm_addons/lint/css-lint.js"],test:function(){return e("css")&&"undefined"!=typeof CSSLint},done:function(a){"css"===a.getOption("mode")&&hintingDone(a)}},jshint:{url:[],test:function(){return e("javascript")&&"undefined"!=typeof JSHINT},done:function(a){"javascript"===a.getOption("mode")&&hintingDone(a,{eqnull:!0})}},htmlhint:{url:["/js/vendor/htmlhint/htmlhint.js","/js/vendor/cm_addons/lint/html-lint.js"],test:function(){return e("htmlmixed")&&"undefined"!=typeof HTMLHint},done:function(a){"htmlmixed"===a.getOption("mode")&&hintingDone(a)}},coffeescripthint:{url:["/js/vendor/coffeelint/coffeelint.min.js","/js/vendor/cm_addons/lint/coffeescript-lint.js"],test:function(){return e("coffeescript")&&"undefined"!=typeof coffeelint},done:function(a){"coffeescript"===a.getOption("mode")&&hintingDone(a)}}},n=$("body");window.hintingDone=function(a,b){var d=a.getOption("mode");"javascript"===d&&(d="js"),"htmlmixed"===d&&(d="html");var e=$.extend({},j);if(e.consoleParent=a.getWrapperElement().parentNode.parentNode,c(a,"lintOpt",e),c(a,"lintRules",$.extend({},b,jsbin.settings[d+"hintOptions"])),e.gutter){var f=a.getOption("gutters");-1===f.indexOf("CodeMirror-lint-markers")&&(f.push("CodeMirror-lint-markers"),c(a,"gutters",f)),c(a,"lint",!0);var g=a.getOption("lineNumbers");c(a,"lineNumbers",!g),c(a,"lineNumbers",g)}else c(a,"lint",!0);e.console&&($document.trigger("sizeeditors"),$(a.consolelint.head).on("click",function(){h||$(this).nextAll().toggle(),setTimeout(function(){$document.trigger("sizeeditors")},10)}))};var o=Object.keys(l);o.forEach(f),window.reloadAddons=function(a){a?a.forEach(f):o.forEach(f)}}(),function(){"use strict";if(jsbin.settings.addons.tern){var a,b={},c=function(b,c){var d={"Ctrl-Q":function(b){a.selectName(b)},"Ctrl-I":function(b){a.showType(b)},"Ctrl-Space":function(b){a.complete(b)}};"undefined"==typeof c&&(c=[]),a=new CodeMirror.TernServer({defs:c,useWorker:!1,cm:b}),b.addKeyMap(d),b.on("cursorActivity",function(b){a.updateArgHints(b)})},d=function(b){"object"==typeof a&&(a.options.defs.push(b),a=new CodeMirror.TernServer({defs:a.options.defs,useWorker:a.options.useWorker,tooltipType:a.options.tooltipType,cm:a.options.cm}))},e=function(a,c){b[a]||$.ajax({url:c,dataType:"json",success:function(c){d(c),b[a]=!0}})},f=function(c,d){b[c]||$.ajax({url:d,dataType:"script",success:function(d){a.server.addFile(c,d),b[c]=!0}})},g=function(a){c(a,ternBasicDefs),b.ecma5=!0,b.browser=!0},h=function(a){for(var b=0;b0?(d.filter(".first").removeClass("first"),a.removeClass("hidden"),d.first().addClass("first")):a.addClass("hidden")}).appendTo(c)},h=function(){if(a=$("#history").detach(),!a.length)return a;var b=$("iframe",a),c=$("#viewing",a),d=a,h=$("tbody",a),i=$("tr",a),j=$("td.created a",a),k=$(".toggle_archive",a),l=null,m=null;return d.delegate("tr:not(.spacer)","click",function(){event.shiftKey||event.metaKey||(window.location=this.getAttribute("data-edit-url"))}),d.delegate(".archive, .unarchive","click",function(){var b=$(this),c=b.parents("tr");return c.toggleClass("archived"),analytics[-1===this.pathname.indexOf("unarchive")?"archive":"unarchive"](jsbin.root+c.data("url")),g(h,a.hasClass("archive_mode")),$.ajax({type:"POST",url:b.attr("href"),error:function(){alert("Something went wrong, please try again"),c.toggleClass("archived"),g(h,a.hasClass("archive_mode"))},success:function(){}}),!1}),k.change(function(){a.toggleClass("archive_mode");var b=a.hasClass("archive_mode");analytics.archiveView(b),g(h,b)}),d.delegate("tr","mouseover",function(){var a=$(this),d=a.attr("data-url");return clearTimeout(m),a.hasClass("spacer")||l===d||(m=setTimeout(function(){i.removeClass("selected"),a.addClass("selected"),l=d,e(d,b),f(d,c)},400)),!1}),$("a[pubdate]",a).attr("pubdate",function(a,b){return b.replace("Z","+0000")}).prettyDate(),setInterval(function(){j.prettyDate()},3e4),setTimeout(function(){g(h,!1)},0),$document.trigger("history:open"),a};$(document).on("jsbinReady",function(){if(!jsbin.embed){var a=$("#panels a"),c=$(".homebtn"),e=b.hasClass("panelsVisible"),f=function(){var b=a.filter(".active").length;1===b&&$(this).hasClass("active")&&d()};c.on("click",d),a.on("mousedown",f),e||d()}})}();var loginVisible=!1,dropdownOpen=!1,keyboardHelpVisible=!1,urlHelpVisible=!1;$document.keydown(function(a){27==a.which&&hideOpen()}),$document.delegate(".modal","click",function(a){$(a.target).is(".modal")&&hideOpen()});var githubIssue=function(){"use strict";function a(){var a="http://github.com/jsbin/jsbin/issues/new",b=["Please provide any additional information, record a screencast ","with http://quickcast.io or http://screenr.com and attach a screenshot ","if possible.\n\n**JS Bin info**\n\n* [%url%](%url%)\n* ",window.navigator.userAgent+"\n",jsbin.user&&jsbin.user.name?"* "+jsbin.user.name:"","\n"].join("");
+return a+"?body="+encodeURIComponent(b.replace(/%url%/g,jsbin.getURL()))}var b=$("#newissue");return $("#help").parent().on("open",function(){b.attr("href",a())}),a}();$("#download").click(function(a){a.preventDefault(),window.location=jsbin.getURL()+"/download",analytics.download()}),$("form.login").submit(function(a){"use strict";a.preventDefault();var b=$(this),c=b.find("input[name=username]").val(),d=b.find("input[name=password]").val(),e=b.find("input[name=email]").val(),f=b.find(".loginFeedback");f.show().text("Checking..."),$.ajax({url:b.attr("action"),data:{username:c,key:d,email:e},type:"POST",dataType:"json",complete:function(a){var b=$.parseJSON(a.responseText)||{};200===a.status?(b.avatar&&$("a.avatar").find("img").remove().end().prepend(' '),b.message?f.text(b.message):window.location=window.location.pathname+window.location.search):(analytics.login(!1),f.text(b.message||'"'+c+'" has already been taken. Please either double check the password, or choose another username.'))}})}),function(){var a,b=$(document.documentElement),c=$("#tip"),d=$("p",c),e=function(a){b.removeClass("showtip"),c.removeClass(),d.html(""),$(window).resize(),a&&setTimeout(a,0)},f=function(f){clearTimeout(a),d.html(f.content),c.removeClass().addClass(f.type||"info"),b.addClass("showtip"),f.autohide&&(a=setTimeout(function(){e()},parseInt(f.autohide,10)||5e3))};$document.on("tip",function(a,b){var g=b;return"string"==typeof b&&(g={},g.content=b,g.type="info"),d.html()===g.content&&c.hasClass(g.type)?f(b):(e(function(){f(g)}),void 0)}),$("#tip").on("click","a.dismiss",function(){return e(),!1}),$document.keydown(function(a){27==a.which&&e()})}();var saving={todo:{html:!1,css:!1,javascript:!1},_inprogress:!1,inprogress:function(a){if("undefined"==typeof a)return saving._inprogress;if(saving._inprogress=a,a===!1){var b=["html","css","javascript"],c=function(){var a=b.pop();a&&saving.todo[a]?(saving._inprogress=!0,updateCode(a,c),saving.todo[a]=!1):a&&c()};c()}}};$("a.save").click(function(a){a.preventDefault(),analytics.milestone();var b=!0;return jsbin.saveDisabled===!0&&(b=!1),saveCode("save",b),!1});var $shareLinks=$("#share .link");$panelCheckboxes=$("#sharemenu #sharepanels input"),$("#sharemenu").bind("open",function(){updateSavedState()}),$document.on("saved",function(){updateSavedState(),$shareLinks.closest(".menu").removeClass("hidden"),$("#jsbinurl").attr("href",jsbin.getURL()).removeClass("hidden"),$("#clone").removeClass("hidden")});var saveChecksum=jsbin.state.checksum||sessionStorage.getItem("checksum")||!1;if(jsbin.state.checksum=saveChecksum,saveChecksum?$("#share div.disabled").removeClass("disabled").unbind("click mousedown mouseup"):$("#share div.disabled").one("click",function(a){a.preventDefault(),$("a.save").click()}),$document.one("saved",function(){$("#share div.disabled").removeClass("disabled").unbind("click mousedown mouseup")}),jsbin.saveDisabled)$document.one("jsbinReady",function(){var a=!1;jsbin.embed||jsbin.sandbox||$document.on("codeChange",function(b,c){if(!c.onload&&!a&&"setValue"!==c.origin){a=!0;var d=-1!==navigator.userAgent.indexOf(" Mac "),e=d?"⌘":"ctrl",f=d?"⇧":"shift",g=d?"":"+";$document.trigger("tip",{type:"notification",content:"You're currently viewing someone else's live stream, but you can clone your own copy ('+e+g+f+g+"S) at any time to save your edits"})}})});else{$(".code.panel .label .name").append("Saved ");var savingLabels={html:$(".panel.html .name span"),javascript:$(".panel.javascript .name span"),css:$(".panel.css .name span")};$document.bind("jsbinReady",function(){jsbin.panels.allEditors(function(a){a.on("processor",function(){jsbin.root!==jsbin.getURL()&&$document.trigger("codeChange",[{panelId:a.id}])})}),$document.bind("codeChange",function(a,b){savingLabels[b.panelId]&&savingLabels[b.panelId].css({opacity:0}).stop(!0,!0)}),$document.bind("saveComplete",throttle(function(a,b){savingLabels[b.panelId].text("Saved").stop(!0,!0).animate({opacity:1},100).delay(1200).animate({opacity:0},500)},500)),$document.bind("codeChange",throttle(function(a,b){if(b.panelId&&!jsbin.state.deleted){var c=b.panelId;if(jsbin.panels.savecontent(),saving.inprogress())return saving.todo[c]=!0,void 0;saving.inprogress(!0),saveChecksum&&jsbin.state.code?updateCode(c):saveCode("save",!0)}},250))})}$("a.clone").click(function(a){a.preventDefault(),jsbin.panels.save(),analytics.clone();var b=setupform("save,new");return b.submit(),!1});var $startingpoint=$("a.startingpoint").click(function(a){return a.preventDefault(),localStorage?(analytics.saveTemplate(),localStorage.setItem("saved-javascript",editors.javascript.getCode()),localStorage.setItem("saved-html",editors.html.getCode()),localStorage.setItem("saved-css",editors.css.getCode()),$document.trigger("tip",{type:"notification",content:"Starting template updated and saved",autohide:3e3})):$document.trigger("tip",{type:"error",content:"Saving templates isn't supported in this browser I'm afraid. Sorry"}),!1});$("a.disabled").on("click mousedown mouseup",function(a){return a.stopImmediatePropagation(),!1}),$("#loginbtn").click(function(){analytics.login(),$(this).toggleClass("open")}),$("a.logout").click(function(a){for(a.preventDefault(),$(this.hash).submit(),i=0;iThis bin is now locked from further changes"),$lockrevision.data("locked",!0),saveChecksum=!1,$document.trigger("locked")),!1}).on("mouseup",function(){return!1});$document.on("saved",function(){$lockrevision.removeClass("icon-lock").addClass("icon-unlocked").data("locked",!1),$lockrevision.html("Click to lock and prevent further changes ")}),$("#share input[type=text], #share textarea").on("beforecopy",function(){analytics.share("copy",this.getAttribute("data-path").substring(1)||"output")});var $panelCheckboxes=$("#sharepanels input").on("change click",updateSavedState);$("#sharemenu").bind("open",function(){$panelCheckboxes.attr("checked",!1),jsbin.panels.getVisible().forEach(function(a){$panelCheckboxes.filter('[data-panel="'+a.id+'"]').attr("checked",!0).change()})});var dropdownOpen=!1,onhover=!1,menuDown=!1,dropdownButtons=$(".button-dropdown, .button-open").mousedown(function(a){return $dropdownLinks.removeClass("hover"),dropdownOpen&&dropdownOpen!==this&&closedropdown(),dropdownOpen||(menuDown=!0,opendropdown(this)),a.preventDefault(),!1}).mouseup(function(){return menuDown?!1:void 0}).click(function(){return menuDown||(analytics.closeMenu(this.hash.substring(1)),closedropdown()),menuDown=!1,!1});$("#actionmenu").click(function(){dropdownOpen=!0});var ignoreUp=!1;$body.bind("mousedown",function(a){dropdownOpen&&$(a.target).closest(".menu").length&&(ignoreUp=!0)}).bind("click mouseup",function(a){return!dropdownOpen||ignoreUp||$(a.target).closest(".menu").length?(ignoreUp=!1,void 0):(closedropdown(),!1)});var fromClick=!1,$dropdownLinks=$(".dropdownmenu a, .dropdownmenu .button").mouseup(function(){setTimeout(closedropdown,0),analytics.selectMenu(this.getAttribute("data-label")||this.hash.substring(1)||this.href),fromClick||(this.hostname===window.location.hostname?$(this).triggerHandler("click")!==!1&&(window.location=this.href):this.getAttribute("target")?window.open(this.href):window.location=this.href),fromClick=!1}).mouseover(function(){$dropdownLinks.removeClass("hover"),$(this).addClass("hover")}).mousedown(function(){fromClick=!0});$("#jsbinurl").click(function(){setTimeout(function(){jsbin.panels.panels.live.hide()},0)}),$("#runwithalerts").click(function(a,b){return analytics.run(b),editors.console.visible?editors.console.render(!0):renderLivePreview(!0),!1}),$("#runconsole").click(function(){return analytics.runconsole(),editors.console.render(!0),!1}),$("#clearconsole").click(function(){return jsconsole.clear(),!1}),$("#showhelp").click(function(){return $body.toggleClass("keyboardHelp"),keyboardHelpVisible=$body.is(".keyboardHelp"),!1}),$("#showurls").click(function(){return $body.toggleClass("urlHelp"),urlHelpVisible=$body.is(".urlHelp"),!1}),$(".code.panel > .label > span.name").dblclick(function(){jsbin.panels.allEditors(function(a){var b=!a.editor.getOption("lineNumbers");a.editor.setOption("lineNumbers",b),jsbin.settings.editor.lineNumbers=b})}),$("#createnew").click(function(a){a.preventDefault();var b,c;for(analytics.createNew(),jsbin.panels.savecontent=function(){},b=0;b'+c+"")}),function(){var a={head://i,metaContent:/content=".*?"/i},b=' \n';$("#addmeta").click(function(){var c=jsbin.panels.panels.html,d=c.editor,e=c.getCode();a.meta.test(e)||(e=a.head.test(e)?e.replace(a.head,"'+jsbin.shareRoot+""})},error:function(){$document.trigger("tip",{type:"error",content:'There was a problem publishing to your vanity URL. Can you try again or file a new issue ?'})}})}),$("a.deletebin").on("click",function(a){a.preventDefault(),confirm("Delete this bin?")&&(analytics["delete"](),$.ajax({type:"post",url:jsbin.getURL()+"/delete",data:{checksum:jsbin.state.checksum},success:function(){jsbin.state.deleted=!0,$document.trigger("tip",{type:"error",content:"This bin is now deleted. You can continue to edit, but once you leave the bin can't be retrieved"})},error:function(a){403===a.status&&$document.trigger("tip",{content:"You don't own this bin, so you can't delete it.",autohide:5e3})}}))}),$("a.archivebin").on("click",function(a){a.preventDefault(),archive()}),$("a.unarchivebin").on("click",function(a){a.preventDefault(),archive(!1)})}(),window.File&&window.FileList&&window.FileReader&&allowDrop(document.body);var Gist=function(){"use strict";var a=!!("withCredentials"in new XMLHttpRequest||"undefined"!=typeof XDomainRequest);if(!a)return $(function(){$("#export-as-gist").remove()});var b=function(a){var b=this,c="";return b.code={},jsbin.user&&jsbin.user.github_token&&(c="?access_token="+jsbin.user.github_token),$.get("https://api.github.com/gists/"+a+c,function(a){a&&($.each(a.files,function(a,c){var d=a.split(".").slice(-1).join("");b.code[d]=c.content}),b.setCode())}),this};return b.prototype.setCode=function(){var a=this;$.each(a.code,function(a,b){var c=jsbin.processors.findByExtension(a),d=c.target||c.id,e=jsbin.panels.panels[d];e&&(processors.set(d,c.id),jsbin.saveDisabled=!0,e.setCode(b),jsbin.saveDisabled=!1)})},$("a.export-as-gist").click(function(){var a={"public":!0,files:{}},b=[{panel:"html"},{panel:"css"},{panel:"javascript",extension:"js"}];b.forEach(function(b){var c;try{c=jsbin.panels.panels[b.panel].getCode()}catch(d){}if(c&&c.length){var e=b.extension||b.panel,f=jsbin.panels.panels[b.panel].processor;f&&f.extensions&&(e=f.extensions[0]||f.name);var g=["jsbin",jsbin.state.code||"untitled",e].join(".");a.files[g]={content:c}}});var c="";return jsbin.user&&jsbin.user.github_token&&(c="?access_token="+jsbin.user.github_token),$.ajax({type:"POST",url:"https://api.github.com/gists"+c,data:JSON.stringify(a),dataType:"json",crossDomain:!0,success:function(a){$document.trigger("tip",{type:"notification",content:'Gist created! Open in new tab. '})},error:function(a,b){$document.trigger("tip",{type:"error",content:"Error: "+b})}}),!1}),b}();!function(){"use strict";function a(a){function d(a,d){var e=d?JSON.parse(d):JSON.parse(a.data);if(e.connections>0&&0===k&&b.addClass("viewers"),k!==e.connections){var f=c.find(".viewers b").removeClass("up down").html(""+e.connections+" "+k+" "+e.connections+" "),g=k>e.connections?"down":"up";setTimeout(function(){f.addClass(g)},0)}k=e.connections,0===k&&setTimeout(function(){b.removeClass("viewers")},250)}function f(){i=new EventSource(jsbin.getURL()+"/stats?checksum="+jsbin.state.checksum),i.addEventListener("stats",throttle(d,1e3))}var g=jsbin.state.metadata||{},h=[],i=null,j=!1;if(g.name&&(c.find(".name b").html(g.name),c.find("img").attr("src",g.avatar),h.push(g.name)),(jsbin.state.checksum||jsbin.user&&g.name===jsbin.user.name)&&(j=!0,h.push("author")),e&&e.stop(),jsbin.state.streaming&&j!==!0?j===!1&&(c.find("time").html("Streaming"),h.push("streaming"),e&&e.start()):c.find("time").html(a?"just now":prettyDate(g.last_updated)),jsbin.checksum||h.push("meta"),g.pro&&h.push("pro"),c.find(".visibility").text(g.visibility),"private"===g.visibility?h.push("private"):"public"===g.visibility&&h.push("public"),jsbin.state.code){b.addClass(h.join(" ")).parent().removeAttr("hidden"),c.click(function(a){a.preventDefault(),b.toggleClass("open")});var k=0;if(jsbin.state.streaming)if(window.EventSource&&j){f();var l=jsbin.getURL();$document.on("saved",function(){var a=window.location.toString();l!==a&&(i.close(),f())})}else jsbin.saveDisabled===!0&&"/edit"===window.location.pathname.slice(-5)&&($.getScript(jsbin.static+"/js/spike.js?"+jsbin.version),$document.on("stats",throttle(d,1e3)))}}if(!jsbin.embed){var b=$("#infocard"),c=b.find("header"),d=c.find("canvas")[0],e=spinner(d);0!==b.length&&(a(),$document.bind("saved",a))}}(),function(){"use strict";function a(){var a=new Date;return a.setTime(+a+36e5),a.toUTCString()}function b(){var b=jsbin.getURL(!0)+"/edit";document.cookie=b?"last="+encodeURIComponent(b)+"; expires="+a()+"; path=/":'last=""; expires=-1; path=/'}function c(a){for(var b=a+"=",c=document.cookie.split(";"),d=0;d>> 0;
+ if (len === 0) {
+ return -1;
+ }
+ var n = 0;
+ if (arguments.length > 0) {
+ n = Number(arguments[1]);
+ if (n != n) { // shortcut for verifying if it's NaN
+ n = 0;
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ }
+ if (n >= len) {
+ return -1;
+ }
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+ for (; k < len; k++) {
+ if (k in t && t[k] === searchElement) {
+ return k;
+ }
+ }
+ return -1;
+ }
+}
+
+// ES5 15.4.4.21
+// http://es5.github.com/#x15.4.4.21
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
+if ('function' !== typeof Array.prototype.reduce) {
+ Array.prototype.reduce = function(callback/*, opt_initialValue*/){
+ 'use strict';
+ if (null === this || 'undefined' === typeof this) {
+ throw new TypeError(
+ 'Array.prototype.reduce called on null or undefined');
+ }
+ if ('function' !== typeof callback) {
+ throw new TypeError(callback + ' is not a function');
+ }
+ var index, value, t = Object( this ),
+ length = t.length >>> 0,
+ isValueSet = false;
+ if (1 < arguments.length) {
+ value = arguments[1];
+ isValueSet = true;
+ }
+ for (index = 0; length > index; ++index) {
+ if (index in t) {
+ if (isValueSet) {
+ value = callback(value, t[index], index, t);
+ }
+ else {
+ value = t[index];
+ isValueSet = true;
+ }
+ }
+ }
+ if (!isValueSet) {
+ throw new TypeError('Reduce of empty array with no initial value');
+ }
+ return value;
+ };
+}
+
+
+// Production steps of ECMA-262, Edition 5, 15.4.4.18
+// Reference: http://es5.github.com/#x15.4.4.18
+if ( !Array.prototype.forEach ) {
+
+ Array.prototype.forEach = function( callback, thisArg ) {
+
+ var T, k;
+
+ if ( this == null ) {
+ throw new TypeError( " this is null or not defined" );
+ }
+
+ // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
+ var O = Object(this);
+
+ // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
+ // 3. Let len be ToUint32(lenValue).
+ var len = O.length >>> 0; // Hack to convert O.length to a UInt32
+
+ // 4. If IsCallable(callback) is false, throw a TypeError exception.
+ // See: http://es5.github.com/#x9.11
+ if ( {}.toString.call(callback) != "[object Function]" ) {
+ throw new TypeError( callback + " is not a function" );
+ }
+
+ // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
+ if ( thisArg ) {
+ T = thisArg;
+ }
+
+ // 6. Let k be 0
+ k = 0;
+
+ // 7. Repeat, while k < len
+ while( k < len ) {
+
+ var kValue;
+
+ // a. Let Pk be ToString(k).
+ // This is implicit for LHS operands of the in operator
+ // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
+ // This step can be combined with c
+ // c. If kPresent is true, then
+ if ( k in O ) {
+
+ // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
+ kValue = O[ k ];
+
+ // ii. Call the Call internal method of callback with T as the this value and
+ // argument list containing kValue, k, and O.
+ callback.call( T, kValue, k, O );
+ }
+ // d. Increase k by 1.
+ k++;
+ }
+ // 8. return undefined
+ };
+}
+
+// https://gist.github.com/1035982
+''.trim||(String.prototype.trim=function(){return this.replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g,'')});
+
+if ( !Object.prototype.hasOwnProperty ) {
+ Object.prototype.hasOwnProperty = function(prop) {
+ var proto = obj.__proto__ || obj.constructor.prototype;
+ return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
+ };
+}
+
+Date.now||(Date.now=function(){return+new Date})
+
+// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
+
+// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
+
+// MIT license
+
+(function() {
+ var lastTime = 0;
+ var vendors = ['ms', 'moz', 'webkit', 'o'];
+ for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
+ window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
+ window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
+ || window[vendors[x]+'CancelRequestAnimationFrame'];
+ }
+
+ if (!window.requestAnimationFrame)
+ window.requestAnimationFrame = function(callback, element) {
+ var currTime = Date.now();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = window.setTimeout(function() { callback(currTime + timeToCall); },
+ timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+
+ if (!window.cancelAnimationFrame)
+ window.cancelAnimationFrame = function(id) {
+ clearTimeout(id);
+ };
+}());
+
+(function () {
+ function Empty() {}
+ var slice = [].slice;
+
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function bind(that) { // .length is 1
+ // 1. Let Target be the this value.
+ var target = this;
+ // 2. If IsCallable(Target) is false, throw a TypeError exception.
+ if (typeof target != "function") {
+ throw new TypeError("Function.prototype.bind called on incompatible " + target);
+ }
+ // 3. Let A be a new (possibly empty) internal list of all of the
+ // argument values provided after thisArg (arg1, arg2 etc), in order.
+ // XXX slicedArgs will stand in for "A" if used
+ var args = slice.call(arguments, 1); // for normal call
+ // 4. Let F be a new native ECMAScript object.
+ // 11. Set the [[Prototype]] internal property of F to the standard
+ // built-in Function prototype object as specified in 15.3.3.1.
+ // 12. Set the [[Call]] internal property of F as described in
+ // 15.3.4.5.1.
+ // 13. Set the [[Construct]] internal property of F as described in
+ // 15.3.4.5.2.
+ // 14. Set the [[HasInstance]] internal property of F as described in
+ // 15.3.4.5.3.
+ var bound = function () {
+
+ if (this instanceof bound) {
+ // 15.3.4.5.2 [[Construct]]
+ // When the [[Construct]] internal method of a function object,
+ // F that was created using the bind function is called with a
+ // list of arguments ExtraArgs, the following steps are taken:
+ // 1. Let target be the value of F's [[TargetFunction]]
+ // internal property.
+ // 2. If target has no [[Construct]] internal method, a
+ // TypeError exception is thrown.
+ // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
+ // property.
+ // 4. Let args be a new list containing the same values as the
+ // list boundArgs in the same order followed by the same
+ // values as the list ExtraArgs in the same order.
+ // 5. Return the result of calling the [[Construct]] internal
+ // method of target providing args as the arguments.
+
+ var result = target.apply(
+ this,
+ args.concat(slice.call(arguments))
+ );
+ if (Object(result) === result) {
+ return result;
+ }
+ return this;
+
+ } else {
+ // 15.3.4.5.1 [[Call]]
+ // When the [[Call]] internal method of a function object, F,
+ // which was created using the bind function is called with a
+ // this value and a list of arguments ExtraArgs, the following
+ // steps are taken:
+ // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
+ // property.
+ // 2. Let boundThis be the value of F's [[BoundThis]] internal
+ // property.
+ // 3. Let target be the value of F's [[TargetFunction]] internal
+ // property.
+ // 4. Let args be a new list containing the same values as the
+ // list boundArgs in the same order followed by the same
+ // values as the list ExtraArgs in the same order.
+ // 5. Return the result of calling the [[Call]] internal method
+ // of target providing boundThis as the this value and
+ // providing args as the arguments.
+
+ // equiv: target.call(this, ...boundArgs, ...args)
+ return target.apply(
+ that,
+ args.concat(slice.call(arguments))
+ );
+
+ }
+
+ };
+ if(target.prototype) {
+ Empty.prototype = target.prototype;
+ bound.prototype = new Empty();
+ // Clean up dangling references.
+ Empty.prototype = null;
+ }
+ // XXX bound.length is never writable, so don't even try
+ //
+ // 15. If the [[Class]] internal property of Target is "Function", then
+ // a. Let L be the length property of Target minus the length of A.
+ // b. Set the length own property of F to either 0 or L, whichever is
+ // larger.
+ // 16. Else set the length own property of F to 0.
+ // 17. Set the attributes of the length own property of F to the values
+ // specified in 15.3.5.1.
+
+ // TODO
+ // 18. Set the [[Extensible]] internal property of F to true.
+
+ // TODO
+ // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
+ // 20. Call the [[DefineOwnProperty]] internal method of F with
+ // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
+ // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
+ // false.
+ // 21. Call the [[DefineOwnProperty]] internal method of F with
+ // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
+ // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
+ // and false.
+
+ // TODO
+ // NOTE Function objects created using Function.prototype.bind do not
+ // have a prototype property or the [[Code]], [[FormalParameters]], and
+ // [[Scope]] internal properties.
+ // XXX can't delete prototype in pure-js.
+
+ // 22. Return F.
+ return bound;
+ };
+ }
+}());
+
+// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
+if (!Object.keys) {
+ Object.keys = (function () {
+ 'use strict';
+ var hasOwnProperty = Object.prototype.hasOwnProperty,
+ hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
+ dontEnums = [
+ 'toString',
+ 'toLocaleString',
+ 'valueOf',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'constructor'
+ ],
+ dontEnumsLength = dontEnums.length;
+
+ return function (obj) {
+ if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
+ throw new TypeError('Object.keys called on non-object');
+ }
+
+ var result = [], prop, i;
+
+ for (prop in obj) {
+ if (hasOwnProperty.call(obj, prop)) {
+ result.push(prop);
+ }
+ }
+
+ if (hasDontEnumBug) {
+ for (i = 0; i < dontEnumsLength; i++) {
+ if (hasOwnProperty.call(obj, dontEnums[i])) {
+ result.push(dontEnums[i]);
+ }
+ }
+ }
+ return result;
+ };
+ }());
+}
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
+if (!Array.prototype.map)
+{
+ Array.prototype.map = function(fun /*, thisArg */)
+ {
+ "use strict";
+
+ if (this === void 0 || this === null)
+ throw new TypeError();
+
+ var t = Object(this);
+ var len = t.length >>> 0;
+ if (typeof fun !== "function")
+ throw new TypeError();
+
+ var res = new Array(len);
+ var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
+ for (var i = 0; i < len; i++)
+ {
+ // NOTE: Absolute correctness would demand Object.defineProperty
+ // be used. But this method is fairly new, and failure is
+ // possible only if Object.prototype or Array.prototype
+ // has a property |i| (very unlikely), so use a less-correct
+ // but more portable alternative.
+ if (i in t)
+ res[i] = fun.call(thisArg, t[i], i, t);
+ }
+
+ return res;
+ };
+};/**
+ * Stringify.
+ * Inspect native browser objects and functions.
+ */
+var stringify = (function () {
+
+ var sortci = function(a, b) {
+ return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
+ };
+
+ var htmlEntities = function (str) {
+ return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
+ };
+
+ /**
+ * Recursively stringify an object. Keeps track of which objects it has
+ * visited to avoid hitting circular references, and a buffer for indentation.
+ * Goes 2 levels deep.
+ */
+ return function stringify(o, visited, buffer) {
+ var i, vi, type = '', parts = [], circular = false;
+ buffer = buffer || '';
+ visited = visited || [];
+
+ // Get out fast with primitives that don't like toString
+ if (o === null) {
+ return 'null';
+ }
+ if (typeof o === 'undefined') {
+ return 'undefined';
+ }
+
+ // Determine the type
+ try {
+ type = ({}).toString.call(o);
+ } catch (e) { // only happens when typeof is protected (...randomly)
+ type = '[object Object]';
+ }
+
+ // Handle the primitive types
+ if (type == '[object Number]') {
+ return ''+o;
+ }
+ if (type == '[object Boolean]') {
+ return o ? 'true' : 'false';
+ }
+ if (type == '[object Function]') {
+ return o.toString().split('\n ').join('\n' + buffer);
+ }
+ if (type == '[object String]') {
+ return '"' + htmlEntities(o.replace(/"/g, '\\"')) + '"';
+ }
+
+ // Check for circular references
+ for (vi = 0; vi < visited.length; vi++) {
+ if (o === visited[vi]) {
+ // Notify the user that a circular object was found and, if available,
+ // show the object's outerHTML (for body and elements)
+ return '[circular ' + type.slice(1) +
+ ('outerHTML' in o ? ' :\n' + htmlEntities(o.outerHTML).split('\n').join('\n' + buffer) : '')
+ }
+ }
+
+ // Remember that we visited this object
+ visited.push(o);
+
+ // Stringify each member of the array
+ if (type == '[object Array]') {
+ for (i = 0; i < o.length; i++) {
+ parts.push(stringify(o[i], visited));
+ }
+ return '[' + parts.join(', ') + ']';
+ }
+
+ // Fake array – very tricksy, get out quickly
+ if (type.match(/Array/)) {
+ return type;
+ }
+
+ var typeStr = type + ' ',
+ newBuffer = buffer + ' ';
+
+ // Dive down if we're less than 2 levels deep
+ if (buffer.length / 2 < 2) {
+
+ var names = [];
+ // Some objects don't like 'in', so just skip them
+ try {
+ for (i in o) {
+ names.push(i);
+ }
+ } catch (e) {}
+
+ names.sort(sortci);
+ for (i = 0; i < names.length; i++) {
+ try {
+ parts.push(newBuffer + names[i] + ': ' + stringify(o[names[i]], visited, newBuffer));
+ } catch (e) {}
+ }
+
+ }
+
+ // If nothing was gathered, return empty object
+ if (!parts.length) return typeStr + '{ ... }';
+
+ // Return the indented object with new lines
+ return typeStr + '{\n' + parts.join(',\n') + '\n' + buffer + '}';
+ };
+}());;/**
+ * Utilities & polyfills
+ */
+
+var prependChild = function(elem, child) { elem.insertBefore(child, elem.firstChild); };
+
+var addEvent = function(elem, event, fn) {
+ if (elem.addEventListener) {
+ elem.addEventListener(event, fn, false);
+ } else {
+ elem.attachEvent("on" + event, function() {
+ // set the this pointer same as addEventListener when fn is called
+ return(fn.call(elem, window.event));
+ });
+ }
+};
+
+if (!window.location.origin) window.location.origin = window.location.protocol+"//"+window.location.host;
+
+var throttle = function (fn, delay) {
+ var timer = null;
+ var throttled = function () {
+ var context = this, args = arguments;
+ throttled.cancel();
+ throttled.timer = setTimeout(function () {
+ fn.apply(context, args);
+ }, delay);
+ };
+
+ throttled.cancel = function () {
+ clearTimeout(throttled.timer);
+ };
+
+ return throttled;
+};
+
+var cleanse = function (s) {
+ return (s||'').replace(/[<&]/g, function (m) { return {'&':'&','<':'<'}[m];});
+};
+
+var getIframeWindow = function (iframeElement) {
+ return iframeElement.contentWindow || iframeElement.contentDocument.parentWindow;
+};;/**
+ * Protect against infinite loops.
+ * Look for for, while and do loops, and insert a check function at the start of
+ * the loop. If the check function is called many many times then it returns
+ * true, preventing the loop from running again.
+ */
+var loopProtect = (function () {
+ 'use strict';
+ var debug = null;
+
+ // the standard loops - note that recursive is not supported
+ var re = /\b(for|while|do)\b/g;
+ var reSingle = /\b(for|while|do)\b/;
+ var labelRe = /\b([a-z_]{1}\w+:)/i;
+ var comments = /(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm;
+
+ var loopProtect = {};
+
+ // used in the loop detection
+ loopProtect.counters = {};
+
+ // expose debug info
+ loopProtect.debug = function (state) {
+ debug = state ? function () {
+ console.log.apply(console, [].slice.apply(arguments));
+ } : function () {};
+ };
+
+ loopProtect.debug(false); // off by default
+
+ // the method - as this could be aliased to something else
+ loopProtect.method = 'window.runnerWindow.protect';
+
+ function inMultilineComment(lineNum, lines) {
+ if (lineNum === 0) {
+ return false;
+ }
+
+ var j = lineNum;
+ var closeCommentTags = 1; // let's assume we're inside a comment
+ var closePos = -1;
+ var openPos = -1;
+
+ do {
+ j -= 1;
+ debug('looking backwards ' + lines[j]);
+ closePos = lines[j].indexOf('*/');
+ openPos = lines[j].indexOf('/*');
+
+ if (closePos !== -1) {
+ closeCommentTags++;
+ }
+
+ if (openPos !== -1) {
+ closeCommentTags--;
+
+ if (closeCommentTags === 0) {
+ debug('- exit: part of a multiline comment');
+ return true;
+ }
+ }
+ } while (j !== 0);
+
+ return false;
+ }
+
+ function inCommentOrString(index, line) {
+ var character;
+ while (--index > -1) {
+ character = line.substr(index, 1);
+ if (character === '"' || character === '\'' || character === '.') {
+ // our loop keyword was actually either in a string or a property, so let's exit and ignore this line
+ debug('- exit: matched inside a string or property key');
+ return true;
+ }
+ if (character === '/' || character === '*') {
+ // looks like a comment, go back one to confirm or not
+ --index;
+ if (character === '/') {
+ // we've found a comment, so let's exit and ignore this line
+ debug('- exit: part of a comment');
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ function directlyBeforeLoop(index, lineNum, lines) {
+ reSingle.lastIndex = 0;
+ labelRe.lastIndex = 0;
+ var beforeLoop = false;
+
+ var theRest = lines.slice(lineNum).join('\n').substr(index).replace(labelRe, '');
+ theRest.replace(reSingle, function (match, capture, i) {
+ var target = theRest.substr(0, i).replace(comments, '').trim();
+ debug('- directlyBeforeLoop: ' + target);
+ if (target.length === 0) {
+ beforeLoop = true;
+ }
+ // strip comments out of the target, and if there's nothing else
+ // it's a valid label...I hope!
+ });
+
+ return beforeLoop;
+ }
+
+ /**
+ * Look for for, while and do loops, and inserts *just* at the start of the
+ * loop, a check function.
+ */
+ loopProtect.rewriteLoops = function (code, offset) {
+ var recompiled = [];
+ var lines = code.split('\n');
+ var disableLoopProtection = false;
+ var method = loopProtect.method;
+ var ignore = {};
+ var pushonly = {};
+ var labelPostion = null;
+
+ var insertReset = function (lineNum, line, matchPosition) {
+ // recompile the line with the reset **just** before the actual loop
+ // so that we insert in to the correct location (instead of possibly
+ // outside the logic
+ return line.slice(0, matchPosition) + ';' + method + '({ line: ' + lineNum + ', reset: true }); ' + line.slice(matchPosition);
+ };
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ lines.forEach(function (line, lineNum) {
+ // reset our regexp each time.
+ re.lastIndex = 0;
+ labelRe.lastIndex = 0;
+
+ if (disableLoopProtection) {
+ return;
+ }
+
+ if (line.toLowerCase().indexOf('noprotect') !== -1) {
+ disableLoopProtection = true;
+ }
+
+ var index = -1;
+ var matchPosition = -1;
+ var originalLineNum = lineNum;
+ // +1 since we're humans and don't read lines numbers from zero
+ var printLineNumber = lineNum - offset + 1;
+ var character = '';
+ // special case for `do` loops, as they're end with `while`
+ var dofound = false;
+ var findwhile = false;
+ var terminator = false;
+ var matches = line.match(re) || [];
+ var match = matches.length ? matches[0] : '';
+ var labelMatch = line.match(labelRe) || [];
+ var openBrackets = 0;
+ var openBraces = 0;
+
+ if (labelMatch.length) {
+ debug('- label match');
+ index = line.indexOf(labelMatch[1]);
+ if (!inCommentOrString(index, line)) {
+ if (!inMultilineComment(lineNum, lines)) {
+ if (directlyBeforeLoop(index, lineNum, lines)) {
+ debug('- found a label: "' + labelMatch[0] + '"');
+ labelPostion = lineNum;
+ } else {
+ debug('- ignored "label", false positive');
+ }
+ } else {
+ debug('- ignored label in multline comment');
+ }
+ } else {
+ debug('- ignored label in string or comment');
+ }
+ }
+
+ if (ignore[lineNum]) {
+ debug(' -exit: ignoring line ' + lineNum +': ' + line);
+ return;
+ }
+
+ if (pushonly[lineNum]) {
+ debug('- exit: ignoring, but adding line ' + lineNum + ': ' + line);
+ recompiled.push(line);
+ return;
+ }
+
+ // if there's more than one match, we just ignore this kind of loop
+ // otherwise I'm going to be writing a full JavaScript lexer...and god
+ // knows I've got better things to be doing.
+ if (match && matches.length === 1 && line.indexOf('jsbin') === -1) {
+ debug('match on ' + match + '\n');
+
+ // there's a special case for protecting `do` loops, we need to first
+ // prtect the `do`, but then ignore the closing `while` statement, so
+ // we reset the search state for this special case.
+ dofound = match === 'do';
+
+ // make sure this is an actual loop command by searching backwards
+ // to ensure it's not a string, comment or object property
+ matchPosition = index = line.indexOf(match);
+
+ // first we need to walk backwards to ensure that our match isn't part
+ // of a string or part of a comment
+ if (inCommentOrString(index, line)) {
+ recompiled.push(line);
+ return;
+ }
+
+ // it's quite possible we're in the middle of a multiline
+ // comment, so we'll cycle up looking for an opening comment,
+ // and if there's one (and not a closing `*/`), then we'll
+ // ignore this line as a comment
+ if (inMultilineComment(lineNum, lines)) {
+ recompiled.push(line);
+ return;
+ }
+
+ // now work our way forward to look for '{'
+ index = line.indexOf(match) + match.length;
+
+ if (index === line.length) {
+ if (index === line.length && lineNum < (lines.length-1)) {
+ // move to the next line
+ debug('- moving to next line');
+ recompiled.push(line);
+ lineNum++;
+ line = lines[lineNum];
+ ignore[lineNum] = true;
+ index = 0;
+ }
+
+ }
+
+ while (index < line.length) {
+ character = line.substr(index, 1);
+ // debug(character, index);
+
+ if (character === '(') {
+ openBrackets++;
+ }
+
+ if (character === ')') {
+ openBrackets--;
+
+ if (openBrackets === 0 && terminator === false) {
+ terminator = index;
+ }
+ }
+
+ if (character === '{') {
+ openBraces++;
+ }
+
+ if (character === '}') {
+ openBraces--;
+ }
+
+ if (openBrackets === 0 && (character === ';' || character === '{')) {
+ // if we're a non-curlies loop, then convert to curlies to get our code inserted
+ if (character === ';') {
+ if (lineNum !== originalLineNum) {
+ debug('- multiline inline loop');
+ // affect the compiled line
+ recompiled[originalLineNum] = recompiled[originalLineNum].substring(0, terminator + 1) + '{\nif (' + method + '({ line: ' + printLineNumber + ' })) break;\n' + recompiled[originalLineNum].substring(terminator + 1);
+ line += '\n}\n';
+ } else {
+ // simpler
+ debug('- single line inline loop');
+ line = line.substring(0, terminator + 1) + '{\nif (' + method + '({ line: ' + printLineNumber + ' })) break;\n' + line.substring(terminator + 1) + '\n}\n';
+ }
+
+ } else if (character === '{') {
+ debug('- multiline with braces');
+ var insert = ';\nif (' + method + '({ line: ' + printLineNumber + ' })) break;\n';
+ line = line.substring(0, index + 1) + insert + line.substring(index + 1);
+
+ index += insert.length;
+ }
+
+ // work out where to put the reset
+ if (lineNum === originalLineNum && labelPostion === null) {
+ debug('- simple reset insert');
+ line = insertReset(printLineNumber, line, matchPosition);
+ index += (';' + method + '({ line: ' + lineNum + ', reset: true }); ').length;
+ } else {
+ // insert the reset above the originalLineNum OR if this loop used
+ // a label, we have to insert the reset *above* the label
+ if (labelPostion === null) {
+ debug('- reset inserted above original line');
+ recompiled[originalLineNum] = insertReset(printLineNumber, recompiled[originalLineNum], matchPosition);
+ } else {
+ debug('- reset inserted above matched label on line ' + labelPostion);
+ if (recompiled[labelPostion] === undefined) {
+ labelPostion--;
+ matchPosition = 0;
+ }
+ recompiled[labelPostion] = insertReset(printLineNumber, recompiled[labelPostion], matchPosition);
+ labelPostion = null;
+ }
+ }
+
+ recompiled.push(line);
+
+ if (!dofound) {
+ return;
+ } else {
+ debug('searching for closing `while` statement for: ' + line);
+ // cycle forward until we find the close brace, after which should
+ // be our while statement to ignore
+ findwhile = false;
+ while (index < line.length) {
+ character = line.substr(index, 1);
+
+ if (character === '{') {
+ openBraces++;
+ }
+
+ if (character === '}') {
+ openBraces--;
+ }
+
+ // debug(character, openBraces);
+
+ if (openBraces === 0) {
+ findwhile = true;
+ } else {
+ findwhile = false;
+ }
+
+ if (openBraces === 0) {
+ debug('outside of closure, looking for `while` statement: ' + line);
+ }
+
+ if (findwhile && line.indexOf('while') !== -1) {
+ debug('- exit as we found `while`: ' + line);
+ pushonly[lineNum] = true;
+ return;
+ }
+
+ index++;
+
+ if (index === line.length && lineNum < (lines.length-1)) {
+ lineNum++;
+ line = lines[lineNum];
+ debug(line);
+ index = 0;
+ }
+ }
+ return;
+ }
+ }
+
+ index++;
+
+ if (index === line.length && lineNum < (lines.length-1)) {
+ // move to the next line
+ debug('- moving to next line');
+ recompiled.push(line);
+ lineNum++;
+ line = lines[lineNum];
+ ignore[lineNum] = true;
+ index = 0;
+ }
+ }
+ } else {
+ // else we're a regular line, and we shouldn't be touched
+ debug('regular line ' + line);
+ recompiled.push(line);
+ }
+ });
+
+ debug('---- source ----');
+ debug(code);
+ debug('---- rewrite ---');
+ debug(recompiled.join('\n'));
+ debug('');
+
+ return disableLoopProtection ? code : recompiled.join('\n');
+ };
+
+ /**
+ * Injected code in to user's code to **try** to protect against infinite
+ * loops cropping up in the code, and killing the browser. Returns true
+ * when the loops has been running for more than 100ms.
+ */
+ loopProtect.protect = function (state) {
+ loopProtect.counters[state.line] = loopProtect.counters[state.line] || {};
+ var line = loopProtect.counters[state.line];
+ var now = (new Date()).getTime();
+
+ if (state.reset) {
+ line.time = now;
+ line.hit = 0;
+ line.last = 0;
+ }
+
+ line.hit++;
+ if ((now - line.time) > 100) {//} && line.hit !== line.last+1) {
+ // We've spent over 100ms on this loop... smells infinite.
+ var msg = 'Exiting potential infinite loop at line ' + state.line + '. To disable loop protection: add "// noprotect" to your code';
+ if (window.proxyConsole) {
+ window.proxyConsole.error(msg);
+ } else {
+ console.error(msg);
+ }
+ // Returning true prevents the loop running again
+ return true;
+ }
+ line.last++;
+ return false;
+ };
+
+ loopProtect.reset = function () {
+ // reset the counters
+ loopProtect.counters = {};
+ };
+
+ return loopProtect;
+
+}());
+
+if (typeof exports !== 'undefined') {
+ module.exports = loopProtect;
+}
+;/** =========================================================================
+ * Console
+ * Proxy console.logs out to the parent window
+ * ========================================================================== */
+
+var proxyConsole = (function () {
+ 'use strict';
+ var supportsConsole = true;
+ try { window.console.log('d[ o_0 ]b'); } catch (e) { supportsConsole = false; }
+
+ var proxyConsole = function() {};
+
+ /**
+ * Stringify all of the console objects from an array for proxying
+ */
+ var stringifyArgs = function (args) {
+ var newArgs = [];
+ // TODO this was forEach but when the array is [undefined] it wouldn't
+ // iterate over them
+ var i = 0, length = args.length, arg;
+ for(; i < length; i++) {
+ arg = args[i];
+ if (typeof arg === 'undefined') {
+ newArgs.push('undefined');
+ } else {
+ newArgs.push(stringify(arg));
+ }
+ }
+ return newArgs;
+ };
+
+ // Create each of these methods on the proxy, and postMessage up to JS Bin
+ // when one is called.
+ var methods = proxyConsole.prototype.methods = [
+ 'debug', 'clear', 'error', 'info', 'log', 'warn', 'dir', 'props', '_raw',
+ 'group', 'groupEnd', 'dirxml', 'table', 'trace', 'assert', 'count',
+ 'markTimeline', 'profile', 'profileEnd', 'time', 'timeEnd', 'timeStamp',
+ 'groupCollapsed'
+ ];
+ methods.forEach(function (method) {
+ // Create console method
+ proxyConsole.prototype[method] = function () {
+ // Replace args that can't be sent through postMessage
+ var originalArgs = [].slice.call(arguments),
+ args = stringifyArgs(originalArgs);
+
+ // Post up with method and the arguments
+ runner.postMessage('console', {
+ method: method === '_raw' ? originalArgs.shift() : method,
+ args: method === '_raw' ? args.slice(1) : args
+ });
+
+ // If the browner supports it, use the browser console but ignore _raw,
+ // as _raw should only go to the proxy console.
+ if (window.console && method !== '_raw') {
+ if (!console[method]) { method = 'log'; }
+ console[method].apply(console, originalArgs);
+ }
+ };
+ });
+
+ return new proxyConsole();
+
+}());;/** =========================================================================
+ * Processor
+ * Modify the prepared source ready to be written to an iframe
+ * ========================================================================== */
+
+var processor = (function () {
+
+ var processor = {};
+
+ processor.blockingMethods = {
+ kill: '',
+ // RS: the empty comment in the end of the harness, ensures any
+ // open comments are closed, and will ensure the harness is hidden
+ // from the user.
+ restore: ''
+ };
+
+ /**
+ * Grab the doctype from a string.
+ *
+ * Returns an object with doctype and tail keys.
+ */
+ processor.getDoctype = (function () {
+ // Cached regex
+ // [\s\S] matches multiline doctypes
+ var regex = //i;
+ return function (str) {
+ var doctype = (str.match(regex) || [''])[0],
+ tail = str.substr(doctype.length);
+ return {
+ doctype: doctype,
+ tail: tail
+ };
+ };
+ }());
+
+ /**
+ * Replace HTML characters with encoded equivatents for debug mode.
+ */
+ processor.debug = function (source) {
+ return '' + source.replace(/[<>&]/g, function (m) {
+ if (m == '<') return '<';
+ if (m == '>') return '>';
+ if (m == '&') return '&';
+ }) + ' ';
+ };
+
+ /**
+ * Render – build the final source code to be written to the iframe. Takes
+ * the original source and an options object.
+ */
+ processor.render = function (source, options) {
+
+ options = options || [];
+ source = source || '';
+
+ var combinedSource = [],
+ realtime = (options.requested !== true),
+ noRealtimeJs = (options.includeJsInRealtime === false);
+
+ // If the render was realtime and we don't want javascript in realtime
+ // renders – Auto-run JS is unchecked – then strip out the Javascript
+ if (realtime && noRealtimeJs) {
+ source = source.replace(/",restore:""},a.getDoctype=function(){var a=//i;return function(b){var c=(b.match(a)||[""])[0],d=b.substr(c.length);return{doctype:c,tail:d}}}(),a.debug=function(a){return""+a.replace(/[<>&]/g,function(a){return"<"==a?"<":">"==a?">":"&"==a?"&":void 0})+" "},a.render=function(b,c){c=c||[],b=b||"";var d=[],e=c.requested!==!0,f=c.includeJsInRealtime===!1;e&&f&&(b=b.replace(/',
+ // RS: the empty comment in the end of the harness, ensures any
+ // open comments are closed, and will ensure the harness is hidden
+ // from the user.
+ restore: ''
+ };
+
+ /**
+ * Grab the doctype from a string.
+ *
+ * Returns an object with doctype and tail keys.
+ */
+ processor.getDoctype = (function () {
+ // Cached regex
+ // [\s\S] matches multiline doctypes
+ var regex = //i;
+ return function (str) {
+ var doctype = (str.match(regex) || [''])[0],
+ tail = str.substr(doctype.length);
+ return {
+ doctype: doctype,
+ tail: tail
+ };
+ };
+ }());
+
+ /**
+ * Replace HTML characters with encoded equivatents for debug mode.
+ */
+ processor.debug = function (source) {
+ return '' + source.replace(/[<>&]/g, function (m) {
+ if (m == '<') return '<';
+ if (m == '>') return '>';
+ if (m == '&') return '&';
+ }) + ' ';
+ };
+
+ /**
+ * Render – build the final source code to be written to the iframe. Takes
+ * the original source and an options object.
+ */
+ processor.render = function (source, options) {
+
+ options = options || [];
+ source = source || '';
+
+ var combinedSource = [],
+ realtime = (options.requested !== true),
+ noRealtimeJs = (options.includeJsInRealtime === false);
+
+ // If the render was realtime and we don't want javascript in realtime
+ // renders – Auto-run JS is unchecked – then strip out the Javascript
+ if (realtime && noRealtimeJs) {
+ source = source.replace(/",restore:""},a.getDoctype=function(){var a=//i;return function(b){var c=(b.match(a)||[""])[0],d=b.substr(c.length);return{doctype:c,tail:d}}}(),a.debug=function(a){return""+a.replace(/[<>&]/g,function(a){return"<"==a?"<":">"==a?">":"&"==a?"&":void 0})+" "},a.render=function(b,c){c=c||[],b=b||"";var d=[],e=c.requested!==!0,f=c.includeJsInRealtime===!1;e&&f&&(b=b.replace(/
+{{#feature request "welcomePanel"}}
+ {{> welcome_panel}}
+{{/feature}}{{/unless}}
@@ -23,7 +33,7 @@
{{#if embed}}
{{else}}
-
-
@@ -156,7 +167,7 @@
-
+
@@ -322,7 +333,7 @@
{{/unless}}
{{#if settings.[ui showblog]}}
-
@@ -401,6 +411,7 @@
Console
Run
+ Clear
-
+ {{/unless}}
@@ -471,10 +484,6 @@ Include alerts, prompts & confirm boxes">Run with JS
ctrl + /
Toggle comment on selected lines
-
ctrl + [
Indents selected lines
@@ -485,7 +494,7 @@ Include alerts, prompts & confirm boxes">Run with JS
tab
- Code complete (JavaScript only) & Emmet expand
+ Code complete & Emmet expand
ctrl + s
@@ -495,22 +504,11 @@ Include alerts, prompts & confirm boxes">Run with JS
ctrl + shift + s
Open the share options
-
-
-
-
JS Bin also supports Emmet/Zen Coding shortcuts
+
Complete list of JS Bin shortcuts
@@ -588,19 +586,10 @@ Include alerts, prompts & confirm boxes">Run with JS
{{/feature}}
-
-{{#if isProduction}}
-
-
+
+{{#unless embed}}
+
+{{/unless}}
+{{#if live}}
+
+
{{else}}
- {{#if concat}}
-
-
+
+ {{#if isProduction}}
+
+
{{else}}
-
- {{#scripts}}{{/scripts}}
+
+ {{#if concat}}
+
+ {{else}}
+ {{#scripts}}{{/scripts}}
+ {{/if}}
+ {{#addons}}{{/addons}}
{{/if}}
- {{#addons}}{{/addons}}
{{/if}}
{{#if live}}
{{/if}}
+
diff --git a/views/partials/account_sidebar.html b/views/partials/account_sidebar.html
index 5f09ca04..93e06cb6 100644
--- a/views/partials/account_sidebar.html
+++ b/views/partials/account_sidebar.html
@@ -1,13 +1,13 @@
+
+
+ {{#if flash_tip}}{{{flash_tip}}}{{/if}}
+
+
Dismiss x
+
{{{body}}}
@@ -52,5 +58,10 @@
+
+
+
diff --git a/views/upgrade.html b/views/upgrade.html
new file mode 100644
index 00000000..b3faf0ca
--- /dev/null
+++ b/views/upgrade.html
@@ -0,0 +1,84 @@
+
+ Upgrade
+
+
+
+Your Pro accounts keep JS Bin 100% free for education
+
+ Aside from the features listed above, your pro account will help keep
+ JS Bin 100% free for educational uses (schools, universities and community
+ training). Those good people will be able to get free training accounts
+ so they can continue to help young students and new-comers with JS Bin in
+ their tool belt.
+
+
+Education is dear to our hearts, and pro accounts allows us to keep developing
+ JS Bin with feature i want to see land, and to help fix and issues that cause
+ problems for noth general users and those students stuck working with limited
+ access to tech (like the version of JS Bin that works without a web connection
+ and entirely from a usb stick with zero install).
+
+
+