#include "EpubDocuments.hpp" #include #include #include #include namespace margelo::nitro::nitroepub { namespace { std::string xmlEscape(const std::string& value) { std::string escaped; escaped.reserve(value.size()); for (const char character : value) { switch (character) { case '&': escaped += "&"; break; case '<': escaped += "<"; break; case '>': escaped += ">"; break; case '"': escaped += """; break; case '\'': escaped += "'"; break; default: escaped += character; break; } } return escaped; } std::string modifiedTimestamp() { const std::time_t now = std::chrono::system_clock::to_time_t( std::chrono::system_clock::now()); std::tm utc{}; #ifdef _WIN32 gmtime_s(&utc, &now); #else gmtime_r(&now, &utc); #endif std::ostringstream timestamp; timestamp << std::put_time(&utc, "%Y-%m-%dT%H:%M:%SZ"); return timestamp.str(); } } // namespace std::string containerDocument() { return R"( )"; } std::string chapterDocument(const EpubArchiveChapter& chapter, const std::string& body, bool hasJavaScript) { const std::string title = xmlEscape(chapter.title); const std::string script = hasJavaScript ? R"( )" : ""; const std::string onLoad = hasJavaScript ? " onload=\"fnEpub()\"" : ""; return R"( )" + title + R"( )" + script + R"( )" + body + R"( )"; } std::string navigationDocument( const EpubArchiveMetadata& metadata, const std::vector& chapters) { std::ostringstream items; for (std::size_t index = 0; index < chapters.size(); ++index) { items << "
  • " << xmlEscape(chapters[index].title) << "
  • \n"; } return R"( )" + xmlEscape(metadata.title) + R"( )"; } std::string ncxDocument( const EpubArchiveMetadata& metadata, const std::vector& chapters) { std::ostringstream points; for (std::size_t index = 0; index < chapters.size(); ++index) { points << " \n" << " " << xmlEscape(chapters[index].title) << "\n" << " \n" << " \n"; } return R"( )" + xmlEscape(metadata.title) + R"( )" + points.str() + R"( )"; } std::string packageDocument( const EpubArchiveMetadata& metadata, const std::vector& chapters, const std::vector& assets, const EpubAsset* cover, bool hasJavaScript) { std::ostringstream manifest; manifest << " \n" << " \n" << " \n"; if (hasJavaScript) { manifest << " \n"; } if (cover != nullptr) { manifest << " archivePath.substr(5)) << "\" media-type=\"" << cover->mediaType << "\" properties=\"cover-image\"/>\n"; } for (const EpubAsset& asset : assets) { manifest << " \n"; } for (std::size_t index = 0; index < chapters.size(); ++index) { manifest << " \n"; } std::ostringstream spine; for (std::size_t index = 0; index < chapters.size(); ++index) { spine << " \n"; } return R"( )" + xmlEscape(metadata.bookId) + R"( )" + xmlEscape(metadata.title) + R"( )" + xmlEscape(metadata.language) + R"( )" + xmlEscape(metadata.author) + R"( )" + xmlEscape(metadata.description) + R"( )" + modifiedTimestamp() + R"( )" + manifest.str() + R"( )" + spine.str() + R"( )"; } } // namespace margelo::nitro::nitroepub