Inline html

This commit is contained in:
Nate Choe
2022-05-06 01:25:29 -05:00
parent eae807410b
commit 08cfe673f1
3 changed files with 144 additions and 66 deletions

View File

@@ -54,5 +54,7 @@ struct linedata {
void identifyline(char *line, struct linedata *prev, struct linedata *ret);
/* prev is almost never used, but sometimes it is. */
char *realcontent(char *line, struct linedata *data);
int isgenerictag(char *text);
/* Identifies open and close tags */
#endif

View File

@@ -19,6 +19,7 @@
#include <string.h>
#include <util.h>
#include <mdutil.h>
#include <inlines.h>
static const char *punctuation = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
@@ -38,12 +39,15 @@ 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 writeautolink(char *data, int i, size_t len, FILE *out);
static int writehardbreak(char *data, int i, size_t len, FILE *out);
static int writerawhtml(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 writechescape(char c, FILE *out);
static int inlinehtmlcase(char *data, char *start, char *end, FILE *out);
/* Returns length of raw html */
void writeline(char *data, FILE *out) {
writedata(data, strlen(data), out);
@@ -63,6 +67,8 @@ void writedata(char *data, size_t len, FILE *out) {
goto special;
if ((newi = writehardbreak(data, i, len, out)) >= 0)
goto special;
if ((newi = writerawhtml(data, i, len, out)) >= 0)
goto special;
if (data[i] == '\\') {
if (strchr(punctuation, data[i + 1]) == NULL)
writechescape('\\', out);
@@ -202,6 +208,48 @@ static int writehardbreak(char *data, int i, size_t len, FILE *out) {
return i + codelen;
}
static int writerawhtml(char *data, int i, size_t len, FILE *out) {
int taglen;
data += i;
taglen = isgenerictag(data);
if (taglen > 0) {
fwrite(data, 1, taglen, out);
return i + taglen;
}
if (memcmp(data, "<!--", 4) == 0) {
char *end, *text;
int j;
text = data + 4;
end = strstr(text, "-->");
if (end == NULL)
goto notcomment;
taglen = end - text;
if (text[0] == '>' || memcmp(text, "->", 2) == 0)
goto notcomment;
if (text[taglen - 1] == '-') {
goto notcomment;
}
for (j = 0; j < taglen - 1; ++j) {
if (memcmp(text + j, "--", 2) == 0)
goto notcomment;
}
fwrite(data, 1, taglen + 7, out);
return i + taglen + 7;
}
notcomment:
if ((taglen = inlinehtmlcase(data, "<?", "?>", out)) > 0)
return i + taglen;
if ((taglen = inlinehtmlcase(data, "<!", ">", out)) > 0)
return i + taglen;
if ((taglen = inlinehtmlcase(data, "<![CDATA[", "]]>", out)) > 0)
return i + taglen;
return -1;
}
static int getlinkinfo(char *data, int i, size_t len,
int *textstart, int *textend,
int *titlestart, int *titleend,
@@ -355,3 +403,18 @@ static void writechescape(char c, FILE *out) {
}
fputc(c, out);
}
static int inlinehtmlcase(char *data, char *start, char *end, FILE *out) {
int i;
int len;
char *endloc;
for (i = 0; start[i] != '\0'; ++i)
if (data[i] != start[i])
return 0;
endloc = strstr(data, end);
if (endloc == NULL)
return 0;
len = endloc - data + strlen(end);
fwrite(data, 1, len, out);
return len;
}

View File

@@ -127,7 +127,6 @@ notheader:
if (line[0] == '<') {
char *testline;
int isopen;
testline = line + 1;
for (i = 0; i < LEN(concretetags); ++i) {
char *aftertag;
@@ -140,12 +139,8 @@ notheader:
return;
}
}
if (testline[0] == '/') {
if (testline[0] == '/')
++testline;
isopen = 0;
}
else
isopen = 1;
for (i = 0; i < LEN(skeletontags); ++i) {
char *aftertag;
aftertag = after(skeletontags[i], testline);
@@ -160,73 +155,15 @@ notheader:
}
}
/* < || </ */
if (!isalpha(testline[0]))
goto nothtml;
++testline;
while (isalnum(testline[0]) || testline[0] == '-')
++testline;
/* <[tag name] || </[tag name] */
for (;;) {
char *newtestline;
newtestline = truncate(testline);
if (!isalpha(newtestline[0]) &&
strchr("_:", newtestline[0]) == NULL)
break;
++newtestline;
while (isalnum(newtestline[0]) ||
strchr("_.:-", newtestline[0]) != NULL)
++newtestline;
/* Swallow attribute name */
newtestline = truncate(newtestline);
if (newtestline[0] == '=') {
char start;
++newtestline;
newtestline = truncate(newtestline);
start = newtestline[0];
switch (start) {
case '\'': case '"':
while (newtestline[0] != start &&
newtestline[0] != '\0')
++newtestline;
if (newtestline[0] == '\0')
goto nothtml;
break;
/* Swallow single/double quoted attribute
* value */
default:
while (strchr("\"'=<>`", newtestline[0])
== NULL &&
newtestline[0] != '\0')
++newtestline;
if (newtestline[0] == '\0')
goto nothtml;
break;
/* Swallow unquoted attribute value */
}
}
/* Swallow attribute value */
testline = newtestline;
}
/* <[tag name][attribute]* || </tag name][attribute]* */
if (isopen && testline[0] == '/')
++testline;
if (testline[0] == '>') {
if (isgenerictag(line)) {
ret->type = GENERICTAG;
ret->data.isfirst = 1;
return;
}
}
nothtml:
ret->type = PLAIN;
ret->data.isfirst = 1;
return;
}
@@ -246,6 +183,82 @@ char *realcontent(char *line, struct linedata *data) {
return NULL;
}
int isgenerictag(char *text) {
int isopen;
char *initialtext;
initialtext = text;
if (text[0] != '<')
return 0;
++text;
if (text[0] == '/') {
++text;
isopen = 0;
}
else
isopen = 1;
/* < || </ */
if (!isalpha(text[0]))
return 0;
while (isalnum(text[0]) || text[0] == '-')
++text;
/* <[tag name] || </[tag name] */
for (;;) {
char *newtext;
newtext = truncate(text);
if (!isalpha(newtext[0]) &&
strchr("_:", newtext[0]) == NULL)
break;
++newtext;
while (isalnum(newtext[0]) ||
strchr("_.:-", newtext[0]) != NULL)
++newtext;
/* Swallow attribute name */
newtext = truncate(newtext);
if (newtext[0] == '=') {
char start;
++newtext;
newtext = truncate(newtext);
start = newtext[0];
switch (start) {
case '\'': case '"':
while (newtext[0] != start &&
newtext[0] != '\0')
++newtext;
if (newtext[0] == '\0')
return 0;
break;
/* Swallow single/double quoted attribute
* value */
default:
while (strchr("\"'=<>`", newtext[0])
== NULL &&
newtext[0] != '\0')
++newtext;
if (newtext[0] == '\0')
return 0;
break;
/* Swallow unquoted attribute value */
}
}
/* Swallow attribute value */
text = newtext;
}
/* <[tag name][attribute]* || </tag name][attribute]* */
if (isopen && text[0] == '/')
++text;
if (text[0] == '>')
return text - initialtext + 1;
return 0;
}
static char *truncate(char *str) {
while (isspace(str[0]))
++str;