cinera.c: Add support for alternative URL prefixes

This is hardcoded for now, for ease of use, pending the config system

Also add Medium to the ProjectInfo array, to save users having to set
this with -m (which option remains available to them)

Reorganise the CSS, Images and JS files back to their location in the
same directory, since a default invocation of the program assumes they
are in the same directory as the Root Directory, to hopefully alleviate
some potential user frustration thanks to the requirement to set their
locations (with -c, -i and -j) before any usable output is produced
This commit is contained in:
Matt Mascarenhas 2017-12-07 21:07:36 +00:00
parent f454e01e28
commit 6f751dd2b2
7 changed files with 173 additions and 137 deletions

View File

@ -14,7 +14,7 @@ typedef struct
version CINERA_APP_VERSION = {
.Major = 0,
.Minor = 5,
.Patch = 5
.Patch = 6
};
#define CINERA_DB_VERSION 1
@ -115,6 +115,8 @@ typedef struct
char *OutLocation;
char *OutIntegratedLocation;
char *ProjectDir;
char *URLPrefix; /* NOTE(matt): This will become a full blown customisable output URL.
For now it simply replaces the ProjectID */
} config;
typedef struct
@ -342,25 +344,28 @@ typedef struct
char *ProjectID;
char *FullName;
char *Unit; // e.g. Day, Episode, Session
int NumberingScheme;
int NumberingScheme; // numbering_schemes
char *Medium;
char *AltURLPrefix; // NOTE(matt): This currently just straight up replaces the ProjectID in the player pages' output directories
} project_info;
project_info ProjectInfo[] =
{
{ "book", "Book Club", "Day", NS_LINEAR },
{ "riscy", "RISCY BUSINESS", "Day", NS_LINEAR },
{ "book", "Book Club", "Day", NS_LINEAR, "research", "" },
{ "pcalc", "pcalc", "Day", NS_LINEAR, "programming", "" },
{ "riscy", "RISCY BUSINESS", "Day", NS_LINEAR, "programming", "" },
{ "chat", "Handmade Chat", "Day", NS_LINEAR },
{ "code", "Handmade Hero", "Day", NS_LINEAR },
{ "intro-to-c", "Intro to C on Windows", "Day", NS_LINEAR },
{ "misc", "Handmade Miscellany", "", NS_LINEAR },
{ "ray", "Handmade Ray", "Day", NS_LINEAR },
{ "chat", "Handmade Chat", "Day", NS_LINEAR, "speech", "" },
{ "code", "Handmade Hero", "Day", NS_LINEAR, "programming", "day" },
{ "intro-to-c", "Intro to C on Windows", "Day", NS_LINEAR, "programming", "day" },
{ "misc", "Handmade Miscellany", "", NS_LINEAR, "admin", "" },
{ "ray", "Handmade Ray", "Day", NS_LINEAR, "programming", "" },
{ "hmdshow", "HandmadeDev Show", "", NS_SEASONAL },
{ "hmdshow", "HandmadeDev Show", "", NS_SEASONAL, "speech", "" },
{ "obbg", "Open Block Building Game", "Episode", NS_LINEAR },
{ "obbg", "Open Block Building Game", "Episode", NS_LINEAR, "programming", "" },
{ "sysadmin", "SysAdmin", "Session", NS_LINEAR },
{ "sysadmin", "SysAdmin", "Session", NS_LINEAR, "admin", "" },
};
#define ArrayCount(A) sizeof(A)/sizeof(*(A))
@ -887,6 +892,62 @@ SanitisePunctuation(char *String)
return String;
}
enum
{
INCLUDE_CSS,
INCLUDE_Images,
INCLUDE_JS,
} include_types;
enum
{
PAGE_PLAYER = 1 << 0,
PAGE_INDEX = 1 << 1
} pages;
void
ConstructURLPrefix(buffer *URLPrefix, int IncludeType, int PageType)
{
ClaimBuffer(URLPrefix, "URLPrefix", 1024);
if(StringsDiffer(Config.RootURL, ""))
{
URLPrefix->Ptr += CopyString(URLPrefix->Ptr, "%s/", Config.RootURL);
}
else
{
if(Config.Edition == EDITION_PROJECT)
{
if(PageType == PAGE_PLAYER)
{
URLPrefix->Ptr += CopyString(URLPrefix->Ptr, "../");
}
URLPrefix->Ptr += CopyString(URLPrefix->Ptr, "../");
}
}
switch(IncludeType)
{
case INCLUDE_CSS:
if(StringsDiffer(Config.CSSDir, ""))
{
URLPrefix->Ptr += CopyString(URLPrefix->Ptr, "%s/", Config.CSSDir);
}
break;
case INCLUDE_Images:
if(StringsDiffer(Config.ImagesDir, ""))
{
URLPrefix->Ptr += CopyString(URLPrefix->Ptr, "%s/", Config.ImagesDir);
}
break;
case INCLUDE_JS:
if(StringsDiffer(Config.JSDir, ""))
{
URLPrefix->Ptr += CopyString(URLPrefix->Ptr, "%s/", Config.JSDir);
}
break;
}
}
enum
{
CreditsError_NoHost,
@ -940,29 +1001,14 @@ SearchCredentials(buffer *CreditsMenu, bool *HasCreditsMenu, char *Person, char
if(*Credentials[CredentialIndex].SupportIcon && *Credentials[CredentialIndex].SupportURL)
{
char URLPrefix[1024] = { 0 };
char *Ptr = URLPrefix;
if(StringsDiffer(Config.RootURL, ""))
{
Ptr += CopyString(Ptr, "%s/", Config.RootURL);
}
else
{
if(Config.Edition == EDITION_PROJECT)
{
Ptr += CopyString(Ptr, "../");
}
}
if(StringsDiffer(Config.ImagesDir, ""))
{
CopyString(Ptr, "%s/", Config.ImagesDir);
}
buffer URLPrefix;
ConstructURLPrefix(&URLPrefix, INCLUDE_Images, PAGE_INDEX);
CopyStringToBuffer(CreditsMenu,
" <a class=\"support\" href=\"%s\" target=\"_blank\"><div class=\"support_icon\" style=\"background-image: url(%s%s);\"></div></a>\n",
Credentials[CredentialIndex].SupportURL,
URLPrefix,
URLPrefix.Location,
Credentials[CredentialIndex].SupportIcon);
DeclaimBuffer(&URLPrefix);
}
CopyStringToBuffer(CreditsMenu,
@ -1684,12 +1730,6 @@ DepartComment(buffer *Template)
}
}
enum
{
PAGE_PLAYER = 1 << 0,
PAGE_INDEX = 1 << 1
} pages;
int
ValidateTemplate(buffer *Errors, template **Template, int PageType)
{
@ -2609,31 +2649,16 @@ AppendedIdentifier:
" };\n"
" </script>\n");
char URLPrefix[1024] = { 0 };
char *Ptr = URLPrefix;
if(StringsDiffer(Config.RootURL, ""))
{
Ptr += CopyString(Ptr, "%s/", Config.RootURL);
}
else
{
if(Config.Edition == EDITION_PROJECT)
{
Ptr += CopyString(Ptr, "../");
}
}
if(StringsDiffer(Config.ImagesDir, ""))
{
CopyString(Ptr, "%s/", Config.ImagesDir);
}
buffer URLPrefix;
ConstructURLPrefix(&URLPrefix, INCLUDE_Images, PAGE_INDEX);
CopyStringToBuffer(&FilterMenu,
" <div class=\"menu filter\">\n"
" <span><img src=\"%scinera_icon_filter.png\"></span>\n"
" <div class=\"filter_container\">\n"
" <div class=\"filter_mode inclusive\">Filter mode: </div>\n"
" <div class=\"filters\">\n",
URLPrefix);
URLPrefix.Location);
DeclaimBuffer(&URLPrefix);
if(Topics.Count > 0)
{
@ -2977,24 +3002,8 @@ AppendedIdentifier:
// TODO(matt): Maybe do something about indentation levels
char URLPrefix[1024] = { 0 };
char *Ptr = URLPrefix;
if(StringsDiffer(Config.RootURL, ""))
{
Ptr += CopyString(Ptr, "%s/", Config.RootURL);
}
else
{
if(Config.Edition == EDITION_PROJECT)
{
Ptr += CopyString(Ptr, "../");
}
}
if(StringsDiffer(Config.CSSDir, ""))
{
CopyString(Ptr, "%s/", Config.CSSDir);
}
buffer URLPrefix;
ConstructURLPrefix(&URLPrefix, INCLUDE_CSS, PAGE_INDEX);
CopyStringToBuffer(&CollationBuffers->IncludesIndex,
"<link rel=\"stylesheet\" type=\"text/css\" href=\"%scinera.css\">\n"
" <link rel=\"stylesheet\" type=\"text/css\" href=\"%scinera__%s.css\">\n"
@ -3003,24 +3012,16 @@ AppendedIdentifier:
"\n"
" <meta charset=\"UTF-8\">\n"
" <meta name=\"generator\" content=\"Cinera %d.%d.%d\">\n",
URLPrefix,
URLPrefix, StringsDiffer(Config.Theme, "") ? Config.Theme : HMML.metadata.project,
URLPrefix,
URLPrefix.Location,
URLPrefix.Location, StringsDiffer(Config.Theme, "") ? Config.Theme : HMML.metadata.project,
URLPrefix.Location,
CINERA_APP_VERSION.Major,
CINERA_APP_VERSION.Minor,
CINERA_APP_VERSION.Patch);
DeclaimBuffer(&URLPrefix);
if(Config.Edition == EDITION_PROJECT)
{
if(!StringsDiffer(Config.RootURL, ""))
{
char Temp[1027];
CopyString(Temp, "../%s", URLPrefix);
CopyString(URLPrefix, Temp);
}
}
ConstructURLPrefix(&URLPrefix, INCLUDE_CSS, PAGE_PLAYER);
CopyStringToBuffer(&CollationBuffers->IncludesPlayer,
"<link rel=\"stylesheet\" type=\"text/css\" href=\"%scinera.css\">\n"
" <link rel=\"stylesheet\" type=\"text/css\" href=\"%scinera__%s.css\">\n"
@ -3028,13 +3029,14 @@ AppendedIdentifier:
"\n"
" <meta charset=\"UTF-8\">\n"
" <meta name=\"generator\" content=\"Cinera %d.%d.%d\">\n",
URLPrefix,
URLPrefix, StringsDiffer(Config.Theme, "") ? Config.Theme : HMML.metadata.project,
URLPrefix,
URLPrefix.Location,
URLPrefix.Location, StringsDiffer(Config.Theme, "") ? Config.Theme : HMML.metadata.project,
URLPrefix.Location,
CINERA_APP_VERSION.Major,
CINERA_APP_VERSION.Minor,
CINERA_APP_VERSION.Patch);
DeclaimBuffer(&URLPrefix);
if(Topics.Count || Media.Count)
{
@ -3061,30 +3063,15 @@ AppendedIdentifier:
CopyStringToBuffer(&CollationBuffers->IncludesPlayer, "\">\n\n");
}
Ptr = URLPrefix;
if(StringsDiffer(Config.RootURL, ""))
{
Ptr += StringLength(Config.RootURL) + 1;
}
else
{
if(Config.Edition == EDITION_PROJECT)
{
Ptr += StringLength("../");
}
}
if(StringsDiffer(Config.JSDir, ""))
{
CopyString(Ptr, "%s/", Config.JSDir);
}
ConstructURLPrefix(&URLPrefix, INCLUDE_JS, PAGE_PLAYER);
CopyStringToBuffer(&CollationBuffers->IncludesPlayer,
" <script type=\"text/javascript\" src=\"%scinera_player_pre.js\"></script>\n",
URLPrefix);
URLPrefix.Location);
CopyStringToBuffer(&CollationBuffers->ScriptPlayer,
" <script type=\"text/javascript\" src=\"%scinera_player_post.js\"></script>\n",
URLPrefix);
URLPrefix.Location);
DeclaimBuffer(&URLPrefix);
if(HasFilterMenu)
{
@ -3764,31 +3751,23 @@ IndexToBuffer(buffers *CollationBuffers)
StringsDiffer(Config.Theme, "") ? Config.Theme : Config.ProjectID,
StringsDiffer(Config.Theme, "") ? Config.Theme : Config.ProjectID);
char URLPrefix[1024] = { 0 };
char *Ptr = URLPrefix;
if(StringsDiffer(Config.RootURL, ""))
{
Ptr += CopyString(Ptr, "%s/", Config.RootURL);
}
else
{
Ptr += CopyString(Ptr, "../");
}
if(StringsDiffer(Config.JSDir, ""))
{
Ptr += CopyString(Ptr, "%s/", Config.JSDir);
}
buffer URLPrefix;
ClaimBuffer(&URLPrefix, "URLPrefix", 1024);
ConstructURLPrefix(&URLPrefix, INCLUDE_JS, PAGE_INDEX);
char Script[512 + StringLength(URLPrefix) + (StringLength(Config.ProjectID) * 2)];
char Script[512 + StringLength(URLPrefix.Location) + (StringLength(Config.ProjectID) * 2)];
CopyString(Script, " </dl>\n"
" <script type=\"text/javascript\">\n"
" var indexLocation = \"%s.index\";\n"
" var projectID = \"%s\";\n"
" var theme = \"%s\";\n"
" var outputURLPrefix = \"%s\";\n"
" </script>\n"
" <script type=\"text/javascript\" src=\"%scinera_search.js\"></script>\n",
Config.ProjectID,
StringsDiffer(Config.Theme, "") ? Config.Theme : Config.ProjectID,
URLPrefix);
StringsDiffer(Config.URLPrefix, "") ? Config.URLPrefix : Config.ProjectID,
URLPrefix.Location);
DeclaimBuffer(&URLPrefix);
int EntryLength = 32 + StringLength(ProjectInfo[ProjectIndex].Unit) + 16 + 256;
@ -3822,16 +3801,34 @@ IndexToBuffer(buffers *CollationBuffers)
CopyStringNoFormatT(Title, Index.File.Buffer.Ptr, '\n');
Title[StringLength(Title) - 1] = '\0';
char BaseFilename[255];
if(StringsDiffer(Config.URLPrefix, ""))
{
char *Ptr = This.BaseFilename + StringLength(Config.ProjectID);
CopyString(BaseFilename, "%s%s", Config.URLPrefix, Ptr);
}
else
{
CopyString(BaseFilename, "%s", This.BaseFilename);
}
if(StringsDiffer(ProjectInfo[ProjectIndex].Unit, ""))
{
CopyStringToBuffer(&CollationBuffers->Index,
" <dt>\n"
" <a href=\"%s\">%s %s: %s</a>\n"
" </dt>\n",
This.BaseFilename,
" <a href=\"%s\">", BaseFilename);
char Text[1024]; // NOTE(matt): Surely this will be big enough
CopyString(Text, "%s %s: %s",
ProjectInfo[ProjectIndex].Unit, // TODO(matt): Do we need to special-case the various numbering schemes?
Number,
Title);
CopyStringToBufferHTMLSafe(&CollationBuffers->Index, Text);
CopyStringToBuffer(&CollationBuffers->Index,
"</a>\n"
" </dt>\n");
}
else
{
@ -3839,7 +3836,7 @@ IndexToBuffer(buffers *CollationBuffers)
" <dt>\n"
" <a href=\"%s\">%s</a>\n"
" </dt>\n",
This.BaseFilename,
BaseFilename,
Title);
}
@ -3863,7 +3860,15 @@ int
GeneratePlayerPage(buffers *CollationBuffers, template *PlayerTemplate, char *BaseFilename)
{
char OutputDir[256];
CopyString(OutputDir, "%s/%s", Config.BaseDir, BaseFilename);
if(StringsDiffer(Config.URLPrefix, ""))
{
char *Ptr = BaseFilename + StringLength(Config.ProjectID);
CopyString(OutputDir, "%s/%s%s", Config.BaseDir, Config.URLPrefix, Ptr);
}
else
{
CopyString(OutputDir, "%s/%s", Config.BaseDir, BaseFilename);
}
char PlayerPagePath[256];
CopyString(PlayerPagePath, "%s/index.html", OutputDir);
@ -3899,7 +3904,15 @@ DeletePlayerPageFromFilesystem(char *BaseFilename)
{
// NOTE(matt): Once we have the notion of an output filename format, we'll need to use that here
char PlayerDirPath[256];
CopyString(PlayerDirPath, "%s/%s", Config.BaseDir, BaseFilename);
if(StringsDiffer(Config.URLPrefix, ""))
{
char *Ptr = BaseFilename + StringLength(Config.ProjectID);
CopyString(PlayerDirPath, "%s/%s%s", Config.BaseDir, Config.URLPrefix, Ptr);
}
else
{
CopyString(PlayerDirPath, "%s/%s", Config.BaseDir, BaseFilename);
}
DIR *PlayerDir;
if((PlayerDir = opendir(PlayerDirPath))) // There is a directory for the Player, which there probably should be if not for manual intervention
@ -4163,7 +4176,8 @@ main(int ArgC, char **Args)
.Theme = "",
.TemplatePlayerLocation = "template_player.html",
.TemplateIndexLocation = "template_index.html",
.UpdateInterval = 4
.UpdateInterval = 4,
.URLPrefix = ""
};
if(getenv("XDG_CACHE_HOME"))
@ -4253,6 +4267,21 @@ main(int ArgC, char **Args)
if(StringsDiffer(Config.ProjectID, ""))
{
Config.Edition = EDITION_PROJECT;
for(int ProjectInfoIndex = 0; ProjectInfoIndex < ArrayCount(ProjectInfo); ++ProjectInfoIndex)
{
if(!StringsDiffer(Config.ProjectID, ProjectInfo[ProjectInfoIndex].ProjectID))
{
if(StringsDiffer(ProjectInfo[ProjectInfoIndex].Medium, ""))
{
Config.DefaultMedium = ProjectInfo[ProjectInfoIndex].Medium;
}
if(StringsDiffer(ProjectInfo[ProjectInfoIndex].AltURLPrefix, ""))
{
Config.URLPrefix = ProjectInfo[ProjectInfoIndex].AltURLPrefix;
}
break;
}
}
}
bool ValidDefaultMedium = FALSE;
@ -4405,6 +4434,7 @@ main(int ArgC, char **Args)
" ID:\t\t\t\t%s\n"
" Input Directory:\t\t%s\n"
" Output Base Directory:\t%s\n"
" Player Page URL Prefix:\t%s\n"
" Default Medium:\t\t%s\n"
" Style / Theme:\t\t%s\n"
"\n"
@ -4413,6 +4443,7 @@ main(int ArgC, char **Args)
Config.ProjectID,
Config.ProjectDir,
Config.BaseDir,
StringsDiffer(Config.URLPrefix, "") ? Config.URLPrefix : Config.ProjectID,
Config.DefaultMedium,
StringsDiffer(Config.Theme, "") ? Config.Theme: Config.ProjectID);

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -17,7 +17,7 @@ var rendering = false;
var dayContainerPrototype = document.createElement("DIV");
dayContainerPrototype.classList.add("dayContainer");
dayContainerPrototype.classList.add(projectID);
dayContainerPrototype.classList.add(theme);
var dayNamePrototype = document.createElement("SPAN");
dayNamePrototype.classList.add("dayName");
@ -25,7 +25,7 @@ dayContainerPrototype.appendChild(dayNamePrototype);
var markerListPrototype = document.createElement("DIV");
markerListPrototype.classList.add("markerList");
markerListPrototype.classList.add(projectID);
markerListPrototype.classList.add(theme);
dayContainerPrototype.appendChild(markerListPrototype);
var markerPrototype = document.createElement("A");
@ -206,7 +206,12 @@ xhr.addEventListener("load", function() {
episode = {};
mode = "none";
} else if (line.startsWith("name:")) {
episode.name = line.slice(6);
if(projectID != outputURLPrefix) {
episode.name = line.slice(6).replace(projectID, outputURLPrefix);
}
else {
episode.name = line.slice(6);
}
} else if (line.startsWith("title:")) {
episode.title = line.slice(7).replace(/"/g, "");
} else if (line.startsWith("markers")) {
@ -233,7 +238,7 @@ xhr.addEventListener("load", function() {
xhr.addEventListener("error", function() {
console.error("Failed to load content");
});
xhr.open("GET", indexLocation);
xhr.open("GET", projectID + ".index");
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.send();

View File

Before

Width:  |  Height:  |  Size: 881 B

After

Width:  |  Height:  |  Size: 881 B