diff --git a/cinera/cinera.c b/cinera/cinera.c index e17809f..8a56577 100644 --- a/cinera/cinera.c +++ b/cinera/cinera.c @@ -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, "
\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" " \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, "
\n" " \n" "
\n" "
Filter mode:
\n" "
\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, "\n" " \n" @@ -3003,24 +3012,16 @@ AppendedIdentifier: "\n" " \n" " \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, "\n" " \n" @@ -3028,13 +3029,14 @@ AppendedIdentifier: "\n" " \n" " \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, " \n", - URLPrefix); + URLPrefix.Location); CopyStringToBuffer(&CollationBuffers->ScriptPlayer, " \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, " \n" " \n" " \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, "
\n" - " %s %s: %s\n" - "
\n", - This.BaseFilename, + " ", 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, + "\n" + " \n"); } else { @@ -3839,7 +3836,7 @@ IndexToBuffer(buffers *CollationBuffers) "
\n" " %s\n" "
\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); diff --git a/cinera/css/cinera.css b/cinera/cinera.css similarity index 100% rename from cinera/css/cinera.css rename to cinera/cinera.css diff --git a/cinera/images/cinera_icon_filter.png b/cinera/cinera_icon_filter.png similarity index 100% rename from cinera/images/cinera_icon_filter.png rename to cinera/cinera_icon_filter.png diff --git a/cinera/js/cinera_player_post.js b/cinera/cinera_player_post.js similarity index 100% rename from cinera/js/cinera_player_post.js rename to cinera/cinera_player_post.js diff --git a/cinera/js/cinera_player_pre.js b/cinera/cinera_player_pre.js similarity index 100% rename from cinera/js/cinera_player_pre.js rename to cinera/cinera_player_pre.js diff --git a/cinera/js/cinera_search.js b/cinera/cinera_search.js similarity index 96% rename from cinera/js/cinera_search.js rename to cinera/cinera_search.js index a66d8ac..a0b97b1 100644 --- a/cinera/js/cinera_search.js +++ b/cinera/cinera_search.js @@ -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(); diff --git a/cinera/images/cinera_sprite_patreon.png b/cinera/cinera_sprite_patreon.png similarity index 100% rename from cinera/images/cinera_sprite_patreon.png rename to cinera/cinera_sprite_patreon.png