Add original source files
This commit is contained in:
parent
6e1bdc8870
commit
98b74941db
|
@ -0,0 +1,49 @@
|
|||
# Copyright (C) 2022 luca0N!
|
||||
#
|
||||
# This file is part of Static Website Generator (swg).
|
||||
#
|
||||
# Static Website Generator (swg) is free software: you can redistribute it
|
||||
# and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
# Public License as published by the Free Software Foundation.
|
||||
#
|
||||
# Static Website Generator (swg) is distributed in the hope that it will be
|
||||
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Static Website Generator (swg). If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
|
||||
PROGRAM_NAME=swg
|
||||
|
||||
CXXC=g++
|
||||
CXXFLAGS=-Wall -Wextra -g -O0 -std=c++17
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
$(PROGRAM_NAME): build/ build/obj/ build/obj/main.o build/obj/ConfigUtils.o build/obj/WebsiteBuilder.o build/obj/SwgRuntime.o
|
||||
$(CXXC) -o $(PROGRAM_NAME) build/obj/main.o build/obj/ConfigUtils.o build/obj/WebsiteBuilder.o build/obj/SwgRuntime.o
|
||||
|
||||
build/obj/main.o: src/main.cxx src/ConfigUtils.hxx src/SwgContext.hxx src/WebsiteBuilder.hxx src/Common.hxx
|
||||
$(CXXC) $(CXXFLAGS) -o build/obj/main.o -c src/main.cxx
|
||||
|
||||
build/obj/ConfigUtils.o: src/ConfigUtils.cxx src/SwgContext.hxx src/Common.hxx
|
||||
$(CXXC) $(CXXFLAGS) -o build/obj/ConfigUtils.o -c src/ConfigUtils.cxx
|
||||
|
||||
build/obj/WebsiteBuilder.o: src/WebsiteBuilder.hxx src/WebsiteBuilder.cxx src/SwgRuntime.hxx src/Common.hxx
|
||||
$(CXXC) $(CXXFLAGS) -o build/obj/WebsiteBuilder.o -c src/WebsiteBuilder.cxx
|
||||
|
||||
build/obj/SwgRuntime.o: src/SwgRuntime.hxx src/SwgRuntime.cxx
|
||||
$(CXXC) $(CXXFLAGS) -o build/obj/SwgRuntime.o -c src/SwgRuntime.cxx
|
||||
|
||||
build/:
|
||||
mkdir -p build/
|
||||
|
||||
build/obj/:
|
||||
mkdir -p build/obj/
|
||||
|
||||
clean:
|
||||
rm -rfv build/ $(PROGRAM_NAME)
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define PROGRAM_NAME "SWG"
|
||||
#define PROGRAM_VERSION 1
|
||||
#define PROGRAM_VERSION_NAME "0.1-dev"
|
||||
#define PROGRAM_COPYRIGHT "luca0N!"
|
||||
#define PROGRAM_COPYRIGHT_YEARS "2022"
|
||||
|
||||
#define RETURN_SUCCESSFUL 0
|
||||
|
||||
#define RETURN_FAILED_INVALID_SYNTAX 1
|
||||
#define RETURN_FAILED_CONFIG_INVALID_SYNTAX 2
|
||||
#define RETURN_FAILED_INVALID_DIRECTORY 3
|
||||
#define RETURN_FAILED_WEBSITE_BUILD_EXISTS 4
|
||||
|
||||
#define RETURN_FAILED_UNKNOWN_ERROR 10
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#include "ConfigUtils.hxx"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include "Common.hxx"
|
||||
|
||||
void parse_config(SwgContext *ctx, std::string const &path) {
|
||||
std::string ctxCfgPath = path;
|
||||
ctxCfgPath += "/swg.cfg";
|
||||
|
||||
FILE *ctxCfgFile = fopen(ctxCfgPath.c_str(), "r");
|
||||
|
||||
if (ctxCfgFile == NULL) {
|
||||
std::cerr << "error: cannot open swg.cfg file, are you sure "
|
||||
<< path << " is a valid SWG directory?" << std::endl;
|
||||
perror(ctxCfgPath.c_str());
|
||||
exit(RETURN_FAILED_INVALID_DIRECTORY);
|
||||
}
|
||||
|
||||
int buflen = 16;
|
||||
char cbuf[buflen];
|
||||
|
||||
// Yes, this looks ugly, but it works for now. Will probably optimize
|
||||
// this in the future :)
|
||||
//
|
||||
// TODO: Optimize config file interpretation
|
||||
|
||||
std::list<std::string> lines = { "" };
|
||||
while (fgets(cbuf, buflen, ctxCfgFile) != NULL) {
|
||||
int eol = -1;
|
||||
for (int c = 0; c < buflen; c++) {
|
||||
if (cbuf[c] == '\0') {
|
||||
break;
|
||||
} else if (cbuf[c] == '\n') {
|
||||
eol = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (eol > -1) {
|
||||
cbuf[eol] = '\0';
|
||||
*(--lines.end()) += cbuf;
|
||||
lines.insert(lines.end(), "");
|
||||
} else
|
||||
*(--lines.end()) += cbuf;
|
||||
}
|
||||
|
||||
fclose(ctxCfgFile);
|
||||
|
||||
std::cout << "Done loading configuration file in memory" << std::endl;
|
||||
|
||||
// Parse configuration file
|
||||
|
||||
enum ConfigNamespace { General, Blogs };
|
||||
ConfigNamespace ns;
|
||||
|
||||
int blogCount = 0;
|
||||
Blog *currentBlog = NULL; // (Blog*) malloc(sizeof(Blog));
|
||||
|
||||
// currentBlog->name = "asd";
|
||||
|
||||
for (std::string line : lines) {
|
||||
// Skip comment lines
|
||||
if (line.c_str()[0] == '#')
|
||||
continue;
|
||||
|
||||
if (line.c_str()[0] == '[') {
|
||||
if (line == "[General]") {
|
||||
ns = General;
|
||||
continue;
|
||||
} else if (line == "[Blogs]") {
|
||||
ns = Blogs;
|
||||
continue;
|
||||
} else {
|
||||
std::cerr << "error: unknown namespace in config file: " << line << std::endl;
|
||||
exit(RETURN_FAILED_CONFIG_INVALID_SYNTAX);
|
||||
}
|
||||
}
|
||||
|
||||
// Skip empty lines
|
||||
if (line == "") continue;
|
||||
|
||||
int end = line.find("=");
|
||||
std::string k = line.substr(0, end),
|
||||
v = line.substr(end + 2,
|
||||
(line.length() - 1) - (end + 2));
|
||||
|
||||
switch (ns) {
|
||||
case General:
|
||||
if (k == "WebsiteName")
|
||||
ctx->websiteName = v;
|
||||
else if (k == "WebsitePublisher")
|
||||
ctx->websitePublisher = v;
|
||||
else if (k == "WebsiteCopyrightHolder")
|
||||
ctx->websiteCopyrightHolder = v;
|
||||
else if (k == "WebsiteCopyrightYears")
|
||||
ctx->websiteCopyrightYears = v;
|
||||
else if (k == "websiteContentLicense")
|
||||
ctx->websiteContentLicense = v;
|
||||
else
|
||||
std::cerr << "warning: unknown key in namespace \"General\": " << k << std::endl;
|
||||
continue;
|
||||
case Blogs:
|
||||
// FIXME: This code only accepts up to 9 blogs.
|
||||
if (line.substr(0, 4) == "Blog") {
|
||||
// Check No.
|
||||
int blogNo = atoi(line.substr(4, 1).c_str());
|
||||
if (blogNo != blogCount &&
|
||||
blogNo != blogCount +1){
|
||||
std::cerr << "error: blog declaration must be incremental (received "
|
||||
<< blogNo << " instead of " << blogCount << " or " << blogCount + 1
|
||||
<< ")" << std::endl;
|
||||
exit(RETURN_FAILED_CONFIG_INVALID_SYNTAX);
|
||||
} else if (blogNo == blogCount + 1) {
|
||||
blogCount++;
|
||||
if (currentBlog != NULL) ctx->blogs.push_back(currentBlog);
|
||||
currentBlog = (Blog*) malloc(sizeof(Blog));
|
||||
// Clear allocated memory
|
||||
memset(currentBlog, 0, sizeof(Blog));
|
||||
}
|
||||
|
||||
assert(currentBlog != NULL);
|
||||
//std::cout << "Attempting to set K/V" << std::endl;
|
||||
|
||||
if (k.substr(5) == "Path") {
|
||||
//std::cout << "Setting path (" << v << ") for " << blogCount << std::endl;
|
||||
strncpy(currentBlog->path, v.c_str(), sizeof(currentBlog->path));
|
||||
} else if (k.substr(5) == "Name") {
|
||||
//std::cout << "Setting name (" << v << ") for " << blogCount << std::endl;
|
||||
strncpy(currentBlog->name, v.c_str(), sizeof(currentBlog->name));
|
||||
} else if (k.substr(5) == "Dir") {
|
||||
strncpy(currentBlog->dir, v.c_str(), sizeof(currentBlog->dir));
|
||||
} else {
|
||||
std::cerr << "warning: unknown key in namespace \"Blogs\": " << k << "\n";
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (currentBlog != NULL) ctx->blogs.push_back(currentBlog);
|
||||
/*std::cout << "Loaded " << blogCount << " blogs into memory" << std::endl;
|
||||
for (Blog *b : ctx->blogs) {
|
||||
std::cout << "\t" << b->name << ": " << b->path << std::endl;
|
||||
}*/
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include "SwgContext.hxx"
|
||||
|
||||
void parse_config(SwgContext *ctx, std::string const &path);
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
struct Blog {
|
||||
char name[64],
|
||||
path[64],
|
||||
dir[64];
|
||||
int test;
|
||||
};
|
||||
|
||||
struct SwgContext {
|
||||
std::string websiteName,
|
||||
websitePublisher,
|
||||
websiteCopyrightHolder,
|
||||
websiteCopyrightYears,
|
||||
websiteContentLicense;
|
||||
|
||||
// TODO: Use smart pointers
|
||||
std::list<Blog*> blogs;
|
||||
};
|
||||
|
||||
/*class SwgContext {
|
||||
public:
|
||||
SwgContext();
|
||||
SwgContext(std::string websiteName, std::string websitePublisher, std::string copyrightHolder, std::string copyrightYears, std::string contentLicense);
|
||||
|
||||
|
||||
private:
|
||||
std::string websiteName, websitePublisher;
|
||||
std::string copyrightHolder, copyrightYears, contentLicense;
|
||||
};
|
||||
|
||||
class BlogEntry {
|
||||
public:
|
||||
BlogEntry(std::string name, std::string path);
|
||||
std::string getBlogName();
|
||||
std::string getBlogPath();
|
||||
private:
|
||||
std::string path, name;
|
||||
};*/
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#include "SwgRuntime.hxx"
|
||||
|
||||
bool swg_rt_global_bool(const char *name, bool ifne) {
|
||||
// TODO: Check for runtime option and return it (if it's set, return ifne otherwise).
|
||||
return ifne;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Utilities for options set during runtime by the end-user (i.e. through command line options).
|
||||
|
||||
bool swg_rt_global_bool(const char *name, bool ifne);
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "SwgRuntime.hxx"
|
||||
#include "SwgContext.hxx"
|
||||
#include "ConfigUtils.hxx"
|
||||
// #include "Blog.h"
|
||||
#include "Common.hxx"
|
||||
|
||||
std::string blog_relative_path(std::string const &pathPrefix, std::string const &path) {
|
||||
return path.substr(pathPrefix.length() - 1);
|
||||
}
|
||||
|
||||
std::string getFilename(std::string const &path) {
|
||||
// Backwards search for directory separator.
|
||||
for (int x = path.length(); x > 0; --x) {
|
||||
if (path[x] == '/')
|
||||
return path.substr(x + 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
bool isValidArticle(std::string const &pathPrefix, std::string const &path) {
|
||||
return std::regex_search(blog_relative_path(pathPrefix, path), std::regex("^/\\d{4}/\\d{2}/.*\\.md"));
|
||||
}
|
||||
|
||||
std::filesystem::path get_output_path(std::string const &path) {
|
||||
std::filesystem::path output = path;
|
||||
return output /= "output";
|
||||
}
|
||||
|
||||
void build_dir_structure(std::string const &path) {
|
||||
// Create directory tree, which will be used for the website.
|
||||
std::filesystem::path rootDir = get_output_path(path);
|
||||
|
||||
// Create output directory if it doesn't exist.
|
||||
try {
|
||||
if(!std::filesystem::exists(rootDir)) std::filesystem::create_directory(rootDir);
|
||||
} catch (std::filesystem::filesystem_error const &e) {
|
||||
std::cerr << "error: fs error while generating output website directory structure on \""
|
||||
<< path << "\": " << e.what() << std::endl;
|
||||
exit(RETURN_FAILED_UNKNOWN_ERROR);
|
||||
}
|
||||
|
||||
// Check if a website has already been built.
|
||||
//
|
||||
// This is a safe measure to prevent overwriting an existing website
|
||||
// output, but it can be skipped if explicitly asked by the end-user.
|
||||
if (!swg_rt_global_bool("overwrite_existing", false)) {
|
||||
std::filesystem::path websiteLock = rootDir /= ".swg_built";
|
||||
if (std::filesystem::exists(websiteLock)) {
|
||||
std::cout << "error: existing website build detected, exiting...\n";
|
||||
exit(RETURN_FAILED_WEBSITE_BUILD_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_template(std::string const &path) {
|
||||
// Template lookup
|
||||
std::string stPath = path;
|
||||
stPath += "/__swg_template.html";
|
||||
FILE *swgTemplate = fopen(stPath.c_str(), "r");
|
||||
if (swgTemplate == NULL) {
|
||||
std::cerr << "error: couldn't open the SWG HTML template file; does it exist?\n";
|
||||
perror(stPath.c_str());
|
||||
exit(RETURN_FAILED_INVALID_DIRECTORY);
|
||||
}
|
||||
|
||||
// Check for content placeholder
|
||||
int buflen = 8;
|
||||
char buf[buflen];
|
||||
std::string htmlTemplate;
|
||||
while (fgets(buf, buflen, swgTemplate) != NULL) {
|
||||
htmlTemplate += buf;
|
||||
}
|
||||
|
||||
fclose(swgTemplate);
|
||||
std::cout << "Loaded HTML template into memory.\n";
|
||||
return htmlTemplate;
|
||||
}
|
||||
|
||||
void build_blog_structure(std::string const &path, std::string const &prefix, std::list<std::string> const &articles, Blog *blog) {
|
||||
std::filesystem::path obp = get_output_path(path) /= blog->dir; // Output Blog Path
|
||||
try {
|
||||
// Create blog directory
|
||||
if (!std::filesystem::exists(obp)) std::filesystem::create_directory(obp);
|
||||
} catch (std::filesystem::filesystem_error const &e) {
|
||||
std::cerr << "error: failed to create directory for blog \"" << blog->name << "\": " << e.what() << std::endl;
|
||||
exit(RETURN_FAILED_UNKNOWN_ERROR);
|
||||
}
|
||||
|
||||
for (std::string const &a : articles) {
|
||||
std::string articlePath = blog_relative_path(prefix, a);
|
||||
std::regex yearMonth("(\\d+)");
|
||||
auto match = std::sregex_iterator(articlePath.begin(), articlePath.end(), yearMonth);
|
||||
|
||||
std::string year = match->str(),
|
||||
month = (++match)->str();
|
||||
|
||||
/*std::cout << "Year for \"" << articlePath << "\": " << year << "\n";
|
||||
std::cout << "Month for \"" << articlePath << "\": " << month << "\n";*/
|
||||
|
||||
// TODO: This code could be optimized by removing directory
|
||||
// checks for every single article. Instead, add
|
||||
// directory-checks for years and months to a queue (skipping
|
||||
// existing ones) and then checking and creating the
|
||||
// directories later as needed.
|
||||
try {
|
||||
// Create directory for the year of this article if it doesn't exist.
|
||||
std::filesystem::path oad = obp /= year; // Output Article Directory
|
||||
if (!std::filesystem::exists(oad)) std::filesystem::create_directory(oad);
|
||||
|
||||
// Do the same for the article month.
|
||||
oad /= month;
|
||||
if (!std::filesystem::exists(oad)) std::filesystem::create_directory(oad);
|
||||
|
||||
// Now create the article file.
|
||||
oad /= getFilename(a);
|
||||
FILE *articleOutput = fopen(oad.string().c_str(), "w");
|
||||
FILE *articleFile = fopen(a.c_str(), "r");
|
||||
|
||||
std::string articleContents;
|
||||
|
||||
int buflen = 512;
|
||||
char buf[buflen];
|
||||
|
||||
while (fgets(buf, buflen, articleFile) != NULL) {
|
||||
articleContents += buf;
|
||||
}
|
||||
|
||||
fclose(articleFile);
|
||||
|
||||
std::string htmlTemplate = get_template(path);
|
||||
// NOTE: std::regex requires the C++11 standard.
|
||||
std::regex contentPlaceholder("<!--\\[_SWG: \\$CONTENT\\]-->");
|
||||
articleContents = std::regex_replace(htmlTemplate, contentPlaceholder, articleContents);
|
||||
|
||||
fputs(articleContents.c_str(), articleOutput);
|
||||
|
||||
fclose(articleOutput);
|
||||
} catch (std::filesystem::filesystem_error const &e) {
|
||||
std::cerr << "error: failed to create directory for an article from blog \""
|
||||
<< blog->name << "\": " << e.what() << std::endl;
|
||||
exit(RETURN_FAILED_UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void build_website(SwgContext &ctx, std::string const &path) {
|
||||
build_dir_structure(path);
|
||||
|
||||
// Blog lookup
|
||||
|
||||
bool failed = false;
|
||||
|
||||
for (Blog *b : ctx.blogs) {
|
||||
std::list<std::string> parsedArticles = { },
|
||||
failedArticles = { };
|
||||
|
||||
// std::filesystem requires the C++17 standard.
|
||||
std::string relativePath = path;
|
||||
relativePath += "/";
|
||||
relativePath += b->path;
|
||||
const std::filesystem::path blogPath(relativePath);
|
||||
try {
|
||||
for (auto const &dir_entry : std::filesystem::recursive_directory_iterator(blogPath)) {
|
||||
// Directory item iteration
|
||||
std::cout << "\t" << dir_entry << std::endl;
|
||||
|
||||
// Check if the item is a Markdown file.
|
||||
std::string filename = getFilename(dir_entry.path());
|
||||
if (dir_entry.is_regular_file() &&
|
||||
filename.find(".md") == filename.length() - 3) {
|
||||
std::cout << "\t\tIs file: " << getFilename(dir_entry.path()) << "\n";
|
||||
// Markdown files should be insite a YYYY/MM directory.
|
||||
if (!isValidArticle(relativePath, dir_entry.path()))
|
||||
failedArticles.insert(failedArticles.end(), dir_entry.path());
|
||||
else parsedArticles.insert(parsedArticles.end(), dir_entry.path());
|
||||
}
|
||||
}
|
||||
} catch (std::filesystem::filesystem_error const &e) {
|
||||
std::cerr << "error: fs error while attempting to read path for "
|
||||
<< b->name << ": " << e.what() << std::endl;
|
||||
failed = true;
|
||||
}
|
||||
|
||||
/*std::cout << "Parsed " << parsedArticles << " articles;\n" <<
|
||||
"Failed to parse " << failedArticles << " articles\n";*/
|
||||
|
||||
for (std::string const &a : parsedArticles)
|
||||
std::cout << "Parsed: " << a << "\n";
|
||||
for (std::string const &a : failedArticles)
|
||||
std::cout << "Unable to parse: " << a << "\n";
|
||||
|
||||
build_blog_structure(path, relativePath, parsedArticles, b);
|
||||
|
||||
free(b);
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
std::cerr << "Refusing to proceed due to previous errors\n";
|
||||
exit(RETURN_FAILED_CONFIG_INVALID_SYNTAX);
|
||||
}
|
||||
|
||||
// Website blog
|
||||
|
||||
// Append blog to website
|
||||
//ctx.appendBlog(blog1);
|
||||
|
||||
// Generate website
|
||||
//ctx.generateWebsite();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SwgContext.hxx"
|
||||
|
||||
void build_website(SwgContext &ctx, std::string const &path);
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "SwgContext.hxx"
|
||||
#include "ConfigUtils.hxx"
|
||||
// #include "Blog.h"
|
||||
#include "Common.hxx"
|
||||
#include "WebsiteBuilder.hxx"
|
||||
|
||||
void printUsage(const char *programName) {
|
||||
std::cerr << programName << ": usage: " << programName << " [path]"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void printIntro() {
|
||||
printf("%s v%s (%d)\nCopyright (C) %s %s\n\n",
|
||||
PROGRAM_NAME, PROGRAM_VERSION_NAME, PROGRAM_VERSION,
|
||||
PROGRAM_COPYRIGHT_YEARS, PROGRAM_COPYRIGHT);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printIntro();
|
||||
|
||||
std::string path;
|
||||
|
||||
// Parse cmdline options
|
||||
switch (argc) {
|
||||
case 1:
|
||||
path = ".";
|
||||
std::cout << "Assuming working directory is \".\""
|
||||
<< std::endl;
|
||||
break;
|
||||
case 2:
|
||||
path = argv[1];
|
||||
std::cout << "Using specified directory: "
|
||||
<< path << std::endl;
|
||||
break;
|
||||
default:
|
||||
printUsage(argv[0]);
|
||||
exit(RETURN_FAILED_INVALID_SYNTAX);
|
||||
break;
|
||||
}
|
||||
|
||||
SwgContext ctx;
|
||||
parse_config(&ctx, path);
|
||||
|
||||
build_website(ctx, path);
|
||||
|
||||
// Website blog
|
||||
|
||||
// Append blog to website
|
||||
//ctx.appendBlog(blog1);
|
||||
|
||||
// Generate website
|
||||
//ctx.generateWebsite();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue