This commit is contained in:
Green
2025-08-11 00:31:40 +03:00
parent baf8321c61
commit 4ea504f688

View File

@ -153,6 +153,17 @@ std::wstring EncodeXmlString(const std::wstring& s)
return sRes; return sRes;
} }
enum class EParagraphPropertie
{
Sup,
Sub,
Strikethrough,
Emphasis,
Strong
};
typedef std::vector<EParagraphPropertie> ParagraphProperties;
class CFb2File_Private class CFb2File_Private
{ {
public: public:
@ -175,6 +186,8 @@ private:
bool m_bInNote; bool m_bInNote;
bool m_bInTable; bool m_bInTable;
ParagraphProperties m_arParagraphProperties;
// STitleInfo* m_pSrcTitleInfo; // Данные об исходнике книги // STitleInfo* m_pSrcTitleInfo; // Данные об исходнике книги
// SPublishInfo* m_pPublishInfo; // Сведения об издании книги // SPublishInfo* m_pPublishInfo; // Сведения об издании книги
// std::map<std::wstring, std::wstring> m_mCustomInfo; // Произвольная информация // std::map<std::wstring, std::wstring> m_mCustomInfo; // Произвольная информация
@ -221,6 +234,58 @@ public:
return m_oLightReader.ReadNextNode() && m_oLightReader.GetName() == L"FictionBook"; return m_oLightReader.ReadNextNode() && m_oLightReader.GetName() == L"FictionBook";
} }
void OpenP(NSStringUtils::CStringBuilder& oBuilder)
{
if (m_bInP || m_bInTable)
return;
oBuilder.WriteString(L"<p>");
m_bInP = true;
}
void CloseP(NSStringUtils::CStringBuilder& oBuilder)
{
if (!m_bInP || m_bInTable)
return;
oBuilder.WriteString(L"</p>");
m_bInP = false;
}
void WriteText(NSStringUtils::CStringBuilder& oBuilder, const std::wstring& wsText, const std::vector<EParagraphPropertie>& arPProperties)
{
if (wsText.end() == std::find_if_not(wsText.begin(), wsText.end(), [](wchar_t wchChar){ return iswspace(wchChar) && 0xa0 != wchChar;}))
return;
OpenP(oBuilder);
for (const EParagraphPropertie ePropertie : arPProperties)
{
switch(ePropertie)
{
case EParagraphPropertie::Sup: oBuilder.WriteString(L"<sup>"); break;
case EParagraphPropertie::Sub: oBuilder.WriteString(L"<sub>"); break;
case EParagraphPropertie::Strikethrough: oBuilder.WriteString(L"<strikethrough>"); break;
case EParagraphPropertie::Emphasis: oBuilder.WriteString(L"<emphasis>"); break;
case EParagraphPropertie::Strong: oBuilder.WriteString(L"<strong>"); break;
}
}
oBuilder.WriteEncodeXmlString(wsText);
for (ParagraphProperties::const_reverse_iterator itPropertie = arPProperties.crbegin(); itPropertie != arPProperties.crend(); ++itPropertie)
{
switch(*itPropertie)
{
case EParagraphPropertie::Sup: oBuilder.WriteString(L"</sup>"); break;
case EParagraphPropertie::Sub: oBuilder.WriteString(L"</sub>"); break;
case EParagraphPropertie::Strikethrough: oBuilder.WriteString(L"</strikethrough>"); break;
case EParagraphPropertie::Emphasis: oBuilder.WriteString(L"</emphasis>"); break;
case EParagraphPropertie::Strong: oBuilder.WriteString(L"</strong>"); break;
}
}
}
// Читает image // Читает image
// НЕ имеет право писать p // НЕ имеет право писать p
void readImage(NSStringUtils::CStringBuilder& oBuilder) void readImage(NSStringUtils::CStringBuilder& oBuilder)
@ -1449,7 +1514,7 @@ public:
// html -> fb2 // html -> fb2
void readStream(NSStringUtils::CStringBuilder& oXml) void readStream(NSStringUtils::CStringBuilder& oXml, ParagraphProperties& arPProperties)
{ {
int nDepth = m_oLightReader.GetDepth(); int nDepth = m_oLightReader.GetDepth();
if (m_oLightReader.IsEmptyNode() || !m_oLightReader.ReadNextSiblingNode2(nDepth)) if (m_oLightReader.IsEmptyNode() || !m_oLightReader.ReadNextSiblingNode2(nDepth))
@ -1458,7 +1523,7 @@ public:
{ {
std::wstring sName = m_oLightReader.GetName(); std::wstring sName = m_oLightReader.GetName();
if (sName == L"#text") if (sName == L"#text")
oXml.WriteEncodeXmlString(m_oLightReader.GetText()); WriteText(oXml, m_oLightReader.GetText(), arPProperties);
else if (sName == L"br" && !m_bInTable) else if (sName == L"br" && !m_bInTable)
{ {
bool bPBB = false, bCBB = false; bool bPBB = false, bCBB = false;
@ -1501,26 +1566,18 @@ public:
m_oLightReader.MoveToElement(); m_oLightReader.MoveToElement();
if (m_bFootnote && !sFootnoteName.empty()) if (m_bFootnote && !sFootnoteName.empty())
{ {
readStream(oFootnote); readStream(oFootnote, arPProperties);
m_mFootnotes.insert(std::make_pair(sFootnoteName, oFootnote.GetData())); m_mFootnotes.insert(std::make_pair(sFootnoteName, oFootnote.GetData()));
m_bFootnote = false; m_bFootnote = false;
} }
else else
readStream(oXml); readStream(oXml, arPProperties);
} }
else if (sName == L"p") else if (sName == L"p")
{ {
if (!m_bInTable && !m_bInP) OpenP(oXml);
{ readStream(oXml, arPProperties);
oXml.WriteString(L"<p>"); CloseP(oXml);
m_bInP = true;
}
readStream(oXml);
if (!m_bInTable && m_bInP)
{
oXml.WriteString(L"</p>");
m_bInP = false;
}
} }
else if (sName == L"title") else if (sName == L"title")
{ {
@ -1564,7 +1621,7 @@ public:
bInH = true; bInH = true;
m_bInP = true; m_bInP = true;
} }
readStream(oXml); readStream(oXml, arPProperties);
if (bInH) if (bInH)
{ {
oXml.WriteString(L"</p></title>"); oXml.WriteString(L"</p></title>");
@ -1590,52 +1647,55 @@ public:
sAlign = sStyle.substr(nAlign + 1, (nAlignEnd < sStyle.length() ? nAlignEnd : sStyle.length()) - nAlign); sAlign = sStyle.substr(nAlign + 1, (nAlignEnd < sStyle.length() ? nAlignEnd : sStyle.length()) - nAlign);
if (sAlign == L"super") if (sAlign == L"super")
{ {
oXml.WriteString(L"<sup>"); arPProperties.push_back(EParagraphPropertie::Sup);
readStream(oXml); readStream(oXml, arPProperties);
oXml.WriteString(L"</sup>"); arPProperties.pop_back();
} }
else if (sAlign == L"sub") else if (sAlign == L"sub")
{ {
oXml.WriteString(L"<sub>"); arPProperties.push_back(EParagraphPropertie::Sub);
readStream(oXml); readStream(oXml, arPProperties);
oXml.WriteString(L"</sub>"); arPProperties.pop_back();
} }
else else
readStream(oXml); readStream(oXml, arPProperties);
} }
else else
readStream(oXml); readStream(oXml, arPProperties);
} }
else if (sName == L"s") else if (sName == L"s")
{ {
oXml.WriteString(L"<strikethrough>"); arPProperties.push_back(EParagraphPropertie::Strikethrough);
readStream(oXml); readStream(oXml, arPProperties);
oXml.WriteString(L"</strikethrough>"); arPProperties.pop_back();
} }
else if (sName == L"i") else if (sName == L"i")
{ {
oXml.WriteString(L"<emphasis>"); arPProperties.push_back(EParagraphPropertie::Emphasis);
readStream(oXml); readStream(oXml, arPProperties);
oXml.WriteString(L"</emphasis>"); arPProperties.pop_back();
} }
else if (sName == L"b") else if (sName == L"b")
{ {
oXml.WriteString(L"<strong>"); arPProperties.push_back(EParagraphPropertie::Strong);
readStream(oXml); readStream(oXml, arPProperties);
oXml.WriteString(L"</strong>"); arPProperties.pop_back();
} }
else if (sName == L"table") else if (sName == L"table")
{ {
oXml.WriteString(L"<table>"); oXml.WriteString(L"<table>");
m_bInTable = true; m_bInTable = true;
readStream(oXml);
ParagraphProperties arTableProperties;
readStream(oXml, arTableProperties);
oXml.WriteString(L"</table>"); oXml.WriteString(L"</table>");
m_bInTable = false; m_bInTable = false;
} }
else if (sName == L"tr") else if (sName == L"tr")
{ {
oXml.WriteString(L"<tr>"); oXml.WriteString(L"<tr>");
readStream(oXml); readStream(oXml, arPProperties);
oXml.WriteString(L"</tr>"); oXml.WriteString(L"</tr>");
} }
else if (sName == L"td" || sName == L"th") else if (sName == L"td" || sName == L"th")
@ -1650,7 +1710,7 @@ public:
} }
m_oLightReader.MoveToElement(); m_oLightReader.MoveToElement();
oXml.WriteString(L">"); oXml.WriteString(L">");
readStream(oXml); readStream(oXml, arPProperties);
oXml.WriteString(L"</td>"); oXml.WriteString(L"</td>");
} }
else if (sName == L"a") else if (sName == L"a")
@ -1690,13 +1750,13 @@ public:
m_oLightReader.MoveToElement(); m_oLightReader.MoveToElement();
oXml.WriteString(L">"); oXml.WriteString(L">");
readStream(oXml); readStream(oXml, arPProperties);
oXml.WriteString(L"</a>"); oXml.WriteString(L"</a>");
} }
else if (sName == L"ul") else if (sName == L"ul")
readLi(oXml, true); readLi(oXml, true, arPProperties);
else if (sName == L"ol") else if (sName == L"ol")
readLi(oXml, false); readLi(oXml, false, arPProperties);
else if (sName == L"img") else if (sName == L"img")
{ {
std::wstring sId, sBinary; std::wstring sId, sBinary;
@ -1716,11 +1776,11 @@ public:
oXml.WriteString(L"<image l:href=\"#img" + sId + L".png\"/>"); oXml.WriteString(L"<image l:href=\"#img" + sId + L".png\"/>");
} }
else else
readStream(oXml); readStream(oXml, arPProperties);
} while (m_oLightReader.ReadNextSiblingNode2(nDepth)); } while (m_oLightReader.ReadNextSiblingNode2(nDepth));
} }
void readLi(NSStringUtils::CStringBuilder& oXml, bool bUl) void readLi(NSStringUtils::CStringBuilder& oXml, bool bUl, ParagraphProperties& arProperties)
{ {
int nNum = 1; int nNum = 1;
while (m_oLightReader.MoveToNextAttribute()) while (m_oLightReader.MoveToNextAttribute())
@ -1734,9 +1794,8 @@ public:
{ {
if (m_oLightReader.GetName() == L"li") if (m_oLightReader.GetName() == L"li")
{ {
if (!m_bInP) OpenP(oXml);
oXml.WriteString(L"<p>");
m_bInP = true;
if (bUl) if (bUl)
oXml.AddCharSafe(183); oXml.AddCharSafe(183);
else else
@ -1773,10 +1832,9 @@ public:
oXml.WriteString(sPoint); oXml.WriteString(sPoint);
} }
oXml.WriteString(L" "); oXml.WriteString(L" ");
readStream(oXml); readStream(oXml, arProperties);
if (m_bInP)
oXml.WriteString(L"</p>"); CloseP(oXml);
m_bInP = false;
} }
} while (m_oLightReader.ReadNextSiblingNode2(nDeath)); } while (m_oLightReader.ReadNextSiblingNode2(nDeath));
} }
@ -2113,6 +2171,7 @@ HRESULT CFb2File::FromHtml(const std::wstring& sHtmlFile, const std::wstring& sD
//XmlUtils::CXmlLiteReader oIndexHtml; //XmlUtils::CXmlLiteReader oIndexHtml;
std::wstring xhtml = htmlToXhtml(sContent, bNeedConvert); std::wstring xhtml = htmlToXhtml(sContent, bNeedConvert);
if (!m_internal->m_oLightReader.FromString(xhtml)) if (!m_internal->m_oLightReader.FromString(xhtml))
return S_FALSE; return S_FALSE;
@ -2123,7 +2182,8 @@ HRESULT CFb2File::FromHtml(const std::wstring& sHtmlFile, const std::wstring& sD
//std::vector<std::wstring> arrBinary; //std::vector<std::wstring> arrBinary;
NSStringUtils::CStringBuilder oDocument; NSStringUtils::CStringBuilder oDocument;
m_internal->readStream(oDocument); ParagraphProperties arProperties;
m_internal->readStream(oDocument, arProperties);
NSStringUtils::CStringBuilder oRes; NSStringUtils::CStringBuilder oRes;
oRes.WriteString(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?><FictionBook xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.0\" xmlns:l=\"http://www.w3.org/1999/xlink\">"); oRes.WriteString(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?><FictionBook xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.0\" xmlns:l=\"http://www.w3.org/1999/xlink\">");