Newer
Older

echicken
committed
* == h5 ==

echicken
committed
* ==== h3 ====

echicken
committed
* ====== h1 ======
* [[http://some.web.site/|some link text]]
* {{http://some.web.site/image.png|some alt text}}
* ** bold **
* // italic //
* __ underline __
* '' monospaced ''
* ** // __ '' bold italic underline monospace '' __ // **

echicken
committed
* * Unordered lists
* * With sub-items
* - Ordered lists
* - With sub-items
* Lines\\ with\\ forced\\ line\\ breaks
* ^this^is^a^table^heading^
* |this|is|a|table|row|
* ^you|can|have|headings|anywhere|
* To do:
* - nested blockquote in HTML
* - image links
* - code blocks
* - text conversion (HTML only probably)
if (typeof Frame == 'undefined') Frame = false;
const state = {
list_level : 0,
links : [],
images : [],
table : [],
blockquote : false,
list_stack : []
};
const config = {
console : {
bold_style : '\1h',

echicken
committed
italic_style : '\1r',
underline_style : '\1g',
list_indent : ' ',
heading_underline : true,
heading_style : '\1h',
link_style : '\1h\1c',
},
html : {
a : '',
ul : 'list-group',
ol : 'list-group',
li : 'list-group-item',
table : 'table table-striped',
thead : '',
tbody : '',
th : '',
tr : '',
td : '',
img : '',
hr : '',
blockquote : 'blockquote'
}
};
if (typeof settings == 'object') {
if (typeof settings.console == 'object') {
Object.keys(settings.console).forEach(function (e) {
config.console[e] = settings.console[e];
});
}
if (typeof settings.html == 'object') {
Object.keys(settings.html).forEach(function (e) {
config.html[e] = settings.html[e];
});
}
if (Frame && target instanceof Frame) target.word_wrap = true;
this.reset = function () {
state.list_level = 0;
state.links = [];
state.images = [];
state.table = [];
state.blockquote = false;
state.list_stack = [];
}
Object.defineProperty(this, 'state', { get : function () {
return state;
}});
Object.defineProperty(this, 'target', {
get : function () {
return target;
},
set : function (t) {
if (t == 'html') {
target = t;
} else if (Frame && t instanceof Frame) {
target = t;
} else if (
typeof t.screen_columns == 'number' && typeof t.putmsg == 'function'
) {
target = t;
} else {
throw 'Invalid output target';
}
}
});
Object.defineProperty(this, 'columns', { get : function () {
if (target == 'html') {
return 0;
} else if (Frame && target instanceof Frame) {
return target.width;
} else {
return target.screen_columns;
}
}});
Object.defineProperty(this, 'config', { value : config });
}
Markdown.prototype.html_tag_format = function (tag, attributes) {
var ret = '<' + tag;
if (this.config.html[tag] != '') {
ret += ' class="' + this.config.html[tag] + '"';
}
if (attributes) {
Object.keys(attributes).forEach(function (e) {
ret += ' ' + e + '="' + attributes[e] + '"'
});
}
return ret + '>';
}
Markdown.prototype.render_text_console = function (text) {
const self = this;
return text.replace(/\*\*([^\*]+)\*\*/g, function (m, c) {
return '\1+' + self.config.console.bold_style + c + '\1-';

echicken
committed
return '\1+' + self.config.console.italic_style + c + '\1-';

echicken
committed
return '\1+' + self.config.console.underline_style + c + '\1-';

echicken
committed
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-';

echicken
committed
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-';
self.state.footnotes.push(c);
return '\1+' + self.config.console.footnote_style + '[' + self.state.footnotes.length + ']\1-';
}
Markdown.prototype.render_text_html = function (text) {
const self = this;
return text.replace(/\\1.(.+)\\1./g, function (m, c) {

echicken
committed
return c;

echicken
committed
return '<i>' + c + '</i>';

echicken
committed
return '<span style="text-decoration:underline;">' + c + '</span>';
return '<code>' + c + '</code>';

echicken
committed
c = c.split('|');
return self.html_tag_format('img', { alt : (c[1] || c[0]), src : c[0] });

echicken
committed
c = c.split('|');
return self.html_tag_format('a', { href : c[0] }) + (c[1] || c[0]) + '</a>';
self.state.footnotes.push(c);
return self.html_tag_format('a', { href : '#f' + self.state.footnotes.length }) + ' [' + self.state.footnotes.length + ']</a>';
}
Markdown.prototype.render_table = function () {
const self = this;
const columns = []; // Length is number of columns, values are column widths
this.state.table.forEach(function (e) {
e.forEach(function (e, i) {
const raw = strip_ctrl(e);
const visible = raw ? raw.length : 0;
if (columns.length < (i + 1)) {
columns.push(visible);
} else if (columns[i] < visible) {
columns[i] = visible;
}
});
});
if (this.target == 'html') {
var nr = i + 1;
if (self.state.table[nr] && self.state.table[nr][n] == ':::') {
typeof self.state.table[nr] !== 'undefined'
&& self.state.table[nr][n] == ':::'
}
if (attr.rowspan < 2) delete attr.rowspan;
}
var nc = n + 1;
if (typeof e[nc] != 'undefined' && e[nc] == '') {
attr.colspan = 1;
while (typeof e[nc] !== 'undefined' && e[nc] == '') {
attr.colspan++;
nc++;
}
if (attr.colspan < 2) delete attr.colspan;
}
if (e[n].search(/^\s\s+/) > -1) attr.style = "text-align:right;";
if (e[n].search(/^\s\s+(.+)\s\s+$/) > -1) attr.style = "text-align:center;";
var tt = i == 0 ? 'th' : 'td';
var tag = [self.html_tag_format(tt, attr), '</' + tt + '/>'];
ret += tag[0] + e[n] + tag[1];
});
ret += '</table><br>';
this.state.table = [];
return ret;
} else {
}
}
Markdown.prototype.render_line_console = function (line) {
var match;
const self = this;

echicken
committed
var ret = this.render_text_console(line);
match = ret.match(/^(\s*)(\*|-)\s+(.+)$/m);

echicken
committed
ret = ret.replace(match[0], '');
if (this.state.table.length) ret += this.render_table();
if (match[2] == '*') {
lt = 'ul';
} else {
lt = 'ol';
}
if (lt == 'ol') this.state.list_stack[this.state.list_level] = 0;
} else if (match[1].length < this.state.list_level) {
if (lt == 'ol') this.state.list_stack.splice(this.state.list_level, 1);
} else if (lt == 'ol') {
if (typeof this.state.list_stack[this.state.list_level] != 'number') {
this.state.list_stack[this.state.list_level] = 0;
} else {
this.state.list_stack[this.state.list_level]++;
}
}
for (var n = 0; n < this.state.list_level; n++) {
}
if (lt == 'ul') {
ret += match[2];
} else {
ret += (this.state.list_stack[this.state.list_level] + 1) + '.';

echicken
committed
ret += ' ' + match[3] + '\r\n';
return ret;
}
if (this.state.list_level) {
ret += '\r\n';
this.state.list_level = 0;
// Table
const tre = /([|^])([^|^]+)(?=[|^])/g;
match = tre.exec(ret);
if (match !== null) {
const _ret = match.input;
const row = [];
do {
match = tre.exec(ret);
} while (match !== null);

echicken
committed
this.state.table.push(row);
ret = ret.replace(_ret, '');
return ret;
} else if (this.state.table.length) {
ret += this.render_table();
}
// Heading
match = ret.match(/^(==+)([^=]+)==+\s*$/m);

echicken
committed
ret = ret.replace(match[0], '');
ret += '\1+';
ret += this.config.console.heading_style;

echicken
committed
ret += match[2];
if (this.config.console.heading_underline) {
ret += '\r\n';
for (var n = 0; n < match[2].length; n++) {
ret += user.settings&USER_NO_EXASCII ? '-' : ascii(196);
}
}
ret += '\1-\r\n\r\n';
return ret;
match = ret.match(/^\s*>\s(.+)$/m);

echicken
committed
return ret.replace(
match[0], quote_msg(word_wrap(match[1]), this.columns - 1)
match = ret.match(/^----+$/m);
if (match !== null) {
var s = '';
while (s.length < this.columns - 1) {
s += user.settings&USER_NO_EXASCII ? '-' : ascii(196);

echicken
committed
return ret.replace(match[0], s) + '\r\n';

echicken
committed
return ret + '\r\n';
}
Markdown.prototype.render_line_html = function (line) {
var match;
const self = this;

echicken
committed
var ret = this.render_text_html(line);
match = ret.match(/^\s*>\s(.+)$/m);

echicken
committed
ret = ret.replace(match[0], '');
if (this.state.table.length) ret += this.render_table();
if (!this.state.blockquote) {
this.state.blockquote = true;
}
return ret + match[1];
} else if (this.state.blockquote) {
ret += '</blockquote>';
this.state.blockquote = false;
}
// Ordered and unordered lists
match = ret.match(/^(\s*)(\*|-)\s+(.+)$/m);

echicken
committed
ret = ret.replace(match[0], '');
if (this.state.table.length) ret += this.render_table();
var lt = (match[2] == '*' ? 'ul' : 'ol');
if (!match[1].length) {
while (this.state.list_stack.length > 1) {
ret += '</' + this.state.list_stack.pop() + '></li>';
}
if (this.state.list_stack.length < 1) {
this.state.list_stack.push(lt);
} else if (match[1].length >= this.state.list_stack.length) {
ret += this.html_tag_format('li');
ret += this.html_tag_format(lt);

echicken
committed
ret += match[3];
return ret;
}
while (this.state.list_stack.length) {
ret += '</' + this.state.list_stack.pop() + '>';
}
match = tre.exec(ret);
if (match !== null) {
const _ret = match.input;
const row = [];
do {
if (match[1] == '^') {
// This is lousy, but if you want table headings to look special,
// then include a 'doku_th' class in your stylesheet.
// You're welcome.
row.push('<span class="doku_th">' + match[2] + '</span>');
} else {
row.push(match[2]);
}
match = tre.exec(ret);
} while (match !== null);

echicken
committed
this.state.table.push(row);
ret = ret.replace(_ret, '');
return ret;
} else if (this.state.table.length) {
ret += this.render_table();
}
// Heading
match = ret.match(/^(==+)([^=]+)==+\s*$/m);

echicken
committed
ret = ret.replace(match[0], '');
var lvl = 6 - Math.min(match[1].split(' ')[0].length, 5);

echicken
committed
ret += match[2];
ret += '</h' + lvl + '>';
return ret;
}
// Horizontal Rule
match = ret.match(/^----+$/m);

echicken
committed
return ret.replace(match[0], '') + this.html_tag_format('hr');

echicken
committed
return ret + '<br>';
}
Markdown.prototype.render_console = function (text) {
const self = this;
text.split(/\n/).forEach(function (e) {
var line = self.render_line_console(e.replace(/\r$/, ''));
if (typeof line == 'string') {
self.target.putmsg(self.target instanceof Frame ? line : word_wrap(line, self.columns));
this.target.putmsg('\1+' + self.config.console.link_style + 'Links:\1-\r\n');
self.target.putmsg('\1+' + self.config.console.link_style + '[' + (i + 1) + '] ' + e.link + '\1-\r\n');
});
this.target.putmsg('\r\n');
}
if (this.state.images.length) {
this.target.putmsg('\1+' + self.config.console.image_style + 'Images:\1-\r\n');
self.target.putmsg('\1+' + self.config.console.image_style + '[' + (i + 1) + '] ' + e.link + '\1-\r\n');
if (this.state.footnotes.length) {
this.target.putmsg('\1+' + self.config.console.footnote_style + 'Footnotes:\1-\r\n');
this.state.footnotes.forEach(function (e, i) {
self.target.putmsg('\1+' + self.config.console.footnote_style + '[' + (i + 1) + '] ' + e + '\1-\r\n');
});
}
}
Markdown.prototype.render_html = function (text) {
const self = this;
text.split(/\n/).forEach(function (e) {
var line = self.render_line_html(e.replace(/\r$/, ''));
if (typeof line == 'string') writeln(line);
});
writeln('<a id="f' + (i + 1) + '">[' + (i + 1) + '] ' + e + '</a><br>');