From 33e220a312290d6392840527f24ce44e0f72bbaf Mon Sep 17 00:00:00 2001 From: bjb568 Date: Mon, 15 Jun 2015 21:31:09 -0400 Subject: [PATCH 1/7] MVP, very slow --- buildpage.js | 2 +- html/dev/canvas.html | 103 ++++++-- http/a/rainbow.js | 353 +++++++++++++++++++++++++++ http/dev/runcanvas.js | 24 +- http/rainbowtest.html | 539 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1000 insertions(+), 21 deletions(-) create mode 100644 http/a/rainbow.js create mode 100644 http/rainbowtest.html diff --git a/buildpage.js b/buildpage.js index 23d783c..e6dc8fa 100644 --- a/buildpage.js +++ b/buildpage.js @@ -950,7 +950,7 @@ http.createServer(function(req, res) { }); }); }); - }, {inhead: ''}); + }, {inhead: '\n'}); }); } else if (req.url.pathname == '/learn/') { respondPage(null, user, req, res, function() { diff --git a/html/dev/canvas.html b/html/dev/canvas.html index 951fc51..19c16ab 100644 --- a/html/dev/canvas.html +++ b/html/dev/canvas.html @@ -1,7 +1,10 @@

$title Save

- +
+ + +
@@ -34,11 +37,11 @@

$title *::-webkit-input-placeholder { color: #888 } *::-moz-placeholder { color: #999 } - html, #content, #footer, #main { background: #000 } + html, #content, #output, #footer, #main { background: #000 } #content { padding-bottom: 4px } #main a:hover { color: #4ff } #main a:active { color: #06f } - #main :not(input):not(button):not(.red):not(a), #main a:not(:hover):not(:active):not(.red), #footer * { color: #fff } + #main :not(input):not(button):not(.red):not(a):not(textarea):not(span), #main a:not(:hover):not(:active):not(.red), #footer * { color: #fff } #main { clear: both } #meta { clear: both; @@ -51,47 +54,59 @@

$title * { + position: absolute; + top: 0; left: 0; + width: 100%; height: 100%; + margin: 0; + padding: 2px; color: #fff; - background: #000; + background: transparent; font-family: monospace; + white-space: pre-wrap; + overflow: auto; font-size: 1rem; + line-height: 1.2; border: 1px solid #fff; resize: none; - margin-bottom: 8px; } - #code, #output { height: calc(50% - 4px) } + .ta-cont code { pointer-events: none } + .ta-cont, #output { height: calc(50% - 4px) } @media (min-width: 600px) { h1 { height: 1.65rem; margin-bottom: .35em; } - #code, #output { height: 100% } - #code { width: 60% } + .ta-cont, #output { height: 100% } + .ta-cont { width: 60% } #output { width: 39%; float: right; } - .fullscreen #code:not(:focus) { width: 39% } - .fullscreen #code:not(:focus) + #output { width: 60% } + .fullscreen .ta-cont:not(:focus) { width: 39% } + .fullscreen .ta-cont:not(:focus) + #output { width: 60% } } @media (min-width: 600px) and (max-width: 800px) { - #code { width: 55% } + .ta-cont { width: 55% } #output { width: 44% } - .fullscreen #code:not(:focus) { width: 44% } - .fullscreen #code:not(:focus) + #output { width: 55% } + .fullscreen .ta-cont:not(:focus) { width: 44% } + .fullscreen .ta-cont:not(:focus) + #output { width: 55% } } @media (min-width: 1500px) { - #code { margin-bottom: 0 } + .ta-cont { margin-bottom: 0 } } @media (min-width: 1600px) { - #code { width: 65% } + .ta-cont { width: 65% } #output { width: 34% } - .fullscreen #code:not(:focus) { width: 34% } - .fullscreen #code:not(:focus) + #output { width: 65% } + .fullscreen .ta-cont:not(:focus) { width: 34% } + .fullscreen .ta-cont:not(:focus) + #output { width: 65% } } .fullscreen #main #output.fullscreen { position: fixed; @@ -188,6 +203,7 @@

$title $title + + +'use strict'; + +String.prototype.replaceAll = function(find, replace) { + if (typeof find == 'string') return this.split(find).join(replace); + var t = this, i, j; + while (typeof(i = find.shift()) == 'string' && typeof(j = replace.shift()) == 'string') t = t.replaceAll(i || '', j || ''); + return t; +}; +String.prototype.repeat = function(num) { + return new Array(++num).join(this); +}; +Number.prototype.bound = function(l, h) { + return isNaN(h) ? Math.min(this, l) : Math.max(Math.min(this, h), l); +}; +HTMLCollection.prototype.indexOf = NodeList.prototype.indexOf = Array.prototype.indexOf; +HTMLCollection.prototype.forEach = NodeList.prototype.forEach = Array.prototype.forEach; +HTMLElement.prototype.insertAfter = function(newEl, refEl) { + if (refEl.nextSibling) refEl.parentNode.insertBefore(newEl, refEl.nextSibling); + else refEl.parentNode.appendChild(newEl); +}; + +function html(input, replaceQuoteOff) { + if (replaceQuoteOff) return input.toString().replaceAll(['&', '<'], ['&amp;', '&lt;']); + return input.toString().replaceAll(['&', '<', '"'], ['&amp;', '&lt;', '&quot;']); +} + +var mdWarnings = []; +function warning(message) { + console.log(message); + mdWarnings.push(message); +} +function spanMarkdown(input) { + input = html(input); + while (input.match(/\^([\w\^]+)/)) input = input.replace(/\^([\w\^]+)/, '<sup>$1</sup>'); + return input + .replaceAll('\u0001', '^') + .replace(/\[(.+?)\|(.+?)\]/g, '<abbr title="$2">$1</abbr>') + .replaceAll('\u0002', '[') + .replace(/\[\[(\d+)\](.*?)\]/g, '<sup class="reference" title="$2">[$1]</sup>') + .replace(/!\[([^\]]+)]\(https?:\/\/([^\s("\\]+\.[^\s"\\]+)\)/g, '<img alt="$1" src="https://$2" />') + .replace(/^https?:\/\/([^\s("\\]+\.[^\s"\\]+\.(svg|png|tiff|jpg|jpeg)(\?[^\s"\\\/]*)?)/g, '<img src="https://$1" />') + .replace(/\[([^\]]+)]\((https?:\/\/[^\s("\\]+\.[^\s"\\]+)\)/g, '$1'.link('$2')) + .replace(/([^;["\\])https?:\/\/([^\s("\\]+\.[^\s"\\]+\.(svg|png|tiff|jpg|jpeg)(\?[^\s"\\\/]*)?)/g, '$1<img src="https://$2" />') + .replace(/([^;["\\])(https?:\/\/([^\s("\\]+\.[^\s"\\]+))/g, '$1' + '$3'.link('$2')) + .replace(/^(https?:\/\/([^\s("\\]+\.[^\s"\\]+))/g, '$2'.link('$1')); +} +function inlineMarkdown(input) { + var output = '', + span = '', + current = [], + tags = { + '`': 'code', + '``': 'samp', + '*': 'em', + '**': 'strong', + '_': 'i', + '–––': 's', + '+++': 'ins', + '---': 'del', + '[c]': 'cite', + '[m]': 'mark', + '[u]': 'u', + '[v]': 'var', + '::': 'kbd', + '"': 'q' + }, + stags = { + sup: { + start: '^(', + end: ')^' + }, + sub: { + start: 'v(', + end: ')v' + }, + small: { + start: '[sm]', + end: '[/sm]' + } + }; + outer: for (var i = 0; i < input.length; i++) { + if (['code', 'samp'].indexOf(current[current.length - 1]) == -1) { + if (input[i] == '\\') span += input[++i].replace('^', '\u0001').replace('[', '\u0002'); + else { + for (var l = 3; l > 0; l--) { + if (tags[input.substr(i, l)]) { + output += spanMarkdown(span); + span = ''; + if (current[current.length - 1] == tags[input.substr(i, l)]) output += '</' + current.pop() + '>'; + else { + if (current.indexOf(tags[input.substr(i, l)]) != -1) warning('Illegal nesting of "' + input.substr(i, l) + '"'); + output += '<' + tags[input.substr(i, l)] + '>'; + current.push(tags[input.substr(i, l)]); + } + i += l - 1; + continue outer; + } + } + for (var j in stags) { + for (var l = 5; l > 0; l--) { + if (stags[j].start == input.substr(i, l)) { + output += spanMarkdown(span) + '<' + j + '>'; + span = ''; + current.push(stags[j].end); + i += l - 1; + continue outer; + } else if (stags[j].end == input.substr(i, l)) { + if (current[current.length - 1] == stags[j].end) { + output += spanMarkdown(span) + '</' + j + '>'; + span = ''; + current.pop(); + i += l - 1; + continue outer; + } else warning('Illegal close tag "' + stags[j].end + '" found'); + } + } + } + span += input[i]; + } + } else if (current[current.length - 1] == 'code' && input[i] == '`') { + current.pop(); + output += '</code>'; + } else if (current[current.length - 1] == 'samp' && input.substr(i, 2) == '``') { + current.pop(); + output += '</samp>'; + i++; + } else output += html(input[i]); + } + output += spanMarkdown(span); + if (current.length) warning('Unclosed tags. <' + current.join('>, <') + '>'); + for (var i = current.length - 1; i >= 0; i--) output += '</' + current[i] + '>'; + return output; +} +function markdown(input) { + if (input.indexOf('\n') == -1 && input.substr(0, 2) != '> ' && input.substr(0, 3) != '>! ' && input.substr(0, 2) != '- ' && input.substr(0, 2) != '* ' && input.substr(0, 4) != ' ' && input[0] != '\t' && !input.match(/^((\d+|[A-z])[.)]|#{1,6}|cite\[\d+\]:) /) && !input.match(/^[-–—]{12,}$/)) return inlineMarkdown(input); + var blockquote = '', + ul = '', + ol = '', + li = '', + code = '', + i; + return input.split('\n').map(function(val, i, arr) { + if (!val) return ''; + var f; + if (val.substr(0, 2) == '> ') { + val = val.substr(2); + if (arr[i + 1] && arr[i + 1].substr(0, 2) == '> ') { + blockquote += val + '\n'; + return ''; + } else { + var arg = blockquote + val; + blockquote = ''; + return '<blockquote>' + markdown(arg) + '</blockquote>'; + } + } else if (val.substr(0, 3) == '>! ') { + val = val.substr(3); + if (arr[i + 1] && arr[i + 1].substr(0, 3) == '>! ') { + blockquote += val + '\n'; + return ''; + } else { + var arg = blockquote + val; + blockquote = ''; + return '<blockquote class="spoiler">' + markdown(arg) + '</blockquote>'; + } + } else if (val.substr(0, 2) == '- ' || val.substr(0, 2) == '* ') { + if (!ul) ul = '<ul>'; + val = val.substr(2); + if (li) { + ul += '<li>' + markdown(li) + '</li>'; + li = ''; + } + if (arr[i + 1] && (arr[i + 1].substr(0, 2) == '- ' || arr[i + 1] && arr[i + 1].substr(0, 2) == '* ')) { + ul += '<li>' + inlineMarkdown(val) + '</li>'; + return ''; + } else if (arr[i + 1] && (arr[i + 1][0] == '\t' || arr[i + 1] && arr[i + 1].substr(0, 4) == ' ')) { + li += val + '\n'; + return ''; + } else { + var arg = ul + '<li>' + markdown(val) + '</li>'; + ul = ''; + return arg + '</ul>'; + } + } else if (f = val.match(/^(\d+|[A-z])[.)] /)) { + if (!ol) ol = '<ol>'; + val = val.substr(f[0].length); + if (li) { + ol += '<li>' + markdown(li) + '</li>'; + li = ''; + } + if (arr[i + 1] && arr[i + 1].match(/^(\d+|[A-z])[.)] /)) { + ol += '<li>' + inlineMarkdown(val) + '</li>'; + return ''; + } else if (arr[i + 1] && (arr[i + 1][0] == '\t' || arr[i + 1] && arr[i + 1].substr(0, 4) == ' ')) { + li += val + '\n'; + return ''; + } else { + var arg = ol + '<li>' + inlineMarkdown(val) + '</li>'; + ol = ''; + return arg + '</ol>'; + } + } else if (li && val[0] == '\t') { + li += val.substr(1) + '\n'; + if (ul && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && arr[i + 1].substr(2) != '- ' && arr[i + 1].substr(2) != '* '))) { + var arg = ul + '<li>' + markdown(li) + '</li>'; + li = ''; + return arg + '</ul>'; + } else if (ol && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && !arr[i + 1].match(/^(\d+|[A-z])[.)] /)))) { + var arg = ol + '<li>' + markdown(li) + '</li>'; + li = ''; + return arg + '</ol>'; + } + return ''; + } else if (li && val.substr(0, 4) == ' ') { + li += val.substr(4) + '\n'; + if (ul && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && arr[i + 1].substr(2) != '- ' && arr[i + 1].substr(2) != '* '))) { + var arg = ul + '<li>' + markdown(li) + '</li>'; + li = ''; + return arg + '</ul>'; + } else if (ol && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && !arr[i + 1].match(/^((\d+|[A-z])|[A-z])[.)] /)))) { + var arg = ol + '<li>' + markdown(li) + '</li>'; + li = ''; + return arg + '</ol>'; + } + return ''; + } else if (val[0] == '\t') { + code += val.substr(1); + if (!arr[i + 1] || (arr[i + 1].substr(0, 4) != ' ' && arr[i + 1][0] != '\t')) { + var arg = html(code); + code = ''; + return '<code class="blk">' + arg + '</code>'; + } else code += '\n'; + return ''; + } else if (val.substr(0, 4) == ' ') { + code += val.substr(4); + if (!arr[i + 1] || (arr[i + 1].substr(0, 4) != ' ' && arr[i + 1][0] != '\t')) { + var arg = html(code); + code = ''; + return '<code class="blk">' + arg + '</code>'; + } else code += '\n'; + return ''; + } else if ((f = val.match(/^#{1,6} /)) && (f = f[0].length - 1)) { + return '<h' + f + '>' + inlineMarkdown(val.substr(f + 1)) + '</h' + f + '>'; + } else if (val.match(/^[-–—]{12,}$/)) { + return '<hr />'; + } else if (i = val.match(/^cite\[(\d+)\]: /)) { + return '<div><sup class="reference-list">' + i[1] + '</sup> ' + inlineMarkdown(val.substr(i[0].length)) + '</div>'; + } else return '<p>' + inlineMarkdown(val) + '</p>'; + }).join(''); +} + +HTMLTextAreaElement.prototype.mdValidate = function(correct) { + var i = mdWarnings.length; + markdown(this.value); + var preverr = this.previousElementSibling && this.previousElementSibling.classList.contains('md-err') ? this.previousElementSibling : null, + err = mdWarnings[i]; + this.lastErrored = err && correct; + if (err && (correct || preverr || this.value.substr(0, this.selectionEnd || Infinity).match(/\s$/))) { + if (preverr) { + if (preverr.firstChild.nodeValue == err) { + if (this.lastErrored && err && correct) { + this.value = this.value.replace(/([^\\]?)(\\*)([`*_–\-+[(:"])/g, function(m, p1, p2, p3, i) { + if (i && !p1) return m; + return p1 + (p2.length % 2 ? p2 : p2 + '\\') + p3; + }); + return true; + } + return err; + } + preverr.parentNode.removeChild(preverr); + } + var span = document.createElement('span'); + span.classList.add('md-err'); + span.appendChild(document.createTextNode(err)); + this.parentNode.insertBefore(span, this); + } else if (preverr) preverr.parentNode.removeChild(preverr); + return err; +}; + +function mdValidateBody() { + if (document.activeElement.mdValidate && document.activeElement.id != 'code') document.activeElement.mdValidate(); +}; +addEventListener('input', mdValidateBody); + +var noPageOverflow = noPageOverflow || false, + pageOverflowMobile = pageOverflowMobile || false, + footerOff = footerOff || false, + mainContentEl = mainContentEl || false, + mainBottomPad = mainBottomPad || 0; + +function minHeight() { + var footer = document.getElementById('footer').offsetHeight, + sidebar = document.getElementById('sidebar'); + if (innerWidth < 1500 && sidebar) footer += sidebar.offsetHeight + 6; + if (noPageOverflow && !(innerWidth < pageOverflowMobile)) { + mainContentEl.style.minHeight = ''; + mainContentEl.style.height = Math.max(innerHeight - (footerOff ? -4 : footer) - mainContentEl.getBoundingClientRect().top + document.body.getBoundingClientRect().top - 12, noPageOverflow) - mainBottomPad + 'px'; + if (sidebar) sidebar.style.height = ''; + } else { + mainContentEl.style.height = ''; + if (navigator.userAgent.indexOf('Mobile') == -1) mainContentEl.style.minHeight = Math.max(0, innerHeight - (footerOff ? -4 : footer) - mainContentEl.getBoundingClientRect().top + document.body.getBoundingClientRect().top - (innerWidth < 1500 ? 6 : 12) - mainBottomPad) + 'px'; + else mainContentEl.style.minHeight = ''; + if (sidebar) { + if (innerWidth >= 1500) sidebar.style.height = mainContentEl.style.minHeight; + else sidebar.style.height = ''; + } + } +} +addEventListener('load', minHeight); +addEventListener('resize', minHeight); + +function request(uri, callback, params) { + var i = new XMLHttpRequest(); + i.open('POST', uri, true); + i.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + i.send(params); + i.onload = function() { + callback(this.status == 204 ? 'Success' : this.responseText); + }; + return i; +} + +function ago(od) { + var d = Math.round((new Date() - od) / 1000); + if (d < 3600) return Math.round(d / 60) + 'm ago'; + else if (d < 86400) return Math.round(d / 3600) + 'h ago'; + else if (d < 2592000) return Math.round(d / 86400) + 'd ago'; + else { + d = new Date(od); + var y = d.getUTCFullYear(); + return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec' ][d.getUTCMonth()] + ' ' + d.getUTCDate() + (y == new Date().getUTCFullYear() ? '' : ' \'' + y.toString().substr(2)); + } +} +function agot(d) { + var time = document.createElement('time'); + time.textContent = ago(d); + time.setAttribute('datetime', new Date(d).toISOString()); + return time; +} + +function textareaHandler(e) { + if (this.noHandle) return delete this.nHandle; + if (!this.hist) this.hist = [{ + body: '', + start: 0, + end: 0 + }]; + if (!this.hIndex) this.hIndex = 0; + if (e.keyCode == 9) { + if (this.selectionStart == this.selectionEnd) { + if (e.shiftKey) { + var cS = this.selectionEnd - 1; + while (this.value[cS] && this.value[cS] != '\n') { + if (this.value[cS] == '\t') { + this.value = this.value.substr(0, cS) + this.value.substr(++cS); + break; + } else cS--; + } + } else { + var oS = this.selectionEnd; + this.value = this.value.substr(0, oS) + '\t' + this.value.substr(oS); + this.selectionStart = this.selectionEnd = ++oS; + } + } else { + var lines = this.value.split('\n'), + i = 0, + start = 0; + while ((i += lines[start].length) < this.selectionStart - start) start++; + var end = start; + i -= lines[start].length; + while ((i += lines[end].length) < this.selectionEnd - end) end++; + i = --start; + while (++i <= end) { + if (e.shiftKey) lines[i][0] != '\t' || (lines[i] = lines[i].substr(1)); + else lines[i] = '\t' + lines[i]; + } + this.value = lines.join('\n'); + var nS = lines.slice(0, ++start).join('\n').length; + this.selectionStart = (nS += nS ? 1 : 0); + this.selectionEnd = nS + lines.slice(start, ++end).join('\n').length; + } + e.preventDefault(); + } else if (e.keyCode == 90 && e.metaKey && !e.altKey) { + e.preventDefault(); + if (this.hIndex == this.hist.length - 1 && this.hist[this.hIndex].body != this.value) { + this.hist.push({ + body: this.value, + start: this.selectionStart, + end: this.selectionEnd + }); + this.hIndex = this.hist.length - 1; + } + var data = this.hist[e.shiftKey ? ++this.hIndex : --this.hIndex]; + console.log(this.hist, this.hIndex); + if (data) { + this.value = data.body; + this.selectionStart = data.start; + this.selectionEnd = data.end; + } else e.shiftKey ? --this.hIndex : ++this.hIndex + } else { + if (this.hist[this.hIndex].body != this.value) this.hist = this.hist.slice(0, this.hIndex + 1); + if (this.timer) clearTimeout(this.timer); + this.timer = setTimeout(function(e) { + if (e.hIndex != e.hist.length - 1) return; + if (e.hist[e.hIndex].body == e.value) return; + e.hist.push({ + body: e.value, + start: e.selectionStart, + end: e.selectionEnd + }); + e.hIndex = e.hist.length - 1; + }, this.lastKeyCode == e.keyCode || [8, 9, 13].indexOf(e.keyCode) == -1 ? 400 : 0, this); + } + this.lastKeyCode = e.keyCode; +} + +addEventListener('DOMContentLoaded', function() { + mainContentEl = mainContentEl || document.getElementById('content'); + if (navigator.userAgent.indexOf('Trident') != -1 || navigator.userAgent.indexOf('MSIE') != -1) { + var span = document.createElement('span'); + span.appendChild(document.createTextNode('This site does not support Microsoft Internet Explorer due to its lack of compatibility with web specifications.')); + document.getElementById('err').appendChild(span); + document.getElementById('cont').hidden = true; + document.getElementById('cont').style.display = 'none'; + } + var e = document.getElementsByTagName('textarea'), + i = e.length; + while (i--) e[i].addEventListener('keydown', textareaHandler); + setInterval(function() { + var times = document.getElementsByTagName('time'); + for (var i = 0; i < times.length; i++) { + var t = ago(Date.parse(times[i].getAttribute('datetime'))); + if (times[i].textContent != t) times[i].textContent = t; + } + }, 100); + minHeight(); +}); + +document.addEventListener('visibilitychange', function() { + if (!document.hidden) { + request('/api/notif', function(res) { + document.getElementById('nav').children[7].classList.toggle('unread', res); + }); + } +}); + +if (navigator.userAgent.indexOf('Mobile') != -1) addEventListener('touchend', function() {}); //Fixes mobile-safari bug with touch listeners in iframes not firing + + \ No newline at end of file From 53848e88b1a5f262254d2f3b71a66fc53cd82d27 Mon Sep 17 00:00:00 2001 From: bjb568 Date: Sun, 21 Jun 2015 16:21:18 -0400 Subject: [PATCH 2/7] New highlighter, still in dev stage --- buildpage.js | 2 +- html/dev/canvas.html | 127 ++--- http/a/main.js | 2 +- http/a/rainbow.js | 19 +- http/dev/runcanvas.js | 627 ++++++++++++++++++++++- http/highlighter.html | 1118 +++++++++++++++++++++++++++++++++++++++++ http/rainbowtest.html | 367 ++++++++++---- 7 files changed, 2075 insertions(+), 187 deletions(-) create mode 100644 http/highlighter.html diff --git a/buildpage.js b/buildpage.js index e6dc8fa..23d783c 100644 --- a/buildpage.js +++ b/buildpage.js @@ -950,7 +950,7 @@ http.createServer(function(req, res) { }); }); }); - }, {inhead: '\n'}); + }, {inhead: ''}); }); } else if (req.url.pathname == '/learn/') { respondPage(null, user, req, res, function() { diff --git a/html/dev/canvas.html b/html/dev/canvas.html index 19c16ab..8dd35c1 100644 --- a/html/dev/canvas.html +++ b/html/dev/canvas.html @@ -1,9 +1,10 @@

$title Save

-
- - +
+ + +
@@ -54,59 +55,74 @@

$title * { - position: absolute; - top: 0; left: 0; - width: 100%; height: 100%; - margin: 0; - padding: 2px; + #code, #code-display { + display: block; + width: calc(100% - 1.2em); min-height: 100%; + padding: 0; + margin: 2px; color: #fff; background: transparent; font-family: monospace; white-space: pre-wrap; - overflow: auto; + word-wrap: break-word; + overflow-wrap: break-word; font-size: 1rem; line-height: 1.2; - border: 1px solid #fff; resize: none; + outline: none; + border: none; + border-left: 1px solid #444; + padding-left: 4px; + } + #code { + position: absolute; + top: 0; + z-index: 1; + color: transparent; + } + #cursor { + display: inline-block; + background: #fff; + position: absolute; } - .ta-cont code { pointer-events: none } - .ta-cont, #output { height: calc(50% - 4px) } + #ta-cont, #output { height: calc(50% - 4px) } @media (min-width: 600px) { h1 { height: 1.65rem; margin-bottom: .35em; } - .ta-cont, #output { height: 100% } - .ta-cont { width: 60% } + #ta-cont, #output { height: 100% } + #ta-cont { width: 60% } #output { width: 39%; float: right; } - .fullscreen .ta-cont:not(:focus) { width: 39% } - .fullscreen .ta-cont:not(:focus) + #output { width: 60% } + .fullscreen #ta-cont:not(:focus) { width: 39% } + .fullscreen #ta-cont:not(:focus) + #output { width: 60% } } @media (min-width: 600px) and (max-width: 800px) { - .ta-cont { width: 55% } + #ta-cont { width: 55% } #output { width: 44% } - .fullscreen .ta-cont:not(:focus) { width: 44% } - .fullscreen .ta-cont:not(:focus) + #output { width: 55% } + .fullscreen #ta-cont:not(:focus) { width: 44% } + .fullscreen #ta-cont:not(:focus) + #output { width: 55% } } @media (min-width: 1500px) { - .ta-cont { margin-bottom: 0 } + #ta-cont { margin-bottom: 0 } } @media (min-width: 1600px) { - .ta-cont { width: 65% } + #ta-cont { width: 65% } #output { width: 34% } - .fullscreen .ta-cont:not(:focus) { width: 34% } - .fullscreen .ta-cont:not(:focus) + #output { width: 65% } + .fullscreen #ta-cont:not(:focus) { width: 34% } + .fullscreen #ta-cont:not(:focus) + #output { width: 65% } } .fullscreen #main #output.fullscreen { position: fixed; @@ -219,17 +235,7 @@

$title $title + + + +vsasdf = function() { + bg(0); + stroke(mousePressed ? '#f00' : none); + font('40px verdana'); + text(100, 100, round(mouseX) + ',' + round(mouseY)); + if (key) print(key); +}; +String.prototype.replaceAll = function(find, replace) { + if (typeof find == 'string') return this.split(find).join(replace); + var t = this, i, j; + while (typeof(i = find.shift()) == 'string' && typeof(j = replace.shift()) == 'string') t = t.replaceAll(i || '', j || ''); + return t; +}; +String.prototype.repeat = function(num) { + return new Array(++num).join(this); +}; +Number.prototype.bound = function(l, h) { + return isNaN(h) ? Math.min(this, l) : Math.max(Math.min(this, h), l); +}; +HTMLCollection.prototype.indexOf = NodeList.prototype.indexOf = Array.prototype.indexOf; +HTMLCollection.prototype.forEach = NodeList.prototype.forEach = Array.prototype.forEach; +HTMLElement.prototype.insertAfter = function(newEl, refEl) { + if (refEl.nextSibling) refEl.parentNode.insertBefore(newEl, refEl.nextSibling); + else refEl.parentNode.appendChild(newEl); +}; + +function html(input, replaceQuoteOff) { + if (replaceQuoteOff) return input.toString().replaceAll(['&', '<'], ['&amp;', '&lt;']); + return input.toString().replaceAll(['&', '<', '"'], ['&amp;', '&lt;', '&quot;']); +} + +var mdWarnings = []; +function warning(message) { + console.log(message); + mdWarnings.push(message); +} +function spanMarkdown(input) { + input = html(input); + while (input.match(/\^([\w\^]+)/)) input = input.replace(/\^([\w\^]+)/, '<sup>$1</sup>'); + return input + .replaceAll('\u0001', '^') + .replace(/\[(.+?)\|(.+?)\]/g, '<abbr title="$2">$1</abbr>') + .replaceAll('\u0002', '[') + .replace(/\[\[(\d+)\](.*?)\]/g, '<sup class="reference" title="$2">[$1]</sup>') + .replace(/!\[([^\]]+)]\(https?:\/\/([^\s("\\]+\.[^\s"\\]+)\)/g, '<img alt="$1" src="https://$2" />') + .replace(/^https?:\/\/([^\s("\\]+\.[^\s"\\]+\.(svg|png|tiff|jpg|jpeg)(\?[^\s"\\\/]*)?)/g, '<img src="https://$1" />') + .replace(/\[([^\]]+)]\((https?:\/\/[^\s("\\]+\.[^\s"\\]+)\)/g, '$1'.link('$2')) + .replace(/([^;["\\])https?:\/\/([^\s("\\]+\.[^\s"\\]+\.(svg|png|tiff|jpg|jpeg)(\?[^\s"\\\/]*)?)/g, '$1<img src="https://$2" />') + .replace(/([^;["\\])(https?:\/\/([^\s("\\]+\.[^\s"\\]+))/g, '$1' + '$3'.link('$2')) + .replace(/^(https?:\/\/([^\s("\\]+\.[^\s"\\]+))/g, '$2'.link('$1')); +} +function inlineMarkdown(input) { + var output = '', + span = '', + current = [], + tags = { + '`': 'code', + '``': 'samp', + '*': 'em', + '**': 'strong', + '_': 'i', + '–––': 's', + '+++': 'ins', + '---': 'del', + '[c]': 'cite', + '[m]': 'mark', + '[u]': 'u', + '[v]': 'var', + '::': 'kbd', + '"': 'q' + }, + stags = { + sup: { + start: '^(', + end: ')^' + }, + sub: { + start: 'v(', + end: ')v' + }, + small: { + start: '[sm]', + end: '[/sm]' + } + }; + outer: for (var i = 0; i < input.length; i++) { + if (['code', 'samp'].indexOf(current[current.length - 1]) == -1) { + if (input[i] == '\\') span += input[++i].replace('^', '\u0001').replace('[', '\u0002'); + else { + for (var l = 3; l > 0; l--) { + if (tags[input.substr(i, l)]) { + output += spanMarkdown(span); + span = ''; + if (current[current.length - 1] == tags[input.substr(i, l)]) output += '</' + current.pop() + '>'; + else { + if (current.indexOf(tags[input.substr(i, l)]) != -1) warning('Illegal nesting of "' + input.substr(i, l) + '"'); + output += '<' + tags[input.substr(i, l)] + '>'; + current.push(tags[input.substr(i, l)]); + } + i += l - 1; + continue outer; + } + } + for (var j in stags) { + for (var l = 5; l > 0; l--) { + if (stags[j].start == input.substr(i, l)) { + output += spanMarkdown(span) + '<' + j + '>'; + span = ''; + current.push(stags[j].end); + i += l - 1; + continue outer; + } else if (stags[j].end == input.substr(i, l)) { + if (current[current.length - 1] == stags[j].end) { + output += spanMarkdown(span) + '</' + j + '>'; + span = ''; + current.pop(); + i += l - 1; + continue outer; + } else warning('Illegal close tag "' + stags[j].end + '" found'); + } + } + } + span += input[i]; + } + } else if (current[current.length - 1] == 'code' && input[i] == '`') { + current.pop(); + output += '</code>'; + } else if (current[current.length - 1] == 'samp' && input.substr(i, 2) == '``') { + current.pop(); + output += '</samp>'; + i++; + } else output += html(input[i]); + } + output += spanMarkdown(span); + if (current.length) warning('Unclosed tags. <' + current.join('>, <') + '>'); + for (var i = current.length - 1; i >= 0; i--) output += '</' + current[i] + '>'; + return output; +} +function markdown(input) { + if (input.indexOf('\n') == -1 && input.substr(0, 2) != '> ' && input.substr(0, 3) != '>! ' && input.substr(0, 2) != '- ' && input.substr(0, 2) != '* ' && input.substr(0, 4) != ' ' && input[0] != '\t' && !input.match(/^((\d+|[A-z])[.)]|#{1,6}|cite\[\d+\]:) /) && !input.match(/^[-–—]{12,}$/)) return inlineMarkdown(input); + var blockquote = '', + ul = '', + ol = '', + li = '', + code = '', + i; + return input.split('\n').map(function(val, i, arr) { + if (!val) return ''; + var f; + if (val.substr(0, 2) == '> ') { + val = val.substr(2); + if (arr[i + 1] && arr[i + 1].substr(0, 2) == '> ') { + blockquote += val + '\n'; + return ''; + } else { + var arg = blockquote + val; + blockquote = ''; + return '<blockquote>' + markdown(arg) + '</blockquote>'; + } + } else if (val.substr(0, 3) == '>! ') { + val = val.substr(3); + if (arr[i + 1] && arr[i + 1].substr(0, 3) == '>! ') { + blockquote += val + '\n'; + return ''; + } else { + var arg = blockquote + val; + blockquote = ''; + return '<blockquote class="spoiler">' + markdown(arg) + '</blockquote>'; + } + } else if (val.substr(0, 2) == '- ' || val.substr(0, 2) == '* ') { + if (!ul) ul = '<ul>'; + val = val.substr(2); + if (li) { + ul += '<li>' + markdown(li) + '</li>'; + li = ''; + } + if (arr[i + 1] && (arr[i + 1].substr(0, 2) == '- ' || arr[i + 1] && arr[i + 1].substr(0, 2) == '* ')) { + ul += '<li>' + inlineMarkdown(val) + '</li>'; + return ''; + } else if (arr[i + 1] && (arr[i + 1][0] == '\t' || arr[i + 1] && arr[i + 1].substr(0, 4) == ' ')) { + li += val + '\n'; + return ''; + } else { + var arg = ul + '<li>' + markdown(val) + '</li>'; + ul = ''; + return arg + '</ul>'; + } + } else if (f = val.match(/^(\d+|[A-z])[.)] /)) { + if (!ol) ol = '<ol>'; + val = val.substr(f[0].length); + if (li) { + ol += '<li>' + markdown(li) + '</li>'; + li = ''; + } + if (arr[i + 1] && arr[i + 1].match(/^(\d+|[A-z])[.)] /)) { + ol += '<li>' + inlineMarkdown(val) + '</li>'; + return ''; + } else if (arr[i + 1] && (arr[i + 1][0] == '\t' || arr[i + 1] && arr[i + 1].substr(0, 4) == ' ')) { + li += val + '\n'; + return ''; + } else { + var arg = ol + '<li>' + inlineMarkdown(val) + '</li>'; + ol = ''; + return arg + '</ol>'; + } + } else if (li && val[0] == '\t') { + li += val.substr(1) + '\n'; + if (ul && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && arr[i + 1].substr(2) != '- ' && arr[i + 1].substr(2) != '* '))) { + var arg = ul + '<li>' + markdown(li) + '</li>'; + li = ''; + return arg + '</ul>'; + } else if (ol && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && !arr[i + 1].match(/^(\d+|[A-z])[.)] /)))) { + var arg = ol + '<li>' + markdown(li) + '</li>'; + li = ''; + return arg + '</ol>'; + } + return ''; + } else if (li && val.substr(0, 4) == ' ') { + li += val.substr(4) + '\n'; + if (ul && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && arr[i + 1].substr(2) != '- ' && arr[i + 1].substr(2) != '* '))) { + var arg = ul + '<li>' + markdown(li) + '</li>'; + li = ''; + return arg + '</ul>'; + } else if (ol && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && !arr[i + 1].match(/^((\d+|[A-z])|[A-z])[.)] /)))) { + var arg = ol + '<li>' + markdown(li) + '</li>'; + li = ''; + return arg + '</ol>'; + } + return ''; + } else if (val[0] == '\t') { + code += val.substr(1); + if (!arr[i + 1] || (arr[i + 1].substr(0, 4) != ' ' && arr[i + 1][0] != '\t')) { + var arg = html(code); + code = ''; + return '<code class="blk">' + arg + '</code>'; + } else code += '\n'; + return ''; + } else if (val.substr(0, 4) == ' ') { + code += val.substr(4); + if (!arr[i + 1] || (arr[i + 1].substr(0, 4) != ' ' && arr[i + 1][0] != '\t')) { + var arg = html(code); + code = ''; + return '<code class="blk">' + arg + '</code>'; + } else code += '\n'; + return ''; + } else if ((f = val.match(/^#{1,6} /)) && (f = f[0].length - 1)) { + return '<h' + f + '>' + inlineMarkdown(val.substr(f + 1)) + '</h' + f + '>'; + } else if (val.match(/^[-–—]{12,}$/)) { + return '<hr />'; + } else if (i = val.match(/^cite\[(\d+)\]: /)) { + return '<div><sup class="reference-list">' + i[1] + '</sup> ' + inlineMarkdown(val.substr(i[0].length)) + '</div>'; + } else return '<p>' + inlineMarkdown(val) + '</p>'; + }).join(''); +} + +HTMLTextAreaElement.prototype.mdValidate = function(correct) { + var i = mdWarnings.length; + markdown(this.value); + var preverr = this.previousElementSibling && this.previousElementSibling.classList.contains('md-err') ? this.previousElementSibling : null, + err = mdWarnings[i]; + this.lastErrored = err && correct; + if (err && (correct || preverr || this.value.substr(0, this.selectionEnd || Infinity).match(/\s$/))) { + if (preverr) { + if (preverr.firstChild.nodeValue == err) { + if (this.lastErrored && err && correct) { + this.value = this.value.replace(/([^\\]?)(\\*)([`*_–\-+[(:"])/g, function(m, p1, p2, p3, i) { + if (i && !p1) return m; + return p1 + (p2.length % 2 ? p2 : p2 + '\\') + p3; + }); + return true; + } + return err; + } + preverr.parentNode.removeChild(preverr); + } + var span = document.createElement('span'); + span.classList.add('md-err'); + span.appendChild(document.createTextNode(err)); + this.parentNode.insertBefore(span, this); + } else if (preverr) preverr.parentNode.removeChild(preverr); + return err; +}; + +function mdValidateBody() { + if (document.activeElement.mdValidate && document.activeElement.id != 'code') document.activeElement.mdValidate(); +}; +addEventListener('input', mdValidateBody); + +var noPageOverflow = noPageOverflow || false, + pageOverflowMobile = pageOverflowMobile || false, + footerOff = footerOff || false, + mainContentEl = mainContentEl || false, + mainBottomPad = mainBottomPad || 0; + +function minHeight() { + var footer = document.getElementById('footer').offsetHeight, + sidebar = document.getElementById('sidebar'); + if (innerWidth < 1500 && sidebar) footer += sidebar.offsetHeight + 6; + if (noPageOverflow && !(innerWidth < pageOverflowMobile)) { + mainContentEl.style.minHeight = ''; + mainContentEl.style.height = Math.max(innerHeight - (footerOff ? -4 : footer) - mainContentEl.getBoundingClientRect().top + document.body.getBoundingClientRect().top - 12, noPageOverflow) - mainBottomPad + 'px'; + if (sidebar) sidebar.style.height = ''; + } else { + mainContentEl.style.height = ''; + if (navigator.userAgent.indexOf('Mobile') == -1) mainContentEl.style.minHeight = Math.max(0, innerHeight - (footerOff ? -4 : footer) - mainContentEl.getBoundingClientRect().top + document.body.getBoundingClientRect().top - (innerWidth < 1500 ? 6 : 12) - mainBottomPad) + 'px'; + else mainContentEl.style.minHeight = ''; + if (sidebar) { + if (innerWidth >= 1500) sidebar.style.height = mainContentEl.style.minHeight; + else sidebar.style.height = ''; + } + } +} +addEventListener('load', minHeight); +addEventListener('resize', minHeight); + +function request(uri, callback, params) { + var i = new XMLHttpRequest(); + i.open('POST', uri, true); + i.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + i.send(params); + i.onload = function() { + callback(this.status == 204 ? 'Success' : this.responseText); + }; + return i; +} + +function ago(od) { + var d = Math.round((new Date() - od) / 1000); + if (d < 3600) return Math.round(d / 60) + 'm ago'; + else if (d < 86400) return Math.round(d / 3600) + 'h ago'; + else if (d < 2592000) return Math.round(d / 86400) + 'd ago'; + else { + d = new Date(od); + var y = d.getUTCFullYear(); + return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec' ][d.getUTCMonth()] + ' ' + d.getUTCDate() + (y == new Date().getUTCFullYear() ? '' : ' \'' + y.toString().substr(2)); + } +} +function agot(d) { + var time = document.createElement('time'); + time.textContent = ago(d); + time.setAttribute('datetime', new Date(d).toISOString()); + return time; +} + +function textareaHandler(e) { + if (this.noHandle) return delete this.nHandle; + if (!this.hist) this.hist = [{ + body: '', + start: 0, + end: 0 + }]; + if (!this.hIndex) this.hIndex = 0; + if (e.keyCode == 9) { + if (this.selectionStart == this.selectionEnd) { + if (e.shiftKey) { + var cS = this.selectionEnd - 1; + while (this.value[cS] && this.value[cS] != '\n') { + if (this.value[cS] == '\t') { + this.value = this.value.substr(0, cS) + this.value.substr(++cS); + break; + } else cS--; + } + } else { + var oS = this.selectionEnd; + this.value = this.value.substr(0, oS) + '\t' + this.value.substr(oS); + this.selectionStart = this.selectionEnd = ++oS; + } + } else { + var lines = this.value.split('\n'), + i = 0, + start = 0; + while ((i += lines[start].length) < this.selectionStart - start) start++; + var end = start; + i -= lines[start].length; + while ((i += lines[end].length) < this.selectionEnd - end) end++; + i = --start; + while (++i <= end) { + if (e.shiftKey) lines[i][0] != '\t' || (lines[i] = lines[i].substr(1)); + else lines[i] = '\t' + lines[i]; + } + this.value = lines.join('\n'); + var nS = lines.slice(0, ++start).join('\n').length; + this.selectionStart = (nS += nS ? 1 : 0); + this.selectionEnd = nS + lines.slice(start, ++end).join('\n').length; + } + e.preventDefault(); + } else if (e.keyCode == 90 && e.metaKey && !e.altKey) { + e.preventDefault(); + if (this.hIndex == this.hist.length - 1 && this.hist[this.hIndex].body != this.value) { + this.hist.push({ + body: this.value, + start: this.selectionStart, + end: this.selectionEnd + }); + this.hIndex = this.hist.length - 1; + } + var data = this.hist[e.shiftKey ? ++this.hIndex : --this.hIndex]; + console.log(this.hist, this.hIndex); + if (data) { + this.value = data.body; + this.selectionStart = data.start; + this.selectionEnd = data.end; + } else e.shiftKey ? --this.hIndex : ++this.hIndex + } else { + if (this.hist[this.hIndex].body != this.value) this.hist = this.hist.slice(0, this.hIndex + 1); + if (this.timer) clearTimeout(this.timer); + this.timer = setTimeout(function(e) { + if (e.hIndex != e.hist.length - 1) return; + if (e.hist[e.hIndex].body == e.value) return; + e.hist.push({ + body: e.value, + start: e.selectionStart, + end: e.selectionEnd + }); + e.hIndex = e.hist.length - 1; + }, this.lastKeyCode == e.keyCode || [8, 9, 13].indexOf(e.keyCode) == -1 ? 400 : 0, this); + } + this.lastKeyCode = e.keyCode; +} + +addEventListener('DOMContentLoaded', function() { + mainContentEl = mainContentEl || document.getElementById('content'); + if (navigator.userAgent.indexOf('Trident') != -1 || navigator.userAgent.indexOf('MSIE') != -1) { + var span = document.createElement('span'); + span.appendChild(document.createTextNode('This site does not support Microsoft Internet Explorer due to its lack of compatibility with web specifications.')); + document.getElementById('err').appendChild(span); + document.getElementById('cont').hidden = true; + document.getElementById('cont').style.display = 'none'; + } + var e = document.getElementsByTagName('textarea'), + i = e.length; + while (i--) e[i].addEventListener('keydown', textareaHandler); + setInterval(function() { + var times = document.getElementsByTagName('time'); + for (var i = 0; i < times.length; i++) { + var t = ago(Date.parse(times[i].getAttribute('datetime'))); + if (times[i].textContent != t) times[i].textContent = t; + } + }, 100); + minHeight(); +}); + +document.addEventListener('visibilitychange', function() { + if (!document.hidden) { + request('/api/notif', function(res) { + document.getElementById('nav').children[7].classList.toggle('unread', res); + }); + } +}); + +if (navigator.userAgent.indexOf('Mobile') != -1) addEventListener('touchend', function() {}); //Fixes mobile-safari bug with touch listeners in iframes not firing + \ No newline at end of file diff --git a/http/rainbowtest.html b/http/rainbowtest.html index e504461..10c8d09 100644 --- a/http/rainbowtest.html +++ b/http/rainbowtest.html @@ -1,97 +1,280 @@ -Syntax Highlighting - - + code .inline-comment { color: #777 } + code .keyword { color: #fd3 } + code .constant, code .string .escape { color: #df0 } + code .string { color: #6C3 } + code .regex { color: #ffa } + code .regex.open, code .regex.close, code .regex.modifier, code .operator { color: #ff8 } + code .operator.assigns { color: #8ff } + code .regex .escape { color: #afa } + code .regex.modifier { font-weight: bold } + code .argument, code .number { color: #3df } + code .newvar { font-weight: bold } + code .function-name { color: #f60 } + code .function-call { color: #f90 } + code .prototype { color: #f00 } + code .punctuation, code .grouper { color: #ccc } + code .cap-var { color: #9ac } + code .browser { color: #9ac } + code .browser.method { color: #9bf } + code .browser.property { color: #acf } + + -'use strict'; - -String.prototype.replaceAll = function(find, replace) { +1,5e;;;0;;; +String.prototype.replaceAll = function(find, replace) { if (typeof find == 'string') return this.split(find).join(replace); var t = this, i, j; while (typeof(i = find.shift()) == 'string' && typeof(j = replace.shift()) == 'string') t = t.replaceAll(i || '', j || ''); @@ -535,5 +718,5 @@ }); if (navigator.userAgent.indexOf('Mobile') != -1) addEventListener('touchend', function() {}); //Fixes mobile-safari bug with touch listeners in iframes not firing - - \ No newline at end of file + + \ No newline at end of file From c26ed749f0b91f76df7d63bc56143ef71af86d26 Mon Sep 17 00:00:00 2001 From: bjb568 Date: Tue, 23 Jun 2015 21:42:53 -0400 Subject: [PATCH 3/7] Add caret --- html/dev/canvas.html | 24 +- http/dev/runcanvas.js | 1413 +++++++++++++++++++++-------------------- 2 files changed, 754 insertions(+), 683 deletions(-) diff --git a/html/dev/canvas.html b/html/dev/canvas.html index 8dd35c1..4b17395 100644 --- a/html/dev/canvas.html +++ b/html/dev/canvas.html @@ -4,7 +4,6 @@

$title -

@@ -66,7 +65,7 @@

$title $title $title '; + } + } + var timeout = setTimeout(handleCode, 100); + code.addEventListener('input', function() { + clearTimeout(timeout); + timeout = setTimeout(handleCode, 100); + onbeforeunload = function() { + return 'You have unsaved code.'; + }; + }); + handleCode(true); + if (save) save.onclick = function() { + if (save.classList.contains('progress')) return; + save.classList.add('progress'); + var savingTimeout = setTimeout(function() { + if (save.textContent == 'Save') save.textContent = 'Saving…'; + }, 200); + request('/api/program/save?type=1', function(res) { + if (res.indexOf('Error') == 0) { + clearTimeout(savingTimeout); + alert(res); + save.textContent = 'Save'; + } else if (res.indexOf('Location') == 0) { + onbeforeunload = null; + location.href = res.split(' ')[1]; + } else if (res == 'Success') { + onbeforeunload = null; + save.textContent = 'Saved'; + document.getElementById('updated').setAttribute('datetime', new Date().toISOString()); + } else { + clearTimeout(savingTimeout); + alert('Unknown error. Response was: ' + res); + } + save.classList.remove('progress'); + }, 'code=' + encodeURIComponent(code.value)); + }; + (document.getElementById('fork') || {}).onclick = function() { + var e = this; + if (e.classList.contains('progress')) return; + e.classList.add('progress'); + e.textContent = 'Saving…'; + var e = e.previousSibling.previousSibling; + e.hidden = e.previousSibling.previousSibling.hidden = true; + request('/api/program/save?type=1&fork=1', function(res) { + if (res.indexOf('Error') == 0) { + e.hidden = false; + e = e.nextSibling.nextSibling; + e.hidden = false; + e.nextSibling.nextSibling.textContent = 'Fork'; + alert(res); + } else if (res.indexOf('Location') == 0) { + onbeforeunload = null; + location.href = res.split(' ')[1]; + } else alert('Unknown error. Response was: ' + res); + e.classList.remove('progress'); + }, 'code=' + encodeURIComponent(code.value)); + }; + if (document.getElementById('meta')) { + if (window.mine) { + document.getElementById('title').onclick = function() { + this.hidden = true; + var edit = document.getElementById('edit-title'); + edit.hidden = false; + edit.focus(); + }; + document.getElementById('edit-title').onblur = function() { + request('/api/program/edit-title', function(res) { + var edit = document.getElementById('edit-title'); + if (res.indexOf('Error') == 0) { + alert(res); + edit.value = document.getElementById('title').textContent; + } else if (res == 'Success') { + edit.hidden = true; + var title = document.getElementById('title'); + title.textContent = edit.value.substr(0, 92) || 'Untitled'; + if (!edit.value) edit.value = 'Untitled'; + title.hidden = false; + } else alert('Unknown error. Response was: ' + res); + }, 'title=' + encodeURIComponent(this.value)); + }; + document.getElementById('edit-title').onkeypress = function(e) { + if (e.keyCode == 13) this.onblur.call(this); + }; + } + up.onclick = function() { + request('/api/program/vote', function(res) { + if (res.indexOf('Error') == 0) alert(res); + else if (res == 'Success') { + document.getElementsByClassName('user-$op-name')[0].getElementsByClassName('rep')[0].textContent -= (dn.classList.contains('clkd') ? -1 : 0) - (up.classList.contains('clkd') ? -1 : 1); + up.classList.toggle('clkd'); + dn.classList.remove('clkd'); + } else alert('Unknown error. Response was: ' + res); + }, 'val=' + (this.classList.contains('clkd') ? 0 : 1)); + }; + dn.onclick = function() { + request('/api/program/vote', function(res) { + if (res.indexOf('Error') == 0) alert(res); + else if (res == 'Success') { + document.getElementsByClassName('user-$op-name')[0].getElementsByClassName('rep')[0].textContent -= (up.classList.contains('clkd') ? 1 : 0) - (dn.classList.contains('clkd') ? 1 : -1); + dn.classList.toggle('clkd'); + up.classList.remove('clkd'); + } else alert('Unknown error. Response was: ' + res); + }, 'val=' + (this.classList.contains('clkd') ? 0 : -1)); + }; + document.getElementById('addcomment').onclick = function() { + setTimeout(function() { + document.getElementById('commentta').focus(); + }, 0); + }; + var socket = new WebSocket('wss://' + location.hostname + ':81/dev/' + id); + document.getElementById('comment').onsubmit = function(e) { + socket.send(JSON.stringify({ + event: 'post', + body: document.getElementById('commentta').value + })); + document.getElementById('commentta').value = ''; + document.getElementById('reset').onclick(); + e.preventDefault(); + }; + document.getElementById('reset').onclick = function() { + location.hash = ''; + history.replaceState('', document.title, window.location.pathname); + document.body.scrollTop = innerHeight; + }; + socket.onmessage = function(e) { + console.log(e.data); + try { + var data = JSON.parse(e.data); + } catch(err) { + console.log(err); + return alert('JSON Error. Response was: ' + e.data); + } + if (data.event == 'add') { + var div = document.createElement('div'); + div.classList.add('comment'); + div.innerHTML = ' ' + markdown(data.body); + if ($rep >= 50) { + div.insertBefore(document.getElementById('content').children[2].cloneNode(true), div.firstChild); + div.firstChild.firstChild.onclick = upvoteComment; + var score = document.createElement('span'); + score.classList.add('score'); + score.appendChild(document.createTextNode(score.dataset.score = 0)); + div.insertBefore(score, div.firstChild); + } + var sig = document.createElement('span'); + sig.classList.add('c-sig'); + sig.appendChild(document.createTextNode('-')); + var a = document.createElement('a'); + a.href = '/user/' + data.user; + a.appendChild(document.createTextNode(data.user)) + sig.appendChild(a); + sig.appendChild(document.createTextNode(', ')); + var permalink = document.createElement('a'); + if (!data.time) data.time = new Date().getTime(); + permalink.appendChild(agot(data.time)); + permalink.href = '#' + (div.id = 'c' + data.id); + sig.appendChild(permalink); + div.appendChild(sig); + document.getElementById('comments').appendChild(div); + } else if (data.event == 'scorechange') { + var c = document.getElementById('c' + data.id); + if (c) c.getElementsByClassName('score')[0].dataset.score = c.getElementsByClassName('score')[0].textContent = data.score; + } else if (data.event == 'err') { + alert('Error: ' + data.body); + if (data.commentUnvote) document.getElementById('c' + data.commentUnvote).getElementsByClassName('up')[0].classList.remove('clkd'); + } + }; + socket.onclose = function() { + if (confirm('Connection error. Reload?')) location.reload(); + }; + var deletebutton = document.getElementById('delete'); + if (deletebutton) { + deletebutton.onclick = function() { + if (confirm('Do you want to delete this program?')) { + request('/api/program/delete', function(res) { + if (res.indexOf('Error') == 0) alert(res); + else if (res == 'Success') location.reload(); + else alert('Unknown error. Response was: ' + res); + }); + } + }; + } + function upvoteComment() { + this.classList.toggle('clkd'); + socket.send(JSON.stringify({ + event: this.classList.contains('clkd') ? 'vote' : 'unvote', + id: parseInt(this.parentNode.parentNode.id.substr(1)) + })); + } + var comments = document.getElementsByClassName('comment'); + for (var i = 0; i < comments.length; i++) { + comments[i].getElementsByClassName('sctrls')[0].firstChild.onclick = upvoteComment; + } + } +}); +function highlight(codeBlock, input) { + var input = typeof(input) == 'string' ? input : codeBlock.textContent, + chunk = '', + warnings = [], + beforeWord, + line = 1, + inVarDec = [], + d, + fc; + while (fc = codeBlock.firstChild) codeBlock.removeChild(fc); + var linenum = document.createElement('span'); + linenum.className = 'line'; + linenum.dataset.linenum = line; + codeBlock.appendChild(linenum); + for (var i = 0; i < input.length; i++) { + var c = input[i], + l; + if (c == '"' || c == "'") { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = c; + var string = document.createElement('span'); + string.className = 'string'; + while ((d = input[++i]) && d != c) { if (d == '\n') { - warnings.push([i, 'Unexpected line end with unterminated regex literal.']); + warnings.push([i, 'Unexpected line end with unterminated string literal.']); break; - } - if (d == '\\') { - if (charclass) charclass.appendChild(document.createTextNode(chunk)); - else regex.appendChild(document.createTextNode(chunk)); + } else if (d == '\\') { + string.appendChild(document.createTextNode(chunk)); chunk = d + (d = input[++i]); var escape = document.createElement('span'); escape.className = 'escape'; - if (d == 'c') chunk += d = input[++i]; - else if (d == 'x' || d == '0') chunk += input[++i] + input[++i]; - else if (d == 'u') chunk += input[++i] + input[++i] + input[++i] + input[++i]; - else if (d.match(/\d/)) { - while (input[++i].match(/\d/)) chunk += input[i]; - i--; - escape.className = 'backreference'; - } + if (d == 'u') { + chunk += d = input[++i]; + if (d == '{') { + while ((d = input[++i]) && d != '}') { + if (d == '\n' || d == string) { + warnings.push([i, 'Unclosed bracket escape sequence.']); + break; + } + chunk += d; + } + if (d == '}') chunk += '}'; + } else chunk += input[++i] + input[++i] + input[++i]; + } else if (c == 'x') chunk += input[++i] + input[++i]; escape.appendChild(document.createTextNode(chunk)); + string.appendChild(escape); chunk = ''; - if (charclass) charclass.appendChild(escape); - else regex.appendChild(escape); if (d == '\n') { - warnings.push([i, 'Unexpected line end with unterminated regex literal.']); - break; + var linenum = document.createElement('span'); + linenum.className = 'line'; + linenum.dataset.linenum = ++line; + string.appendChild(linenum); + } + } else chunk += d; + } + if (d) chunk += d; + string.appendChild(document.createTextNode(chunk)); + codeBlock.appendChild(string); + chunk = ''; + if (d == '\n') { + var linenum = document.createElement('span'); + linenum.className = 'line'; + linenum.dataset.linenum = ++line; + codeBlock.appendChild(linenum); + } + } else if (c == '/' && input[i + 1] == '/') { + i++; + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = '//'; + var comment = document.createElement('span'); + comment.className = 'inline-comment'; + while ((d = input[++i]) && d != '\n') chunk += d; + if (d) chunk += '\n'; + comment.appendChild(document.createTextNode(chunk)); + codeBlock.appendChild(comment); + chunk = ''; + if (d) { + var linenum = document.createElement('span'); + linenum.className = 'line'; + linenum.dataset.linenum = ++line; + codeBlock.appendChild(linenum); + } + } else if (c == '/' && input[i + 1] == '*') { + i++; + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = '/*'; + var comment = document.createElement('span'); + comment.className = 'inline-comment'; + while ((d = input[++i]) && (d != '/' || input[i - 1] != '*')) { + chunk += d; + if (d == '\n') { + comment.appendChild(document.createTextNode(chunk)); + chunk = ''; + var linenum = document.createElement('span'); + linenum.className = 'line'; + linenum.dataset.linenum = ++line; + comment.appendChild(linenum); + } + } + if (d) chunk += d; + comment.appendChild(document.createTextNode(chunk)); + codeBlock.appendChild(comment); + chunk = ''; + if (d == '\n') { + var linenum = document.createElement('span'); + linenum.className = 'line'; + linenum.dataset.linenum = ++line; + codeBlock.appendChild(linenum); + } + } else if (c == '/') { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var regex = document.createElement('span'); + regex.className = 'regex'; + var regexOpen = document.createElement('span'); + regexOpen.className = 'open'; + regexOpen.appendChild(document.createTextNode('/')); + regex.appendChild(regexOpen); + var d, + charclass = false; + while ((d = input[++i]) && d != '/') { + if (d == '\n') { + warnings.push([i, 'Unexpected line end with unterminated regex literal.']); + break; + } + if (d == '\\') { + if (charclass) charclass.appendChild(document.createTextNode(chunk)); + else regex.appendChild(document.createTextNode(chunk)); + chunk = d + (d = input[++i]); + var escape = document.createElement('span'); + escape.className = 'escape'; + if (d == 'c') chunk += d = input[++i]; + else if (d == 'x' || d == '0') chunk += input[++i] + input[++i]; + else if (d == 'u') chunk += input[++i] + input[++i] + input[++i] + input[++i]; + else if (d.match(/\d/)) { + while (input[++i].match(/\d/)) chunk += input[i]; + i--; + escape.className = 'backreference'; + } + escape.appendChild(document.createTextNode(chunk)); + chunk = ''; + if (charclass) charclass.appendChild(escape); + else regex.appendChild(escape); + if (d == '\n') { + warnings.push([i, 'Unexpected line end with unterminated regex literal.']); + break; } } else if (charclass) { if (d == ']') { @@ -377,551 +780,207 @@ function highlight(codeBlock) { for (var j = str.length - 1; j >= 0; j--) { if (str[j].match(/[\s=(]/)) { fnameNodes.push(node.splitText(j + 1)); - var fname = document.createElement('span'); - fname.className = 'function-name'; - for (var j = fnameNodes.length - 1; j >= 0; j--) fname.appendChild(fnameNodes[j]); - codeBlock.insertBefore(fname, endNode); - if (endNode.tagName) fname.appendChild(endNode); - break prevNodes; - } - } - fnameNodes.push(node); - } - } else if (node.textContent.match(/\S/)) break; - } - var funcKeyword = document.createElement('span'); - funcKeyword.className = 'keyword'; - funcKeyword.appendChild(document.createTextNode('function')); - codeBlock.appendChild(funcKeyword); - i += 7; - var fname = document.createElement('span'); - fname.className = 'function-name'; - while ((c = input[++i]) && c != '(') { - chunk += c; - if (c == '\n') { - fname.appendChild(document.createTextNode(chunk)); - chunk = ''; - var linenum = document.createElement('span'); - linenum.className = 'line'; - linenum.dataset.linenum = ++line; - fname.appendChild(linenum); - } - } - fname.appendChild(document.createTextNode(chunk)); - codeBlock.appendChild(fname); - chunk = ''; - if (input[i] != '(') { - warnings.push([i, 'Arguments not found.']); - i--; - } else { - var paren = document.createElement('span'); - paren.className = 'punctuation'; - paren.appendChild(document.createTextNode('(')); - codeBlock.appendChild(paren); - while ((c = input[++i]) && c != ')') { - if (c == ',') { - var arg = document.createElement('span'); - arg.className = 'argument'; - arg.appendChild(document.createTextNode(chunk)); - codeBlock.appendChild(arg); - chunk = ''; - var comma = document.createElement('span'); - comma.className = 'punctuation'; - comma.appendChild(document.createTextNode(',')); - codeBlock.appendChild(comma); - } else chunk += c; - } - var arg = document.createElement('span'); - arg.className = 'argument'; - arg.appendChild(document.createTextNode(chunk)); - codeBlock.appendChild(arg); - chunk = ''; - if (c) { - var paren = document.createElement('span'); - paren.className = 'punctuation'; - paren.appendChild(document.createTextNode(')')); - codeBlock.appendChild(paren); - } else { - warnings.push([i, 'Unclosed argument list.']); - i--; - } - } - } else if (c == '(') { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var lastChunk = codeBlock.lastChild.nodeValue; - if (lastChunk) { - var call = codeBlock.lastChild.splitText(Math.max(lastChunk.lastIndexOf(' '), lastChunk.lastIndexOf('\t'), lastChunk.lastIndexOf('\n'), 0)); - var callspan = document.createElement('span'); - callspan.className = 'function-call'; - callspan.appendChild(call); - codeBlock.appendChild(callspan); - } - var charspan = document.createElement('span'); - charspan.className = 'punctuation'; - charspan.appendChild(document.createTextNode('(')); - codeBlock.appendChild(charspan); - if (inVarDec[0]) inVarDec[0].parens++; - } else if (['++', '--', '*=', '/=', '%=', '+=', '-=', '&=', '|=', '^='].indexOf(input.substr(i, 2)) != -1) { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var operator = document.createElement('span'); - operator.className = 'operator assigns'; - operator.appendChild(document.createTextNode(input.substr(i, 2))); - codeBlock.appendChild(operator); - i++; - } else if (input.substr(i, 3) == '<<=' || input.substr(i, 3) == '>>=') { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var operator = document.createElement('span'); - operator.className = 'operator assigns'; - operator.appendChild(document.createTextNode(input.substr(i, 3))); - codeBlock.appendChild(operator); - i += 2; - } else if (input.substr(i, 3) == '>>>=') { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var operator = document.createElement('span'); - operator.className = 'operator assigns'; - operator.appendChild(document.createTextNode(input.substr(i, 3))); - codeBlock.appendChild(operator); - i += 3; - } else if ('?:'.indexOf(c) != -1) { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var operator = document.createElement('span'); - operator.className = 'operator'; - operator.appendChild(document.createTextNode(c)); - codeBlock.appendChild(operator); - } else if (['<=', '>=', '==', '!=', '<<', '>>', '&&', '||'].indexOf(input.substr(i, 2)) != -1) { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var operator = document.createElement('span'); - operator.className = 'operator'; - operator.appendChild(document.createTextNode(input.substr(i, 2))); - codeBlock.appendChild(operator); - i++; - } else if (input.substr(i, 3) == '===' || input.substr(i, 3) == '!==' || input.substr(i, 3) == '>>>') { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var operator = document.createElement('span'); - operator.className = 'operator'; - operator.appendChild(document.createTextNode(input.substr(i, 3))); - codeBlock.appendChild(operator); - i += 2; - } else if (beforeWord && c.match(/\d/)) { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var start = i; - if (c == '0' && (c = input[++i])) { - if (c.toLowerCase() == 'b') { - while ('01'.indexOf(input[++i]) != -1); - } else if (c.toLowerCase() == 'o') { - while ('01234567'.indexOf(input[++i]) != -1); - } else if (c.toLowerCase() == 'x') { - while ('0123456789abcdefABCDEF'.indexOf(input[++i]) != -1); - } else if (c.match(/[\d\w]/)) warnings.push([i, 'Bad number literal.']); - var num = document.createElement('span'); - num.className = 'number'; - num.appendChild(document.createTextNode(input.substring(start, i--))); - codeBlock.appendChild(num); - } else { - while ('0123456789.'.indexOf(input[i]) != -1) i++; - if ((input[i] || '').toLowerCase() == 'e') { - if ('+-'.indexOf(input[i])) i++; - if ('0123456789'.indexOf(input[i]) == -1) warnings.push([i, 'No exponent found after "e".']); - else i++; - while ('0123456789.'.indexOf(input[i]) != -1) i++; - } - var num = document.createElement('span'); - num.className = 'number'; - num.appendChild(document.createTextNode(input.substring(start, i))); - codeBlock.appendChild(num); - i--; - } - } else if ('=.,;)[]{}'.indexOf(c) != -1) { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var charspan = document.createElement('span'); - charspan.className = ({'=': 'equals', '.': 'dot'})[c] || 'punctuation'; - charspan.appendChild(document.createTextNode(c)); - codeBlock.appendChild(charspan); - if (inVarDec[0]) { - if (c == ')') inVarDec[0].parens--; - if (inVarDec[0].parens < 0) warnings.push([i, 'Unexpected close paren, make sure you use a semicolon after a variable declaration.']); - if (c == '[') inVarDec[0].brackets++; - if (c == ']') inVarDec[0].brackets--; - if (inVarDec[0].brackets < 0) warnings.push([i, 'Unexpected close bracket, make sure you use a semicolon after a variable declaration.']); - if (c == '{') inVarDec[0].braces++; - if (c == '}') inVarDec[0].braces--; - if (inVarDec[0].braces < 0) warnings.push([i, 'Unexpected close brace, make sure you use a semicolon after a variable declaration.']); - if (Math.max(inVarDec[0].parens, inVarDec[0].brackets, inVarDec[0].braces) == 0) { - if (c == '=') inVarDec[0].equals = true; - if (c == ',') inVarDec[0].equals = false; - } - if (c == ';') inVarDec.shift(); - } - } else if (c == '\n') { - codeBlock.appendChild(document.createTextNode(chunk + '\n')); - chunk = ''; - var linenum = document.createElement('span'); - linenum.className = 'line'; - linenum.dataset.linenum = ++line; - codeBlock.appendChild(linenum); - } else if (c.match(/\S/) && inVarDec[0] && !inVarDec[0].equals && Math.max(inVarDec[0].parens, inVarDec[0].brackets, inVarDec[0].braces) == 0) { - codeBlock.appendChild(document.createTextNode(chunk)); - chunk = ''; - var newvar = document.createElement('span'); - newvar.className = 'newvar'; - newvar.appendChild(document.createTextNode(c)); - codeBlock.appendChild(newvar); - } else chunk += c; - } - codeBlock.appendChild(document.createTextNode(chunk)); - codeBlock.className = 'line-dig' + Math.floor(Math.log10(line)); - return warnings; -} -addEventListener('DOMContentLoaded', function() { - var code = document.getElementById('code'), - codeDisplay = document.getElementById('code-display'), - taCont = document.getElementById('ta-cont'), - output = document.getElementById('output'), - save = document.getElementById('save'), - up = document.getElementById('up'), - dn = document.getElementById('dn'); - codeDisplay.appendChild(document.createTextNode(code.value)); - code.lastValue = code.value; - highlight(codeDisplay); - taCont.className = codeDisplay.className; - function handleTAInput() { - var codeScrollDiff = code.scrollHeight - code.offsetHeight; - if (code.value == code.lastValue) return; - codeDisplay.textContent = code.lastValue = code.value; // - highlight(codeDisplay); - taCont.className = codeDisplay.className; - code.style.height = codeDisplay.offsetHeight + 'px'; - taCont.scrollTop += codeScrollDiff; - } - code.addEventListener('keypress', function() { - setTimeout(handleTAInput, 0); - }); - code.addEventListener('keyup', function() { - setTimeout(handleTAInput, 0); - }); - code.addEventListener('keydown', function() { - setTimeout(handleTAInput, 0); - }); - code.addEventListener('input', handleTAInput); - code.addEventListener('keypress', function(e) { - var oldSelectionStart = this.selectionStart; - var pairChars = {}; - pairChars[40] = '()'; - pairChars[91] = '[]'; - pairChars[123] = '{}'; - var endChars = {}; - endChars[41] = ')'; - endChars[93] = ']'; - endChars[125] = '}'; - if (e.keyCode == 13) { - var cut = (this.value.substr(0, oldSelectionStart).match(/(\S([ \t]+)| +)$/) || ['', '', ''])[2].length; - this.value = this.value.substr(0, oldSelectionStart - cut) + this.value.substr(oldSelectionStart); - oldSelectionStart = this.selectionStart = this.selectionEnd = oldSelectionStart - cut; - if (this.value[oldSelectionStart - 1] == ',') this.eIndent = true; - var tabs = this.value.substr(0, oldSelectionStart) - .split('\n')[this.value.substr(0, oldSelectionStart).split('\n').length - 1] - .split('\t').length - - ( - ('{([:,'.indexOf(this.value[oldSelectionStart - 1]) + 1) - ? 0 - : ( - this.value[oldSelectionStart - 1] == ';' && this.eIndent - ? (this.eIndent = false || 2) - : 1 - ) - ); - this.value = this.value.substr(0, this.selectionStart) + '\n' + '\t'.repeat(tabs) + (['{}', '()', '[]'].indexOf(this.value.substr(oldSelectionStart - 1, 2)) == -1 ? '' : '\n' + '\t'.repeat(tabs - 1)) + this.value.substr(this.selectionStart); - this.selectionEnd = this.selectionStart = ++oldSelectionStart + tabs; - e.preventDefault(); - } else if (e.keyCode == 34) { - if (this.value[this.selectionStart] != '"') this.value = this.value.substr(0, this.selectionStart) + '""' + this.value.substr(this.selectionStart); - this.selectionEnd = this.selectionStart = ++oldSelectionStart; - e.preventDefault(); - } else if (e.keyCode == 39) { - if (this.value[this.selectionStart] != "'") this.value = this.value.substr(0, this.selectionStart) + "''" + this.value.substr(this.selectionStart); - this.selectionEnd = this.selectionStart = ++oldSelectionStart; - e.preventDefault(); - } else if (pairChars[e.keyCode]) { - this.value = this.value.substr(0, this.selectionStart) + pairChars[e.keyCode] + this.value.substr(this.selectionStart); - this.selectionEnd = ++oldSelectionStart; - e.preventDefault(); - } else if (endChars[e.keyCode] && this.value[this.selectionStart] == endChars[e.keyCode]) { - this.selectionStart = ++this.selectionEnd; - e.preventDefault(); - } else if (e.keyCode == 61 && this.value.substr(0, this.selectionStart).match(/(draw|refresh) $/)) { - var tabs = this.value.substr(0, oldSelectionStart).split('\n')[this.value.substr(0, oldSelectionStart).split('\n').length - 1].split('\t').length; - this.value = this.value.substr(0, this.selectionStart) + '= function() {\n' + '\t'.repeat(tabs) + '\n' + '\t'.repeat(tabs - 1) + '}' + this.value.substr(this.selectionStart); - this.selectionEnd = this.selectionStart = oldSelectionStart + 15 + tabs; - e.preventDefault(); - } else if (e.keyCode == 44) { - this.value = this.value.substr(0, this.selectionStart) + ', ' + this.value.substr(this.selectionStart); - this.selectionEnd = this.selectionStart = oldSelectionStart + 2; - e.preventDefault(); - } - }); - code.addEventListener('keydown', function(e) { - if (e.keyCode == 8 && this.selectionStart == this.selectionEnd) { - if ( - (this.value[this.selectionStart - 1] == '"' && this.value[this.selectionStart] == '"') || - (this.value[this.selectionStart - 1] == "'" && this.value[this.selectionStart] == "'") || - (this.value[this.selectionStart - 1] == '(' && this.value[this.selectionStart] == ')') || - (this.value[this.selectionStart - 1] == '[' && this.value[this.selectionStart] == ']') || - (this.value[this.selectionStart - 1] == '{' && this.value[this.selectionStart] == '}') - ) { - var oldSelectionStart = this.selectionStart; - this.value = this.value.substr(0, this.selectionStart - 1) + this.value.substr(this.selectionStart + 1); - this.selectionEnd = --oldSelectionStart; - e.preventDefault(); - } - } - }); - var fullScreen = false, - fsBtn = document.getElementById('fullscreen-button'), - regLayout = document.getElementById('regular-layout'); - function enableFullScreen() { - document.body.classList.add('fullscreen'); - fsBtn.hidden = false; - regLayout.hidden = false; - } - if (regLayout) regLayout.onclick = function() { - document.body.classList.remove('fullscreen'); - this.hidden = true; - }; - function hashChangeFullScreenHandler() { - if (location.hash == '#fullscreen') { - output.classList.add('fullscreen'); - document.body.classList.add('noscrl'); - document.getElementById('close-fullscreen').hidden = false; - output.focus(); - } else { - output.classList.remove('fullscreen'); - document.body.classList.remove('noscrl'); - document.getElementById('close-fullscreen').hidden = true; - code.focus(); - } - } - if (fsBtn) { - fsBtn.onclick = function() { - document.getElementById('close-fullscreen').hidden = false; - enableFullScreen(); - }; - addEventListener('hashchange', hashChangeFullScreenHandler); - hashChangeFullScreenHandler(); - } - var oldValue; - function handleCode(init) { - if (code.value != oldValue) { - oldValue = code.value; - var lines = code.value.split('\n'); - for (var i = 0; i < lines.length; i++) { - if (lines[i].indexOf('requestEnableFullScreen;') == 0) { - lines[i] = 'requestFullLayoutMode();' + lines[i].substr(25); - if (navigator.userAgent.indexOf('Mobile') == -1 && !fullScreen) enableFullScreen(); - } - } - if (save && !save.classList.contains('progress')) save.textContent = 'Save'; - output.srcdoc = 'Output frame
'; - } - } - var timeout = setTimeout(handleCode, 100); - code.addEventListener('input', function() { - clearTimeout(timeout); - timeout = setTimeout(handleCode, 100); - onbeforeunload = function() { - return 'You have unsaved code.'; - }; - }); - handleCode(true); - if (save) save.onclick = function() { - if (save.classList.contains('progress')) return; - save.classList.add('progress'); - var savingTimeout = setTimeout(function() { - if (save.textContent == 'Save') save.textContent = 'Saving…'; - }, 200); - request('/api/program/save?type=1', function(res) { - if (res.indexOf('Error') == 0) { - clearTimeout(savingTimeout); - alert(res); - save.textContent = 'Save'; - } else if (res.indexOf('Location') == 0) { - onbeforeunload = null; - location.href = res.split(' ')[1]; - } else if (res == 'Success') { - onbeforeunload = null; - save.textContent = 'Saved'; - document.getElementById('updated').setAttribute('datetime', new Date().toISOString()); - } else { - clearTimeout(savingTimeout); - alert('Unknown error. Response was: ' + res); - } - save.classList.remove('progress'); - }, 'code=' + encodeURIComponent(code.value)); - }; - (document.getElementById('fork') || {}).onclick = function() { - var e = this; - if (e.classList.contains('progress')) return; - e.classList.add('progress'); - e.textContent = 'Saving…'; - var e = e.previousSibling.previousSibling; - e.hidden = e.previousSibling.previousSibling.hidden = true; - request('/api/program/save?type=1&fork=1', function(res) { - if (res.indexOf('Error') == 0) { - e.hidden = false; - e = e.nextSibling.nextSibling; - e.hidden = false; - e.nextSibling.nextSibling.textContent = 'Fork'; - alert(res); - } else if (res.indexOf('Location') == 0) { - onbeforeunload = null; - location.href = res.split(' ')[1]; - } else alert('Unknown error. Response was: ' + res); - e.classList.remove('progress'); - }, 'code=' + encodeURIComponent(code.value)); - }; - if (document.getElementById('meta')) { - if (window.mine) { - document.getElementById('title').onclick = function() { - this.hidden = true; - var edit = document.getElementById('edit-title'); - edit.hidden = false; - edit.focus(); - }; - document.getElementById('edit-title').onblur = function() { - request('/api/program/edit-title', function(res) { - var edit = document.getElementById('edit-title'); - if (res.indexOf('Error') == 0) { - alert(res); - edit.value = document.getElementById('title').textContent; - } else if (res == 'Success') { - edit.hidden = true; - var title = document.getElementById('title'); - title.textContent = edit.value.substr(0, 92) || 'Untitled'; - if (!edit.value) edit.value = 'Untitled'; - title.hidden = false; - } else alert('Unknown error. Response was: ' + res); - }, 'title=' + encodeURIComponent(this.value)); - }; - document.getElementById('edit-title').onkeypress = function(e) { - if (e.keyCode == 13) this.onblur.call(this); - }; - } - up.onclick = function() { - request('/api/program/vote', function(res) { - if (res.indexOf('Error') == 0) alert(res); - else if (res == 'Success') { - document.getElementsByClassName('user-$op-name')[0].getElementsByClassName('rep')[0].textContent -= (dn.classList.contains('clkd') ? -1 : 0) - (up.classList.contains('clkd') ? -1 : 1); - up.classList.toggle('clkd'); - dn.classList.remove('clkd'); - } else alert('Unknown error. Response was: ' + res); - }, 'val=' + (this.classList.contains('clkd') ? 0 : 1)); - }; - dn.onclick = function() { - request('/api/program/vote', function(res) { - if (res.indexOf('Error') == 0) alert(res); - else if (res == 'Success') { - document.getElementsByClassName('user-$op-name')[0].getElementsByClassName('rep')[0].textContent -= (up.classList.contains('clkd') ? 1 : 0) - (dn.classList.contains('clkd') ? 1 : -1); - dn.classList.toggle('clkd'); - up.classList.remove('clkd'); - } else alert('Unknown error. Response was: ' + res); - }, 'val=' + (this.classList.contains('clkd') ? 0 : -1)); - }; - document.getElementById('addcomment').onclick = function() { - setTimeout(function() { - document.getElementById('commentta').focus(); - }, 0); - }; - var socket = new WebSocket('wss://' + location.hostname + ':81/dev/' + id); - document.getElementById('comment').onsubmit = function(e) { - socket.send(JSON.stringify({ - event: 'post', - body: document.getElementById('commentta').value - })); - document.getElementById('commentta').value = ''; - document.getElementById('reset').onclick(); - e.preventDefault(); - }; - document.getElementById('reset').onclick = function() { - location.hash = ''; - history.replaceState('', document.title, window.location.pathname); - document.body.scrollTop = innerHeight; - }; - socket.onmessage = function(e) { - console.log(e.data); - try { - var data = JSON.parse(e.data); - } catch(err) { - console.log(err); - return alert('JSON Error. Response was: ' + e.data); + var fname = document.createElement('span'); + fname.className = 'function-name'; + for (var j = fnameNodes.length - 1; j >= 0; j--) fname.appendChild(fnameNodes[j]); + codeBlock.insertBefore(fname, endNode); + if (endNode.tagName) fname.appendChild(endNode); + break prevNodes; + } + } + fnameNodes.push(node); + } + } else if (node.textContent.match(/\S/)) break; } - if (data.event == 'add') { - var div = document.createElement('div'); - div.classList.add('comment'); - div.innerHTML = ' ' + markdown(data.body); - if ($rep >= 50) { - div.insertBefore(document.getElementById('content').children[2].cloneNode(true), div.firstChild); - div.firstChild.firstChild.onclick = upvoteComment; - var score = document.createElement('span'); - score.classList.add('score'); - score.appendChild(document.createTextNode(score.dataset.score = 0)); - div.insertBefore(score, div.firstChild); + var funcKeyword = document.createElement('span'); + funcKeyword.className = 'keyword'; + funcKeyword.appendChild(document.createTextNode('function')); + codeBlock.appendChild(funcKeyword); + i += 7; + var fname = document.createElement('span'); + fname.className = 'function-name'; + while ((c = input[++i]) && c != '(') { + chunk += c; + if (c == '\n') { + fname.appendChild(document.createTextNode(chunk)); + chunk = ''; + var linenum = document.createElement('span'); + linenum.className = 'line'; + linenum.dataset.linenum = ++line; + fname.appendChild(linenum); } - var sig = document.createElement('span'); - sig.classList.add('c-sig'); - sig.appendChild(document.createTextNode('-')); - var a = document.createElement('a'); - a.href = '/user/' + data.user; - a.appendChild(document.createTextNode(data.user)) - sig.appendChild(a); - sig.appendChild(document.createTextNode(', ')); - var permalink = document.createElement('a'); - if (!data.time) data.time = new Date().getTime(); - permalink.appendChild(agot(data.time)); - permalink.href = '#' + (div.id = 'c' + data.id); - sig.appendChild(permalink); - div.appendChild(sig); - document.getElementById('comments').appendChild(div); - } else if (data.event == 'scorechange') { - var c = document.getElementById('c' + data.id); - if (c) c.getElementsByClassName('score')[0].dataset.score = c.getElementsByClassName('score')[0].textContent = data.score; - } else if (data.event == 'err') { - alert('Error: ' + data.body); - if (data.commentUnvote) document.getElementById('c' + data.commentUnvote).getElementsByClassName('up')[0].classList.remove('clkd'); } - }; - socket.onclose = function() { - if (confirm('Connection error. Reload?')) location.reload(); - }; - var deletebutton = document.getElementById('delete'); - if (deletebutton) { - deletebutton.onclick = function() { - if (confirm('Do you want to delete this program?')) { - request('/api/program/delete', function(res) { - if (res.indexOf('Error') == 0) alert(res); - else if (res == 'Success') location.reload(); - else alert('Unknown error. Response was: ' + res); - }); + fname.appendChild(document.createTextNode(chunk)); + codeBlock.appendChild(fname); + chunk = ''; + if (input[i] != '(') { + warnings.push([i, 'Arguments not found.']); + i--; + } else { + var paren = document.createElement('span'); + paren.className = 'punctuation'; + paren.appendChild(document.createTextNode('(')); + codeBlock.appendChild(paren); + while ((c = input[++i]) && c != ')') { + if (c == ',') { + var arg = document.createElement('span'); + arg.className = 'argument'; + arg.appendChild(document.createTextNode(chunk)); + codeBlock.appendChild(arg); + chunk = ''; + var comma = document.createElement('span'); + comma.className = 'punctuation'; + comma.appendChild(document.createTextNode(',')); + codeBlock.appendChild(comma); + } else chunk += c; } - }; - } - function upvoteComment() { - this.classList.toggle('clkd'); - socket.send(JSON.stringify({ - event: this.classList.contains('clkd') ? 'vote' : 'unvote', - id: parseInt(this.parentNode.parentNode.id.substr(1)) - })); - } - var comments = document.getElementsByClassName('comment'); - for (var i = 0; i < comments.length; i++) { - comments[i].getElementsByClassName('sctrls')[0].firstChild.onclick = upvoteComment; - } + var arg = document.createElement('span'); + arg.className = 'argument'; + arg.appendChild(document.createTextNode(chunk)); + codeBlock.appendChild(arg); + chunk = ''; + if (c) { + var paren = document.createElement('span'); + paren.className = 'punctuation'; + paren.appendChild(document.createTextNode(')')); + codeBlock.appendChild(paren); + } else { + warnings.push([i, 'Unclosed argument list.']); + i--; + } + } + } else if (c == '(') { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var lastChunk = codeBlock.lastChild.nodeValue; + if (lastChunk) { + var call = codeBlock.lastChild.splitText(Math.max(lastChunk.lastIndexOf(' '), lastChunk.lastIndexOf('\t'), lastChunk.lastIndexOf('\n'), 0)); + var callspan = document.createElement('span'); + callspan.className = 'function-call'; + callspan.appendChild(call); + codeBlock.appendChild(callspan); + } + var charspan = document.createElement('span'); + charspan.className = 'punctuation'; + charspan.appendChild(document.createTextNode('(')); + codeBlock.appendChild(charspan); + if (inVarDec[0]) inVarDec[0].parens++; + } else if (['++', '--', '*=', '/=', '%=', '+=', '-=', '&=', '|=', '^='].indexOf(input.substr(i, 2)) != -1) { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var operator = document.createElement('span'); + operator.className = 'operator assigns'; + operator.appendChild(document.createTextNode(input.substr(i, 2))); + codeBlock.appendChild(operator); + i++; + } else if (input.substr(i, 3) == '<<=' || input.substr(i, 3) == '>>=') { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var operator = document.createElement('span'); + operator.className = 'operator assigns'; + operator.appendChild(document.createTextNode(input.substr(i, 3))); + codeBlock.appendChild(operator); + i += 2; + } else if (input.substr(i, 3) == '>>>=') { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var operator = document.createElement('span'); + operator.className = 'operator assigns'; + operator.appendChild(document.createTextNode(input.substr(i, 3))); + codeBlock.appendChild(operator); + i += 3; + } else if ('?:'.indexOf(c) != -1) { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var operator = document.createElement('span'); + operator.className = 'operator'; + operator.appendChild(document.createTextNode(c)); + codeBlock.appendChild(operator); + } else if (['<=', '>=', '==', '!=', '<<', '>>', '&&', '||'].indexOf(input.substr(i, 2)) != -1) { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var operator = document.createElement('span'); + operator.className = 'operator'; + operator.appendChild(document.createTextNode(input.substr(i, 2))); + codeBlock.appendChild(operator); + i++; + } else if (input.substr(i, 3) == '===' || input.substr(i, 3) == '!==' || input.substr(i, 3) == '>>>') { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var operator = document.createElement('span'); + operator.className = 'operator'; + operator.appendChild(document.createTextNode(input.substr(i, 3))); + codeBlock.appendChild(operator); + i += 2; + } else if (beforeWord && c.match(/\d/)) { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var start = i; + if (c == '0' && (c = input[++i])) { + if (c.toLowerCase() == 'b') { + while ('01'.indexOf(input[++i]) != -1); + } else if (c.toLowerCase() == 'o') { + while ('01234567'.indexOf(input[++i]) != -1); + } else if (c.toLowerCase() == 'x') { + while ('0123456789abcdefABCDEF'.indexOf(input[++i]) != -1); + } else if (c.match(/[\d\w]/)) warnings.push([i, 'Bad number literal.']); + var num = document.createElement('span'); + num.className = 'number'; + num.appendChild(document.createTextNode(input.substring(start, i--))); + codeBlock.appendChild(num); + } else { + while ('0123456789.'.indexOf(input[i]) != -1) i++; + if ((input[i] || '').toLowerCase() == 'e') { + if ('+-'.indexOf(input[i])) i++; + if ('0123456789'.indexOf(input[i]) == -1) warnings.push([i, 'No exponent found after "e".']); + else i++; + while ('0123456789.'.indexOf(input[i]) != -1) i++; + } + var num = document.createElement('span'); + num.className = 'number'; + num.appendChild(document.createTextNode(input.substring(start, i))); + codeBlock.appendChild(num); + i--; + } + } else if ('=.,;)[]{}'.indexOf(c) != -1) { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var charspan = document.createElement('span'); + charspan.className = ({'=': 'equals', '.': 'dot'})[c] || 'punctuation'; + charspan.appendChild(document.createTextNode(c)); + codeBlock.appendChild(charspan); + if (inVarDec[0]) { + if (c == ')') inVarDec[0].parens--; + if (inVarDec[0].parens < 0) warnings.push([i, 'Unexpected close paren, make sure you use a semicolon after a variable declaration.']); + if (c == '[') inVarDec[0].brackets++; + if (c == ']') inVarDec[0].brackets--; + if (inVarDec[0].brackets < 0) warnings.push([i, 'Unexpected close bracket, make sure you use a semicolon after a variable declaration.']); + if (c == '{') inVarDec[0].braces++; + if (c == '}') inVarDec[0].braces--; + if (inVarDec[0].braces < 0) warnings.push([i, 'Unexpected close brace, make sure you use a semicolon after a variable declaration.']); + if (Math.max(inVarDec[0].parens, inVarDec[0].brackets, inVarDec[0].braces) == 0) { + if (c == '=') inVarDec[0].equals = true; + if (c == ',') inVarDec[0].equals = false; + } + if (c == ';') inVarDec.shift(); + } + } else if (c == '\n') { + codeBlock.appendChild(document.createTextNode(chunk + '\n')); + chunk = ''; + var linenum = document.createElement('span'); + linenum.className = 'line'; + linenum.dataset.linenum = ++line; + codeBlock.appendChild(linenum); + } else if (c.match(/\S/) && inVarDec[0] && !inVarDec[0].equals && Math.max(inVarDec[0].parens, inVarDec[0].brackets, inVarDec[0].braces) == 0) { + codeBlock.appendChild(document.createTextNode(chunk)); + chunk = ''; + var newvar = document.createElement('span'); + newvar.className = 'newvar'; + newvar.appendChild(document.createTextNode(c)); + codeBlock.appendChild(newvar); + } else chunk += c; } -}); \ No newline at end of file + codeBlock.appendChild(document.createTextNode(chunk)); + codeBlock.className = 'line-dig' + Math.floor(Math.log10(line)); + return warnings; +} \ No newline at end of file From bbd5a3013a2f6470dd1f7f8f816ea462d4b77038 Mon Sep 17 00:00:00 2001 From: bjb568 Date: Wed, 24 Jun 2015 20:14:00 -0400 Subject: [PATCH 4/7] canvas.js: print() can have multiple args --- http/dev/canvas.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/http/dev/canvas.js b/http/dev/canvas.js index 966ede1..0fbd726 100644 --- a/http/dev/canvas.js +++ b/http/dev/canvas.js @@ -163,9 +163,14 @@ function removeLog() { resetLog(); document.getElementById('console').hidden = true; } -function print(input) { +function print() { var pre = document.createElement('pre'); - pre.innerHTML = input; + for (var i = 0; i < arguments.length; i++) { + pre.appendChild(document.createTextNode(' ')); + var span = document.createElement('span'); + span.innerHTML = arguments[i]; + pre.appendChild(span); + } document.getElementById('console').appendChild(pre); document.getElementById('console').hidden = false; } From 68692afaeaa7143d9c4927bacfccf7842d6274d5 Mon Sep 17 00:00:00 2001 From: bjb568 Date: Wed, 24 Jun 2015 20:47:02 -0400 Subject: [PATCH 5/7] Corrected newvar handling --- http/dev/runcanvas.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/http/dev/runcanvas.js b/http/dev/runcanvas.js index b4929a1..fb7e511 100644 --- a/http/dev/runcanvas.js +++ b/http/dev/runcanvas.js @@ -708,12 +708,13 @@ function highlight(codeBlock, input) { keyword.className = 'keyword'; keyword.appendChild(document.createTextNode(input.substr(i, l))); codeBlock.appendChild(keyword); - if (input.substr(i, 3) == 'var') inVarDec.unshift({ + if (input.substr(i, l) == 'var') inVarDec.unshift({ parens: 0, brackets: 0, braces: 0, equals: false }); + if (input.substr(i, l) == 'in') inVarDec.shift(); i += l - 1; } else if (beforeWord && ( (['top'].indexOf(input.substr(i, 3)) != -1 && !(input[i + 3] || '').match(/\w/) && (l = 3)) || @@ -972,10 +973,14 @@ function highlight(codeBlock, input) { linenum.dataset.linenum = ++line; codeBlock.appendChild(linenum); } else if (c.match(/\S/) && inVarDec[0] && !inVarDec[0].equals && Math.max(inVarDec[0].parens, inVarDec[0].brackets, inVarDec[0].braces) == 0) { + var newvar; codeBlock.appendChild(document.createTextNode(chunk)); chunk = ''; - var newvar = document.createElement('span'); - newvar.className = 'newvar'; + if (codeBlock.lastChild.className == 'newvar') newvar = codeBlock.lastChild; + else { + newvar = document.createElement('span'); + newvar.className = 'newvar'; + } newvar.appendChild(document.createTextNode(c)); codeBlock.appendChild(newvar); } else chunk += c; From d5b3aa7fc01f4935fa370013baf04297feb5b274 Mon Sep 17 00:00:00 2001 From: bjb568 Date: Wed, 24 Jun 2015 20:55:07 -0400 Subject: [PATCH 6/7] Remove dev files, clean up --- html/dev/canvas.html | 2 + http/a/rainbow.js | 342 ------------- http/dev/runcanvas.js | 23 +- http/highlighter.html | 1118 ----------------------------------------- http/rainbowtest.html | 722 -------------------------- 5 files changed, 13 insertions(+), 2194 deletions(-) delete mode 100644 http/a/rainbow.js delete mode 100644 http/highlighter.html delete mode 100644 http/rainbowtest.html diff --git a/html/dev/canvas.html b/html/dev/canvas.html index 4b17395..23ba558 100644 --- a/html/dev/canvas.html +++ b/html/dev/canvas.html @@ -296,6 +296,8 @@

$title var mine = $mine, id = $id, + opName = '$op-name', + myRep = $rep, footerOff = true, noPageOverflow = 400, pageOverflowMobile = true, diff --git a/http/a/rainbow.js b/http/a/rainbow.js deleted file mode 100644 index 4aaad04..0000000 --- a/http/a/rainbow.js +++ /dev/null @@ -1,342 +0,0 @@ -// Derivitive of Rainbow 1.2 (liceneced under Apache License V2.0, see rainbowco.de and https://github.com/ccampbell/rainbow ) -var Rainbow = (function() { - var replacements = {}, - replacementPositions = {}, - languagePatterns = {}, - bypassDefaults = {}, - level = 0, - defaultLang = 0; - function matchInsideOtherMatch(start, end) { // Prevents a regex pattern from matching inside of a bigger pattern - for (var key in replacementPositions[level]) { - key = parseInt(key, 10); - if ((start != key || end != replacementPositions[level][key]) && start <= key && end >= replacementPositions[level][key]) { // If block completely is enclosed by another block, remove the other block - delete replacementPositions[level][key]; - delete replacements[level][key]; - } - if (start >= key && start < replacementPositions[level][key] || end > key && end < replacementPositions[level][key]) return true; // Return true if they intersect - } - return false; - } - function processPattern(regex, pattern, code, callback) { // Finds occurances of a regex pattern in a block of code that should be processed, stores positions of where they should be replaced within the string - var match = regex.exec(code); - if (!match) return callback(); - if (!pattern.name && typeof pattern.matches[0] == 'string') { // Treat match 0 the same way as name - pattern.name = pattern.matches[0]; - delete pattern.matches[0]; - } - var replacement = match[0], - startPos = match.index, - endPos = startPos + match[0].length, - processNext = function() { - var nextCall = function() { - processPattern(regex, pattern, code, callback); - }; - return nextCall(); - }; - if (matchInsideOtherMatch(startPos, endPos)) return processNext(); // Skip if it's not a child match and it falls inside of another match that already happened - var onMatchSuccess = function(replacement) { - if (pattern.name) replacement = '' + replacement + ''; - if (!replacements[level]) { // store what needs to be replaced with what's at this position - replacements[level] = {}; - replacementPositions[level] = {}; - } - replacements[level][startPos] = { - 'replace': match[0], - 'with': replacement - }; - replacementPositions[level][startPos] = endPos; - if (Math.random() < 0.005) setTimeout(processNext, 0); - else processNext(); - }, - groupKeys = keys(pattern.matches), - processGroup = function(i, groupKeys, callback) { - if (i >= groupKeys.length) { - return callback(replacement); - } - var processNextGroup = function() { - processGroup(++i, groupKeys, callback); - }, - block = match[groupKeys[i]]; - if (!block) return processNextGroup(); - var group = pattern.matches[groupKeys[i]], - language = group.language, - currentProcessGroup = group.name && group.matches ? group.matches : group, - replaceAndContinue = function(block, replaceBlock, matchName) { - var index = 0; - for (var j = 1; j < groupKeys[i]; j++) { - if (match[j]) index += match[j].length; - } - replacement = replaceAtPosition(index, block, matchName ? '' + replaceBlock + '' : replaceBlock, replacement); - processNextGroup(); - }; - if (language) { // If this is a sublanguage, process the block using that language - return highlightBlockForLanguage(block, language, function(code) { - replaceAndContinue(block, code); - }); - } - if (typeof group == 'string') return replaceAndContinue(block, block, group); // If this is a string then this match is directly mapped to selector so just wrap it in a span and continue - processCodeWithPatterns(block, currentProcessGroup.length ? currentProcessGroup : [currentProcessGroup], function(code) { // processCodeWithPatterns always expects an array so we convert strings here - replaceAndContinue(block, code, group.matches ? group.name : 0); - }); - }; - processGroup(0, groupKeys, onMatchSuccess); - } - function replaceAtPosition(position, replace, replaceWith, code) { - return code.substr(0, position) + code.substr(position).replace(replace, replaceWith); - } - function keys(object) { // Sorts object by index descending - var locations = [], - replacement; - for (var location in object) { - if (object.hasOwnProperty(location)) locations.push(location); - } - return locations.sort(function(a, b) { - return b - a; - }); - } - function processCodeWithPatterns(code, patterns, callback) { - level++; // Increase level so that replacements will not conflict with each other when processing subblocks of code - function workOnPatterns(patterns, i) { // Processed patterns one at a time - if (i < patterns.length) { - return processPattern(patterns[i].pattern, patterns[i], code, function() { - workOnPatterns(patterns, ++i); - }); - } - processReplacements(code, function(code) { - delete replacements[level]; - delete replacementPositions[level]; - level--; - callback(code); - }); - } - workOnPatterns(patterns, 0); - } - function processReplacements(code, callback) { - function processReplacement(code, positions, i, callback) { - if (i < positions.length) { - var pos = positions[i], - replacement = replacements[level][pos]; - code = replaceAtPosition(pos, replacement.replace, replacement.with, code); - return processReplacement(code, positions, ++i, callback); - } - callback(code); - } - var stringPositions = keys(replacements[level]); - processReplacement(code, stringPositions, 0, callback); - } - function highlightBlockForLanguage(code, language, callback) { - var patterns = languagePatterns[language] || [], - defaultPatterns = languagePatterns[defaultLang] || []; - processCodeWithPatterns(code, bypassDefaults[language] ? patterns : patterns.concat(defaultPatterns), callback); - } - function highlightCodeBlock(codeBlocks, i, callback) { - if (i < codeBlocks.length) { - var block = codeBlocks[i], - language = block.dataset.language; - if (!block.classList.contains('rainbow') && language) { - block.classList.add('rainbow'); - return highlightBlockForLanguage(block.innerHTML, language, function(code) { - code = code.split('\n'); - block.classList.add('line-dig' + Math.floor(Math.log10(code.length))); - block.innerHTML = code.map(function(line, i) { - return '' + line; - }).join('\n'); - replacements = {}; - replacementPositions = {}; - highlightCodeBlock(codeBlocks, ++i, callback); - }); - } - return highlightCodeBlock(codeBlocks, ++i, callback); - } - if (callback) callback(); - } - function highlight(node, callback) { - if (node.tagName == 'code') highlightCodeBlock([node], 0); - node = node instanceof Event ? document : node; - highlightCodeBlock(node.getElementsByTagName('code'), 0, callback); - } - return { - extend: function(language, patterns, bypass) { - if (arguments.length == 1) { // Extend the default language rules - patterns = language; - language = defaultLang; - } - bypassDefaults[language] = bypass; - languagePatterns[language] = patterns.concat(languagePatterns[language] || []); - }, - color: function() { - if (typeof arguments[0] == 'string') return highlightBlockForLanguage(html(arguments[0]), arguments[1], arguments[2]); - if (typeof arguments[0] == 'function') return highlight(0, arguments[0]); - highlight(arguments[0], arguments[1]); - } - }; -})(); -document.addEventListener('DOMContentLoaded', Rainbow.color, false); -Rainbow.extend([ - { - matches: { - 1: { - name: 'string', - matches: { - name: 'escape', - pattern: /\\u\{.{1,6}\}|\\u.{4}|\\x.{2}|\\(.)/g - } - } - }, - pattern: /(('|")([^\\\1]|\\.)*?(\2))/gm - }, - { - name: 'comment', - pattern: /\/\*[\s\S]*?\*\/|(\/\/|\#)[\s\S]*?$/gm - }, - { - matches: { - 1: 'number' - }, - pattern: /(?:^|\D)(-?\d+(\.\d+)?(e(\+|\-)?\d+)?(f|d)?|0x[\da-f]+)\b/gi - }, - { - matches: { - 1: 'keyword' - }, - pattern: /\b(and|array|as|b(ool(ean)?|reak)|c(ase|atch|har|lass|on(st|tinue))|d(ef|elete|o(uble)?)|e(cho|lse(if)?|xit|xtends|xcept)|f(inally|loat|or(each)?|unction)|global|if|import|in(stanceof)?|int(eger)?|long|new|object|of|or|pr(int|ivate|otected)|public|return|self|st(ring|ruct|atic)|switch|th(en|is|row)|this|try|typeof|(un)?signed|var|void|while|yield)(?=\(|\b)/gi - }, - { - name: 'constant', - pattern: /true|false|null|nil/g - }, - { - name: 'operator assigns', - pattern: /(\*|\/|%|\+|-|<<|>>(>)?|&|\^|\|)?=|\+\+|--/g - }, - { - name: 'operator', - pattern: /!|==|===|!=|!==|\+|-|\*|\/|%|&(lt|gt);=?|<<|>>(>)?|&{1,2}|\|\|?|\^/g - }, - { - name: 'grouper', - pattern: /[()[\]{}]/g - }, - { - name: 'punctuation', - pattern: /\.|,|;/g - }, - { - matches: { - 1: 'function call' - }, - pattern: /(\w+?)(?=\()/g - }, - { - matches: { - 1: 'keyword', - 2: 'function', - 3: 'arguments' - }, - pattern: /(function)\s+(.*?)\((.*)\)/g - } -]); -var globals = ['AnalyserNode','Animation','AnimationEffect','AnimationEffectReadOnly','AnimationEvent','AnimationTimeline','AnonymousContent','ApplicationCache','ApplicationCacheErrorEvent','Array','ArrayBuffer','Attr','Audio','AudioBuffer','AudioBufferSourceNode','AudioContext','AudioDestinationNode','AudioListener','AudioNode','AudioParam','AudioProcessingEvent','AudioStreamTrack','AutocompleteErrorEvent','BarProp','BatteryManager','BeforeLoadEvent','BeforeUnloadEvent','BiquadFilterNode','Blob','BlobEvent','Boolean','BroadcastChannel','CDATASection','CSS','CSS2Properties','CSSCharsetRule','CSSConditionRule','CSSCounterStyleRule','CSSFontFaceRule','CSSFoundFaceLoadEvent','CSSFoundFaceRule','CSSFoundFeatureValuesRule','CSSGroupingRule','CSSImportRule','CSSKeyframeRule','CSSKeyframesRule','CSSMediaRule','CSSMozDocumentRule','CSSNameSpaceRule','CSSPageRule','CSSPrimitiveValue','CSSRule','CSSRuleList','CSSStyleDeclaration','CSSStyleRule','CSSStyleSheet','CSSSupportsRule','CSSUnknownRule','CSSValue','CSSValueList','CSSViewportRule','Cache','CacheStorage','CanvasGradiant','CanvasGradient','CanvasPattern','CanvasRenderingContext2D','CaretPosition','ChannelMergerNode','ChannelSplitterNode','CharacterData','ClientRect','ClientRectList','ClipboardEvent','CloseEvent','CommandEvent','Comment','CompositionEvent','Console','Controllers','ConvolverNode','Counter','Crypto','CryptoKey','CustomEvent','DOMCursor','DOMError','DOMException','DOMImplementation','DOMMatrix','DOMMatrixReadOnly','DOMParser','DOMPoint','DOMPointReadOnly','DOMQuad','DOMRect','DOMRectList','DOMRectReadOnly','DOMRequest','DOMSettableTokenList','DOMStringList','DOMStringMap','DOMTokenList','DOMTransactionEvent','DataChannel','DataTransfer','DataTransferItem','DataTransferItemList','DataView','Date','DelayNode','DesktopNotification','DesktopNotificationCenter','DeviceLightEvent','DeviceMotionEvent','DeviceOrientationEvent','DeviceProximityEvent','Document','DocumentFragment','DocumentTimeline','DocumentType','DragEvent','DynamicsCompressorNode','Element','Entity','EntityReference','Error','ErrorEvent','EvalError','Event','EventException','EventSource','EventTarget','External','File','FileError','FileList','FileReader','Float32Array','Float64Array','FocusEvent','FontFace','FontFaceSet','FormData','Function','GainNode','Gamepad','GamepadAxisMoveEvent','GamepadButton','GamepadButtonEvent','GamepadEvent','HTMIFrameElement','HTMLAllCollection','HTMLAnchorElement','HTMLAppletElement','HTMLAreaElement','HTMLAudioElement','HTMLBRElement','HTMLBaseElement','HTMLBaseFontElement','HTMLBodyElement','HTMLButtonElement','HTMLCanvasElement','HTMLCollection','HTMLContentElement','HTMLDListElement','HTMLDataElement','HTMLDataListElement','HTMLDetailsElement','HTMLDialogElement','HTMLDirectoryElement','HTMLDivElement','HTMLDocument','HTMLElement','HTMLEmbedElement','HTMLFieldSetElement','HTMLFontElement','HTMLFormControlsCollection','HTMLFormElement','HTMLFrameElement','HTMLFrameSetElement','HTMLHRElement','HTMLHeadElement','HTMLHeadingElement','HTMLHtmlElement','HTMLIFrameElement','HTMLImageElement','HTMLInputElement','HTMLKeygenElement','HTMLLIElement','HTMLLabelElement','HTMLLegendElement','HTMLLinkElement','HTMLMEdiaElement','HTMLMapElement','HTMLMarqueeElement','HTMLMediaElement','HTMLMenuElement','HTMLMenuItemElement','HTMLMetaElement','HTMLMeterElement','HTMLModElement','HTMLOListElement','HTMLObjectElement','HTMLOptGroupElement','HTMLOptionElement','HTMLOptionsCollection','HTMLOutputElement','HTMLPRogressElement','HTMLParagraphElement','HTMLParamElement','HTMLPictureElement','HTMLPreElement','HTMLProgressElement','HTMLPropertiesCollection','HTMLQuoteElement','HTMLScriptElement','HTMLSelectElement','HTMLShadowElement','HTMLSourceElement','HTMLSpanElement','HTMLStyleElement','HTMLTableCaptionElement','HTMLTableCellElement','HTMLTableColElement','HTMLTableElement','HTMLTableRowElement','HTMLTableSectionElement','HTMLTemplateElement','HTMLTextAreaElement','HTMLTitleElement','HTMLTrackElement','HTMLUListElement','HTMLUnknownElement','HTMLVideoElement','HashChangeEvent','Headers','History','IDBCursor','IDBCursorWithValue','IDBDatabase','IDBFactory','IDBFileHandle','IDBFileRequest','IDBIndex','IDBKeyRange','IDBMutableFile','IDBObjectStore','IDBOpenDBRequest','IDBRequest','IDBTransaction','IDBVersionChangeEvent','Image','ImageBitmap','ImageData','Infinity','InputEvent','InputMethodContext','InstallTrigger','Int1','Int16Array','Int32Array','Int8Array','InternalError','Intl','Iterator','JSON','KeyEvent','KeyboardEvent','KeyframeEffectReadOnly','LocalMediaStream','Location','MIDIAccess','MIDIConnectionEvent','MIDIInput','MIDIInputMap','MIDIMessageEvent','MIDIOutput','MIDIOutputMap','MIDIPort','Map','Math','MediaController','MediaDeviceInfo','MediaDevices','MediaElementAudioSourceNode','MediaEncryptedEvent','MediaError','MediaKeyError','MediaKeyEvent','MediaKeyMessageEvent','MediaKeyNeededEvent','MediaKeySession','MediaKeyStatusMap','MediaKeySystemAccess','MediaKeys','MediaList','MediaQueryList','MediaQueryListEvent','MediaRecorder','MediaSource','MediaStream','MediaStreamAudioDestinationNode','MediaStreamAudioSourceNode','MediaStreamEvent','MediaStreamTrack','MediaStreamTrackEvent','MessageChannel','MessageEvent','MessagePort','MimeType','MimeTypeArray','MouseEvent','MouseSCrollEvent','MozCSSKeyframeRule','MozCSSKeyframesRule','MozMmsMessage','MozMobileMessagethread','MozPowerManager','MozSettingsEvent','MozSnsNessage','MutationEvent','MutationObserver','MutationRecord','NaN','NamedNodeMap','Navigator','Node','NodeFilter','NodeIterator','NodeList','Notation','Notification','NozContactChangeEvent','NptifyPaintEvent','Number','Object','OfflineAudioCompletionEvent','OfflineAudioContext','OfflineResourceList','Option','OscillatorNode','OverflowEvent','PageTransitionEvent','PaintRequest','PaintRequestList','PannerNode','Path2D','Performance','PerformanceEntry','PerformanceMark','PerformanceMeasure','PerformanceNavigation','PerformanceResourceTiming','PerformanceTiming','PeriodicWave','PermissionStatus','Permissions','Plugin','PluginArray','PopStateEvent','PopupBlockedEvent','ProcessingInstruction','ProgressEvent','Promise','PropertyNodeList','Proxy','PushManager','PushSubscription','RGBColor','RTCDataChannelEvent','RTCIceCandidate','RTCPeerConnectionEvent','RTCRtpReceiver','RTCRtpSender','RTCSessionDescription','RTCStatsReport','RadioNodeList','Range','RangeError','RangeException','ReadableByteStream','ReadableStream','RecordErrorEvent','Rect','ReferenceError','RegExp','Request','Response','SCriptProcessorNode','SCrollAreaEvent','SQLException','SVGAElement','SVGAltGlyphDefElement','SVGAltGlyphElement','SVGAltGlyphItemElement','SVGAngle','SVGAnimateColorElement','SVGAnimateElement','SVGAnimateMotionElement','SVGAnimateTransformElement','SVGAnimatedAngle','SVGAnimatedBoolean','SVGAnimatedEnumeration','SVGAnimatedInteger','SVGAnimatedLength','SVGAnimatedLengthList','SVGAnimatedNumber','SVGAnimatedNumberList','SVGAnimatedPreserveAspectRatio','SVGAnimatedRect','SVGAnimatedString','SVGAnimatedTransformList','SVGAnimationElement','SVGCircleElement','SVGClipPathElement','SVGColor','SVGComponentTransferFunctionElement','SVGCursorElement','SVGDefsElement','SVGDescElement','SVGDiscardElement','SVGDocument','SVGElement','SVGElementInstance','SVGElementInstanceList','SVGEllipseElement','SVGEscElement','SVGException','SVGFEBlendElement','SVGFEColorMatrixElement','SVGFEComplenentTransferElement','SVGFEComponentTransferElement','SVGFECompositeElement','SVGFEConvolveMatrixElement','SVGFEDiffuseLightingElement','SVGFEDisplacementMapElement','SVGFEDistanceLightElement','SVGFEDistantLightElement','SVGFEDropShadowElement','SVGFEFloodElement','SVGFEFuncAElement','SVGFEFuncBElement','SVGFEFuncGElement','SVGFEFuncRElement','SVGFEGaussianBlurElement','SVGFEImageElement','SVGFEMergeElement','SVGFEMergeNodeElement','SVGFEMorphologyElement','SVGFEOffsetElement','SVGFEPointLightElement','SVGFESpectacularLightingElement','SVGFESpecularLightingElement','SVGFESpotLightElement','SVGFETileElement','SVGFETurbulanceElement','SVGFETurbulenceElement','SVGFilterElement','SVGFontElement','SVGFontFaceElement','SVGFontFaceFormatElement','SVGFontFaceNameElement','SVGFontFaceSrcElement','SVGFontFaceUriElement','SVGForeignObjectElement','SVGGElement','SVGGelement','SVGGeometryElement','SVGGlyphElement','SVGGlyphRefElement','SVGGradientElement','SVGGraphicsElement','SVGHKernElement','SVGImageElement','SVGLength','SVGLengthList','SVGLineElement','SVGLinearGradientElement','SVGMPathElement','SVGMarkerElement','SVGMaskElement','SVGMatrix','SVGMetadataElement','SVGMissingGlyphElement','SVGNumber','SVGNumberList','SVGPaint','SVGPathElement','SVGPathSeg','SVGPathSegArcAbs','SVGPathSegArcRel','SVGPathSegClosePath','SVGPathSegCurvetoCubicAbs','SVGPathSegCurvetoCubicRel','SVGPathSegCurvetoCubicSmoothAbs','SVGPathSegCurvetoCubicSmoothRel','SVGPathSegCurvetoCubigRel','SVGPathSegCurvetoQuadraticAbs','SVGPathSegCurvetoQuadraticRel','SVGPathSegCurvetoQuadraticSmoothAbs','SVGPathSegCurvetoQuadraticSmoothRel','SVGPathSegCurvetoQuarticAbs','SVGPathSegCurvetoQuarticRel','SVGPathSegCurvetoQuarticSmoothAbs','SVGPathSegCurvetoQuarticSmoothRel','SVGPathSegLinetoAbs','SVGPathSegLinetoHorizontalAbs','SVGPathSegLinetoHorizontalRel','SVGPathSegLinetoRel','SVGPathSegLinetoVerticalAbs','SVGPathSegLinetoVerticalRel','SVGPathSegList','SVGPathSegMovetoAbs','SVGPathSegMovetoRel','SVGPatternElement','SVGPoint','SVGPointList','SVGPolygonElement','SVGPolylineElement','SVGPreserveAspectRatio','SVGRadialGradientElement','SVGRect','SVGRectElement','SVGRenderingIntent','SVGSVGElement','SVGScriptElement','SVGSetElement','SVGStopElement','SVGStringList','SVGStyleElement','SVGSwitchElement','SVGSymbolElement','SVGTRefElement','SVGTSpanElement','SVGTextContentElement','SVGTextElement','SVGTextPathElement','SVGTextPositioningElement','SVGTitleElement','SVGTransform','SVGTransformList','SVGUnitTypes','SVGUseElement','SVGVKernElement','SVGViewElement','SVGViewSpec','SVGZoomAndPan','SVGZoomEvent','Screen','ScreenOrientation','ScriptProcessorNode','SecurityPolicyViolationEvent','Selection','ServiceWorker','ServiceWorkerContainer','ServiceWorkerRegistration','Set','ShadowRoot','SharedWorker','SimpleGestureEvent','SourceBuffer','SourceBufferList','SpeechSynthesisEvent','SpeechSynthesisUtterance','StereoPannerNode','StopIteration','Storage','StorageEvent','String','StyleSheet','StyleSheetList','SubtleCrypto','Symbol','SymbolSyntaxError','SyntaxError','TetEncoder','Text','TextDecoder','TextEncoder','TextEvent','TextMetrics','TextTrack','TextTrackCue','TextTrackCueList','TextTrackList','TimeEvent','TimeRanges','Touch','TouchEvent','TouchList','TrackEvent','TransitionEvent','TreeWalker','TypeError','UIEvent','URIError','URL','URLSearchParams','Uint16Array','Uint32Array','Uint8Array','Uint8ClampedArray','UserMessageHandler','UserMessageHandlersNamespace','UserProximityEvent','VTTCue','VTTRegion','ValidityState','VideoPlaybackQuality','VideoStreamTrack','WaveShaperNode','WeakMap','WeakSet','WebGLActiveInfo','WebGLBuffer','WebGLContextEvent','WebGLFramebuffer','WebGLProgram','WebGLRenderBuffer','WebGLRenderbuffer','WebGLRenderingContext','WebGLShader','WebGLShaderPrecisionFormat','WebGLTexture','WebGLUniformLocation','WebGLVertextArray','WebKitAnimationEvent','WebKitCSSFilterValue','WebKitCSSKeyframeRule','WebKitCSSKeyframesRule','WebKitCSSMatrix','WebKitCSSRegionRule','WebKitCSSTransformValue','WebKitDataCue','WebKitMediaKeyError','WebKitMediaKeyMessageEvent','WebKitMediaKeySession','WebKitMediaKeys','WebKitMutationObserver','WebKitNamespace','WebKitPoint','WebKitTransitionEvent','WebSocket','WheelEVent','WheelEvent','Window','Worker','XMLDocument','XMLHTTPRequest','XMLHTTPRequestEventTarget','XMLHTTPRequestUpload','XMLHttpRequest','XMLHttpRequestEventTarget','XMLHttpRequestException','XMLHttpRequestProgressEvent','XMLHttpRequestUpload','XMLSerializer','XMLStylesheetProcessingInstruction','XPathEvaluater','XPathEvaluator','XPathException','XPathExperssion','XPathExpression','XPathResult','XPatyResult','XSLTProcessor','__proto__','alert','applicationCache','atob','blur','btoa','caches','cancelAnimationFrame','captureEvents','chrome','clearInterval','clearMaxGCPauseAccumulator','clearTimeout','clientInformation','close','closed','confirm','connectShark','console','constructor','content','crypto','decodeUIComponent','decodeURI','decodeURIComponent','defaultStatus','defaultstatus','devicePixelRatio','disconnectShark','document','dump','dumpProfile','encodeURI','encodeURIComponent','escape','eval','event','external','fetch','find','focus','frameElement','frames','fullScreen','getComputedStyle','getDefaultComputedStyle','getMaxGCPauseSinceClear','getSelection','history','indexedDB','innerHeight','innerWidth','isFinite','isNaN','length','localStorage','location','locationbar','matchMedia','menubar','moveBy','moveTo','mozAnimationStartTime','mozCancelAnimationFrame','mozCancelRequestAnimationFrame','mozContact','mozInnerScreenX','mozInnerScreenY','mozPaintCount','mozRTCIceCandidate','mozRTCPeerConnection','mozRTCSessionDescription','mozRequestAnimationFrame','name','navigator','netscape','offscreenBuffering','onabort','onafterprint','onbeforeprint','onbeforeunload','onblur','oncanplay','oncanplaythrough','onchange','onclick','oncontextmenu','ondblclick','ondevicelight','ondevicemotion','ondeviceorientation','ondeviceproximity','ondrag','ondragend','ondragenter','ondragleave','ondragover','ondragstart','ondrop','ondurationchange','onemptied','onended','onerror','onfocus','onhashchange','oninput','oninvalid','onkeydown','onkeypress','onkeyup','onlanguagechange','onload','onloadeddata','onloadedmetadata','onloadstart','onmessage','onmousedown','onmouseenter','onmouseleave','onmousemove','onmouseout','onmouseover','onmouseup','onmousewheel','onmozfullscreenchange','onmozfullscreenerror','onmozpointerlockchange','onmozpointerlockerror','onoffline','ononline','onpagehide','onpageshow','onpause','onplay','onplaying','onpopstate','onprogress','onratechange','onreset','onresize','onscroll','onsearch','onseeked','onseeking','onselect','onshow','onstalled','onstorage','onsubmit','onsuspend','ontimeupdate','ontransitionend','onunload','onuserproximity','onvolumechange','onwaiting','onwebkitanimationend','onwebkitanimationiteration','onwebkitanimationstart','onwebkittransitionend','onwheel','open','opener','outerHeight','outerWidth','pageXOffset','pageYOffset','parent','parseFloat','parseInt','pauseProfilers','performance','personalbar','postMessage','print','prompt','releaseEvents','requestAnimationFrame','resizeBy','resizeTo','resumeProfilers','screen','screenLeft','screenTop','screenX','screenY','scroll','scrollBy','scrollByLines','scrollByPages','scrollMaxX','scrollMaxY','scrollTo','scrollX','scrollY','scrollbars','self','sessionStorage','setInterval','setResizable','setTimeout','showModalDialog','sidebar','sizeToContent','speechSynthesis','startProfiling','startShark','status','statusbar','stop','stopProfiling','stopShark','styleMedia','toolbar','top','undefined','unescape','uneval','updateCommands','webkitAudioContext','webkitAudioPannerNode','webkitIDBCursor','webkitIDBDatabase','webkitIDBFactory','webkitIDBIndex','webkitIDBKeyRange','webkitIDBObjectStore','webkitIDBRequest','webkitIDBTransaction','webkitIndexedDB','webkitMediaStream','webkitNotifications','webkitOfflineAudioContext','webkitRTCPeerConnection','webkitSpeechGrammar','webkitSpeechGrammarList','webkitSpeechRecognition','webkitSpeechRecognitionError','webkitSpeechRecognitionEvent','webkitStorageInfo','webkitURL','window'], - methods = { - document: ['open', 'close', 'write', 'writeln', 'clear', 'captureEvents', 'releaseEvents', 'getElementsByTagName', 'getElementsByTagNameNS', 'getElementsByClassName', 'createDocumentFragment', 'createTextNode', 'createComment', 'createProcessingInstruction', 'importNode', 'adoptNode', 'createAttribute', 'createAttributeNS', 'createEvent', 'createRange', 'createNodeIterator', 'createTreeWalker', 'createCDATASection', 'getElementsByName', 'hasFocus', 'execCommand', 'queryCommandEnabled', 'queryCommandIndeterm', 'queryCommandState', 'queryCommandSupported', 'queryCommandValue', 'elementFromPoint', 'elementsFromPoint', 'getSelection', 'exitPointerLock', 'registerElement', 'createElement', 'createElementNS', 'caretRangeFromPoint', 'getCSSCanvasContext', 'webkitCancelFullScreen', 'webkitExitFullscreen', 'getElementById', 'querySelector', 'querySelectorAll', 'createExpression', 'createNSResolver', 'evaluate', 'hasChildNodes', 'normalize', 'cloneNode', 'isEqualNode', 'compareDocumentPosition', 'contains', 'lookupPrefix', 'lookupNamespaceURI', 'isDefaultNamespace', 'insertBefore', 'appendChild', 'replaceChild', 'removeChild', 'isSameNode', 'addEventListener', 'removeEventListener', 'dispatchEvent', 'createEntityReference', 'getOverrideStyle', 'webkitGetNamedFlows', 'isSupported', 'getItems', 'releaseCapture', 'mozSetImageElement', 'mozCancelFullScreen', 'mozExitPointerLock', 'enableStyleSheetsForSet', 'caretPositionFromPoint', 'getBoxQuads', 'convertQuadFromNode', 'convertRectFromNode', 'convertPointFromNode'] - }; -Rainbow.extend('javascript', [ - { - matches: { - 1: 'browser', - 2: 'punctuation', - 3: 'browser method' - }, - pattern: new RegExp('(document)(\\.)(' + methods.document.join('|') + ')(?=\\()', 'g') - }, - { - matches: { - 1: 'punctuation', - 2: 'browser property' - }, - pattern: /(\.)(length|name|width|height|x|y|z|classList|children|childNodes|(previous|next)(Element)?Sibling|parent(Element|Node)|(first|last)child|dataset)/g - }, - { - matches: { - 1: 'punctuation', - 2: 'browser method' - }, - pattern: /(\.)(apply|bind|call|cloneNode|form|isArray|observe|of|toString|toFixed|addEventListener|removeEventListener)(?=\()/g - }, - { - matches: { - 1: 'browser', - 2: 'punctuation', - 3: 'browser method' - }, - pattern: /(JSON)(\.)(parse|stringify)(?=\()/g - }, - { - matches: { - 1: 'browser', - 2: 'punctuation', - 3: 'browser' - }, - pattern: /(Number)(\.)(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NaN|NEGATIVE_INFINITY|POSITIVE_INFINITY)/g - }, - { - matches: { - 1: 'browser', - 2: 'punctuation', - 3: 'browser method' - }, - pattern: /(Number)(\.)(isNaN|isFinite|isInteger|isSafeInteger|parseFloat|parseInt)(?=\()/g - }, - { - matches: { - 1: 'support property' - }, - pattern: /\.(length|node(Name|Value))\b/g - }, - { - name: 'regex', - matches: { - 1: 'regex open', - 2: { - name: 'escape', - pattern: /\\(.){1}/g - }, - 3: 'regex close', - 4: 'regex modifier' - }, - pattern: /(\/)(?!\*)((?:[^\\\1\n]|\\.)+?)(\/)([igm]{0,3})/g - }, - { - matches: { - 1: 'keyword', - 2: [ - { - name: 'function prototype', - pattern: /prototype/g - }, - { - name: 'browser', - pattern: new RegExp('\\b(' + globals.join('|') + ')\\b', 'g') - }, - { - name: 'function', - pattern: /\w+/g - }, - { - name: 'punctuation', - pattern: /\./g - } - ], - 3: 'operator assigns', - 4: 'keyword', - 5: 'grouper', - 6: 'arguments', - 7: 'grouper' - }, - pattern: /(var)?(?:\s|^)(\S+)\s*(=)\s*(function)\s*(\()(.*)(\))/g - }, - { - name: 'browser', - pattern: new RegExp('\\b(' + globals.join('|') + ')\\b', 'g') - }, -]); \ No newline at end of file diff --git a/http/dev/runcanvas.js b/http/dev/runcanvas.js index fb7e511..1f845de 100644 --- a/http/dev/runcanvas.js +++ b/http/dev/runcanvas.js @@ -13,6 +13,13 @@ function insertNodeAtPosition(node, refNode, pos) { } } var blinkTimeout; +function upvoteComment() { + this.classList.toggle('clkd'); + socket.send(JSON.stringify({ + event: this.classList.contains('clkd') ? 'vote' : 'unvote', + id: parseInt(this.parentNode.parentNode.id.substr(1)) + })); +} addEventListener('DOMContentLoaded', function() { var code = document.getElementById('code'), codeDisplay = document.getElementById('code-display'), @@ -57,7 +64,6 @@ addEventListener('DOMContentLoaded', function() { caret.id = 'caret'; caret.appendChild(document.createTextNode('\xA0')); insertNodeAtPosition(caret, codeDisplay, cursorPos); - console.log(blinkTimeout); clearTimeout(blinkTimeout); blinkTimeout = setTimeout(blink, 500); } @@ -293,7 +299,7 @@ addEventListener('DOMContentLoaded', function() { request('/api/program/vote', function(res) { if (res.indexOf('Error') == 0) alert(res); else if (res == 'Success') { - document.getElementsByClassName('user-$op-name')[0].getElementsByClassName('rep')[0].textContent -= (dn.classList.contains('clkd') ? -1 : 0) - (up.classList.contains('clkd') ? -1 : 1); + document.getElementsByClassName('user-' + opName)[0].getElementsByClassName('rep')[0].textContent -= (dn.classList.contains('clkd') ? -1 : 0) - (up.classList.contains('clkd') ? -1 : 1); up.classList.toggle('clkd'); dn.classList.remove('clkd'); } else alert('Unknown error. Response was: ' + res); @@ -303,7 +309,7 @@ addEventListener('DOMContentLoaded', function() { request('/api/program/vote', function(res) { if (res.indexOf('Error') == 0) alert(res); else if (res == 'Success') { - document.getElementsByClassName('user-$op-name')[0].getElementsByClassName('rep')[0].textContent -= (up.classList.contains('clkd') ? 1 : 0) - (dn.classList.contains('clkd') ? 1 : -1); + document.getElementsByClassName('user-' + opName)[0].getElementsByClassName('rep')[0].textContent -= (up.classList.contains('clkd') ? 1 : 0) - (dn.classList.contains('clkd') ? 1 : -1); dn.classList.toggle('clkd'); up.classList.remove('clkd'); } else alert('Unknown error. Response was: ' + res); @@ -341,7 +347,7 @@ addEventListener('DOMContentLoaded', function() { var div = document.createElement('div'); div.classList.add('comment'); div.innerHTML = ' ' + markdown(data.body); - if ($rep >= 50) { + if (myRep >= 50) { div.insertBefore(document.getElementById('content').children[2].cloneNode(true), div.firstChild); div.firstChild.firstChild.onclick = upvoteComment; var score = document.createElement('span'); @@ -354,7 +360,7 @@ addEventListener('DOMContentLoaded', function() { sig.appendChild(document.createTextNode('-')); var a = document.createElement('a'); a.href = '/user/' + data.user; - a.appendChild(document.createTextNode(data.user)) + a.appendChild(document.createTextNode(data.user)); sig.appendChild(a); sig.appendChild(document.createTextNode(', ')); var permalink = document.createElement('a'); @@ -387,13 +393,6 @@ addEventListener('DOMContentLoaded', function() { } }; } - function upvoteComment() { - this.classList.toggle('clkd'); - socket.send(JSON.stringify({ - event: this.classList.contains('clkd') ? 'vote' : 'unvote', - id: parseInt(this.parentNode.parentNode.id.substr(1)) - })); - } var comments = document.getElementsByClassName('comment'); for (var i = 0; i < comments.length; i++) { comments[i].getElementsByClassName('sctrls')[0].firstChild.onclick = upvoteComment; diff --git a/http/highlighter.html b/http/highlighter.html deleted file mode 100644 index 2d863a9..0000000 --- a/http/highlighter.html +++ /dev/null @@ -1,1118 +0,0 @@ - - - -Syntax Highlighting - - - - -vsasdf = function() { - bg(0); - stroke(mousePressed ? '#f00' : none); - font('40px verdana'); - text(100, 100, round(mouseX) + ',' + round(mouseY)); - if (key) print(key); -}; -String.prototype.replaceAll = function(find, replace) { - if (typeof find == 'string') return this.split(find).join(replace); - var t = this, i, j; - while (typeof(i = find.shift()) == 'string' && typeof(j = replace.shift()) == 'string') t = t.replaceAll(i || '', j || ''); - return t; -}; -String.prototype.repeat = function(num) { - return new Array(++num).join(this); -}; -Number.prototype.bound = function(l, h) { - return isNaN(h) ? Math.min(this, l) : Math.max(Math.min(this, h), l); -}; -HTMLCollection.prototype.indexOf = NodeList.prototype.indexOf = Array.prototype.indexOf; -HTMLCollection.prototype.forEach = NodeList.prototype.forEach = Array.prototype.forEach; -HTMLElement.prototype.insertAfter = function(newEl, refEl) { - if (refEl.nextSibling) refEl.parentNode.insertBefore(newEl, refEl.nextSibling); - else refEl.parentNode.appendChild(newEl); -}; - -function html(input, replaceQuoteOff) { - if (replaceQuoteOff) return input.toString().replaceAll(['&', '<'], ['&amp;', '&lt;']); - return input.toString().replaceAll(['&', '<', '"'], ['&amp;', '&lt;', '&quot;']); -} - -var mdWarnings = []; -function warning(message) { - console.log(message); - mdWarnings.push(message); -} -function spanMarkdown(input) { - input = html(input); - while (input.match(/\^([\w\^]+)/)) input = input.replace(/\^([\w\^]+)/, '<sup>$1</sup>'); - return input - .replaceAll('\u0001', '^') - .replace(/\[(.+?)\|(.+?)\]/g, '<abbr title="$2">$1</abbr>') - .replaceAll('\u0002', '[') - .replace(/\[\[(\d+)\](.*?)\]/g, '<sup class="reference" title="$2">[$1]</sup>') - .replace(/!\[([^\]]+)]\(https?:\/\/([^\s("\\]+\.[^\s"\\]+)\)/g, '<img alt="$1" src="https://$2" />') - .replace(/^https?:\/\/([^\s("\\]+\.[^\s"\\]+\.(svg|png|tiff|jpg|jpeg)(\?[^\s"\\\/]*)?)/g, '<img src="https://$1" />') - .replace(/\[([^\]]+)]\((https?:\/\/[^\s("\\]+\.[^\s"\\]+)\)/g, '$1'.link('$2')) - .replace(/([^;["\\])https?:\/\/([^\s("\\]+\.[^\s"\\]+\.(svg|png|tiff|jpg|jpeg)(\?[^\s"\\\/]*)?)/g, '$1<img src="https://$2" />') - .replace(/([^;["\\])(https?:\/\/([^\s("\\]+\.[^\s"\\]+))/g, '$1' + '$3'.link('$2')) - .replace(/^(https?:\/\/([^\s("\\]+\.[^\s"\\]+))/g, '$2'.link('$1')); -} -function inlineMarkdown(input) { - var output = '', - span = '', - current = [], - tags = { - '`': 'code', - '``': 'samp', - '*': 'em', - '**': 'strong', - '_': 'i', - '–––': 's', - '+++': 'ins', - '---': 'del', - '[c]': 'cite', - '[m]': 'mark', - '[u]': 'u', - '[v]': 'var', - '::': 'kbd', - '"': 'q' - }, - stags = { - sup: { - start: '^(', - end: ')^' - }, - sub: { - start: 'v(', - end: ')v' - }, - small: { - start: '[sm]', - end: '[/sm]' - } - }; - outer: for (var i = 0; i < input.length; i++) { - if (['code', 'samp'].indexOf(current[current.length - 1]) == -1) { - if (input[i] == '\\') span += input[++i].replace('^', '\u0001').replace('[', '\u0002'); - else { - for (var l = 3; l > 0; l--) { - if (tags[input.substr(i, l)]) { - output += spanMarkdown(span); - span = ''; - if (current[current.length - 1] == tags[input.substr(i, l)]) output += '</' + current.pop() + '>'; - else { - if (current.indexOf(tags[input.substr(i, l)]) != -1) warning('Illegal nesting of "' + input.substr(i, l) + '"'); - output += '<' + tags[input.substr(i, l)] + '>'; - current.push(tags[input.substr(i, l)]); - } - i += l - 1; - continue outer; - } - } - for (var j in stags) { - for (var l = 5; l > 0; l--) { - if (stags[j].start == input.substr(i, l)) { - output += spanMarkdown(span) + '<' + j + '>'; - span = ''; - current.push(stags[j].end); - i += l - 1; - continue outer; - } else if (stags[j].end == input.substr(i, l)) { - if (current[current.length - 1] == stags[j].end) { - output += spanMarkdown(span) + '</' + j + '>'; - span = ''; - current.pop(); - i += l - 1; - continue outer; - } else warning('Illegal close tag "' + stags[j].end + '" found'); - } - } - } - span += input[i]; - } - } else if (current[current.length - 1] == 'code' && input[i] == '`') { - current.pop(); - output += '</code>'; - } else if (current[current.length - 1] == 'samp' && input.substr(i, 2) == '``') { - current.pop(); - output += '</samp>'; - i++; - } else output += html(input[i]); - } - output += spanMarkdown(span); - if (current.length) warning('Unclosed tags. <' + current.join('>, <') + '>'); - for (var i = current.length - 1; i >= 0; i--) output += '</' + current[i] + '>'; - return output; -} -function markdown(input) { - if (input.indexOf('\n') == -1 && input.substr(0, 2) != '> ' && input.substr(0, 3) != '>! ' && input.substr(0, 2) != '- ' && input.substr(0, 2) != '* ' && input.substr(0, 4) != ' ' && input[0] != '\t' && !input.match(/^((\d+|[A-z])[.)]|#{1,6}|cite\[\d+\]:) /) && !input.match(/^[-–—]{12,}$/)) return inlineMarkdown(input); - var blockquote = '', - ul = '', - ol = '', - li = '', - code = '', - i; - return input.split('\n').map(function(val, i, arr) { - if (!val) return ''; - var f; - if (val.substr(0, 2) == '> ') { - val = val.substr(2); - if (arr[i + 1] && arr[i + 1].substr(0, 2) == '> ') { - blockquote += val + '\n'; - return ''; - } else { - var arg = blockquote + val; - blockquote = ''; - return '<blockquote>' + markdown(arg) + '</blockquote>'; - } - } else if (val.substr(0, 3) == '>! ') { - val = val.substr(3); - if (arr[i + 1] && arr[i + 1].substr(0, 3) == '>! ') { - blockquote += val + '\n'; - return ''; - } else { - var arg = blockquote + val; - blockquote = ''; - return '<blockquote class="spoiler">' + markdown(arg) + '</blockquote>'; - } - } else if (val.substr(0, 2) == '- ' || val.substr(0, 2) == '* ') { - if (!ul) ul = '<ul>'; - val = val.substr(2); - if (li) { - ul += '<li>' + markdown(li) + '</li>'; - li = ''; - } - if (arr[i + 1] && (arr[i + 1].substr(0, 2) == '- ' || arr[i + 1] && arr[i + 1].substr(0, 2) == '* ')) { - ul += '<li>' + inlineMarkdown(val) + '</li>'; - return ''; - } else if (arr[i + 1] && (arr[i + 1][0] == '\t' || arr[i + 1] && arr[i + 1].substr(0, 4) == ' ')) { - li += val + '\n'; - return ''; - } else { - var arg = ul + '<li>' + markdown(val) + '</li>'; - ul = ''; - return arg + '</ul>'; - } - } else if (f = val.match(/^(\d+|[A-z])[.)] /)) { - if (!ol) ol = '<ol>'; - val = val.substr(f[0].length); - if (li) { - ol += '<li>' + markdown(li) + '</li>'; - li = ''; - } - if (arr[i + 1] && arr[i + 1].match(/^(\d+|[A-z])[.)] /)) { - ol += '<li>' + inlineMarkdown(val) + '</li>'; - return ''; - } else if (arr[i + 1] && (arr[i + 1][0] == '\t' || arr[i + 1] && arr[i + 1].substr(0, 4) == ' ')) { - li += val + '\n'; - return ''; - } else { - var arg = ol + '<li>' + inlineMarkdown(val) + '</li>'; - ol = ''; - return arg + '</ol>'; - } - } else if (li && val[0] == '\t') { - li += val.substr(1) + '\n'; - if (ul && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && arr[i + 1].substr(2) != '- ' && arr[i + 1].substr(2) != '* '))) { - var arg = ul + '<li>' + markdown(li) + '</li>'; - li = ''; - return arg + '</ul>'; - } else if (ol && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && !arr[i + 1].match(/^(\d+|[A-z])[.)] /)))) { - var arg = ol + '<li>' + markdown(li) + '</li>'; - li = ''; - return arg + '</ol>'; - } - return ''; - } else if (li && val.substr(0, 4) == ' ') { - li += val.substr(4) + '\n'; - if (ul && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && arr[i + 1].substr(2) != '- ' && arr[i + 1].substr(2) != '* '))) { - var arg = ul + '<li>' + markdown(li) + '</li>'; - li = ''; - return arg + '</ul>'; - } else if (ol && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && !arr[i + 1].match(/^((\d+|[A-z])|[A-z])[.)] /)))) { - var arg = ol + '<li>' + markdown(li) + '</li>'; - li = ''; - return arg + '</ol>'; - } - return ''; - } else if (val[0] == '\t') { - code += val.substr(1); - if (!arr[i + 1] || (arr[i + 1].substr(0, 4) != ' ' && arr[i + 1][0] != '\t')) { - var arg = html(code); - code = ''; - return '<code class="blk">' + arg + '</code>'; - } else code += '\n'; - return ''; - } else if (val.substr(0, 4) == ' ') { - code += val.substr(4); - if (!arr[i + 1] || (arr[i + 1].substr(0, 4) != ' ' && arr[i + 1][0] != '\t')) { - var arg = html(code); - code = ''; - return '<code class="blk">' + arg + '</code>'; - } else code += '\n'; - return ''; - } else if ((f = val.match(/^#{1,6} /)) && (f = f[0].length - 1)) { - return '<h' + f + '>' + inlineMarkdown(val.substr(f + 1)) + '</h' + f + '>'; - } else if (val.match(/^[-–—]{12,}$/)) { - return '<hr />'; - } else if (i = val.match(/^cite\[(\d+)\]: /)) { - return '<div><sup class="reference-list">' + i[1] + '</sup> ' + inlineMarkdown(val.substr(i[0].length)) + '</div>'; - } else return '<p>' + inlineMarkdown(val) + '</p>'; - }).join(''); -} - -HTMLTextAreaElement.prototype.mdValidate = function(correct) { - var i = mdWarnings.length; - markdown(this.value); - var preverr = this.previousElementSibling && this.previousElementSibling.classList.contains('md-err') ? this.previousElementSibling : null, - err = mdWarnings[i]; - this.lastErrored = err && correct; - if (err && (correct || preverr || this.value.substr(0, this.selectionEnd || Infinity).match(/\s$/))) { - if (preverr) { - if (preverr.firstChild.nodeValue == err) { - if (this.lastErrored && err && correct) { - this.value = this.value.replace(/([^\\]?)(\\*)([`*_–\-+[(:"])/g, function(m, p1, p2, p3, i) { - if (i && !p1) return m; - return p1 + (p2.length % 2 ? p2 : p2 + '\\') + p3; - }); - return true; - } - return err; - } - preverr.parentNode.removeChild(preverr); - } - var span = document.createElement('span'); - span.classList.add('md-err'); - span.appendChild(document.createTextNode(err)); - this.parentNode.insertBefore(span, this); - } else if (preverr) preverr.parentNode.removeChild(preverr); - return err; -}; - -function mdValidateBody() { - if (document.activeElement.mdValidate && document.activeElement.id != 'code') document.activeElement.mdValidate(); -}; -addEventListener('input', mdValidateBody); - -var noPageOverflow = noPageOverflow || false, - pageOverflowMobile = pageOverflowMobile || false, - footerOff = footerOff || false, - mainContentEl = mainContentEl || false, - mainBottomPad = mainBottomPad || 0; - -function minHeight() { - var footer = document.getElementById('footer').offsetHeight, - sidebar = document.getElementById('sidebar'); - if (innerWidth < 1500 && sidebar) footer += sidebar.offsetHeight + 6; - if (noPageOverflow && !(innerWidth < pageOverflowMobile)) { - mainContentEl.style.minHeight = ''; - mainContentEl.style.height = Math.max(innerHeight - (footerOff ? -4 : footer) - mainContentEl.getBoundingClientRect().top + document.body.getBoundingClientRect().top - 12, noPageOverflow) - mainBottomPad + 'px'; - if (sidebar) sidebar.style.height = ''; - } else { - mainContentEl.style.height = ''; - if (navigator.userAgent.indexOf('Mobile') == -1) mainContentEl.style.minHeight = Math.max(0, innerHeight - (footerOff ? -4 : footer) - mainContentEl.getBoundingClientRect().top + document.body.getBoundingClientRect().top - (innerWidth < 1500 ? 6 : 12) - mainBottomPad) + 'px'; - else mainContentEl.style.minHeight = ''; - if (sidebar) { - if (innerWidth >= 1500) sidebar.style.height = mainContentEl.style.minHeight; - else sidebar.style.height = ''; - } - } -} -addEventListener('load', minHeight); -addEventListener('resize', minHeight); - -function request(uri, callback, params) { - var i = new XMLHttpRequest(); - i.open('POST', uri, true); - i.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - i.send(params); - i.onload = function() { - callback(this.status == 204 ? 'Success' : this.responseText); - }; - return i; -} - -function ago(od) { - var d = Math.round((new Date() - od) / 1000); - if (d < 3600) return Math.round(d / 60) + 'm ago'; - else if (d < 86400) return Math.round(d / 3600) + 'h ago'; - else if (d < 2592000) return Math.round(d / 86400) + 'd ago'; - else { - d = new Date(od); - var y = d.getUTCFullYear(); - return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec' ][d.getUTCMonth()] + ' ' + d.getUTCDate() + (y == new Date().getUTCFullYear() ? '' : ' \'' + y.toString().substr(2)); - } -} -function agot(d) { - var time = document.createElement('time'); - time.textContent = ago(d); - time.setAttribute('datetime', new Date(d).toISOString()); - return time; -} - -function textareaHandler(e) { - if (this.noHandle) return delete this.nHandle; - if (!this.hist) this.hist = [{ - body: '', - start: 0, - end: 0 - }]; - if (!this.hIndex) this.hIndex = 0; - if (e.keyCode == 9) { - if (this.selectionStart == this.selectionEnd) { - if (e.shiftKey) { - var cS = this.selectionEnd - 1; - while (this.value[cS] && this.value[cS] != '\n') { - if (this.value[cS] == '\t') { - this.value = this.value.substr(0, cS) + this.value.substr(++cS); - break; - } else cS--; - } - } else { - var oS = this.selectionEnd; - this.value = this.value.substr(0, oS) + '\t' + this.value.substr(oS); - this.selectionStart = this.selectionEnd = ++oS; - } - } else { - var lines = this.value.split('\n'), - i = 0, - start = 0; - while ((i += lines[start].length) < this.selectionStart - start) start++; - var end = start; - i -= lines[start].length; - while ((i += lines[end].length) < this.selectionEnd - end) end++; - i = --start; - while (++i <= end) { - if (e.shiftKey) lines[i][0] != '\t' || (lines[i] = lines[i].substr(1)); - else lines[i] = '\t' + lines[i]; - } - this.value = lines.join('\n'); - var nS = lines.slice(0, ++start).join('\n').length; - this.selectionStart = (nS += nS ? 1 : 0); - this.selectionEnd = nS + lines.slice(start, ++end).join('\n').length; - } - e.preventDefault(); - } else if (e.keyCode == 90 && e.metaKey && !e.altKey) { - e.preventDefault(); - if (this.hIndex == this.hist.length - 1 && this.hist[this.hIndex].body != this.value) { - this.hist.push({ - body: this.value, - start: this.selectionStart, - end: this.selectionEnd - }); - this.hIndex = this.hist.length - 1; - } - var data = this.hist[e.shiftKey ? ++this.hIndex : --this.hIndex]; - console.log(this.hist, this.hIndex); - if (data) { - this.value = data.body; - this.selectionStart = data.start; - this.selectionEnd = data.end; - } else e.shiftKey ? --this.hIndex : ++this.hIndex - } else { - if (this.hist[this.hIndex].body != this.value) this.hist = this.hist.slice(0, this.hIndex + 1); - if (this.timer) clearTimeout(this.timer); - this.timer = setTimeout(function(e) { - if (e.hIndex != e.hist.length - 1) return; - if (e.hist[e.hIndex].body == e.value) return; - e.hist.push({ - body: e.value, - start: e.selectionStart, - end: e.selectionEnd - }); - e.hIndex = e.hist.length - 1; - }, this.lastKeyCode == e.keyCode || [8, 9, 13].indexOf(e.keyCode) == -1 ? 400 : 0, this); - } - this.lastKeyCode = e.keyCode; -} - -addEventListener('DOMContentLoaded', function() { - mainContentEl = mainContentEl || document.getElementById('content'); - if (navigator.userAgent.indexOf('Trident') != -1 || navigator.userAgent.indexOf('MSIE') != -1) { - var span = document.createElement('span'); - span.appendChild(document.createTextNode('This site does not support Microsoft Internet Explorer due to its lack of compatibility with web specifications.')); - document.getElementById('err').appendChild(span); - document.getElementById('cont').hidden = true; - document.getElementById('cont').style.display = 'none'; - } - var e = document.getElementsByTagName('textarea'), - i = e.length; - while (i--) e[i].addEventListener('keydown', textareaHandler); - setInterval(function() { - var times = document.getElementsByTagName('time'); - for (var i = 0; i < times.length; i++) { - var t = ago(Date.parse(times[i].getAttribute('datetime'))); - if (times[i].textContent != t) times[i].textContent = t; - } - }, 100); - minHeight(); -}); - -document.addEventListener('visibilitychange', function() { - if (!document.hidden) { - request('/api/notif', function(res) { - document.getElementById('nav').children[7].classList.toggle('unread', res); - }); - } -}); - -if (navigator.userAgent.indexOf('Mobile') != -1) addEventListener('touchend', function() {}); //Fixes mobile-safari bug with touch listeners in iframes not firing - \ No newline at end of file diff --git a/http/rainbowtest.html b/http/rainbowtest.html deleted file mode 100644 index 10c8d09..0000000 --- a/http/rainbowtest.html +++ /dev/null @@ -1,722 +0,0 @@ - - - - Syntax Highlighting - - - - -1,5e;;;0;;; -String.prototype.replaceAll = function(find, replace) { - if (typeof find == 'string') return this.split(find).join(replace); - var t = this, i, j; - while (typeof(i = find.shift()) == 'string' && typeof(j = replace.shift()) == 'string') t = t.replaceAll(i || '', j || ''); - return t; -}; -String.prototype.repeat = function(num) { - return new Array(++num).join(this); -}; -Number.prototype.bound = function(l, h) { - return isNaN(h) ? Math.min(this, l) : Math.max(Math.min(this, h), l); -}; -HTMLCollection.prototype.indexOf = NodeList.prototype.indexOf = Array.prototype.indexOf; -HTMLCollection.prototype.forEach = NodeList.prototype.forEach = Array.prototype.forEach; -HTMLElement.prototype.insertAfter = function(newEl, refEl) { - if (refEl.nextSibling) refEl.parentNode.insertBefore(newEl, refEl.nextSibling); - else refEl.parentNode.appendChild(newEl); -}; - -function html(input, replaceQuoteOff) { - if (replaceQuoteOff) return input.toString().replaceAll(['&', '<'], ['&amp;', '&lt;']); - return input.toString().replaceAll(['&', '<', '"'], ['&amp;', '&lt;', '&quot;']); -} - -var mdWarnings = []; -function warning(message) { - console.log(message); - mdWarnings.push(message); -} -function spanMarkdown(input) { - input = html(input); - while (input.match(/\^([\w\^]+)/)) input = input.replace(/\^([\w\^]+)/, '<sup>$1</sup>'); - return input - .replaceAll('\u0001', '^') - .replace(/\[(.+?)\|(.+?)\]/g, '<abbr title="$2">$1</abbr>') - .replaceAll('\u0002', '[') - .replace(/\[\[(\d+)\](.*?)\]/g, '<sup class="reference" title="$2">[$1]</sup>') - .replace(/!\[([^\]]+)]\(https?:\/\/([^\s("\\]+\.[^\s"\\]+)\)/g, '<img alt="$1" src="https://$2" />') - .replace(/^https?:\/\/([^\s("\\]+\.[^\s"\\]+\.(svg|png|tiff|jpg|jpeg)(\?[^\s"\\\/]*)?)/g, '<img src="https://$1" />') - .replace(/\[([^\]]+)]\((https?:\/\/[^\s("\\]+\.[^\s"\\]+)\)/g, '$1'.link('$2')) - .replace(/([^;["\\])https?:\/\/([^\s("\\]+\.[^\s"\\]+\.(svg|png|tiff|jpg|jpeg)(\?[^\s"\\\/]*)?)/g, '$1<img src="https://$2" />') - .replace(/([^;["\\])(https?:\/\/([^\s("\\]+\.[^\s"\\]+))/g, '$1' + '$3'.link('$2')) - .replace(/^(https?:\/\/([^\s("\\]+\.[^\s"\\]+))/g, '$2'.link('$1')); -} -function inlineMarkdown(input) { - var output = '', - span = '', - current = [], - tags = { - '`': 'code', - '``': 'samp', - '*': 'em', - '**': 'strong', - '_': 'i', - '–––': 's', - '+++': 'ins', - '---': 'del', - '[c]': 'cite', - '[m]': 'mark', - '[u]': 'u', - '[v]': 'var', - '::': 'kbd', - '"': 'q' - }, - stags = { - sup: { - start: '^(', - end: ')^' - }, - sub: { - start: 'v(', - end: ')v' - }, - small: { - start: '[sm]', - end: '[/sm]' - } - }; - outer: for (var i = 0; i < input.length; i++) { - if (['code', 'samp'].indexOf(current[current.length - 1]) == -1) { - if (input[i] == '\\') span += input[++i].replace('^', '\u0001').replace('[', '\u0002'); - else { - for (var l = 3; l > 0; l--) { - if (tags[input.substr(i, l)]) { - output += spanMarkdown(span); - span = ''; - if (current[current.length - 1] == tags[input.substr(i, l)]) output += '</' + current.pop() + '>'; - else { - if (current.indexOf(tags[input.substr(i, l)]) != -1) warning('Illegal nesting of "' + input.substr(i, l) + '"'); - output += '<' + tags[input.substr(i, l)] + '>'; - current.push(tags[input.substr(i, l)]); - } - i += l - 1; - continue outer; - } - } - for (var j in stags) { - for (var l = 5; l > 0; l--) { - if (stags[j].start == input.substr(i, l)) { - output += spanMarkdown(span) + '<' + j + '>'; - span = ''; - current.push(stags[j].end); - i += l - 1; - continue outer; - } else if (stags[j].end == input.substr(i, l)) { - if (current[current.length - 1] == stags[j].end) { - output += spanMarkdown(span) + '</' + j + '>'; - span = ''; - current.pop(); - i += l - 1; - continue outer; - } else warning('Illegal close tag "' + stags[j].end + '" found'); - } - } - } - span += input[i]; - } - } else if (current[current.length - 1] == 'code' && input[i] == '`') { - current.pop(); - output += '</code>'; - } else if (current[current.length - 1] == 'samp' && input.substr(i, 2) == '``') { - current.pop(); - output += '</samp>'; - i++; - } else output += html(input[i]); - } - output += spanMarkdown(span); - if (current.length) warning('Unclosed tags. <' + current.join('>, <') + '>'); - for (var i = current.length - 1; i >= 0; i--) output += '</' + current[i] + '>'; - return output; -} -function markdown(input) { - if (input.indexOf('\n') == -1 && input.substr(0, 2) != '> ' && input.substr(0, 3) != '>! ' && input.substr(0, 2) != '- ' && input.substr(0, 2) != '* ' && input.substr(0, 4) != ' ' && input[0] != '\t' && !input.match(/^((\d+|[A-z])[.)]|#{1,6}|cite\[\d+\]:) /) && !input.match(/^[-–—]{12,}$/)) return inlineMarkdown(input); - var blockquote = '', - ul = '', - ol = '', - li = '', - code = '', - i; - return input.split('\n').map(function(val, i, arr) { - if (!val) return ''; - var f; - if (val.substr(0, 2) == '> ') { - val = val.substr(2); - if (arr[i + 1] && arr[i + 1].substr(0, 2) == '> ') { - blockquote += val + '\n'; - return ''; - } else { - var arg = blockquote + val; - blockquote = ''; - return '<blockquote>' + markdown(arg) + '</blockquote>'; - } - } else if (val.substr(0, 3) == '>! ') { - val = val.substr(3); - if (arr[i + 1] && arr[i + 1].substr(0, 3) == '>! ') { - blockquote += val + '\n'; - return ''; - } else { - var arg = blockquote + val; - blockquote = ''; - return '<blockquote class="spoiler">' + markdown(arg) + '</blockquote>'; - } - } else if (val.substr(0, 2) == '- ' || val.substr(0, 2) == '* ') { - if (!ul) ul = '<ul>'; - val = val.substr(2); - if (li) { - ul += '<li>' + markdown(li) + '</li>'; - li = ''; - } - if (arr[i + 1] && (arr[i + 1].substr(0, 2) == '- ' || arr[i + 1] && arr[i + 1].substr(0, 2) == '* ')) { - ul += '<li>' + inlineMarkdown(val) + '</li>'; - return ''; - } else if (arr[i + 1] && (arr[i + 1][0] == '\t' || arr[i + 1] && arr[i + 1].substr(0, 4) == ' ')) { - li += val + '\n'; - return ''; - } else { - var arg = ul + '<li>' + markdown(val) + '</li>'; - ul = ''; - return arg + '</ul>'; - } - } else if (f = val.match(/^(\d+|[A-z])[.)] /)) { - if (!ol) ol = '<ol>'; - val = val.substr(f[0].length); - if (li) { - ol += '<li>' + markdown(li) + '</li>'; - li = ''; - } - if (arr[i + 1] && arr[i + 1].match(/^(\d+|[A-z])[.)] /)) { - ol += '<li>' + inlineMarkdown(val) + '</li>'; - return ''; - } else if (arr[i + 1] && (arr[i + 1][0] == '\t' || arr[i + 1] && arr[i + 1].substr(0, 4) == ' ')) { - li += val + '\n'; - return ''; - } else { - var arg = ol + '<li>' + inlineMarkdown(val) + '</li>'; - ol = ''; - return arg + '</ol>'; - } - } else if (li && val[0] == '\t') { - li += val.substr(1) + '\n'; - if (ul && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && arr[i + 1].substr(2) != '- ' && arr[i + 1].substr(2) != '* '))) { - var arg = ul + '<li>' + markdown(li) + '</li>'; - li = ''; - return arg + '</ul>'; - } else if (ol && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && !arr[i + 1].match(/^(\d+|[A-z])[.)] /)))) { - var arg = ol + '<li>' + markdown(li) + '</li>'; - li = ''; - return arg + '</ol>'; - } - return ''; - } else if (li && val.substr(0, 4) == ' ') { - li += val.substr(4) + '\n'; - if (ul && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && arr[i + 1].substr(2) != '- ' && arr[i + 1].substr(2) != '* '))) { - var arg = ul + '<li>' + markdown(li) + '</li>'; - li = ''; - return arg + '</ul>'; - } else if (ol && (!arr[i + 1] || (arr[i + 1][0] != '\t' && arr[i + 1].substr(0, 4) != ' ' && !arr[i + 1].match(/^((\d+|[A-z])|[A-z])[.)] /)))) { - var arg = ol + '<li>' + markdown(li) + '</li>'; - li = ''; - return arg + '</ol>'; - } - return ''; - } else if (val[0] == '\t') { - code += val.substr(1); - if (!arr[i + 1] || (arr[i + 1].substr(0, 4) != ' ' && arr[i + 1][0] != '\t')) { - var arg = html(code); - code = ''; - return '<code class="blk">' + arg + '</code>'; - } else code += '\n'; - return ''; - } else if (val.substr(0, 4) == ' ') { - code += val.substr(4); - if (!arr[i + 1] || (arr[i + 1].substr(0, 4) != ' ' && arr[i + 1][0] != '\t')) { - var arg = html(code); - code = ''; - return '<code class="blk">' + arg + '</code>'; - } else code += '\n'; - return ''; - } else if ((f = val.match(/^#{1,6} /)) && (f = f[0].length - 1)) { - return '<h' + f + '>' + inlineMarkdown(val.substr(f + 1)) + '</h' + f + '>'; - } else if (val.match(/^[-–—]{12,}$/)) { - return '<hr />'; - } else if (i = val.match(/^cite\[(\d+)\]: /)) { - return '<div><sup class="reference-list">' + i[1] + '</sup> ' + inlineMarkdown(val.substr(i[0].length)) + '</div>'; - } else return '<p>' + inlineMarkdown(val) + '</p>'; - }).join(''); -} - -HTMLTextAreaElement.prototype.mdValidate = function(correct) { - var i = mdWarnings.length; - markdown(this.value); - var preverr = this.previousElementSibling && this.previousElementSibling.classList.contains('md-err') ? this.previousElementSibling : null, - err = mdWarnings[i]; - this.lastErrored = err && correct; - if (err && (correct || preverr || this.value.substr(0, this.selectionEnd || Infinity).match(/\s$/))) { - if (preverr) { - if (preverr.firstChild.nodeValue == err) { - if (this.lastErrored && err && correct) { - this.value = this.value.replace(/([^\\]?)(\\*)([`*_–\-+[(:"])/g, function(m, p1, p2, p3, i) { - if (i && !p1) return m; - return p1 + (p2.length % 2 ? p2 : p2 + '\\') + p3; - }); - return true; - } - return err; - } - preverr.parentNode.removeChild(preverr); - } - var span = document.createElement('span'); - span.classList.add('md-err'); - span.appendChild(document.createTextNode(err)); - this.parentNode.insertBefore(span, this); - } else if (preverr) preverr.parentNode.removeChild(preverr); - return err; -}; - -function mdValidateBody() { - if (document.activeElement.mdValidate && document.activeElement.id != 'code') document.activeElement.mdValidate(); -}; -addEventListener('input', mdValidateBody); - -var noPageOverflow = noPageOverflow || false, - pageOverflowMobile = pageOverflowMobile || false, - footerOff = footerOff || false, - mainContentEl = mainContentEl || false, - mainBottomPad = mainBottomPad || 0; - -function minHeight() { - var footer = document.getElementById('footer').offsetHeight, - sidebar = document.getElementById('sidebar'); - if (innerWidth < 1500 && sidebar) footer += sidebar.offsetHeight + 6; - if (noPageOverflow && !(innerWidth < pageOverflowMobile)) { - mainContentEl.style.minHeight = ''; - mainContentEl.style.height = Math.max(innerHeight - (footerOff ? -4 : footer) - mainContentEl.getBoundingClientRect().top + document.body.getBoundingClientRect().top - 12, noPageOverflow) - mainBottomPad + 'px'; - if (sidebar) sidebar.style.height = ''; - } else { - mainContentEl.style.height = ''; - if (navigator.userAgent.indexOf('Mobile') == -1) mainContentEl.style.minHeight = Math.max(0, innerHeight - (footerOff ? -4 : footer) - mainContentEl.getBoundingClientRect().top + document.body.getBoundingClientRect().top - (innerWidth < 1500 ? 6 : 12) - mainBottomPad) + 'px'; - else mainContentEl.style.minHeight = ''; - if (sidebar) { - if (innerWidth >= 1500) sidebar.style.height = mainContentEl.style.minHeight; - else sidebar.style.height = ''; - } - } -} -addEventListener('load', minHeight); -addEventListener('resize', minHeight); - -function request(uri, callback, params) { - var i = new XMLHttpRequest(); - i.open('POST', uri, true); - i.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - i.send(params); - i.onload = function() { - callback(this.status == 204 ? 'Success' : this.responseText); - }; - return i; -} - -function ago(od) { - var d = Math.round((new Date() - od) / 1000); - if (d < 3600) return Math.round(d / 60) + 'm ago'; - else if (d < 86400) return Math.round(d / 3600) + 'h ago'; - else if (d < 2592000) return Math.round(d / 86400) + 'd ago'; - else { - d = new Date(od); - var y = d.getUTCFullYear(); - return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec' ][d.getUTCMonth()] + ' ' + d.getUTCDate() + (y == new Date().getUTCFullYear() ? '' : ' \'' + y.toString().substr(2)); - } -} -function agot(d) { - var time = document.createElement('time'); - time.textContent = ago(d); - time.setAttribute('datetime', new Date(d).toISOString()); - return time; -} - -function textareaHandler(e) { - if (this.noHandle) return delete this.nHandle; - if (!this.hist) this.hist = [{ - body: '', - start: 0, - end: 0 - }]; - if (!this.hIndex) this.hIndex = 0; - if (e.keyCode == 9) { - if (this.selectionStart == this.selectionEnd) { - if (e.shiftKey) { - var cS = this.selectionEnd - 1; - while (this.value[cS] && this.value[cS] != '\n') { - if (this.value[cS] == '\t') { - this.value = this.value.substr(0, cS) + this.value.substr(++cS); - break; - } else cS--; - } - } else { - var oS = this.selectionEnd; - this.value = this.value.substr(0, oS) + '\t' + this.value.substr(oS); - this.selectionStart = this.selectionEnd = ++oS; - } - } else { - var lines = this.value.split('\n'), - i = 0, - start = 0; - while ((i += lines[start].length) < this.selectionStart - start) start++; - var end = start; - i -= lines[start].length; - while ((i += lines[end].length) < this.selectionEnd - end) end++; - i = --start; - while (++i <= end) { - if (e.shiftKey) lines[i][0] != '\t' || (lines[i] = lines[i].substr(1)); - else lines[i] = '\t' + lines[i]; - } - this.value = lines.join('\n'); - var nS = lines.slice(0, ++start).join('\n').length; - this.selectionStart = (nS += nS ? 1 : 0); - this.selectionEnd = nS + lines.slice(start, ++end).join('\n').length; - } - e.preventDefault(); - } else if (e.keyCode == 90 && e.metaKey && !e.altKey) { - e.preventDefault(); - if (this.hIndex == this.hist.length - 1 && this.hist[this.hIndex].body != this.value) { - this.hist.push({ - body: this.value, - start: this.selectionStart, - end: this.selectionEnd - }); - this.hIndex = this.hist.length - 1; - } - var data = this.hist[e.shiftKey ? ++this.hIndex : --this.hIndex]; - console.log(this.hist, this.hIndex); - if (data) { - this.value = data.body; - this.selectionStart = data.start; - this.selectionEnd = data.end; - } else e.shiftKey ? --this.hIndex : ++this.hIndex - } else { - if (this.hist[this.hIndex].body != this.value) this.hist = this.hist.slice(0, this.hIndex + 1); - if (this.timer) clearTimeout(this.timer); - this.timer = setTimeout(function(e) { - if (e.hIndex != e.hist.length - 1) return; - if (e.hist[e.hIndex].body == e.value) return; - e.hist.push({ - body: e.value, - start: e.selectionStart, - end: e.selectionEnd - }); - e.hIndex = e.hist.length - 1; - }, this.lastKeyCode == e.keyCode || [8, 9, 13].indexOf(e.keyCode) == -1 ? 400 : 0, this); - } - this.lastKeyCode = e.keyCode; -} - -addEventListener('DOMContentLoaded', function() { - mainContentEl = mainContentEl || document.getElementById('content'); - if (navigator.userAgent.indexOf('Trident') != -1 || navigator.userAgent.indexOf('MSIE') != -1) { - var span = document.createElement('span'); - span.appendChild(document.createTextNode('This site does not support Microsoft Internet Explorer due to its lack of compatibility with web specifications.')); - document.getElementById('err').appendChild(span); - document.getElementById('cont').hidden = true; - document.getElementById('cont').style.display = 'none'; - } - var e = document.getElementsByTagName('textarea'), - i = e.length; - while (i--) e[i].addEventListener('keydown', textareaHandler); - setInterval(function() { - var times = document.getElementsByTagName('time'); - for (var i = 0; i < times.length; i++) { - var t = ago(Date.parse(times[i].getAttribute('datetime'))); - if (times[i].textContent != t) times[i].textContent = t; - } - }, 100); - minHeight(); -}); - -document.addEventListener('visibilitychange', function() { - if (!document.hidden) { - request('/api/notif', function(res) { - document.getElementById('nav').children[7].classList.toggle('unread', res); - }); - } -}); - -if (navigator.userAgent.indexOf('Mobile') != -1) addEventListener('touchend', function() {}); //Fixes mobile-safari bug with touch listeners in iframes not firing - - \ No newline at end of file From 0a735eb18641bcdd6657474159c6198dc8ceca39 Mon Sep 17 00:00:00 2001 From: bjb568 Date: Wed, 24 Jun 2015 22:11:02 -0400 Subject: [PATCH 7/7] Show highlight warnings --- html/dev/canvas.html | 4 ++++ http/dev/runcanvas.js | 49 ++++++++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/html/dev/canvas.html b/html/dev/canvas.html index 23ba558..cc45803 100644 --- a/html/dev/canvas.html +++ b/html/dev/canvas.html @@ -249,6 +249,10 @@

$title