Proper series detection
This commit is contained in:
@@ -67,6 +67,18 @@ std::string stripHtml(const std::string& html) {
|
||||
while (!out.empty() && out.back() == ' ') out.pop_back();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string trim(const std::string& in) {
|
||||
size_t start = 0;
|
||||
while (start < in.size() && (in[start] == ' ' || in[start] == '\n' || in[start] == '\r' || in[start] == '\t')) {
|
||||
++start;
|
||||
}
|
||||
size_t end = in.size();
|
||||
while (end > start && (in[end - 1] == ' ' || in[end - 1] == '\n' || in[end - 1] == '\r' || in[end - 1] == '\t')) {
|
||||
--end;
|
||||
}
|
||||
return in.substr(start, end - start);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool ContentOpfParser::setup() {
|
||||
@@ -217,12 +229,15 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
|
||||
if (self->state == IN_METADATA && (strcmp(name, "meta") == 0 || strcmp(name, "opf:meta") == 0)) {
|
||||
const char* metaName = nullptr;
|
||||
const char* metaContent = nullptr;
|
||||
const char* metaProperty = nullptr;
|
||||
|
||||
for (int i = 0; atts[i]; i += 2) {
|
||||
if (strcmp(atts[i], "name") == 0) {
|
||||
metaName = atts[i + 1];
|
||||
} else if (strcmp(atts[i], "content") == 0) {
|
||||
metaContent = atts[i + 1];
|
||||
} else if (strcmp(atts[i], "property") == 0) {
|
||||
metaProperty = atts[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +250,23 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
|
||||
self->seriesIndex = metaContent;
|
||||
}
|
||||
}
|
||||
|
||||
// EPUB 3 collection metadata:
|
||||
// <meta property="belongs-to-collection">Series Name</meta>
|
||||
// <meta property="group-position">1</meta>
|
||||
if (metaProperty) {
|
||||
if (strcmp(metaProperty, "belongs-to-collection") == 0 && self->series.empty()) {
|
||||
self->series.clear();
|
||||
self->state = IN_BOOK_SERIES;
|
||||
return;
|
||||
}
|
||||
if (strcmp(metaProperty, "group-position") == 0 && self->seriesIndex.empty()) {
|
||||
self->seriesIndex.clear();
|
||||
self->state = IN_BOOK_SERIES_INDEX;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -411,6 +443,16 @@ void XMLCALL ContentOpfParser::characterData(void* userData, const XML_Char* s,
|
||||
self->description.append(s, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_BOOK_SERIES) {
|
||||
self->series.append(s, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_BOOK_SERIES_INDEX) {
|
||||
self->seriesIndex.append(s, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void XMLCALL ContentOpfParser::endElement(void* userData, const XML_Char* name) {
|
||||
@@ -456,6 +498,18 @@ void XMLCALL ContentOpfParser::endElement(void* userData, const XML_Char* name)
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_BOOK_SERIES && (strcmp(name, "meta") == 0 || strcmp(name, "opf:meta") == 0)) {
|
||||
self->series = trim(self->series);
|
||||
self->state = IN_METADATA;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_BOOK_SERIES_INDEX && (strcmp(name, "meta") == 0 || strcmp(name, "opf:meta") == 0)) {
|
||||
self->seriesIndex = trim(self->seriesIndex);
|
||||
self->state = IN_METADATA;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_METADATA && (strcmp(name, "metadata") == 0 || strcmp(name, "opf:metadata") == 0)) {
|
||||
self->state = IN_PACKAGE;
|
||||
return;
|
||||
|
||||
@@ -18,6 +18,8 @@ class ContentOpfParser final : public Print {
|
||||
IN_BOOK_AUTHOR,
|
||||
IN_BOOK_LANGUAGE,
|
||||
IN_BOOK_DESCRIPTION,
|
||||
IN_BOOK_SERIES,
|
||||
IN_BOOK_SERIES_INDEX,
|
||||
IN_MANIFEST,
|
||||
IN_SPINE,
|
||||
IN_GUIDE,
|
||||
|
||||
Reference in New Issue
Block a user