diff --git a/exec/load/markdown.js b/exec/load/markdown.js
index 389c22dc6bf342cf5de90148971c0d13cb338306..3d6ee9b2bb1800543246c990488b173e8dd51ad8 100644
--- a/exec/load/markdown.js
+++ b/exec/load/markdown.js
@@ -1,30 +1,23 @@
 /*
- * Synchronet-flavoured Markdown
- * # Heading
- * Lists end on first line not starting with a list prefix
- * * Unordered list item\r\n
- *  * Unordered list sub-item\r\n
- *   * Unordered list sub-sub-item\r\n ...
- * 1. Numbered list item\r\n ...
- *  1. Numbered list sub-item\r\n ...
- *  2. Another numbered list sub-item\r\n ...
- *   1. Numbered list sub-sub-item\r\n ...
- * 2. Another numbered list item
-  * *Emphasis* (high colour)
- * _ctext_ colour (where c is a CTRL-A colour)
+ * Partial DokuWiki markdown parser/renderer
+ * == h5 ==
+ * ==== h3 ====
+ * ====== h1 ======
+ * [[http://some.web.site/|some link text]]
+ * To-do: image links
+ * {{http://some.web.site/image.png|some alt text}}
+ * ** bold **
+ * // italic //
+ * __ underline __
+ * To-do: monospace '' text
  * > blockquote
- * [Link text](url) a link
- * ![Alt text](url) an image
- * --- A horizontal rule
- * this|is|a|table|header
- * this|is|a|table|row
+ * To-do: nested blockquote in HTML
+ * * Unordered lists
+ *  * With sub-items
+ * - Ordered lists
+ *  - With sub-items
+ *
  */
-
- /* To do:
-  * configurable tags instead of <b> and <i>
-  * code blocks / syntax highlighting
- */
-
 load('sbbsdefs.js');
 
 if (typeof Frame == 'undefined') Frame = false;
@@ -43,6 +36,8 @@ function Markdown(target, settings) {
   const config = {
     console : {
       bold_style : '\1h',
+      italic_style : '\1r',
+      underline_style : '\1g',
       list_indent : '\t',
       heading_underline : true,
       heading_style : '\1h',
@@ -130,50 +125,53 @@ Markdown.prototype.html_tag_format = function (tag, attributes) {
   return ret + '>';
 }
 
-Markdown.prototype.colorize_console = function (str) {
-  const self = this;
-  str = str.replace(/_([krgybmcw0-7])/ig, function (m, c1, c2) {
-    return '\1+\1' + c1;
-  });
-  return str.replace(/_/g, '\1-');
-}
-
 Markdown.prototype.render_text_console = function (text) {
   const self = this;
-  var ret = text.replace(/\*([^\*]+)\*/g, function (m, c) {
+  var ret = text.replace(/\*\*([^\*]+)\*\*/g, function (m, c) {
     return '\1+' + self.config.console.bold_style + c + '\1-';
   });
-  ret = ret.replace(/!\[([^\]]+)\]\(([^\)]+)\)/g, function (m, c1, c2) {
-    self.state.images.push({ text : c1, link : c2 });
-    return '\1+' + self.config.console.image_style + c1 + ' [' + self.state.images.length + ']\1-';
+  ret = ret.replace(/\/\/([^\/]+)\/\//g, function (m, c) {
+    return '\1+' + self.config.console.italic_style + c + '\1-';
   });
-  ret = ret.replace(/\[([^\]]+)\]\(([^\)]+)\)/g, function (m, c1, c2) {
-    self.state.links.push({ text : c1, link : c2 });
-    return '\1+' + self.config.console.link_style + c1 + ' [' + self.state.links.length + ']\1-';
+  ret = ret.replace(/__([^_]+)__/g, function (m, c) {
+    return '\1+' + self.config.console.underline_style + c + '\1-';
   });
-  return this.colorize_console(ret);
-}
-
-Markdown.prototype.italicize = function (str) {
-  const self = this;
-  str = str.replace(/_([krgybmcw0-7])(.+)/ig, function (m, c1, c2) {
-    return '<i>' + self.italicize(c2);
+  ret = ret.replace(/\{\{(.+)\}\}/g, function (m, c) {
+    c = c.split('|');
+    self.state.images.push({ text : (c[1] || c[0]), link : c[0] });
+    return '\1+' + self.config.console.image_style + (c[1] || c[0]) + ' [' + self.state.images.length + ']\1-';
+  });
+  ret = ret.replace(/\[\[([^\]]+)\]\]/g, function (m, c) {
+    c = c.split('|');
+    self.state.links.push({ text : c[1] || c[0], link : c[0] });
+    return '\1+' + self.config.console.link_style + (c[1] || c[0]) + ' [' + self.state.links.length + ']\1-';
   });
-  return str.replace(/_/g, '</i>');
+  return ret;
 }
 
 Markdown.prototype.render_text_html = function (text) {
   const self = this;
-  var ret = text.replace(/\*([^\*]+)\*/g, function (m, c) {
+  var ret = text.replace(/\\1.(.+)\\1./g, function (m, c) {
+    return c;
+  });
+  ret = ret.replace(/\*\*([^\*]+)\*\*/g, function (m, c) {
     return '<b>' + c + '</b>';
   });
-  ret = ret.replace(/!\[([^\]]+)\]\(([^\)]+)\)/g, function (m, c1, c2) {
-    return self.html_tag_format('img', { alt : c1, src : c2 });
+  ret = ret.replace(/\/\/([^\/]+)\/\//g, function (m, c) {
+    return '<i>' + c + '</i>';
+  });
+  ret = ret.replace(/__([^_]+)__/g, function (m, c) {
+    return '<span style="text-decoration:underline;">' + c + '</span>';
+  });
+  ret = ret.replace(/\{\{(.+)\}\}/g, function (m, c) {
+    c = c.split('|');
+    return self.html_tag_format('img', { alt : (c[1] || c[0]), src : c[0] });
   });
-  ret = ret.replace(/\[([^\]]+)\]\(([^\)]+)\)/g, function (m, c1, c2) {
-    return self.html_tag_format('a', { href : c2 }) + c1 + '</a>';
+  ret = ret.replace(/\[\[([^\]]+)\]\]/g, function (m, c) {
+    c = c.split('|');
+    return self.html_tag_format('a', { href : c[0] }) + (c[1] || c[0]) + '</a>';
   });
-  return this.italicize(ret);
+  return ret;
 }
 
 Markdown.prototype.render_table = function () {
@@ -252,12 +250,13 @@ Markdown.prototype.render_table = function () {
 Markdown.prototype.render_line_console = function (line) {
 
   var match;
-  var ret = '';
   const self = this;
+  var ret = this.render_text_console(line);
 
   // Ordered and unordered lists
-  match = line.match(/^(\s*)(\*|\d\.)\s+(.+)$/);
+  match = ret.match(/^(\s*)(\*|-)\s+(.+)$/);
   if (match !== null) {
+    ret = ret.replace(match[0], '');
     if (this.state.table.length) ret += this.render_table();
     var lt = (match[2] == '*' ? 'ul' : 'ol');
     if (match[1].length > this.state.list_level) {
@@ -271,9 +270,9 @@ Markdown.prototype.render_line_console = function (line) {
     if (lt == 'ul') {
       ret += match[2];
     } else {
-      ret += match[2].substring(0, match[2].length - 1) + ')';
+      ret += (this.state.list_level + 1) + '.'; // This is busted; maintain something in list_stack
     }
-    ret += ' ' + this.render_text_console(match[3]) + '\r\n';
+    ret += ' ' + match[3] + '\r\n';
     return ret;
   }
   if (this.state.list_level) {
@@ -281,22 +280,21 @@ Markdown.prototype.render_line_console = function (line) {
     this.state.list_level = 0;
   }
 
-  row = line.split('|');
+  row = ret.split('|');
   if (row.length > 1) {
-    this.state.table.push(row.map(function (e) {
-      return self.render_text_console(e);
-    }));
+    this.state.table.push(row);
     return;
   } else if (this.state.table.length) {
     ret += this.render_table();
   }
 
   // Heading
-  match = line.match(/^(#+)\s+(.*)$/);
+  match = ret.match(/^(==+)\s(.+)\s==+$/);
   if (match !== null) {
+    ret = ret.replace(match[0], '');
     ret += '\1+';
     ret += this.config.console.heading_style;
-    ret += this.render_text_console(match[2]);
+    ret += match[2];
     if (this.config.console.heading_underline) {
       ret += '\r\n';
       for (var n = 0; n < match[2].length; n++) {
@@ -308,36 +306,37 @@ Markdown.prototype.render_line_console = function (line) {
   }
 
   // Blockquote
-  match = line.match(/^\s*>\s(.+)$/);
+  match = ret.match(/^\s*>\s(.+)$/);
   if (match !== null) {
-    return ret + quote_msg(
-      word_wrap(this.render_text_console(match[1])), this.columns - 1
+    return ret.replace(
+      match[0], quote_msg(word_wrap(match[1]), this.columns - 1)
     ) + '\r\n';
   }
 
   // Horizontal Rule
-  match = line.match(/^---+$/);
+  match = ret.match(/^----+$/);
   if (match !== null) {
     var s = '';
     while (s.length < this.columns - 1) {
       s += '-';
     }
-    return ret + s + '\r\n';
+    return ret.replace(match[0], s) + '\r\n';
   }
 
-  return ret + this.render_text_console(line) + '\r\n';
+  return ret + '\r\n';
 
 }
 
 Markdown.prototype.render_line_html = function (line) {
 
   var match;
-  var ret = '';
   const self = this;
+  var ret = this.render_text_html(line);
 
   // Blockquote
-  match = line.match(/^\s*>\s(.+)$/);
+  match = ret.match(/^\s*>\s(.+)$/);
   if (match !== null) {
+    ret = ret.replace(match[0], '');
     if (this.state.table.length) ret += this.render_table();
     if (!this.state.blockquote) {
       ret += this.html_tag_format('blockquote');
@@ -350,8 +349,9 @@ Markdown.prototype.render_line_html = function (line) {
   }
 
   // Ordered and unordered lists
-  match = line.match(/^(\s*)(\*|\d\.)\s+(.+)$/);
+  match = ret.match(/^(\s*)(\*|-)\s+(.+)$/);
   if (match !== null) {
+    ret = ret.replace(match[0], '');
     if (this.state.table.length) ret += this.render_table();
     var lt = (match[2] == '*' ? 'ul' : 'ol');
     if (!match[1].length) {
@@ -368,7 +368,7 @@ Markdown.prototype.render_line_html = function (line) {
       ret += this.html_tag_format(lt);
     }
     ret += this.html_tag_format('li');
-    ret += this.render_text_html(match[3]);
+    ret += match[3];
     ret += '</li>';
     return ret;
   }
@@ -376,33 +376,32 @@ Markdown.prototype.render_line_html = function (line) {
     ret += '</' + this.state.list_stack.pop() + '>';
   }
 
-  row = line.split('|');
+  row = ret.split('|');
   if (row.length > 1) {
-    this.state.table.push(row.map(function (e) {
-      return self.render_text_html(e);
-    }));
+    this.state.table.push(row);
     return;
   } else if (this.state.table.length) {
     ret += this.render_table();
   }
 
   // Heading
-  match = line.match(/^#+\s+(.*)$/);
+  match = ret.match(/^(==+)\s(.+)\s==+$/);
   if (match !== null) {
-    var lvl = Math.min(match[0].split(' ')[0].length, 5);
+    ret = ret.replace(match[0], '');
+    var lvl = 6 - Math.min(match[1].split(' ')[0].length, 5);
     ret += '<h' + lvl + '>';
-    ret += this.render_text_html(match[1]);
+    ret += match[2];
     ret += '</h' + lvl + '>';
     return ret;
   }
 
   // Horizontal Rule
-  match = line.match(/^---+$/);
+  match = ret.match(/^----+$/);
   if (match !== null) {
-    return ret + this.html_tag_format('hr');
+    return ret.replace(match[0], '') + this.html_tag_format('hr');
   }
 
-  return ret + this.render_text_html(line) + '<br>';
+  return ret + '<br>';
 
 }