diff --git a/www/demo.css b/www/demo.css
new file mode 100644
index 0000000000..fed6e03fd4
--- /dev/null
+++ b/www/demo.css
@@ -0,0 +1,153 @@
+html, body {
+ margin: 0;
+ padding: 0;
+ font-family: Helvetica, Arial, Verdana, sans-serif;
+ background-color: #DDF;
+ height: 100%;
+}
+
+textarea {
+ font-family: monospace;
+}
+
+#header {
+ margin: 0;
+ padding: 0.4em 0 0 0;
+ text-align: center;
+ color: #002;
+}
+
+#header h1 {
+ font-size: 2em;
+}
+
+#header * {
+ margin: 0;
+ padding: 0;
+ line-height: 1em;
+ font-weight: 100;
+}
+
+#header a {
+ color: #005;
+ position: relative;
+ z-index: 20;
+}
+
+#bothContainers {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ margin-top: 2.4em;
+ width: 100%;
+}
+
+#leftContainer, #rightContainer {
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ width: 48.5%;
+ top: 0;
+ bottom: 0;
+}
+
+#leftContainer {
+ float: left;
+ left: 1%;
+}
+
+#rightContainer {
+ float: right;
+ right: 1%;
+}
+
+#rightContainer > * {
+ float: right;
+}
+
+.label {
+ margin: 0;
+ padding: 0;
+ position: relative;
+ width: 100%;
+ display: block;
+}
+
+.label * {
+ position: relative;
+ font-weight: 900;
+}
+
+.label span {
+ color: #444;
+}
+
+#outputType {
+ display: block;
+ margin-left: auto;
+ font-weight: 900;
+ font-family: Arial, Verdana, sans-serif;
+ background-color: #dacccc;
+ color: #444;
+ border: 1px solid #999;
+}
+
+.pane {
+ margin: 1.6em 0em 0.2em;
+ padding: 0.6em;
+ background-color: #eee;
+ display: block;
+ border: 1px solid #000;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ position: absolute;
+ overflow: auto;
+}
+
+#previewPane {
+ background-color: #f3eeee;
+}
+
+#outputPane {
+ background-color: #6c6666;
+ color: #fff;
+ display: none;
+}
+
+#syntaxPane {
+ background-color: #e6dede;
+ background-color: #f7ecec;
+ display: none;
+}
+
+#inputPane {
+ background-color: #fff;
+}
+
+#previewPane {
+ padding: 0;
+}
+
+#previewPane > * {
+ margin-left: 4px;
+ margin-right: 4px;
+}
+
+#previewPane > blockquote {
+ margin-left: 3em;
+}
+
+#previewPane > :first-child {
+ margin-top: 4px; /* pane padding */
+}
+
+#previewPane * {
+ line-height: 1.4em;
+}
+
+#previewPane code {
+ font-size: 1.3em;
+}
+
diff --git a/www/demo.html b/www/demo.html
new file mode 100644
index 0000000000..4181e07778
--- /dev/null
+++ b/www/demo.html
@@ -0,0 +1,244 @@
+
+
+ Marked Demo Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/www/demo.js b/www/demo.js
new file mode 100644
index 0000000000..36668a4d7f
--- /dev/null
+++ b/www/demo.js
@@ -0,0 +1,105 @@
+$(function () {
+ var $inputElem = $('#input');
+ var $outputTypeElem = $('#outputType');
+ var $previewElem = $('#preview');
+ var $htmlElem = $('#html');
+ var $lexerElem = $('#lexer');
+ var $syntaxElem = $('#syntax');
+ var inputDirty = true;
+ var $activeElem = null;
+
+ if (top.document.location.href.match(/\?blank=1$/)) {
+ $inputElem.val('');
+ }
+
+ $outputTypeElem.change(function () {
+ $('#rightContainer .pane').hide();
+ $activeElem = $('#' + $outputTypeElem.val()).show();
+ }).change();
+
+ var noticeChange = function () {
+ inputDirty = true;
+ };
+ $inputElem.
+ change(noticeChange).
+ keyup(noticeChange).
+ keypress(noticeChange).
+ keydown(noticeChange);
+
+ var jsonString = function (input) {
+ var output = (input + '').
+ replace(/\n/g, '\\n').
+ replace(/\r/g, '\\r').
+ replace(/\t/g, '\\t').
+ replace(/\f/g, '\\f').
+ replace(/[\\"']/g, '\\$&').
+ replace(/\u0000/g, '\\0');
+ return '"' + output + '"';
+ };
+
+ var getScrollSize = function () {
+ var e = $activeElem[0];
+
+ return e.scrollHeight - e.clientHeight;
+ };
+ var getScrollPercent = function () {
+ var size = getScrollSize();
+
+ if (size <= 0) {
+ return 1;
+ }
+
+ return $activeElem.scrollTop() / size;
+ };
+ var setScrollPercent = function (percent) {
+ $activeElem.scrollTop(percent * getScrollSize());
+ };
+
+ var delayTime = 1;
+ var checkForChanges = function () {
+ if (inputDirty) {
+ inputDirty = false;
+ var startTime = new Date();
+
+ // Save scroll position
+ var scrollPercent = getScrollPercent();
+
+ // Convert
+ var markdown = $inputElem.val();
+ var lexed = marked.lexer(markdown);
+
+ // Grab lexed output and convert to a string before the parser
+ // destroys the data
+ var lexedList = [];
+
+ for (var i = 0; i < lexed.length; i ++) {
+ var lexedLine = [];
+ for (var j in lexed[i]) {
+ lexedLine.push(j + ":" + jsonString(lexed[i][j]));
+ }
+ lexedList.push("{" + lexedLine.join(", ") + "}");
+ }
+
+ var parsed = marked.parser(lexed);
+
+ // Assign
+ $previewElem.html(parsed);
+ $htmlElem.val(parsed);
+ $lexerElem.val(lexedList.join("\n"));
+
+ // Set the scroll percent
+ setScrollPercent(scrollPercent);
+
+ var endTime = new Date();
+ delayTime = endTime - startTime;
+ if (delayTime < 50) {
+ delayTime = 50;
+ } else if (delayTime > 500) {
+ delayTime = 1000;
+ }
+ }
+ window.setTimeout(checkForChanges, delayTime);
+ };
+ checkForChanges();
+ setScrollPercent(0);
+});