Add Article namespace for metadata parsing

Added a new namespace used for parsing article metadata embedded in
article Markdown files, and updated the Makefile accordingly.
This commit is contained in:
luca0N! 2022-04-22 18:02:44 -03:00
parent 7dc67e3563
commit 0624e9bb60
Signed by: luca0N
GPG Key ID: 2E7B4655CF16D7D6
3 changed files with 191 additions and 3 deletions

View File

@ -24,8 +24,8 @@ CXXFLAGS=-Wall -Wextra -g -O0 -std=c++17
.PHONY: clean .PHONY: clean
$(PROGRAM_NAME): build/ build/obj/ build/obj/main.o build/obj/ConfigUtils.o build/obj/WebsiteBuilder.o build/obj/SwgRuntime.o build/obj/MarkdownParser.o $(PROGRAM_NAME): build/ build/obj/ build/obj/main.o build/obj/ConfigUtils.o build/obj/WebsiteBuilder.o build/obj/SwgRuntime.o build/obj/MarkdownParser.o build/obj/Article.o
$(CXXC) -o $(PROGRAM_NAME) build/obj/main.o build/obj/ConfigUtils.o build/obj/WebsiteBuilder.o build/obj/SwgRuntime.o build/obj/MarkdownParser.o $(CXXC) -o $(PROGRAM_NAME) build/obj/main.o build/obj/ConfigUtils.o build/obj/WebsiteBuilder.o build/obj/SwgRuntime.o build/obj/MarkdownParser.o build/obj/Article.o
build/obj/main.o: src/main.cxx src/ConfigUtils.hxx src/SwgContext.hxx src/WebsiteBuilder.hxx src/Common.hxx 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 $(CXXC) $(CXXFLAGS) -o build/obj/main.o -c src/main.cxx
@ -33,7 +33,7 @@ build/obj/main.o: src/main.cxx src/ConfigUtils.hxx src/SwgContext.hxx src/Websit
build/obj/ConfigUtils.o: src/ConfigUtils.cxx src/SwgContext.hxx src/Common.hxx build/obj/ConfigUtils.o: src/ConfigUtils.cxx src/SwgContext.hxx src/Common.hxx
$(CXXC) $(CXXFLAGS) -o build/obj/ConfigUtils.o -c src/ConfigUtils.cxx $(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 src/MarkdownParser.hxx build/obj/WebsiteBuilder.o: src/WebsiteBuilder.hxx src/WebsiteBuilder.cxx src/SwgRuntime.hxx src/Common.hxx src/MarkdownParser.hxx src/Article.hxx
$(CXXC) $(CXXFLAGS) -o build/obj/WebsiteBuilder.o -c src/WebsiteBuilder.cxx $(CXXC) $(CXXFLAGS) -o build/obj/WebsiteBuilder.o -c src/WebsiteBuilder.cxx
build/obj/SwgRuntime.o: src/SwgRuntime.hxx src/SwgRuntime.cxx build/obj/SwgRuntime.o: src/SwgRuntime.hxx src/SwgRuntime.cxx
@ -42,6 +42,9 @@ build/obj/SwgRuntime.o: src/SwgRuntime.hxx src/SwgRuntime.cxx
build/obj/MarkdownParser.o: src/MarkdownParser.hxx src/MarkdownParser.cxx build/obj/MarkdownParser.o: src/MarkdownParser.hxx src/MarkdownParser.cxx
$(CXXC) $(CXXFLAGS) -o build/obj/MarkdownParser.o -c src/MarkdownParser.cxx $(CXXC) $(CXXFLAGS) -o build/obj/MarkdownParser.o -c src/MarkdownParser.cxx
build/obj/Article.o: src/Article.hxx src/Article.cxx
$(CXXC) $(CXXFLAGS) -o build/obj/Article.o -c src/Article.cxx
build/: build/:
mkdir -p build/ mkdir -p build/

135
src/Article.cxx Normal file
View File

@ -0,0 +1,135 @@
/*
* 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 "Article.hxx"
#include <iostream>
#include <list>
#include <string.h>
#include "Common.hxx"
enum IterationStage {
CHECKING_TITLE,
READING_TITLE,
CHECKING
};
namespace Article {
/*
* FIXME: The article metadata declaration uses the same INI format as
* swg.cfg. Since they use the exact same format, we could unify the .cfg
* parsing into one function.
*/
void get_metadata(std::string const &path, Metadata *m) {
memset(m, 0, sizeof(Metadata));
FILE *a = fopen(path.c_str(), "r");
int buflen = 16;
char buf[buflen];
const char *det_article = "<!--SwgArticle";
size_t det_article_pos = 0;
bool reading_metadata = false,
done = false,
skip = false;
std::list<std::string> cfg_lines = { "" };
while (fgets(buf, buflen, a) != NULL) {
// Ignore blank lines or lines starting with a comment.
if (buf[0] == '\n' || buf[0] == '#') continue;
int eol = -1;
for (int c = 0; c < buflen; c++) {
// Check if this loop has already done what it's supposed to do by checking if the title has been set.
if (done || buf[c] == '\0') break;
if (!reading_metadata) {
// FIXME: This code will not work if buflen < strlen(det_article).
if (buf[c] == det_article[det_article_pos]) {
det_article_pos++;
} else {
// TODO: Instead of exiting with an
// error code, prompt the end user
// whether the build should continue
// (while ignoring this article) or
// stop.
std::cerr << "error: invalid article: " << path << "\n";
exit(RETURN_FAILED_UNKNOWN_ERROR);
}
if (det_article_pos == strlen(det_article)) {
reading_metadata = true;
skip = true;
}
}
// Check end of HTML comment
if (buf[c] == '-' &&
buf[c+1] == '-' &&
buf[c+2] == '>') {
reading_metadata = false;
done = true;
break;
}
if (buf[c] == '\n')
eol = c;
}
if (skip) { skip = false; continue; }
if (done) break;
if (reading_metadata) {
if (eol > -1) {
buf[eol] = '\0';
*(--cfg_lines.end()) += buf;
cfg_lines.insert(cfg_lines.end(), "");
} else
*(--cfg_lines.end()) += buf;
}
}
bool reading_article_metadata = false;
for (std::string const &line : cfg_lines) {
std::cout << "[!] Line: " << line << "\n";
// Check namespace
if (reading_article_metadata) {
std::string k_title = "Title=",
k_authors = "Authors=",
k_published = "Published=";
if (line.find(k_title) == 0)
strncpy(m->title, line.substr(k_title.length()).c_str(), sizeof(m->title));
else if (line.find(k_authors) == 0)
strncpy(m->authors, line.substr(k_authors.length()).c_str(), sizeof(m->authors));
else if (line.find(k_published) == 0)
m->publish_ts = atoi(line.substr(k_published.length()).c_str());
else
std::cerr << "warning: ignoring unknown key/value due to unknown key: " << line << std::endl;
} else if (line[0] == '[') {
if (line == "[ArticleMetadata]") {
reading_article_metadata = true;
} else {
std::cerr << "error: article properties has unknown namespace: " << line << std::endl;
exit(RETURN_FAILED_CONFIG_INVALID_SYNTAX);
}
}
}
fclose(a);
}
};

50
src/Article.hxx Normal file
View File

@ -0,0 +1,50 @@
/*
* 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>
namespace Article {
struct Metadata {
char title[128];
char authors[128]; // Author (or authors) for this article
// Epoch timestamps
long original_ts; // Original article timestamp (for "Originally written on [...]")
long publish_ts; // (for "Published on [...]")
long update_ts; // (for "Last updated on [...]")
// Article flags
bool partially_obsoleted,
obsoleted,
mature_content;
char partially_obsoleted_reason[256],
obsoleted_reason[256],
obsoletion_followup_article[128],
mature_content_reason[256];
};
void get_metadata(std::string const &path, Metadata *m);
}