diff --git a/Common/3dParty/html/htmltoxhtml.h b/Common/3dParty/html/htmltoxhtml.h
index 04dbdc22aa..71e78b520f 100644
--- a/Common/3dParty/html/htmltoxhtml.h
+++ b/Common/3dParty/html/htmltoxhtml.h
@@ -11,7 +11,6 @@
#include "../../../DesktopEditor/common/File.h"
#include "../../../DesktopEditor/common/Directory.h"
#include "../../../DesktopEditor/common/StringBuilder.h"
-#include "../../../DesktopEditor/xml/include/xmlutils.h"
#include "../../../UnicodeConverter/UnicodeConverter.h"
#include "../../../HtmlFile2/src/StringFinder.h"
diff --git a/HtmlFile2/Common.h b/HtmlFile2/Common.h
new file mode 100644
index 0000000000..203d33d645
--- /dev/null
+++ b/HtmlFile2/Common.h
@@ -0,0 +1,37 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include
+
+namespace HTML
+{
+void replace_all(std::wstring& s, const std::wstring& s1, const std::wstring& s2)
+{
+ size_t pos = s.find(s1);
+ size_t l = s2.length();
+ while (pos != std::string::npos)
+ {
+ if (!(s1 == L"&" && s2 == L"&" && s.length() > pos + 4 && s[pos] == L'&' && s[pos + 1] == L'a' && s[pos + 2] == L'm' && s[pos + 3] == L'p' && s[pos + 4] == L';'))
+ s.replace(pos, s1.length(), s2);
+ pos = s.find(s1, pos + l);
+ }
+}
+
+std::wstring EncodeXmlString(const std::wstring& s)
+{
+ std::wstring sRes = s;
+
+ replace_all(sRes, L"&", L"&");
+ replace_all(sRes, L"<", L"<");
+ replace_all(sRes, L">", L">");
+ replace_all(sRes, L"\"", L""");
+ replace_all(sRes, L"\'", L"'");
+ replace_all(sRes, L"\n", L"
");
+ replace_all(sRes, L"\r", L"
");
+ replace_all(sRes, L"\t", L" ");
+
+ return sRes;
+}
+}
+
+#endif // COMMON_H
diff --git a/HtmlFile2/HTML2OOXMLInterpretator.cpp b/HtmlFile2/HTML2OOXMLInterpretator.cpp
new file mode 100644
index 0000000000..4b4d3b9c92
--- /dev/null
+++ b/HtmlFile2/HTML2OOXMLInterpretator.cpp
@@ -0,0 +1,342 @@
+#include "HTML2OOXMLInterpretator.h"
+
+#include "../DesktopEditor/common/File.h"
+#include
+#include
+
+namespace HTML
+{
+inline bool ElementInTable(const std::vector& arSelectors);
+
+CHTML2OOXMLInterpretator::CHTML2OOXMLInterpretator()
+ : m_pCurrentDocument(&m_oDocXml), m_nFootnoteId(1), m_nHyperlinkId(1), m_nNumberingId(1), m_nId(1), m_nShapeId(1)
+{}
+
+bool CHTML2OOXMLInterpretator::OpenP()
+{
+ if (m_oState.m_bInP)
+ return false;
+
+ m_pCurrentDocument->WriteString(L"");
+ m_oState.m_bInP = true;
+ m_oState.m_bWasPStyle = false;
+
+ return true;
+}
+
+bool CHTML2OOXMLInterpretator::OpenR()
+{
+ if (m_oState.m_bInR)
+ return false;
+
+ m_pCurrentDocument->WriteString(L"");
+ m_oState.m_bInR = true;
+ return true;
+}
+
+bool CHTML2OOXMLInterpretator::OpenT()
+{
+ if (m_oState.m_bInT)
+ return false;
+
+ m_pCurrentDocument->WriteString(L"");
+ m_oState.m_bInT = true;
+ return true;
+}
+
+void CHTML2OOXMLInterpretator::CloseP(std::vector& arSelectors)
+{
+ m_oState.m_bWasSpace = true;
+
+ if (!m_oState.m_bInP)
+ return;
+
+ CloseT();
+ CloseR();
+
+ if (m_oState.m_bInHyperlink)
+ {
+ if (arSelectors.rend() != std::find_if(arSelectors.rbegin(), arSelectors.rend(), [](const NSCSS::CNode& oNode) { return L"a" == oNode.m_wsName; }))
+ {
+ m_pCurrentDocument->WriteString(L"");
+ m_oState.m_bInHyperlink = false;
+ }
+ }
+
+ m_pCurrentDocument->WriteString(L"");
+ m_oState.m_bInP = false;
+}
+
+void CHTML2OOXMLInterpretator::CloseR()
+{
+ if (!m_oState.m_bInR)
+ return;
+
+ m_pCurrentDocument->WriteString(L"");
+ m_oState.m_bInR = false;
+}
+
+void CHTML2OOXMLInterpretator::CloseT()
+{
+ if (!m_oState.m_bInT)
+ return;
+
+ m_pCurrentDocument->WriteString(L"");
+ m_oState.m_bInT = false;
+}
+
+void CHTML2OOXMLInterpretator::OpenCrossHyperlink(const std::wstring& wsRef, std::vector& arSelectors, CTextSettings& oTS)
+{
+ if (!OpenP())
+ CloseR();
+ else
+ WritePPr(arSelectors, oTS);
+
+ m_oState.m_bInHyperlink = true;
+
+ m_pCurrentDocument->WriteString(L"WriteEncodeXmlString(AddAnchor(wsAnchorValue));
+
+ m_pCurrentDocument->WriteString(L"\">");
+}
+
+void CHTML2OOXMLInterpretator::OpenExternalHyperlink(const std::wstring& wsRef, const std::wstring& wsTooltip, std::vector& arSelectors, CTextSettings& oTS)
+{
+ if (!OpenP())
+ CloseR();
+ else
+ WritePPr(arSelectors, oTS);
+
+ // Пишем рельсы
+ XmlString& oRelationshipXml(m_oDocXmlRels);
+
+ if (*&m_pCurrentDocument == &m_oNoteXml)
+ oRelationshipXml = m_oNoteXmlRels;
+
+ oRelationshipXml.WriteString(L"");
+
+ m_oState.m_bInHyperlink = true;
+ // Пишем в document.xml
+ m_pCurrentDocument->WriteString(L"WriteEncodeXmlString(wsTooltip);
+ m_pCurrentDocument->WriteString(L"\" r:id=\"rHyp");
+ m_pCurrentDocument->WriteString(std::to_wstring(m_nHyperlinkId++));
+ m_pCurrentDocument->WriteString(L"\">");
+}
+
+void CHTML2OOXMLInterpretator::CloseCrossHyperlink(std::vector& arSelectors, std::wstring wsFootnote, const std::wstring& wsRef)
+{
+ if (!m_oState.m_bInP)
+ return;
+
+ CloseExternalHyperlink();
+
+ bool bFootnote = false;
+ if (arSelectors.size() > 1)
+ {
+ const NSCSS::CNode& oNode = arSelectors[arSelectors.size() - 2];
+ bFootnote = oNode.m_wsName == L"p" && oNode.m_wsClass == L"MsoFootnoteText";
+ }
+
+ // Сноска
+ if (!wsFootnote.empty())
+ {
+ if (!bFootnote)
+ {
+ std::wstring sFootnoteID = std::to_wstring(m_nFootnoteId++);
+ OpenR();
+ m_pCurrentDocument->WriteString(L"WriteString(sFootnoteID);
+ m_pCurrentDocument->WriteString(L"\"/>");
+ CloseR();
+ m_mFootnotes.insert(std::make_pair(wsFootnote, sFootnoteID));
+ }
+ else
+ {
+ OpenR();
+ m_pCurrentDocument->WriteString(L"");
+ CloseR();
+ }
+ }
+}
+
+void CHTML2OOXMLInterpretator::CloseExternalHyperlink()
+{
+ if (!m_oState.m_bInP && !m_oState.m_bInHyperlink)
+ return;
+
+ CloseT();
+ CloseR();
+ m_pCurrentDocument->WriteString(L"");
+ m_oState.m_bInHyperlink = false;
+}
+
+std::wstring CHTML2OOXMLInterpretator::WritePPr(std::vector& arSelectors, CTextSettings& oTS)
+{
+ OpenP();
+
+ if (m_oState.m_bWasPStyle)
+ return L"";
+
+ std::wstring sPStyle = GetStyle(*arSelectors.back().m_pCompiledStyle, true);
+
+ if (sPStyle.empty() && !ElementInTable(arSelectors))
+ sPStyle = L"normal-web";
+
+ if (sPStyle.empty() && oTS.sPStyle.empty() && 0 > oTS.nLi)
+ return L"";
+
+ m_oXmlStyle.WriteLitePStyle(oTS.oAdditionalStyle);
+ const std::wstring sPSettings = m_oXmlStyle.GetStyle();
+ m_oXmlStyle.Clear();
+
+ m_pCurrentDocument->WriteNodeBegin(L"w:pPr");
+
+ if (!sPStyle.empty())
+ {
+ m_pCurrentDocument->WriteString(L"WriteString(sPStyle);
+ m_pCurrentDocument->WriteString(L"\"/>");
+ }
+
+ if (oTS.nLi >= 0)
+ m_pCurrentDocument->WriteString(L"");
+
+ m_pCurrentDocument->WriteString(oTS.sPStyle + sPSettings);
+ m_pCurrentDocument->WriteNodeEnd(L"w:pPr");
+ m_oState.m_bWasPStyle = true;
+
+ return sPStyle;
+}
+
+void CHTML2OOXMLInterpretator::WriteEmptyParagraph(bool bVahish, bool bInP)
+{
+ if (!bInP)
+ m_pCurrentDocument->WriteString(L"");
+
+ m_pCurrentDocument->WriteString(L"");
+
+ if (bVahish)
+ m_pCurrentDocument->WriteString(L"");
+
+ m_pCurrentDocument->WriteString(L"");
+
+ if (!bInP)
+ m_pCurrentDocument->WriteString(L"");
+}
+
+std::wstring CHTML2OOXMLInterpretator::WriteBookmark(const std::wstring& wsId)
+{
+ const std::wstring sCrossId = std::to_wstring(m_mBookmarks.size() + 1);
+ std::wstring sName;
+
+ if (m_mBookmarks.end() != m_mBookmarks.find(wsId))
+ sName = wsId + L"_" + std::to_wstring(++m_mBookmarks[wsId]);
+ else
+ {
+ const anchors_map::const_iterator itFound{m_mAnchors.find(wsId)};
+
+ if (m_mAnchors.end() != itFound)
+ sName = itFound->second;
+ else
+ sName = AddAnchor(wsId);
+
+ m_mBookmarks.insert({wsId, 1});
+ }
+
+ m_pCurrentDocument->WriteString(L"WriteString(sCrossId);
+ m_pCurrentDocument->WriteString(L"\" w:name=\"");
+ m_pCurrentDocument->WriteEncodeXmlString(sName);
+ m_pCurrentDocument->WriteString(L"\"/>");
+
+ return sCrossId;
+}
+
+std::wstring CHTML2OOXMLInterpretator::AddAnchor(const std::wstring& wsAnchorValue)
+{
+ const anchors_map::iterator itFound = m_mAnchors.find(wsAnchorValue);
+
+ if (m_mAnchors.end() != itFound)
+ return itFound->second;
+
+ const std::wstring wsAnchorId{L"anchor-" + std::to_wstring(m_mAnchors.size() + 1)};
+ m_mAnchors[wsAnchorValue] = wsAnchorId;
+
+ return wsAnchorId;
+}
+
+std::wstring CHTML2OOXMLInterpretator::GetStyle(const NSCSS::CCompiledStyle& oStyle, bool bParagraphStyle)
+{
+ if ((bParagraphStyle && !m_oXmlStyle.WritePStyle(oStyle)) || (!bParagraphStyle && !m_oXmlStyle.WriteRStyle(oStyle)))
+ return L"";
+
+ m_oStylesXml.WriteString(m_oXmlStyle.GetStyle());
+ return m_oXmlStyle.GetIdAndClear();
+}
+
+XmlString& CHTML2OOXMLInterpretator::GetStylesXml()
+{
+ return m_oStylesXml;
+}
+
+XmlString& CHTML2OOXMLInterpretator::GetDocRelsXml()
+{
+ return m_oDocXmlRels;
+}
+
+XmlString& CHTML2OOXMLInterpretator::GetNotesRelsXml()
+{
+ return m_oNoteXmlRels;
+}
+
+XmlString& CHTML2OOXMLInterpretator::GetDocumentXml()
+{
+ return m_oDocXml;
+}
+
+XmlString& CHTML2OOXMLInterpretator::GetNotesXml()
+{
+ return m_oNoteXml;
+}
+
+XmlString& CHTML2OOXMLInterpretator::GetNumberingXml()
+{
+ return m_oNumberXml;
+}
+
+XmlString& CHTML2OOXMLInterpretator::GetWebSettingsXml()
+{
+ return m_oWebSettings;
+}
+
+XmlString& CHTML2OOXMLInterpretator::GetCurrentDocument()
+{
+ return *m_pCurrentDocument;
+}
+
+void CHTML2OOXMLInterpretator::PrintData()
+{
+ std::wcout << m_oDocXml.GetData() << std::endl;
+}
+
+inline bool ElementInTable(const std::vector& arSelectors)
+{
+ return arSelectors.crend() != std::find_if(arSelectors.crbegin(), arSelectors.crend(), [](const NSCSS::CNode& oNode) { return L"table" == oNode.m_wsName; });
+}
+}
diff --git a/HtmlFile2/HTML2OOXMLInterpretator.h b/HtmlFile2/HTML2OOXMLInterpretator.h
new file mode 100644
index 0000000000..881549007b
--- /dev/null
+++ b/HtmlFile2/HTML2OOXMLInterpretator.h
@@ -0,0 +1,101 @@
+#ifndef HTML2OOXMLINTERPRETATOR_H
+#define HTML2OOXMLINTERPRETATOR_H
+
+// #include "HTMLInterpretator.h"
+#include "../DesktopEditor/common/StringBuilder.h"
+
+#include "../Common/3dParty/html/css/src/xhtml/CDocumentStyle.h"
+#include "../Common/3dParty/html/css/src/CNode.h"
+#include "../TextSettings.h"
+#include "HTMLInterpretator.h"
+
+namespace HTML
+{
+using XmlString = NSStringUtils::CStringBuilder;
+
+class CHTML2OOXMLInterpretator : public IHTMLInterpretator
+{
+ XmlString m_oStylesXml; // styles.xml
+ XmlString m_oDocXmlRels; // document.xml.rels
+ XmlString m_oNoteXmlRels; // footnotes.xml.rels
+ XmlString m_oDocXml; // document.xml
+ XmlString m_oNoteXml; // footnotes.xml
+ XmlString m_oNumberXml; // numbering.xml
+ XmlString m_oWebSettings; // webSettings.xml
+
+ XmlString *m_pCurrentDocument; //Текущее место записи
+
+ NSCSS::CDocumentStyle m_oXmlStyle; // Ooxml стиль
+
+ struct TState
+ {
+ bool m_bInP; // открыт?
+ bool m_bInR; // открыт?
+ bool m_bInT; // открыт?
+ bool m_bWasPStyle; // записан?
+ bool m_bWasSpace; // Был пробел?
+ bool m_bInHyperlink; // открыт?
+
+ bool m_bBanUpdatePageData; // Запретить обновление данных о странице?
+
+ std::wstring m_wsNote;
+
+ // HtmlTag m_eLastElement;
+
+ TState()
+ : m_bInP(false), m_bInR(false), m_bInT(false), m_bWasPStyle(false), m_bWasSpace(true), m_bInHyperlink(false), m_bBanUpdatePageData(false)/*, m_eLastElement(HTML_TAG(UNKNOWN))*/
+ {}
+ } m_oState;
+
+ int m_nFootnoteId; // ID сноски
+ int m_nHyperlinkId; // ID ссылки
+ int m_nNumberingId; // ID списка
+ int m_nId; // ID остальные элементы
+ int m_nShapeId; // Id shape's
+
+ std::map m_mFootnotes; // Сноски
+ std::map m_mBookmarks; // Закладки
+ using anchors_map = std::map;
+ anchors_map m_mAnchors; // Map якорей с индивидуальными id
+public:
+ CHTML2OOXMLInterpretator();
+
+ bool OpenP();
+ bool OpenR();
+ bool OpenT();
+
+ void CloseP(std::vector& sSelectors);
+ void CloseR();
+ void CloseT();
+
+ void OpenCrossHyperlink(const std::wstring& wsRef, std::vector& arSelectors, CTextSettings& oTS);
+ void OpenExternalHyperlink(const std::wstring& wsRef, const std::wstring& wsTooltip, std::vector& arSelectors, CTextSettings& oTS);
+
+ void CloseCrossHyperlink(std::vector& arSelectors, std::wstring wsFootnote, const std::wstring& wsRef);
+ void CloseExternalHyperlink();
+
+ std::wstring WritePPr(std::vector& arSelectors, CTextSettings& oTS);
+
+ void WriteEmptyParagraph(bool bVahish = false, bool bInP = false) override;
+
+ std::wstring WriteBookmark(const std::wstring& wsId);
+ std::wstring AddAnchor(const std::wstring& wsAnchorValue);
+
+ std::wstring GetStyle(const NSCSS::CCompiledStyle& oStyle, bool bParagraphStyle);
+
+ XmlString& GetStylesXml();
+ XmlString& GetDocRelsXml();
+ XmlString& GetNotesRelsXml();
+ XmlString& GetDocumentXml();
+ XmlString& GetNotesXml();
+ XmlString& GetNumberingXml();
+ XmlString& GetWebSettingsXml();
+ XmlString& GetCurrentDocument();
+
+ #ifdef _DEBUG
+ virtual void PrintData() override;
+ #endif
+};
+}
+
+#endif // HTML2OOXMLINTERPRETATOR_H
diff --git a/HtmlFile2/HTMLInterpretator.h b/HtmlFile2/HTMLInterpretator.h
new file mode 100644
index 0000000000..b54fe19f50
--- /dev/null
+++ b/HtmlFile2/HTMLInterpretator.h
@@ -0,0 +1,58 @@
+#ifndef HTMLINTERPRETATOR_H
+#define HTMLINTERPRETATOR_H
+
+namespace HTML
+{
+class IHTMLInterpretator
+{
+public:
+ IHTMLInterpretator() = default;
+ virtual ~IHTMLInterpretator() = default;
+
+ virtual void WriteEmptyParagraph(bool bVahish = false, bool bInP = false) = 0;
+
+ #ifdef _DEBUG
+ virtual void PrintData() = 0;
+ #endif
+
+ // virtual bool ReadText(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadA(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadAbbr(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadBold(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadBdo(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadBdi(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadBr(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadCenter(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadItalic(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadCode(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadKbd(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadSamp(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadStrike(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadFont(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool readImage(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadUnderline(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadMark(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadQ(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadSup(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadSub(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool readSVG(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool readInput(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadSpan(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadNobr(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadBasefont(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadDD(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadDiv(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadBlockquote(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadHr(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadListElement(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadList(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool readMenu(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadPre(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadTable(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadRuby(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadTextarea(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+ // virtual bool ReadDetails(NSStringUtils::CStringBuilder& oXml, std::vector& sSelectors, TTextSettings& oTS) = 0;
+};
+}
+
+#endif // HTMLINTERPRETATOR_H
diff --git a/HtmlFile2/HTMLReader.cpp b/HtmlFile2/HTMLReader.cpp
new file mode 100644
index 0000000000..e0aeab33bb
--- /dev/null
+++ b/HtmlFile2/HTMLReader.cpp
@@ -0,0 +1,881 @@
+#include "HTMLReader.h"
+
+#include "../Common/Network/FileTransporter/include/FileTransporter.h"
+#include "../DesktopEditor/common/File.h"
+#include "../DesktopEditor/common/Path.h"
+
+#include "Common.h"
+#include "Tags/HTMLTags2OOXML.h"
+#include "../Common/3dParty/html/gumbo-parser/src/gumbo.h"
+#include
+#include
+
+namespace HTML
+{
+#define HTML_TAG(tag) GUMBO_TAG_##tag
+#define ADD_TAG(strName, enumName) {strName, HTML_TAG(enumName)}
+#define SKIP_TAG SCRIPT
+#define UNKNOWN_TAG GumboTag::GUMBO_TAG_UNKNOWN
+
+#define HtmlTag GumboTag
+
+const std::map m_HTML_TAGS
+{
+ ADD_TAG(L"a", A),
+ ADD_TAG(L"abbr", ABBR),
+ ADD_TAG(L"acronym", ACRONYM),
+ ADD_TAG(L"address", ADDRESS),
+ ADD_TAG(L"applet", APPLET),
+ ADD_TAG(L"area", AREA),
+ ADD_TAG(L"article", ARTICLE),
+ ADD_TAG(L"aside", ASIDE),
+ ADD_TAG(L"audio", AUDIO),
+ ADD_TAG(L"b", B),
+ ADD_TAG(L"base", BASE),
+ ADD_TAG(L"basefont", BASEFONT),
+ ADD_TAG(L"bdi", BDI),
+ ADD_TAG(L"bdo", BDO),
+ ADD_TAG(L"bgsound", BGSOUND),
+ ADD_TAG(L"blockquote", BLOCKQUOTE),
+ ADD_TAG(L"big", BIG),
+ ADD_TAG(L"body", BODY),
+ ADD_TAG(L"blink", BLINK),
+ ADD_TAG(L"br", BR),
+ ADD_TAG(L"button", BUTTON),
+ ADD_TAG(L"canvas", CANVAS),
+ ADD_TAG(L"caption", CAPTION),
+ ADD_TAG(L"center", CENTER),
+ ADD_TAG(L"cite", CITE),
+ ADD_TAG(L"code", CODE),
+ ADD_TAG(L"col", COL),
+ ADD_TAG(L"colgroup", COLGROUP),
+ ADD_TAG(L"command", SKIP_TAG), // Данного обозначения нет, но т.к.мы всё равно пропускаем, то делаем script
+ ADD_TAG(L"comment", SKIP_TAG), // Данного обозначения нет, но т.к.мы всё равно пропускаем, то делаем script
+ ADD_TAG(L"datalist", DATALIST),
+ ADD_TAG(L"dd", DD),
+ ADD_TAG(L"del", DEL),
+ ADD_TAG(L"details", DETAILS),
+ ADD_TAG(L"dfn", DFN),
+ ADD_TAG(L"dir", DIR),
+ ADD_TAG(L"div", DIV),
+ ADD_TAG(L"dl", DL),
+ ADD_TAG(L"dt", DT),
+ ADD_TAG(L"em", EM),
+ ADD_TAG(L"embed", EMBED),
+ ADD_TAG(L"fieldset", FIELDSET),
+ ADD_TAG(L"figcaption", FIGCAPTION),
+ ADD_TAG(L"figure", FIGURE),
+ ADD_TAG(L"font", FONT),
+ ADD_TAG(L"form", FORM),
+ ADD_TAG(L"footer", FOOTER),
+ ADD_TAG(L"frame", FRAME),
+ ADD_TAG(L"frameset", FRAMESET),
+ ADD_TAG(L"h1", H1),
+ ADD_TAG(L"h2", H2),
+ ADD_TAG(L"h3", H3),
+ ADD_TAG(L"h4", H4),
+ ADD_TAG(L"h5", H5),
+ ADD_TAG(L"h6", H6),
+ ADD_TAG(L"head", HEAD),
+ ADD_TAG(L"header", HEADER),
+ ADD_TAG(L"hgroup", HGROUP),
+ ADD_TAG(L"hr", HR),
+ ADD_TAG(L"html", HTML),
+ ADD_TAG(L"i", I),
+ ADD_TAG(L"iframe", IFRAME),
+ ADD_TAG(L"img", IMG),
+ ADD_TAG(L"input", INPUT),
+ ADD_TAG(L"ins", INS),
+ ADD_TAG(L"isindex", ISINDEX),
+ ADD_TAG(L"kbd", KBD),
+ ADD_TAG(L"keygen", KEYGEN),
+ ADD_TAG(L"label", LABEL),
+ ADD_TAG(L"legend", LEGEND),
+ ADD_TAG(L"li", LI),
+ ADD_TAG(L"link", LINK),
+ ADD_TAG(L"main", MAIN),
+ ADD_TAG(L"map", MAP),
+ ADD_TAG(L"marquee", MARQUEE),
+ ADD_TAG(L"mark", MARK),
+ ADD_TAG(L"menu", MENU),
+ ADD_TAG(L"meta", META),
+ ADD_TAG(L"meter", METER),
+ ADD_TAG(L"nav", NAV),
+ ADD_TAG(L"nobr", NOBR),
+ ADD_TAG(L"noembed", NOEMBED),
+ ADD_TAG(L"noframes", NOFRAMES),
+ ADD_TAG(L"noscript", NOSCRIPT),
+ ADD_TAG(L"object", OBJECT),
+ ADD_TAG(L"ol", OL),
+ ADD_TAG(L"optgroup", OPTGROUP),
+ ADD_TAG(L"option", OPTION),
+ ADD_TAG(L"output", OUTPUT),
+ ADD_TAG(L"p", P),
+ ADD_TAG(L"param", PARAM),
+ ADD_TAG(L"plaintext", PLAINTEXT),
+ ADD_TAG(L"pre", PRE),
+ ADD_TAG(L"progress", PROGRESS),
+ ADD_TAG(L"q", Q),
+ ADD_TAG(L"rp", RP),
+ ADD_TAG(L"rt", RT),
+ ADD_TAG(L"ruby", RUBY),
+ ADD_TAG(L"s", S),
+ ADD_TAG(L"samp", SAMP),
+ ADD_TAG(L"script", SCRIPT),
+ ADD_TAG(L"section", SECTION),
+ ADD_TAG(L"select", SELECT),
+ ADD_TAG(L"small", SMALL),
+ ADD_TAG(L"span", SPAN),
+ ADD_TAG(L"source", SOURCE),
+ ADD_TAG(L"strike", STRIKE),
+ ADD_TAG(L"strong", STRONG),
+ ADD_TAG(L"style", STYLE),
+ ADD_TAG(L"sub", SUB),
+ ADD_TAG(L"summary", SUMMARY),
+ ADD_TAG(L"sup", SUP),
+ ADD_TAG(L"table", TABLE),
+ ADD_TAG(L"tbody", TBODY),
+ ADD_TAG(L"td", TD),
+ ADD_TAG(L"textarea", TEXTAREA),
+ ADD_TAG(L"tfoot", TFOOT),
+ ADD_TAG(L"th", TH),
+ ADD_TAG(L"thead", THEAD),
+ ADD_TAG(L"time", TIME),
+ ADD_TAG(L"title", TITLE),
+ ADD_TAG(L"tr", TR),
+ ADD_TAG(L"tt", TT),
+ ADD_TAG(L"u", U),
+ ADD_TAG(L"ul", UL),
+ ADD_TAG(L"var", VAR),
+ ADD_TAG(L"video", VIDEO),
+ ADD_TAG(L"wbr", WBR),
+ ADD_TAG(L"xmp", XMP),
+
+ ADD_TAG(L"svg", SVG)
+};
+inline std::wstring GetArgumentValue(XmlUtils::CXmlLiteReader& oLiteReader, const std::wstring& wsArgumentName, const std::wstring& wsDefaultValue = L"");
+inline bool CheckArgumentMath(const std::wstring& wsNodeName, const std::wstring& wsStyleName);
+inline HtmlTag GetHtmlTag(const std::wstring& wsStrTag);
+inline bool UnreadableNode(const std::wstring& wsNodeName);
+inline bool TagIsUnprocessed(const std::wstring& wsTagName);
+
+CHTMLReader::CHTMLReader()
+ : m_pInterpretator(new CHTML2OOXMLInterpretator())
+{
+ m_mTags[HTML_TAG(A)] = new TAnchor((CHTML2OOXMLInterpretator*)m_pInterpretator);
+}
+
+CHTMLReader::~CHTMLReader()
+{
+ if (nullptr != m_pInterpretator)
+ delete m_pInterpretator;
+}
+
+HRESULT CHTMLReader::ReadFromFile(const std::wstring& wsFileName)
+{
+ if (!HTML2XHTML(wsFileName) || !m_oLightReader.IsValid() || !IsHTML())
+ return S_FALSE;
+
+ m_sSrc = NSSystemPath::GetDirectoryName(wsFileName);
+ // m_sDst = sDst;
+
+ ReadStyle();
+
+ // Переходим в начало
+ if(!m_oLightReader.MoveToStart())
+ return S_FALSE;
+
+ // if(oParams && oParams->m_bNeedPageBreakBefore)
+ // m_internal->PageBreakBefore();
+
+ ReadDocument();
+ return S_OK;
+}
+
+bool CHTMLReader::IsHTML()
+{
+ return ((m_oLightReader.MoveToStart() && m_oLightReader.ReadNextNode()) ? m_oLightReader.GetName() == L"html" : false) && m_oLightReader.MoveToStart();
+}
+
+bool CHTMLReader::HTML2XHTML(const std::wstring& wsFileName)
+{
+ BYTE* pData;
+ DWORD nLength;
+ if (!NSFile::CFileBinary::ReadAllBytes(wsFileName, &pData, nLength))
+ return false;
+
+ std::string sFileContent = XmlUtils::GetUtf8FromFileContent(pData, nLength);
+
+ bool bNeedConvert = true;
+ if (nLength > 4)
+ {
+ if (pData[0] == 0xFF && pData[1] == 0xFE && !(pData[2] == 0x00 && pData[3] == 0x00))
+ bNeedConvert = false;
+ if (pData[0] == 0xFE && pData[1] == 0xFF)
+ bNeedConvert = false;
+
+ if (pData[0] == 0xFF && pData[1] == 0xFE && pData[2] == 0x00 && pData[3] == 0x00)
+ bNeedConvert = false;
+ if (pData[0] == 0 && pData[1] == 0 && pData[2] == 0xFE && pData[3] == 0xFF)
+ bNeedConvert = false;
+ }
+
+ RELEASEARRAYOBJECTS(pData);
+
+ size_t nFind = sFileContent.find("version=\"");
+ if(nFind != std::string::npos)
+ {
+ nFind += 9;
+ size_t nFindEnd = sFileContent.find("\"", nFind);
+ if(nFindEnd != std::string::npos)
+ sFileContent.replace(nFind, nFindEnd - nFind, "1.0");
+ }
+
+ // const std::wstring sRes{htmlToXhtml(sFileContent, bNeedConvert)};
+
+ #ifdef SAVE_NORMALIZED_HTML
+ #if 1 == SAVE_NORMALIZED_HTML
+ NSFile::CFileBinary oWriter;
+ if (oWriter.CreateFileW(m_sTmp + L"/res.html"))
+ {
+ oWriter.WriteStringUTF8(sRes);
+ oWriter.CloseFile();
+ }
+ #endif
+ #endif
+
+ return m_oLightReader.FromString(UTF8_TO_U(sFileContent));
+}
+
+void CHTMLReader::ReadStyle()
+{
+ if(m_oLightReader.IsEmptyNode())
+ return;
+
+ const int nDeath = m_oLightReader.GetDepth();
+ std::wstring sName;
+
+ while(m_oLightReader.ReadNextSiblingNode(nDeath))
+ {
+ sName = m_oLightReader.GetName();
+
+ if(sName == L"body")
+ ReadStyle2();
+ else
+ {
+ // Стиль по ссылке
+ if(sName == L"link")
+ {
+ while(m_oLightReader.MoveToNextAttribute())
+ ReadStyleFromNetwork();
+
+ m_oLightReader.MoveToElement();
+ }
+ // тэг style содержит стили для styles.xml
+ else if(sName == L"style")
+ m_oStylesCalculator.AddStyles(m_oLightReader.GetText2());
+ else
+ ReadStyle();
+ }
+ }
+}
+
+void CHTMLReader::ReadStyle2()
+{
+ std::wstring sName = m_oLightReader.GetName();
+ // Стиль по ссылке
+ if(sName == L"link")
+ {
+ while(m_oLightReader.MoveToNextAttribute())
+ ReadStyleFromNetwork();
+ m_oLightReader.MoveToElement();
+ }
+ // тэг style содержит стили для styles.xml
+ else if(sName == L"style")
+ m_oStylesCalculator.AddStyles(m_oLightReader.GetText2());
+
+ const int nDeath = m_oLightReader.GetDepth();
+ while(m_oLightReader.ReadNextSiblingNode(nDeath))
+ {
+ if(!m_oLightReader.IsEmptyNode())
+ ReadStyle2();
+ }
+}
+
+void CHTMLReader::ReadStyleFromNetwork()
+{
+ if(m_oLightReader.GetName() != L"href")
+ return;
+ std::wstring sRef = m_oLightReader.GetText();
+ if(NSFile::GetFileExtention(sRef) != L"css")
+ return;
+ std::wstring sFName = NSFile::GetFileName(sRef);
+ // Стиль в сети
+ if(sRef.substr(0, 4) == L"http")
+ {
+ sFName = m_sTmp + L'/' + sFName;
+ NSNetwork::NSFileTransport::CFileDownloader oDownloadStyle(sRef, false);
+ oDownloadStyle.SetFilePath(sFName);
+ if(oDownloadStyle.DownloadSync())
+ {
+ m_oStylesCalculator.AddStylesFromFile(sFName);
+ NSFile::CFileBinary::Remove(sFName);
+ }
+ }
+ else
+ {
+ m_oStylesCalculator.AddStylesFromFile(m_sSrc + L'/' + sFName);
+ m_oStylesCalculator.AddStylesFromFile(m_sSrc + L'/' + sRef);
+ }
+}
+
+void CHTMLReader::ReadDocument()
+{
+ m_oLightReader.ReadNextNode();
+
+ int nDeath = m_oLightReader.GetDepth();
+ while(m_oLightReader.ReadNextSiblingNode(nDeath))
+ {
+ std::wstring sName = m_oLightReader.GetName();
+ if(sName == L"head")
+ ReadHead();
+ else if(sName == L"body")
+ ReadBody();
+ }
+}
+
+void CHTMLReader::ReadHead()
+{
+ if(m_oLightReader.IsEmptyNode())
+ return;
+ int nDeath = m_oLightReader.GetDepth();
+ while (m_oLightReader.ReadNextSiblingNode(nDeath))
+ {
+ const std::wstring wsName = m_oLightReader.GetName();
+ // Базовый адрес
+ if (L"base" == wsName)
+ m_sBase = GetArgumentValue(m_oLightReader, L"href");
+ }
+
+ m_oLightReader.MoveToElement();
+}
+
+void CHTMLReader::ReadBody()
+{
+ std::vector arSelectors;
+
+ arSelectors.push_back(NSCSS::CNode(L"html", L"", L""));
+
+ GetSubClass(arSelectors);
+
+ /*
+ if (!sSelectors.back().m_mAttributes.empty())
+ {
+ std::map::iterator itFound = sSelectors.back().m_mAttributes.find(L"bgcolor");
+
+ if (sSelectors.back().m_mAttributes.end() != itFound)
+ {
+ NSCSS::NSProperties::CColor oColor;
+ oColor.SetValue(itFound->second);
+
+ if (!oColor.Empty() && !oColor.None())
+ {
+ const std::wstring wsHEXColor{oColor.ToHEX()};
+
+ if (!wsHEXColor.empty())
+ m_oDocXml.WriteString(L"");
+
+ sSelectors.back().m_mAttributes.erase(itFound);
+ }
+ }
+ }
+
+ m_oLightReader.MoveToElement();
+ */
+
+ CTextSettings oTS;
+ ReadStream(arSelectors, oTS);
+}
+
+bool CHTMLReader::ReadStream(std::vector& arSelectors, CTextSettings& oTS, bool bInsertEmptyP)
+{
+ int nDeath = m_oLightReader.GetDepth();
+ if(m_oLightReader.IsEmptyNode() || !m_oLightReader.ReadNextSiblingNode2(nDeath))
+ {
+ if (bInsertEmptyP)
+ m_pInterpretator->WriteEmptyParagraph(true, true);
+ // WriteEmptyParagraph(sSelectors, oTS);
+ return false;
+ // WriteEmptyParagraph(sSelectors, oTS);
+ // if (bInsertEmptyP)
+ // {
+ // wrP(oXml, sSelectors, oTS);
+ // wrRPr(oXml, sSelectors, oTS);
+ // CloseP(oXml, sSelectors);
+ // m_oState.m_bInP = false;
+
+ // return true;
+ // }
+ }
+
+ bool bResult = false;
+
+ do
+ {
+ if (ReadInside(arSelectors, oTS))
+ bResult = true;
+ } while(m_oLightReader.ReadNextSiblingNode2(nDeath));
+
+ if (!bResult && bInsertEmptyP)
+ m_pInterpretator->WriteEmptyParagraph(true, true);
+ // WriteEmptyParagraph(sSelectors, oTS);
+
+ // if (!bResult && bInsertEmptyP)
+ // {
+ // wrP(oXml, sSelectors, oTS);
+ // wrRPr(oXml, sSelectors, oTS);
+ // CloseP(oXml, sSelectors);
+ // m_oState.m_bInP = false;
+ // }
+
+ return bResult;
+}
+
+bool CHTMLReader::ReadInside(std::vector& arSelectors, CTextSettings& oTS)
+{
+ const std::wstring wsName{m_oLightReader.GetName()};
+
+ //TODO:: обработать все варианты return'а
+ // if(wsName == L"#text")
+ // return m_pInterpretator->ReadText(oXml, arSelectors, oTS);
+
+ if (UnreadableNode(wsName) || TagIsUnprocessed(wsName))
+ return false;
+
+ GetSubClass(arSelectors);
+
+ bool bResult = true;
+
+ const HtmlTag eHtmlTag{GetHtmlTag(wsName)};
+
+ switch(eHtmlTag)
+ {
+ case HTML_TAG(A):
+ case HTML_TAG(AREA):
+ {
+ bResult = ReadA(arSelectors, oTS);
+ break;
+ }
+ default:
+ break;
+ // case HTML_TAG(ABBR):
+ // {
+ // bResult = m_pInterpretator->ReadAbbr(oXml, arSelectors, oTS, sNote);
+ // break;
+ // }
+ // case HTML_TAG(B):
+ // case HTML_TAG(STRONG):
+ // {
+ // bResult = m_pInterpretator->ReadBold(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(BDO):
+ // {
+ // bResult = m_pInterpretator->ReadBdo(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(BDI):
+ // {
+ // bResult = m_pInterpretator->ReadBdi(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(BR):
+ // {
+ // bResult = m_pInterpretator->ReadBr(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(CENTER):
+ // {
+ // bResult = m_pInterpretator->ReadCenter(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(CITE):
+ // case HTML_TAG(DFN):
+ // case HTML_TAG(EM):
+ // case HTML_TAG(I):
+ // case HTML_TAG(VAR):
+ // {
+ // bResult = m_pInterpretator->ReadItalic(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(CODE):
+ // case HTML_TAG(TT):
+ // {
+ // bResult = m_pInterpretator->ReadCode(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(KBD):
+ // {
+ // bResult = m_pInterpretator->ReadKbd(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(SAMP):
+ // {
+ // bResult = m_pInterpretator->ReadSamp(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(DEL):
+ // case HTML_TAG(S):
+ // case HTML_TAG(STRIKE):
+ // {
+ // bResult = m_pInterpretator->ReadStrike(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(FONT):
+ // {
+ // bResult = m_pInterpretator->ReadFont(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(IMG):
+ // {
+ // bResult = m_pInterpretator->readImage(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(INS):
+ // case HTML_TAG(U):
+ // {
+ // bResult = m_pInterpretator->ReadUnderline(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(MARK):
+ // {
+ // bResult = m_pInterpretator->ReadMark(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(Q):
+ // {
+ // bResult = m_pInterpretator->ReadQ(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(SUP):
+ // {
+ // bResult = m_pInterpretator->ReadSup(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(SUB):
+ // {
+ // bResult = m_pInterpretator->ReadSub(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(SVG):
+ // {
+ // m_pInterpretator->readSVG(oXml, sSelectors, oTS);
+
+ // wrP(oXml, sSelectors, oTS);
+ // bResult = readSVG(m_oLightReader.GetOuterXml());
+
+ // if (bResult)
+ // ImageRels(oXml, -1, L"", L"png");
+
+ // break;
+ // }
+ // case HTML_TAG(INPUT):
+ // {
+ // bResult = readInput(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(CANVAS):
+ // case HTML_TAG(VIDEO):
+ // case HTML_TAG(MATH):
+ // case HTML_TAG(IFRAME):
+ // case HTML_TAG(EMBED):
+ // case HTML_TAG(WBR):
+ // case HTML_TAG(AUDIO):
+ // case HTML_TAG(BGSOUND):
+ // case HTML_TAG(APPLET):
+ // case HTML_TAG(BLINK):
+ // case HTML_TAG(KEYGEN):
+ // case HTML_TAG(TITLE):
+ // case HTML_TAG(STYLE):
+ // case HTML_TAG(SCRIPT):
+ // {
+ // //Если встретили не обрабатываемые теги, то просто пропускаем
+ // sSelectors.pop_back();
+ // return false;
+ // }
+ // case HTML_TAG(SPAN):
+ // {
+ // bResult = ReadSpan(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(NOBR):
+ // {
+ // bResult = ReadNobr(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(BASEFONT):
+ // {
+ // bResult = ReadBasefont(oXml, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(BUTTON):
+ // case HTML_TAG(LABEL):
+ // case HTML_TAG(DATA):
+ // case HTML_TAG(OBJECT):
+ // case HTML_TAG(NOSCRIPT):
+ // case HTML_TAG(OUTPUT):
+ // case HTML_TAG(TIME):
+ // case HTML_TAG(SMALL):
+ // case HTML_TAG(PROGRESS):
+ // case HTML_TAG(HGROUP):
+ // case HTML_TAG(METER):
+ // case HTML_TAG(ACRONYM):
+ // case HTML_TAG(BIG):
+ // {
+ // bResult = eadStream(sSelectors, oTS);
+ // break;
+ // }
+ // default:
+ // {
+ // NSStringUtils::CStringBuilder oXmlData;
+ // TState oCurentState{m_oState};
+
+ // CloseP(&oXmlData, sSelectors);
+
+ // switch(eHtmlTag)
+ // {
+ // case HTML_TAG(ADDRESS):
+ // {
+ // bResult = ReadItalic(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(DD):
+ // {
+ // bResult = ReadDD(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(ASIDE):
+ // case HTML_TAG(DIV):
+ // {
+ // bResult = ReadDiv(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(BLOCKQUOTE):
+ // {
+ // bResult = ReadBlockquote(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(ARTICLE):
+ // case HTML_TAG(HEADER):
+ // case HTML_TAG(MAIN):
+ // case HTML_TAG(SUMMARY):
+ // case HTML_TAG(FOOTER):
+ // case HTML_TAG(NAV):
+ // case HTML_TAG(FIGCAPTION):
+ // case HTML_TAG(FORM):
+ // case HTML_TAG(OPTION):
+ // case HTML_TAG(DT):
+ // case HTML_TAG(P):
+ // case HTML_TAG(SECTION):
+ // case HTML_TAG(FIGURE):
+ // case HTML_TAG(DL):
+ // case HTML_TAG(LEGEND):
+ // case HTML_TAG(MAP):
+ // case HTML_TAG(H1):
+ // case HTML_TAG(H2):
+ // case HTML_TAG(H3):
+ // case HTML_TAG(H4):
+ // case HTML_TAG(H5):
+ // case HTML_TAG(H6):
+ // {
+ // bResult = readStream(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(HR):
+ // {
+ // bResult = ReadHr(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(LI):
+ // {
+ // bResult = ReadListElement(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(OL):
+ // case HTML_TAG(UL):
+ // {
+ // bResult = ReadList(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(MENU):
+ // case HTML_TAG(SELECT):
+ // case HTML_TAG(DATALIST):
+ // case HTML_TAG(DIR):
+ // {
+ // bResult = readLi(&oXmlData, sSelectors, oTS, HTML_TAG(OL) != eHtmlTag);
+ // break;
+ // }
+ // case HTML_TAG(PRE):
+ // case HTML_TAG(XMP):
+ // {
+ // bResult = ReadPre(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(TABLE):
+ // {
+ // bResult = ParseTable(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(RUBY):
+ // {
+ // bResult = ParseRuby(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(TEXTAREA):
+ // case HTML_TAG(FIELDSET):
+ // {
+ // bResult = ReadTextarea(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // case HTML_TAG(DETAILS):
+ // {
+ // bResult = ReadDetails(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // default:
+ // {
+ // bResult = readStream(&oXmlData, sSelectors, oTS);
+ // break;
+ // }
+ // }
+
+ // readNote(&oXmlData, sSelectors, sNote);
+
+ // CloseP(&oXmlData, sSelectors);
+
+ // if (bResult)
+ // WriteToStringBuilder(oXmlData, *oXml);
+ // else
+ // m_oState = oCurentState;
+ // }
+ }
+
+ // if (HTML_TAG(DIV) != eHtmlTag && HTML_TAG(ASIDE) != eHtmlTag)
+ // {
+ // if (bResult)
+ // m_oState.m_eLastElement = eHtmlTag;
+
+ // m_oState.m_bBanUpdatePageData = true;
+ // }
+
+ // readNote(oXml, sSelectors, sNote);
+ arSelectors.pop_back();
+ return bResult;
+}
+
+bool CHTMLReader::ReadA(std::vector& arSelectors, CTextSettings& oTS)
+{
+ if (!m_mTags[HTML_TAG(A)]->Open(arSelectors, oTS))
+ return false;
+
+ if(!ReadStream(arSelectors, oTS))
+ m_pInterpretator->WriteEmptyParagraph(true);
+
+ m_mTags[HTML_TAG(A)]->Close(arSelectors);
+
+ #ifdef _DEBUG
+ m_pInterpretator->PrintData();
+ #endif
+
+ return true;
+}
+
+void CHTMLReader::GetSubClass(std::vector& sSelectors)
+{
+ NSCSS::CNode oNode;
+
+ oNode.m_wsName = m_oLightReader.GetName();
+ // Стиль по атрибуту
+ while(m_oLightReader.MoveToNextAttribute())
+ {
+ std::wstring sName = m_oLightReader.GetName();
+ if(sName == L"class")
+ oNode.m_wsClass = EncodeXmlString(m_oLightReader.GetText());
+ else if(sName == L"id")
+ {
+ oNode.m_wsId = EncodeXmlString(m_oLightReader.GetText());
+ // WriteEmptyBookmark(oXml, oNode.m_wsId);
+
+ if (!m_oStylesCalculator.HaveStylesById(oNode.m_wsId))
+ oNode.m_wsId.clear();
+ }
+ else if(sName == L"style")
+ oNode.m_wsStyle += m_oLightReader.GetText();
+ else
+ {
+ if (CheckArgumentMath(oNode.m_wsName, sName))
+ oNode.m_mAttributes[sName] = m_oLightReader.GetText();
+ }
+ }
+ m_oLightReader.MoveToElement();
+ sSelectors.push_back(oNode);
+
+ m_oStylesCalculator.CalculateCompiledStyle(sSelectors);
+}
+
+inline std::wstring GetArgumentValue(XmlUtils::CXmlLiteReader& oLiteReader, const std::wstring& wsArgumentName, const std::wstring& wsDefaultValue)
+{
+ if (!oLiteReader.MoveToFirstAttribute())
+ return wsDefaultValue;
+
+ std::wstring wsValue{wsDefaultValue};
+
+ do
+ {
+ if (wsArgumentName == oLiteReader.GetName())
+ {
+ wsValue = oLiteReader.GetText();
+ break;
+ }
+ } while (oLiteReader.MoveToNextAttribute());
+
+ oLiteReader.MoveToElement();
+ return wsValue;
+}
+
+// Так как CSS калькулятор не знает для какой ноды производится расчет стиля
+// и не знает, что некоторые стили предназначены только определенной ноде,
+// то проще пока обрабатывать это заранее
+// ! Используется для стилей, заданных через аргументы !
+inline bool CheckArgumentMath(const std::wstring& wsNodeName, const std::wstring& wsStyleName)
+{
+ if (L"border" == wsStyleName && L"table" != wsNodeName)
+ return false;
+
+ return true;
+}
+
+inline HtmlTag GetHtmlTag(const std::wstring& wsStrTag)
+{
+ std::map::const_iterator oFound = m_HTML_TAGS.find(wsStrTag);
+
+ if (oFound == m_HTML_TAGS.cend())
+ {
+ if (wsStrTag.length() > 3 && wsStrTag.compare(wsStrTag.length() - 3, 3, L"svg") == 0)
+ return HTML_TAG(SVG);
+ return UNKNOWN_TAG;
+ }
+
+ return oFound->second;
+}
+
+inline bool UnreadableNode(const std::wstring& wsNodeName)
+{
+ return L"head" == wsNodeName || L"meta" == wsNodeName || L"style" == wsNodeName;
+}
+
+inline bool TagIsUnprocessed(const std::wstring& wsTagName)
+{
+ return L"xml" == wsTagName;
+}
+}
diff --git a/HtmlFile2/HTMLReader.h b/HtmlFile2/HTMLReader.h
new file mode 100644
index 0000000000..560b46fba0
--- /dev/null
+++ b/HtmlFile2/HTMLReader.h
@@ -0,0 +1,55 @@
+#ifndef HTMLREADER_H
+#define HTMLREADER_H
+
+#include "../Common/3dParty/html/css/src/CCssCalculator.h"
+#include "../DesktopEditor/xml/include/xmlutils.h"
+
+#include "HTMLInterpretator.h"
+#include "Tags/HTMLTags.h"
+
+namespace HTML
+{
+class CHTMLReader
+{
+ XmlUtils::CXmlLiteReader m_oLightReader; // SAX Reader
+ NSCSS::CCssCalculator m_oStylesCalculator; // Css калькулятор
+
+ NSCSS::NSProperties::CPage m_oPageData; // Стили страницы
+
+ std::wstring m_sTmp; // Temp папка
+ std::wstring m_sSrc; // Директория источника
+ std::wstring m_sDst; // Директория назначения
+ std::wstring m_sBase; // Полный базовый адрес
+ std::wstring m_sCore; // Путь до корневого файла (используется для работы с Epub)
+
+ IHTMLInterpretator *m_pInterpretator;
+
+ std::map m_mTags;
+public:
+ CHTMLReader();
+ ~CHTMLReader();
+
+ HRESULT ReadFromFile(const std::wstring& wsFileName);
+private:
+ bool IsHTML();
+
+ bool HTML2XHTML(const std::wstring& wsFileName);
+
+ void ReadStyle();
+ void ReadStyle2();
+ void ReadStyleFromNetwork();
+
+ void ReadDocument();
+ void ReadHead();
+ void ReadBody();
+
+ bool ReadStream(std::vector& arSelectors, CTextSettings& oTS, bool bInsertEmptyP = false);
+ bool ReadInside(std::vector& arSelectors, CTextSettings& oTS);
+
+ bool ReadA(std::vector& arSelectors, CTextSettings& oTS);
+
+ void GetSubClass(std::vector& sSelectors);
+};
+}
+
+#endif // HTMLREADER_H
diff --git a/HtmlFile2/HtmlFile2.pro b/HtmlFile2/HtmlFile2.pro
index 780ed03313..59ba70256f 100644
--- a/HtmlFile2/HtmlFile2.pro
+++ b/HtmlFile2/HtmlFile2.pro
@@ -31,8 +31,17 @@ include($$CORE_ROOT_DIR/Common/3dParty/boost/boost.pri)
ADD_DEPENDENCY(kernel, UnicodeConverter, graphics, kernel_network)
-SOURCES += htmlfile2.cpp
+SOURCES += htmlfile2.cpp \
+ HTML2OOXMLInterpretator.cpp \
+ HTMLReader.cpp
HEADERS += htmlfile2.h \
./src/StringFinder.h \
- ./src/Languages.h
+ ./src/Languages.h \
+ Common.h \
+ HTML2OOXMLInterpretator.h \
+ HTMLInterpretator.h \
+ HTMLReader.h \
+ Tags/HTMLTags.h \
+ Tags/HTMLTags2OOXML.h \
+ TextSettings.h
diff --git a/HtmlFile2/Tags/HTMLTags.h b/HtmlFile2/Tags/HTMLTags.h
new file mode 100644
index 0000000000..c545b0fd26
--- /dev/null
+++ b/HtmlFile2/Tags/HTMLTags.h
@@ -0,0 +1,43 @@
+#ifndef HTMLTAGS_H
+#define HTMLTAGS_H
+
+#include "../Common/3dParty/html/css/src/CNode.h"
+#include "../TextSettings.h"
+
+namespace HTML
+{
+struct ITag
+{
+ virtual ~ITag() = default;
+ virtual bool Open(std::vector& sSelectors, CTextSettings& oTS) = 0;
+ virtual void Close(std::vector& sSelectors) = 0;
+};
+
+template
+struct TTag : public ITag
+{
+ T* m_pInterpretator;
+
+ TTag(T* pInterpretator)
+ : m_pInterpretator(pInterpretator)
+ {}
+ virtual ~TTag() = default;
+ virtual bool Open(std::vector& sSelectors, CTextSettings& oTS) = 0;
+ virtual void Close(std::vector& sSelectors) = 0;
+
+ bool ValidInterpretator() const
+ {
+ return nullptr != m_pInterpretator;
+ }
+};
+
+template
+struct TAnchor : public TTag
+{
+ virtual bool Open(std::vector& sSelectors, CTextSettings& oTS) = 0;
+ virtual void Close(std::vector& sSelectors) = 0;
+};
+
+}
+
+#endif // HTMLTAGS_H
diff --git a/HtmlFile2/Tags/HTMLTags2OOXML.h b/HtmlFile2/Tags/HTMLTags2OOXML.h
new file mode 100644
index 0000000000..3a39786426
--- /dev/null
+++ b/HtmlFile2/Tags/HTMLTags2OOXML.h
@@ -0,0 +1,123 @@
+#ifndef HTMLTAGS2OOXML_H
+#define HTMLTAGS2OOXML_H
+
+#include "HTMLTags.h"
+#include "HTML2OOXMLInterpretator.h"
+
+namespace HTML
+{
+template<>
+struct TAnchor : public TTag
+{
+ TAnchor(CHTML2OOXMLInterpretator* pInterpretator)
+ : TTag(pInterpretator)
+ {}
+
+ virtual bool Open(std::vector& arSelectors, CTextSettings& oTS)
+ {
+ if (!ValidInterpretator())
+ return false;
+
+ std::wstring wsRef;
+ std::wstring wsAlt;
+ bool bCross = false;
+
+ std::map& mAttributes(arSelectors.back().m_mAttributes);
+
+ std::map::const_iterator itFound = mAttributes.find(L"href");
+
+ bool bFounded = false;
+
+ if (mAttributes.cend() != itFound)
+ {
+ wsRef = itFound->second;
+ if(wsRef.find('#') != std::wstring::npos)
+ bCross = true;
+
+ bFounded = true;
+ }
+ else
+ itFound = mAttributes.find(L"name");
+
+ if (!bFounded)
+ {
+ if (mAttributes.cend() != itFound)
+ {
+ m_pInterpretator->WriteBookmark(itFound->second);
+ bFounded = true;
+ }
+ else
+ itFound = mAttributes.find(L"alt");
+ }
+
+ if (!bFounded)
+ {
+ if (mAttributes.cend() != itFound)
+ {
+ wsAlt = itFound->second;
+ bFounded = true;
+ }
+ }
+
+ if (!bFounded)
+ return false;
+
+ std::wstring wsTooltip(wsRef);
+
+ itFound = mAttributes.find(L"title");
+
+ if (mAttributes.cend() != itFound)
+ wsTooltip = itFound->second;
+
+ if (bCross)
+ m_pInterpretator->OpenCrossHyperlink(wsRef, arSelectors, oTS);
+ else
+ m_pInterpretator->OpenExternalHyperlink(wsRef, wsTooltip, arSelectors, oTS);
+
+ return true;
+ }
+ virtual void Close(std::vector& arSelectors)
+ {
+ if (!ValidInterpretator())
+ return;
+
+ bool bCross = false;
+ std::wstring wsFootnote;
+
+ std::map& mAttributes(arSelectors.back().m_mAttributes);
+ std::map::const_iterator itFound;
+
+ if (arSelectors.back().m_wsStyle.find(L"mso-footnote-id") != std::wstring::npos)
+ wsFootnote = arSelectors.back().m_wsStyle.substr(arSelectors.back().m_wsStyle.rfind(L':') + 1);
+ else
+ {
+ itFound = mAttributes.find(L"epub:type");
+
+ if (mAttributes.cend() != itFound && itFound->second.find(L"noteref"))
+ wsFootnote = L"href";
+ }
+
+ std::wstring wsRef;
+ itFound = mAttributes.find(L"href");
+
+ if (mAttributes.cend() != itFound)
+ {
+ wsRef = itFound->second;
+ if(itFound->second.find('#') != std::wstring::npos)
+ bCross = true;
+ }
+
+ if (bCross)
+ {
+ if (wsFootnote == L"href")
+ wsFootnote = wsRef.substr(wsRef.find('#') + 1);
+
+ m_pInterpretator->CloseCrossHyperlink(arSelectors, wsFootnote, wsRef);
+ }
+ else
+ m_pInterpretator->CloseExternalHyperlink();
+ }
+};
+}
+
+#endif // HTMLTAGS2OOXML_H
diff --git a/HtmlFile2/TextSettings.h b/HtmlFile2/TextSettings.h
new file mode 100644
index 0000000000..7e71d9c90f
--- /dev/null
+++ b/HtmlFile2/TextSettings.h
@@ -0,0 +1,48 @@
+#ifndef TEXTSETTINGS_H
+#define TEXTSETTINGS_H
+
+#include "../Common/3dParty/html/css/src/CCompiledStyle.h"
+
+namespace HTML
+{
+// Настройки текста
+struct CTextSettings
+{
+ bool bBdo; // Реверс текста
+ bool bPre; // Сохранение форматирования (Сохранение пробелов, табуляций, переносов строк)
+ bool bQ; // Цитата
+ bool bAddSpaces; // Добавлять пробелы перед текстом?
+ bool bMergeText; // Объединять подряд идущий текст в 1?
+ int nLi; // Уровень списка
+ bool bNumberingLi; // Является ли список нумерованным
+
+ std::wstring sPStyle;
+
+ enum ETextMode
+ {
+ Normal,
+ Superscript,
+ Subscript
+ } eTextMode;
+
+ NSCSS::CCompiledStyle oAdditionalStyle;
+
+ CTextSettings()
+ : bBdo(false), bPre(false), bQ(false), bAddSpaces(true), bMergeText(false), nLi(-1), bNumberingLi(false), eTextMode(Normal)
+ {}
+
+ CTextSettings(const CTextSettings& oTS) :
+ bBdo(oTS.bBdo), bPre(oTS.bPre), bQ(oTS.bQ), bAddSpaces(oTS.bAddSpaces), bMergeText(oTS.bMergeText),
+ nLi(oTS.nLi), bNumberingLi(oTS.bNumberingLi), sPStyle(oTS.sPStyle), eTextMode(oTS.eTextMode),
+ oAdditionalStyle(oTS.oAdditionalStyle)
+ {}
+
+ void AddPStyle(const std::wstring& wsStyle)
+ {
+ if (std::wstring::npos == sPStyle.find(wsStyle))
+ sPStyle += wsStyle;
+ }
+};
+}
+
+#endif // TEXTSETTINGS_H
diff --git a/HtmlFile2/htmlfile2.cpp b/HtmlFile2/htmlfile2.cpp
index 25f752ec87..dff9f0253e 100644
--- a/HtmlFile2/htmlfile2.cpp
+++ b/HtmlFile2/htmlfile2.cpp
@@ -28,6 +28,8 @@
#include
+#include "HTMLReader.h"
+
#ifndef VALUE2STR
#define VALUE_TO_STRING(x) #x
#define VALUE2STR(x) VALUE_TO_STRING(x)
@@ -267,7 +269,7 @@ struct CTextSettings
bool bPre; // Сохранение форматирования (Сохранение пробелов, табуляций, переносов строк)
bool bQ; // Цитата
bool bAddSpaces; // Добавлять пробелы перед текстом?
- bool bMergeText; // Объединять подяр идущий текст в 1?
+ bool bMergeText; // Объединять подряд идущий текст в 1?
int nLi; // Уровень списка
bool bNumberingLi; // Является ли список нумерованным
@@ -2488,16 +2490,6 @@ private:
sSelectors.push_back(NSCSS::CNode(L"html", L"", L""));
GetSubClass(&m_oDocXml, sSelectors);
- /*
- std::wstring sCrossId = std::to_wstring(m_nCrossId++);
- m_oDocXml.WriteString(L"");
- */
if (!sSelectors.back().m_mAttributes.empty())
{
@@ -2688,7 +2680,9 @@ private:
pXml->WriteEncodeXmlString(wsNote);
pXml->WriteString(L"\"");
pXml->WriteString(L"");
+
const bool bResult = readStream(pXml, arSelectors, oTS);
+
pXml->WriteString(L"");
wsNote.clear();
@@ -5122,6 +5116,10 @@ void CHtmlFile2::SetCoreDirectory(const std::wstring& wsFolder)
HRESULT CHtmlFile2::OpenHtml(const std::wstring& sSrc, const std::wstring& sDst, CHtmlParams* oParams)
{
+ HTML::CHTMLReader oHTMLReader;
+
+ oHTMLReader.ReadFromFile(sSrc);
+
if(!m_internal->m_oLightReader.IsValid())
if(!IsHtmlFile(sSrc))
return S_FALSE;
diff --git a/HtmlFile2/test/main.cpp b/HtmlFile2/test/main.cpp
index eb2fb2553c..ea6d1abe70 100644
--- a/HtmlFile2/test/main.cpp
+++ b/HtmlFile2/test/main.cpp
@@ -6,6 +6,13 @@
#include "../../DesktopEditor/common/Directory.h"
#include "../../OfficeUtils/src/OfficeUtils.h"
+#include "../../Common/3dParty/md/md2html.h"
+
+#include
+#include