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:
parent
2f5057f36b
commit
95d0f63da0
|
@ -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, "<");
|
||||||
|
String++;
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
CopyStringToBuffer(Dest, ">");
|
||||||
|
String++;
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
CopyStringToBuffer(Dest, "&");
|
||||||
|
String++;
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
CopyStringToBuffer(Dest, """);
|
||||||
|
String += 2;
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
CopyStringToBuffer(Dest, "'");
|
||||||
|
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\">—%s, %s</div>\n"
|
" <div class=\"quote_byline\">—%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),
|
||||||
|
|
Loading…
Reference in New Issue