hmml_to_html.c: CSV "-escaping [#20] and EDITION

EDITION gives us a way to conditionally handle and warn about features
that depend on network infrastructure, notably member / project info
This commit is contained in:
Matt Mascarenhas 2017-06-10 17:47:47 +01:00
parent 2f5057f36b
commit 95d0f63da0
1 changed files with 101 additions and 15 deletions

View File

@ -21,6 +21,13 @@ typedef unsigned int bool;
#define Kilobytes(Bytes) Bytes << 10 #define Kilobytes(Bytes) Bytes << 10
#define Megabytes(Bytes) Bytes << 20 #define Megabytes(Bytes) Bytes << 20
enum
{
EDITION_SINGLE = 0,
EDITION_PROJECT = 1,
EDITION_NETWORK = 2
} EDITION;
typedef struct typedef struct
{ {
char *Location; char *Location;
@ -72,6 +79,8 @@ char *Credentials[ ][5] =
{ "abnercoimbre", "Abner Coimbre", "https://handmade.network/m/abnercoimbre", "patreon_logo.png", "https://patreon.com/handmade_dev"}, { "abnercoimbre", "Abner Coimbre", "https://handmade.network/m/abnercoimbre", "patreon_logo.png", "https://patreon.com/handmade_dev"},
}; };
#define EDITION EDITION_SINGLE
#define ArrayCount(A) sizeof(A)/sizeof(*(A)) #define ArrayCount(A) sizeof(A)/sizeof(*(A))
void void
@ -239,6 +248,45 @@ CopyStringToBufferHTMLSafe(buffer *Dest, char *String)
} }
} }
void
CopyStringToBufferCSVSafe(buffer *Dest, char *String)
{
while(*String)
{
if(Dest->Ptr - Dest->Location >= Dest->Size)
{
fprintf(stderr, "CopyStringToBufferHTMLSafe: %s cannot accommodate %d-character string\n", Dest->ID, StringLength(String));
__asm__("int3");
}
switch(*String)
{
case '<':
CopyStringToBuffer(Dest, "&lt;");
String++;
break;
case '>':
CopyStringToBuffer(Dest, "&gt;");
String++;
break;
case '&':
CopyStringToBuffer(Dest, "&amp;");
String++;
break;
case '\"':
CopyStringToBuffer(Dest, "&quot;");
String += 2;
break;
case '\'':
CopyStringToBuffer(Dest, "&#39;");
String++;
break;
default:
*Dest->Ptr++ = *String++;
break;
}
}
}
int int
StringsDiffer(char *A, char *B) StringsDiffer(char *A, char *B)
{ {
@ -257,7 +305,7 @@ StringsDifferL(char *A, char *B, int LengthofA)
{ {
++i; ++i;
} }
if(!A[i] && LengthofA == i) if(!A[i] && LengthofA == i && B[i] == ' ')
{ {
return FALSE; return FALSE;
} }
@ -674,8 +722,6 @@ BuildQuote(quote_info *Info, char *Speaker, int ID)
{ {
// TODO(matt): Pull these paths from the config // TODO(matt): Pull these paths from the config
// Also notable that there are different paths for different projects // Also notable that there are different paths for different projects
//
// TODO(matt): Handle csv's double quote escaping stuff
char *QuoteDir = "/home/matt/git/GitHub/insofaras/25fc16d58a297a486334"; char *QuoteDir = "/home/matt/git/GitHub/insofaras/25fc16d58a297a486334";
if(!StringsDiffer(Speaker, "handmade_hero")) if(!StringsDiffer(Speaker, "handmade_hero"))
@ -708,7 +754,6 @@ BuildQuote(quote_info *Info, char *Speaker, int ID)
while(InPtr - Buffer < Length) while(InPtr - Buffer < Length)
{ {
char InID[4] = { 0 }; char InID[4] = { 0 };
char *OutPtr = InID; char *OutPtr = InID;
while(*InPtr != ',') while(*InPtr != ',')
@ -1282,11 +1327,26 @@ TimecodeToSeconds(Anno->time));
CopyStringToBuffer(&AnnotationClass, " authored"); CopyStringToBuffer(&AnnotationClass, " authored");
hsl_colour AuthorColour; hsl_colour AuthorColour;
StringToColourHash(&AuthorColour, Anno->author); StringToColourHash(&AuthorColour, Anno->author);
CopyStringToBuffer(&Text, if(EDITION == EDITION_NETWORK)
{
fprintf(stderr, "%s:%d - TODO(matt): Implement author hoverbox\n", __FILE__, __LINE__);
// NOTE(matt): We should get instructions on how to get this info in the config
CopyStringToBuffer(&Text,
"<a class=\"author\" href=\"https://handmade.network/m/%s\" target=\"blank\" style=\"color: hsl(%d, %d%%, %d%%); text-decoration: none\" data-hue=\"%d\" data-saturation=\"%d%%\">%s</a> ",
Anno->author,
AuthorColour.Hue, AuthorColour.Saturation, AuthorColour.Lightness,
AuthorColour.Hue, AuthorColour.Saturation,
Anno->author);
}
else
{
CopyStringToBuffer(&Text,
"<span class=\"author\" style=\"color: hsl(%d, %d%%, %d%%);\" data-hue=\"%d\" data-saturation=\"%d%%\">%s</span> ", "<span class=\"author\" style=\"color: hsl(%d, %d%%, %d%%);\" data-hue=\"%d\" data-saturation=\"%d%%\">%s</span> ",
AuthorColour.Hue, AuthorColour.Saturation, AuthorColour.Lightness, AuthorColour.Hue, AuthorColour.Saturation, AuthorColour.Lightness,
AuthorColour.Hue, AuthorColour.Saturation, AuthorColour.Hue, AuthorColour.Saturation,
Anno->author); Anno->author);
}
if(!HasMedium) if(!HasMedium)
{ {
HasMedium = TRUE; HasMedium = TRUE;
@ -1308,14 +1368,26 @@ Anno->author);
{ {
hsl_colour MemberColour; hsl_colour MemberColour;
StringToColourHash(&MemberColour, Anno->markers[MarkerIndex].marker); StringToColourHash(&MemberColour, Anno->markers[MarkerIndex].marker);
CopyStringToBuffer(&Text, if(EDITION == EDITION_NETWORK)
// TODO(matt): Hoverbox {
// We should get instructions on how to get this info in the config fprintf(stderr, "%s:%d - TODO(matt): Implement member hoverbox\n", __FILE__, __LINE__);
// NOTE(matt): We should get instructions on how to get this info in the config
CopyStringToBuffer(&Text,
"<a class=\"member\" href=\"https://handmade.network/m/%s\" target=\"blank\" style=\"color: hsl(%d, %d%%, %d%%); text-decoration: none\" data-hue=\"%d\" data-saturation=\"%d%%\">%.*s</a>", "<a class=\"member\" href=\"https://handmade.network/m/%s\" target=\"blank\" style=\"color: hsl(%d, %d%%, %d%%); text-decoration: none\" data-hue=\"%d\" data-saturation=\"%d%%\">%.*s</a>",
Anno->markers[MarkerIndex].marker, Anno->markers[MarkerIndex].marker,
MemberColour.Hue, MemberColour.Saturation, MemberColour.Lightness, MemberColour.Hue, MemberColour.Saturation, MemberColour.Lightness,
MemberColour.Hue, MemberColour.Saturation, MemberColour.Hue, MemberColour.Saturation,
StringLength(Readable), InPtr); StringLength(Readable), InPtr);
}
else
{
CopyStringToBuffer(&Text,
"<span class=\"member\" style=\"color: hsl(%d, %d%%, %d%%);\" data-hue=\"%d\" data-saturation=\"%d%%\">%.*s</span>",
MemberColour.Hue, MemberColour.Saturation, MemberColour.Lightness,
MemberColour.Hue, MemberColour.Saturation,
StringLength(Readable), InPtr);
}
InPtr += StringLength(Readable); InPtr += StringLength(Readable);
++MarkerIndex; ++MarkerIndex;
} }
@ -1323,14 +1395,25 @@ StringLength(Readable), InPtr);
{ {
hsl_colour ProjectColour; hsl_colour ProjectColour;
StringToColourHash(&ProjectColour, Anno->markers[MarkerIndex].marker); StringToColourHash(&ProjectColour, Anno->markers[MarkerIndex].marker);
CopyStringToBuffer(&Text, if(EDITION == EDITION_NETWORK)
// TODO(matt): Hoverbox {
// We should get instructions on how to get this info in the config fprintf(stderr, "%s:%d - TODO(matt): Implement project hoverbox\n", __FILE__, __LINE__);
// NOTE(matt): We should get instructions on how to get this info in the config
CopyStringToBuffer(&Text,
"<a class=\"project\" href=\"https://%s.handmade.network/\" target=\"blank\" style=\"color: hsl(%d, %d%%, %d%%); text-decoration: none\" data-hue=\"%d\" data-saturation=\"%d%%\">%s</a>", "<a class=\"project\" href=\"https://%s.handmade.network/\" target=\"blank\" style=\"color: hsl(%d, %d%%, %d%%); text-decoration: none\" data-hue=\"%d\" data-saturation=\"%d%%\">%s</a>",
Anno->markers[MarkerIndex].marker, Anno->markers[MarkerIndex].marker,
ProjectColour.Hue, ProjectColour.Saturation, ProjectColour.Lightness, ProjectColour.Hue, ProjectColour.Saturation, ProjectColour.Lightness,
ProjectColour.Hue, ProjectColour.Saturation, ProjectColour.Hue, ProjectColour.Saturation,
Readable); Readable);
}
else
{
CopyStringToBuffer(&Text,
"<span class=\"project\" style=\"color: hsl(%d, %d%%, %d%%);\" data-hue=\"%d\" data-saturation=\"%d%%\">%s</span>",
ProjectColour.Hue, ProjectColour.Saturation, ProjectColour.Lightness,
ProjectColour.Hue, ProjectColour.Saturation,
Readable);
}
InPtr += StringLength(Readable); InPtr += StringLength(Readable);
++MarkerIndex; ++MarkerIndex;
} }
@ -1539,16 +1622,19 @@ AppendedIdentifier:
" <span data-id=\"&#%d;\" class=\"ref\">\n" " <span data-id=\"&#%d;\" class=\"ref\">\n"
" <span class=\"ref_content\">\n" " <span class=\"ref_content\">\n"
" <div class=\"source\">Quote %d</div>\n" " <div class=\"source\">Quote %d</div>\n"
" <div class=\"ref_title\">%s</div>\n" " <div class=\"ref_title\">",
QuoteIdentifier,
Anno->quote.id);
CopyStringToBufferCSVSafe(&QuoteMenu, QuoteInfo.Text);
CopyStringToBuffer(&QuoteMenu, "</div>\n"
" <div class=\"quote_byline\">&mdash;%s, %s</div>\n" " <div class=\"quote_byline\">&mdash;%s, %s</div>\n"
" </span>\n" " </span>\n"
" <div class=\"ref_indices\">\n" " <div class=\"ref_indices\">\n"
" <span data-timestamp=\"%d\" class=\"timecode\"><span class=\"ref_index\">[&#%d;]</span><span class=\"time\">%s</span></span>\n" " <span data-timestamp=\"%d\" class=\"timecode\"><span class=\"ref_index\">[&#%d;]</span><span class=\"time\">%s</span></span>\n"
" </div>\n" " </div>\n"
" </span>\n", " </span>\n",
QuoteIdentifier,
Anno->quote.id,
QuoteInfo.Text,
HMML.metadata.twitch ? HMML.metadata.twitch : HMML.metadata.member, HMML.metadata.twitch ? HMML.metadata.twitch : HMML.metadata.member,
QuoteInfo.Date, QuoteInfo.Date,
TimecodeToSeconds(Anno->time), TimecodeToSeconds(Anno->time),