Inline image support

This commit is contained in:
Nate Choe
2022-05-01 04:03:18 -05:00
parent 0b134cabb2
commit 4e70c61ae5

View File

@@ -17,6 +17,11 @@ struct escape escapes[] = {
static int writecodespan(char *data, int i, size_t len, FILE *out); static int writecodespan(char *data, int i, size_t len, FILE *out);
static int writelink(char *data, int i, size_t len, FILE *out); static int writelink(char *data, int i, size_t len, FILE *out);
static int writeimage(char *data, int i, size_t len, FILE *out);
static int getlinkinfo(char *data, int i, size_t len,
int *textstart, int *textend,
int *titlestart, int *titleend,
int *linkstart, int *linkend);
static void writeescaped(char *data, size_t len, FILE *out); static void writeescaped(char *data, size_t len, FILE *out);
static void writechescape(char c, FILE *out); static void writechescape(char c, FILE *out);
@@ -32,6 +37,8 @@ void writedata(char *data, size_t len, FILE *out) {
goto special; goto special;
if ((newi = writelink(data, i, len, out)) >= 0) if ((newi = writelink(data, i, len, out)) >= 0)
goto special; goto special;
if ((newi = writeimage(data, i, len, out)) >= 0)
goto special;
if (data[i] == '\\') { if (data[i] == '\\') {
if (strchr(punctuation, data[i + 1]) == NULL) if (strchr(punctuation, data[i + 1]) == NULL)
writechescape('\\', out); writechescape('\\', out);
@@ -76,6 +83,52 @@ static int writecodespan(char *data, int i, size_t len, FILE *out) {
static int writelink(char *data, int i, size_t len, FILE *out) { static int writelink(char *data, int i, size_t len, FILE *out) {
int textstart, textend, titlestart, titleend, linkstart, linkend; int textstart, textend, titlestart, titleend, linkstart, linkend;
i = getlinkinfo(data, i, len, &textstart, &textend,
&titlestart, &titleend,
&linkstart, &linkend);
if (i < 0)
return -1;
fputs("<a href='", out);
writeescaped(data + linkstart, linkend - linkstart, out);
fputc('\'', out);
if (titlestart >= 0) {
fputs(" title='", out);
writeescaped(data + titlestart, titleend - titlestart, out);
fputc('\'', out);
}
fputc('>', out);
writeescaped(data + textstart, textend - textstart, out);
fputs("</a>", out);
return i;
}
static int writeimage(char *data, int i, size_t len, FILE *out) {
int textstart, textend, titlestart, titleend, linkstart, linkend;
if (data[i++] != '!')
return -1;
i = getlinkinfo(data, i, len, &textstart, &textend,
&titlestart, &titleend,
&linkstart, &linkend);
if (i < 0)
return -1;
fputs("<img src='", out);
writeescaped(data + linkstart, linkend - linkstart, out);
fputc('\'', out);
if (titlestart >= 0) {
fputs(" title='", out);
writeescaped(data + titlestart, titleend - titlestart, out);
fputc('\'', out);
}
fputs(" alt='", out);
writeescaped(data + textstart, textend - textstart, out);
fputs("'>", out);
return i;
}
static int getlinkinfo(char *data, int i, size_t len,
int *textstart, int *textend,
int *titlestart, int *titleend,
int *linkstart, int *linkend) {
int count; int count;
enum { enum {
INITIAL, INITIAL,
@@ -99,7 +152,7 @@ static int writelink(char *data, int i, size_t len, FILE *out) {
return -1; return -1;
state = GETTEXT; state = GETTEXT;
count = 1; count = 1;
textstart = i + 1; *textstart = i + 1;
break; break;
case GETTEXT: case GETTEXT:
if (data[i] == '[') if (data[i] == '[')
@@ -107,8 +160,8 @@ static int writelink(char *data, int i, size_t len, FILE *out) {
if (data[i] == ']') if (data[i] == ']')
--count; --count;
if (count == 0) { if (count == 0) {
textend = i; *textend = i;
linkstart = i; *linkstart = i;
state = GETDESTSTART; state = GETDESTSTART;
} }
break; break;
@@ -120,11 +173,11 @@ static int writelink(char *data, int i, size_t len, FILE *out) {
case GETDESTDETERMINE: case GETDESTDETERMINE:
if (data[i] == '<') { if (data[i] == '<') {
state = GETDESTPOINTY; state = GETDESTPOINTY;
linkstart = i + 1; *linkstart = i + 1;
} }
else { else {
state = GETDESTNORMAL; state = GETDESTNORMAL;
linkstart = i--; *linkstart = i--;
count = 0; count = 0;
} }
break; break;
@@ -132,7 +185,7 @@ static int writelink(char *data, int i, size_t len, FILE *out) {
if (data[i] == '<' && data[i - 1] != '\\') if (data[i] == '<' && data[i - 1] != '\\')
return -1; return -1;
if (data[i] == '>' && data[i - 1] != '\\') { if (data[i] == '>' && data[i - 1] != '\\') {
linkend = i; *linkend = i;
state = GETTITLEDETERMINE; state = GETTITLEDETERMINE;
} }
break; break;
@@ -143,53 +196,53 @@ static int writelink(char *data, int i, size_t len, FILE *out) {
--count; --count;
if (count < 0) { if (count < 0) {
state = GETTITLEDETERMINE; state = GETTITLEDETERMINE;
linkend = i--; *linkend = i--;
break; break;
} }
if (count != 0) if (count != 0)
break; break;
if (isctrl(data[i]) || data[i] == ' ') { if (isctrl(data[i]) || data[i] == ' ') {
state = GETTITLEDETERMINE; state = GETTITLEDETERMINE;
linkend = i; *linkend = i;
} }
break; break;
case GETTITLEDETERMINE: case GETTITLEDETERMINE:
switch (data[i]) { switch (data[i]) {
case '"': case '"':
state = GETTITLEDOUBLEQUOTE; state = GETTITLEDOUBLEQUOTE;
titlestart = i + 1; *titlestart = i + 1;
break; break;
case '\'': case '\'':
state = GETTITLESINGLEQUOTE; state = GETTITLESINGLEQUOTE;
titlestart = i + 1; *titlestart = i + 1;
break; break;
case '(': case '(':
state = GETTITLEPAREN; state = GETTITLEPAREN;
count = 1; count = 1;
titlestart = i + 1; *titlestart = i + 1;
break; break;
default: default:
--i; --i;
titlestart = titleend = -1; *titlestart = *titleend = -1;
state = NEARLYTHERE; state = NEARLYTHERE;
} }
break; break;
case GETTITLEDOUBLEQUOTE: case GETTITLEDOUBLEQUOTE:
if (data[i] == '"' && data[i - 1] != '\\') { if (data[i] == '"' && data[i - 1] != '\\') {
titleend = i; *titleend = i;
state = NEARLYTHERE; state = NEARLYTHERE;
} }
break; break;
case GETTITLESINGLEQUOTE: case GETTITLESINGLEQUOTE:
if (data[i] == '\'' && data[i - 1] != '\\') { if (data[i] == '\'' && data[i - 1] != '\\') {
titleend = i; *titleend = i;
state = NEARLYTHERE; state = NEARLYTHERE;
} }
break; break;
case GETTITLEPAREN: case GETTITLEPAREN:
if (data[i] == '(' || data[i] == ')') { if (data[i] == '(' || data[i] == ')') {
if (data[i - 1] != '\\') { if (data[i - 1] != '\\') {
titleend = i; *titleend = i;
state = NEARLYTHERE; state = NEARLYTHERE;
} }
} }
@@ -206,18 +259,6 @@ static int writelink(char *data, int i, size_t len, FILE *out) {
done: done:
if (state != DONE) if (state != DONE)
return -1; return -1;
fputs("<a", out);
fputs(" href='", out);
writeescaped(data + linkstart, linkend - linkstart, out);
fputc('\'', out);
if (titlestart >= 0) {
fputs(" title='", out);
writeescaped(data + titlestart, titleend - titlestart, out);
fputc('\'', out);
}
fputc('>', out);
writeescaped(data + textstart, textend - textstart, out);
fputs("</a>", out);
return i; return i;
} }