Add hyperlink support to MarkdownParser
MarkdownParser now supports hyperlinks.
This commit is contained in:
parent
99e2f412cd
commit
c4d83a9eef
|
@ -22,18 +22,53 @@
|
||||||
#include "MarkdownParser.hxx"
|
#include "MarkdownParser.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#define ASCII_DIGIT_START 48
|
#define ASCII_DIGIT_START 48
|
||||||
|
|
||||||
|
enum HyperlinkStage {
|
||||||
|
NONE, // not reading a hyperlink
|
||||||
|
READING_CONTENTS, // reading the contents (like text) of a hyperlink
|
||||||
|
EXPECTING_URL, // done reading contents of hyperlink; expecting its URL to be specified
|
||||||
|
READING_URL // reading the hyperlink url
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string html,
|
||||||
|
tag_a_text_buf, // used for storing the text contents of a hyperlink
|
||||||
|
tag_a_buf; // used for storing the hyperlink address
|
||||||
|
enum HyperlinkStage tag_a = NONE;
|
||||||
|
|
||||||
|
void append(std::string const &s) {
|
||||||
|
// TODO: add proper error handling.
|
||||||
|
assert(tag_a != EXPECTING_URL);
|
||||||
|
switch(tag_a) {
|
||||||
|
case NONE:
|
||||||
|
html += s;
|
||||||
|
break;
|
||||||
|
case READING_CONTENTS:
|
||||||
|
tag_a_text_buf += s;
|
||||||
|
break;
|
||||||
|
case READING_URL:
|
||||||
|
tag_a_buf += s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void append(const char *c) {
|
||||||
|
append(std::string(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup() {
|
||||||
|
html = "";
|
||||||
|
}
|
||||||
|
|
||||||
namespace MarkdownParser {
|
namespace MarkdownParser {
|
||||||
|
|
||||||
std::string make_html(std::filesystem::path const &path) {
|
std::string make_html(std::filesystem::path const &path) {
|
||||||
|
cleanup();
|
||||||
FILE *mdFile = fopen(path.string().c_str(), "r");
|
FILE *mdFile = fopen(path.string().c_str(), "r");
|
||||||
// TODO: Add proper error handling.
|
// TODO: Add proper error handling.
|
||||||
assert(mdFile != NULL);
|
assert(mdFile != NULL);
|
||||||
|
|
||||||
std::string html;
|
|
||||||
|
|
||||||
int buflen = 64;
|
int buflen = 64;
|
||||||
char buf[buflen];
|
char buf[buflen];
|
||||||
|
|
||||||
|
@ -105,25 +140,24 @@ std::string make_html(std::filesystem::path const &path) {
|
||||||
// Bold check
|
// Bold check
|
||||||
// Check whether this character has been escaped.
|
// Check whether this character has been escaped.
|
||||||
if (buf[x-1] == '\\') {
|
if (buf[x-1] == '\\') {
|
||||||
html += "*";
|
append(&c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
html += tag_b ? "</b>" : "<b>";
|
append(tag_b ? "</b>" : "<b>");
|
||||||
tag_b = !tag_b;
|
tag_b = !tag_b;
|
||||||
break;
|
break;
|
||||||
case '_':
|
case '_':
|
||||||
// Italics check
|
// Italics check
|
||||||
|
|
||||||
// Check whether this character has
|
// Check whether this character has
|
||||||
// been escaped.
|
// been escaped.
|
||||||
|
|
||||||
if (buf[x-1] == '\\') {
|
if (buf[x-1] == '\\') {
|
||||||
html += "_";
|
append(&c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
html += tag_i ? "</i>" : "<i>";
|
append(tag_i ? "</i>" : "<i>");
|
||||||
tag_i = !tag_i;
|
tag_i = !tag_i;
|
||||||
break;
|
break;
|
||||||
case '#':
|
case '#':
|
||||||
|
@ -133,7 +167,7 @@ std::string make_html(std::filesystem::path const &path) {
|
||||||
// beginning of a new line. Ignore it
|
// beginning of a new line. Ignore it
|
||||||
// if this is not a new line.
|
// if this is not a new line.
|
||||||
if (!newline) {
|
if (!newline) {
|
||||||
html += "#";
|
append(&c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +177,7 @@ std::string make_html(std::filesystem::path const &path) {
|
||||||
// Check if this header was specified
|
// Check if this header was specified
|
||||||
// right at the beginning of the line.
|
// right at the beginning of the line.
|
||||||
(tag_h == 0 && x != 0)) {
|
(tag_h == 0 && x != 0)) {
|
||||||
html += "#";
|
append(&c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,14 +226,55 @@ std::string make_html(std::filesystem::path const &path) {
|
||||||
ignoreSpace = true;
|
ignoreSpace = true;
|
||||||
tag_li = true;
|
tag_li = true;
|
||||||
break;
|
break;
|
||||||
|
case '[':
|
||||||
|
// Hyperlink text declaration has begun
|
||||||
|
if (tag_a != NONE) {
|
||||||
|
// Cannot add hyperlinks inside of hyperlinks;
|
||||||
|
append(&c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tag_a_buf = "";
|
||||||
|
tag_a_text_buf = "";
|
||||||
|
tag_a = READING_CONTENTS;
|
||||||
|
break;
|
||||||
|
case ']':
|
||||||
|
// Hyperlink text declaration ended
|
||||||
|
if (tag_a != READING_CONTENTS) {
|
||||||
|
// Ignore if not reading hyperlink.
|
||||||
|
append(&c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tag_a = EXPECTING_URL;
|
||||||
|
break;
|
||||||
|
case '(':
|
||||||
|
// Hyperlink address declaration has begun
|
||||||
|
if (tag_a != EXPECTING_URL) {
|
||||||
|
append(&c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tag_a = READING_URL;
|
||||||
|
break;
|
||||||
|
case ')':
|
||||||
|
// Hyperlink address declaration ended
|
||||||
|
if (tag_a != READING_URL) {
|
||||||
|
append(&c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tag_a = NONE;
|
||||||
|
append("<a href=\"");
|
||||||
|
append(tag_a_buf);
|
||||||
|
append("\">");
|
||||||
|
append(tag_a_text_buf);
|
||||||
|
append("</a>");
|
||||||
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
if (ignoreSpace) {
|
if (ignoreSpace) {
|
||||||
ignoreSpace = false;
|
ignoreSpace = false;
|
||||||
break;
|
break;
|
||||||
} else html += ' ';
|
} else append(" ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
html += c;
|
append(&c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue