Skip to content
Snippets Groups Projects
Commit 3e80028a authored by echicken's avatar echicken
Browse files

Support some DokuWiki stuff (headings, links, media, bold, italic, underline, lists)

Some things broken for now (lists, HTML blockquote need some work).
Tables will need a bunch of work.
Need to add monospace text for HTML.
Code blocks & text conversions still a to-do.
HTML sub/sup/del will need to be removed on the console side.
Footnote support needs to be added.
Wiki-specific stuff ... eh.
parent 48f6ff16
No related branches found
No related tags found
No related merge requests found
/* /*
* Synchronet-flavoured Markdown * Partial DokuWiki markdown parser/renderer
* # Heading * == h5 ==
* Lists end on first line not starting with a list prefix * ==== h3 ====
* * Unordered list item\r\n * ====== h1 ======
* * Unordered list sub-item\r\n * [[http://some.web.site/|some link text]]
* * Unordered list sub-sub-item\r\n ... * To-do: image links
* 1. Numbered list item\r\n ... * {{http://some.web.site/image.png|some alt text}}
* 1. Numbered list sub-item\r\n ... * ** bold **
* 2. Another numbered list sub-item\r\n ... * // italic //
* 1. Numbered list sub-sub-item\r\n ... * __ underline __
* 2. Another numbered list item * To-do: monospace '' text
* *Emphasis* (high colour)
* _ctext_ colour (where c is a CTRL-A colour)
* > blockquote * > blockquote
* [Link text](url) a link * To-do: nested blockquote in HTML
* ![Alt text](url) an image * * Unordered lists
* --- A horizontal rule * * With sub-items
* this|is|a|table|header * - Ordered lists
* this|is|a|table|row * - With sub-items
*
*/ */
/* To do:
* configurable tags instead of <b> and <i>
* code blocks / syntax highlighting
*/
load('sbbsdefs.js'); load('sbbsdefs.js');
if (typeof Frame == 'undefined') Frame = false; if (typeof Frame == 'undefined') Frame = false;
...@@ -43,6 +36,8 @@ function Markdown(target, settings) { ...@@ -43,6 +36,8 @@ function Markdown(target, settings) {
const config = { const config = {
console : { console : {
bold_style : '\1h', bold_style : '\1h',
italic_style : '\1r',
underline_style : '\1g',
list_indent : '\t', list_indent : '\t',
heading_underline : true, heading_underline : true,
heading_style : '\1h', heading_style : '\1h',
...@@ -130,50 +125,53 @@ Markdown.prototype.html_tag_format = function (tag, attributes) { ...@@ -130,50 +125,53 @@ Markdown.prototype.html_tag_format = function (tag, attributes) {
return ret + '>'; 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) { Markdown.prototype.render_text_console = function (text) {
const self = this; 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-'; return '\1+' + self.config.console.bold_style + c + '\1-';
}); });
ret = ret.replace(/!\[([^\]]+)\]\(([^\)]+)\)/g, function (m, c1, c2) { ret = ret.replace(/\/\/([^\/]+)\/\//g, function (m, c) {
self.state.images.push({ text : c1, link : c2 }); return '\1+' + self.config.console.italic_style + c + '\1-';
return '\1+' + self.config.console.image_style + c1 + ' [' + self.state.images.length + ']\1-';
}); });
ret = ret.replace(/\[([^\]]+)\]\(([^\)]+)\)/g, function (m, c1, c2) { ret = ret.replace(/__([^_]+)__/g, function (m, c) {
self.state.links.push({ text : c1, link : c2 }); return '\1+' + self.config.console.underline_style + c + '\1-';
return '\1+' + self.config.console.link_style + c1 + ' [' + self.state.links.length + ']\1-';
}); });
return this.colorize_console(ret); ret = ret.replace(/\{\{(.+)\}\}/g, function (m, c) {
} c = c.split('|');
self.state.images.push({ text : (c[1] || c[0]), link : c[0] });
Markdown.prototype.italicize = function (str) { return '\1+' + self.config.console.image_style + (c[1] || c[0]) + ' [' + self.state.images.length + ']\1-';
const self = this; });
str = str.replace(/_([krgybmcw0-7])(.+)/ig, function (m, c1, c2) { ret = ret.replace(/\[\[([^\]]+)\]\]/g, function (m, c) {
return '<i>' + self.italicize(c2); 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) { Markdown.prototype.render_text_html = function (text) {
const self = this; 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>'; return '<b>' + c + '</b>';
}); });
ret = ret.replace(/!\[([^\]]+)\]\(([^\)]+)\)/g, function (m, c1, c2) { ret = ret.replace(/\/\/([^\/]+)\/\//g, function (m, c) {
return self.html_tag_format('img', { alt : c1, src : c2 }); 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) { ret = ret.replace(/\[\[([^\]]+)\]\]/g, function (m, c) {
return self.html_tag_format('a', { href : c2 }) + c1 + '</a>'; 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 () { Markdown.prototype.render_table = function () {
...@@ -252,12 +250,13 @@ Markdown.prototype.render_table = function () { ...@@ -252,12 +250,13 @@ Markdown.prototype.render_table = function () {
Markdown.prototype.render_line_console = function (line) { Markdown.prototype.render_line_console = function (line) {
var match; var match;
var ret = '';
const self = this; const self = this;
var ret = this.render_text_console(line);
// Ordered and unordered lists // Ordered and unordered lists
match = line.match(/^(\s*)(\*|\d\.)\s+(.+)$/); match = ret.match(/^(\s*)(\*|-)\s+(.+)$/);
if (match !== null) { if (match !== null) {
ret = ret.replace(match[0], '');
if (this.state.table.length) ret += this.render_table(); if (this.state.table.length) ret += this.render_table();
var lt = (match[2] == '*' ? 'ul' : 'ol'); var lt = (match[2] == '*' ? 'ul' : 'ol');
if (match[1].length > this.state.list_level) { if (match[1].length > this.state.list_level) {
...@@ -271,9 +270,9 @@ Markdown.prototype.render_line_console = function (line) { ...@@ -271,9 +270,9 @@ Markdown.prototype.render_line_console = function (line) {
if (lt == 'ul') { if (lt == 'ul') {
ret += match[2]; ret += match[2];
} else { } 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; return ret;
} }
if (this.state.list_level) { if (this.state.list_level) {
...@@ -281,22 +280,21 @@ Markdown.prototype.render_line_console = function (line) { ...@@ -281,22 +280,21 @@ Markdown.prototype.render_line_console = function (line) {
this.state.list_level = 0; this.state.list_level = 0;
} }
row = line.split('|'); row = ret.split('|');
if (row.length > 1) { if (row.length > 1) {
this.state.table.push(row.map(function (e) { this.state.table.push(row);
return self.render_text_console(e);
}));
return; return;
} else if (this.state.table.length) { } else if (this.state.table.length) {
ret += this.render_table(); ret += this.render_table();
} }
// Heading // Heading
match = line.match(/^(#+)\s+(.*)$/); match = ret.match(/^(==+)\s(.+)\s==+$/);
if (match !== null) { if (match !== null) {
ret = ret.replace(match[0], '');
ret += '\1+'; ret += '\1+';
ret += this.config.console.heading_style; ret += this.config.console.heading_style;
ret += this.render_text_console(match[2]); ret += match[2];
if (this.config.console.heading_underline) { if (this.config.console.heading_underline) {
ret += '\r\n'; ret += '\r\n';
for (var n = 0; n < match[2].length; n++) { for (var n = 0; n < match[2].length; n++) {
...@@ -308,36 +306,37 @@ Markdown.prototype.render_line_console = function (line) { ...@@ -308,36 +306,37 @@ Markdown.prototype.render_line_console = function (line) {
} }
// Blockquote // Blockquote
match = line.match(/^\s*>\s(.+)$/); match = ret.match(/^\s*>\s(.+)$/);
if (match !== null) { if (match !== null) {
return ret + quote_msg( return ret.replace(
word_wrap(this.render_text_console(match[1])), this.columns - 1 match[0], quote_msg(word_wrap(match[1]), this.columns - 1)
) + '\r\n'; ) + '\r\n';
} }
// Horizontal Rule // Horizontal Rule
match = line.match(/^---+$/); match = ret.match(/^----+$/);
if (match !== null) { if (match !== null) {
var s = ''; var s = '';
while (s.length < this.columns - 1) { while (s.length < this.columns - 1) {
s += '-'; 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) { Markdown.prototype.render_line_html = function (line) {
var match; var match;
var ret = '';
const self = this; const self = this;
var ret = this.render_text_html(line);
// Blockquote // Blockquote
match = line.match(/^\s*>\s(.+)$/); match = ret.match(/^\s*>\s(.+)$/);
if (match !== null) { if (match !== null) {
ret = ret.replace(match[0], '');
if (this.state.table.length) ret += this.render_table(); if (this.state.table.length) ret += this.render_table();
if (!this.state.blockquote) { if (!this.state.blockquote) {
ret += this.html_tag_format('blockquote'); ret += this.html_tag_format('blockquote');
...@@ -350,8 +349,9 @@ Markdown.prototype.render_line_html = function (line) { ...@@ -350,8 +349,9 @@ Markdown.prototype.render_line_html = function (line) {
} }
// Ordered and unordered lists // Ordered and unordered lists
match = line.match(/^(\s*)(\*|\d\.)\s+(.+)$/); match = ret.match(/^(\s*)(\*|-)\s+(.+)$/);
if (match !== null) { if (match !== null) {
ret = ret.replace(match[0], '');
if (this.state.table.length) ret += this.render_table(); if (this.state.table.length) ret += this.render_table();
var lt = (match[2] == '*' ? 'ul' : 'ol'); var lt = (match[2] == '*' ? 'ul' : 'ol');
if (!match[1].length) { if (!match[1].length) {
...@@ -368,7 +368,7 @@ Markdown.prototype.render_line_html = function (line) { ...@@ -368,7 +368,7 @@ Markdown.prototype.render_line_html = function (line) {
ret += this.html_tag_format(lt); ret += this.html_tag_format(lt);
} }
ret += this.html_tag_format('li'); ret += this.html_tag_format('li');
ret += this.render_text_html(match[3]); ret += match[3];
ret += '</li>'; ret += '</li>';
return ret; return ret;
} }
...@@ -376,33 +376,32 @@ Markdown.prototype.render_line_html = function (line) { ...@@ -376,33 +376,32 @@ Markdown.prototype.render_line_html = function (line) {
ret += '</' + this.state.list_stack.pop() + '>'; ret += '</' + this.state.list_stack.pop() + '>';
} }
row = line.split('|'); row = ret.split('|');
if (row.length > 1) { if (row.length > 1) {
this.state.table.push(row.map(function (e) { this.state.table.push(row);
return self.render_text_html(e);
}));
return; return;
} else if (this.state.table.length) { } else if (this.state.table.length) {
ret += this.render_table(); ret += this.render_table();
} }
// Heading // Heading
match = line.match(/^#+\s+(.*)$/); match = ret.match(/^(==+)\s(.+)\s==+$/);
if (match !== null) { 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 += '<h' + lvl + '>';
ret += this.render_text_html(match[1]); ret += match[2];
ret += '</h' + lvl + '>'; ret += '</h' + lvl + '>';
return ret; return ret;
} }
// Horizontal Rule // Horizontal Rule
match = line.match(/^---+$/); match = ret.match(/^----+$/);
if (match !== null) { 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>';
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment