From 65a4fa90a5c3d13e55ca4006e5419bc3c8d7ebc5 Mon Sep 17 00:00:00 2001 From: Kirill Polyakov Date: Sun, 1 Feb 2026 23:53:35 +0300 Subject: [PATCH] Fixed bugs --- .../html/css/src/CCssCalculator_Private.cpp | 10 +- Common/3dParty/html/css/src/CNode.cpp | 11 +- HtmlFile2/HTMLReader.cpp | 30 +- HtmlFile2/Table.cpp | 5 + HtmlFile2/Table.h | 1 + HtmlFile2/Tags/HTMLTags.h | 3 +- HtmlFile2/Tags/MDTags.cpp | 303 ++++++++++++------ HtmlFile2/Tags/MDTags.h | 30 +- HtmlFile2/Tags/OOXMLTags.cpp | 68 ++-- HtmlFile2/Writers/IWriter.h | 2 +- HtmlFile2/Writers/MDWriter.cpp | 195 ++++++++++- HtmlFile2/Writers/MDWriter.h | 48 ++- HtmlFile2/Writers/OOXMLWriter.cpp | 43 ++- HtmlFile2/Writers/OOXMLWriter.h | 8 +- 14 files changed, 559 insertions(+), 198 deletions(-) diff --git a/Common/3dParty/html/css/src/CCssCalculator_Private.cpp b/Common/3dParty/html/css/src/CCssCalculator_Private.cpp index 1e40d19fcb..68172e8a3e 100644 --- a/Common/3dParty/html/css/src/CCssCalculator_Private.cpp +++ b/Common/3dParty/html/css/src/CCssCalculator_Private.cpp @@ -29,11 +29,11 @@ namespace NSCSS for (size_t i = 0; i < arLeftSelectors.size(); ++i) { - if (arLeftSelectors[i] < arRightSelectors[i]) - return true; + if (!(arLeftSelectors[i] < arRightSelectors[i])) + return false; } - return false; + return true; } CStyleStorage::CStyleStorage() @@ -556,9 +556,9 @@ namespace NSCSS return true; } - const std::map, CCompiledStyle>::iterator oItem = m_mUsedStyles.find(arSelectors); + const std::map, CCompiledStyle>::const_iterator oItem = m_mUsedStyles.find(arSelectors); - if (oItem != m_mUsedStyles.end()) + if (oItem != m_mUsedStyles.cend()) { arSelectors.back().SetCompiledStyle(new CCompiledStyle(oItem->second)); return true; diff --git a/Common/3dParty/html/css/src/CNode.cpp b/Common/3dParty/html/css/src/CNode.cpp index 28a14f5b2f..0dd9603d34 100644 --- a/Common/3dParty/html/css/src/CNode.cpp +++ b/Common/3dParty/html/css/src/CNode.cpp @@ -17,8 +17,7 @@ namespace NSCSS m_wsStyle(oNode.m_wsStyle), m_mAttributes(oNode.m_mAttributes) { #ifdef CSS_CALCULATOR_WITH_XHTML - m_pCompiledStyle = new CCompiledStyle(); - *m_pCompiledStyle = *oNode.m_pCompiledStyle; + m_pCompiledStyle = new CCompiledStyle(*oNode.m_pCompiledStyle); #endif } @@ -112,9 +111,9 @@ namespace NSCSS bool CNode::operator==(const CNode& oNode) const { return((m_wsId == oNode.m_wsId) && - (m_wsName == oNode.m_wsName) && - (m_wsClass == oNode.m_wsClass) && - (m_wsStyle == oNode.m_wsStyle) && - (m_mAttributes == oNode.m_mAttributes)); + (m_wsName == oNode.m_wsName) && + (m_wsClass == oNode.m_wsClass) && + (m_wsStyle == oNode.m_wsStyle) && + (m_mAttributes == oNode.m_mAttributes)); } } diff --git a/HtmlFile2/HTMLReader.cpp b/HtmlFile2/HTMLReader.cpp index 2706d5b309..944251f150 100644 --- a/HtmlFile2/HTMLReader.cpp +++ b/HtmlFile2/HTMLReader.cpp @@ -276,11 +276,14 @@ void CHTMLReader::InitMDTags() m_mTags[HTML_TAG(TABLE)] = std::make_shared>(pWriter); m_mTags[HTML_TAG(TR)] = std::make_shared>(pWriter); m_mTags[HTML_TAG(TD)] = std::make_shared>(pWriter); + m_mTags[HTML_TAG(OL)] = std::make_shared>(pWriter); + m_mTags[HTML_TAG(LI)] = std::make_shared>(pWriter); + m_mTags[HTML_TAG(PRE)] = std::make_shared>(pWriter); - std::shared_ptr oPreformatted{std::make_shared>(pWriter)}; + std::shared_ptr oCode{std::make_shared>(pWriter)}; - m_mTags[HTML_TAG(PRE)] = oPreformatted; - m_mTags[HTML_TAG(KBD)] = oPreformatted; + m_mTags[HTML_TAG(CODE)] = oCode; + m_mTags[HTML_TAG(KBD)] = oCode; std::shared_ptr oIgnoredTag{std::make_shared()}; @@ -603,8 +606,9 @@ bool CHTMLReader::ReadInside(std::vector& arSelectors) case HTML_TAG(CODE): case HTML_TAG(SAMP): case HTML_TAG(TT): + case HTML_TAG(OUTPUT): { - bResult = ReadDefaultTag(HTML_TAG(PRE), arSelectors); + bResult = ReadDefaultTag(HTML_TAG(CODE), arSelectors); break; } case HTML_TAG(KBD): @@ -701,7 +705,6 @@ bool CHTMLReader::ReadInside(std::vector& arSelectors) 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): @@ -1003,7 +1006,6 @@ bool CHTMLReader::ReadTable(std::vector& arSelectors) oTable.Shorten(); oTable.CompleteTable(); - // oTable.ConvertToOOXML(*oXml); if (!m_mTags[HTML_TAG(TABLE)]->Open(arSelectors, &oTable)) return false; @@ -1021,14 +1023,14 @@ bool CHTMLReader::ReadTable(std::vector& arSelectors) else if (arRows.size() - 1 == unRow)\ eRowPosition = ERowPosition::Last;\ \ - if (!m_mTags[HTML_TAG(TR)]->Open(arSelectors, boost::tuple(arRows[unRow]->GetStyles(), oTable, parse_mode, eRowPosition)))\ + if (!m_mTags[HTML_TAG(TR)]->Open(arSelectors, boost::tuple(&arRows[unRow]->GetStyles(), oTable, parse_mode, eRowPosition)))\ continue;\ \ const std::vector& arCells{arRows[unRow]->GetCells()};\ \ for (UINT unCol = 0; unCol < arCells.size(); ++unCol)\ {\ - m_mTags[HTML_TAG(TD)]->Open(arSelectors, boost::tuple(*arCells[unCol], oTable, unCol, parse_mode, eRowPosition));\ + m_mTags[HTML_TAG(TD)]->Open(arSelectors, boost::tuple(*arCells[unCol], oTable, unCol, parse_mode, eRowPosition));\ \ if (0 != arCells[unCol]->GetData()->GetCurSize())\ WriteToStringBuilder(*(arCells[unCol]->GetData()), *(m_pWriter->GetCurrentDocument()));\ @@ -1041,8 +1043,16 @@ bool CHTMLReader::ReadTable(std::vector& arSelectors) m_mTags[HTML_TAG(TR)]->Close(arSelectors);\ }} - for (const std::vector& arHeader : oTable.GetHeaders()) - CONVERT_ROWS(arHeader, ERowParseMode::Header) + if (!oTable.HaveHeader()) + { + if (m_mTags[HTML_TAG(TR)]->Open(arSelectors, boost::tuple(nullptr, oTable, ERowParseMode::Header, ERowPosition::First))) + m_mTags[HTML_TAG(TR)]->Close(arSelectors); + } + else + { + for (const std::vector& arHeader : oTable.GetHeaders()) + CONVERT_ROWS(arHeader, ERowParseMode::Header) + } CONVERT_ROWS(oTable.GetRows(), ERowParseMode::Body) CONVERT_ROWS(oTable.GetFoothers(), ERowParseMode::Foother) diff --git a/HtmlFile2/Table.cpp b/HtmlFile2/Table.cpp index 90ef6fea73..9e31a3a000 100644 --- a/HtmlFile2/Table.cpp +++ b/HtmlFile2/Table.cpp @@ -452,6 +452,11 @@ bool CStorageTable::HaveColgroups() const return !m_arColgroups.empty(); } +bool CStorageTable::HaveHeader() const +{ + return !m_arHeaders.empty(); +} + UINT CStorageTable::GetRowCount() const { return m_arRows.size(); diff --git a/HtmlFile2/Table.h b/HtmlFile2/Table.h index fb4b3f0afe..b3c828ece6 100644 --- a/HtmlFile2/Table.h +++ b/HtmlFile2/Table.h @@ -201,6 +201,7 @@ public: bool Empty() const; bool HaveCaption(); bool HaveColgroups() const; + bool HaveHeader() const; UINT GetRowCount() const; const TTableStyles& GetTableStyles() const; const TTableCellStyle* GetColStyle(UINT unColumnNumber) const; diff --git a/HtmlFile2/Tags/HTMLTags.h b/HtmlFile2/Tags/HTMLTags.h index f0ee9c9e9f..627a26dad9 100644 --- a/HtmlFile2/Tags/HTMLTags.h +++ b/HtmlFile2/Tags/HTMLTags.h @@ -38,7 +38,7 @@ public: virtual bool Open(const std::vector& arSelectors, const boost::any& oExtraData = boost::any()) = 0; virtual void Close(const std::vector& arSelectors) = 0; - bool ValidInterpretator() const + bool ValidWriter() const { return nullptr != m_pWriter; } @@ -83,6 +83,7 @@ CREATE_TAG(CCaption); CREATE_TAG(CTable); CREATE_TAG(CTableRow); CREATE_TAG(CTableCell); +CREATE_TAG(CCode); } #endif // HTMLTAGS_H diff --git a/HtmlFile2/Tags/MDTags.cpp b/HtmlFile2/Tags/MDTags.cpp index 3e7a47354a..1fd573d16c 100644 --- a/HtmlFile2/Tags/MDTags.cpp +++ b/HtmlFile2/Tags/MDTags.cpp @@ -12,34 +12,31 @@ CAnchor::CAnchor(CMDWriter* pWriter) bool CAnchor::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - m_pWriter->GetCurrentDocument()->AddCharSafe(L'['); + m_pWriter->WriteString(L"["); return true; } void CAnchor::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; - XmlString* pCurrentDocument{m_pWriter->GetCurrentDocument()}; - - pCurrentDocument->AddCharSafe(L']'); + m_pWriter->WriteString(L"]"); std::wstring wsHref, wsTitle; - if (!arSelectors.back().GetAttributeValue(L"href", wsHref) || - !arSelectors.back().GetAttributeValue(L"title", wsTitle)) - return; + arSelectors.back().GetAttributeValue(L"href", wsHref); + arSelectors.back().GetAttributeValue(L"title", wsTitle); - pCurrentDocument->WriteString(L'(' + wsHref); + m_pWriter->WriteString(L'(' + wsHref); if (!wsTitle.empty()) - pCurrentDocument->WriteString(L" \"" + wsTitle + L'"'); + m_pWriter->WriteString(L" \"" + wsTitle + L'"'); - pCurrentDocument->AddCharSafe(L')'); + m_pWriter->WriteString(L")"); } CBold::CBold(CMDWriter* pWriter) @@ -48,20 +45,20 @@ CBold::CBold(CMDWriter* pWriter) bool CBold::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - m_pWriter->GetCurrentDocument()->WriteString(L"**"); + m_pWriter->WriteString(L"**", true); return true; } void CBold::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; - m_pWriter->GetCurrentDocument()->WriteString(L"**"); + m_pWriter->WriteString(L"**", true); } CBreak::CBreak(CMDWriter* pWriter) @@ -70,10 +67,10 @@ CBreak::CBreak(CMDWriter* pWriter) bool CBreak::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - m_pWriter->GetCurrentDocument()->WriteString(m_pWriter->GetParametrs().m_wsLineBreak); + m_pWriter->WriteBreakLine(); return true; } @@ -87,20 +84,20 @@ CItalic::CItalic(CMDWriter* pWriter) bool CItalic::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - m_pWriter->GetCurrentDocument()->AddCharSafe(L'*'); + m_pWriter->WriteString(L"*", true); return true; } void CItalic::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; - m_pWriter->GetCurrentDocument()->AddCharSafe(L'*'); + m_pWriter->WriteString(L"*", true); } CStrike::CStrike(CMDWriter* pWriter) @@ -109,20 +106,20 @@ CStrike::CStrike(CMDWriter* pWriter) bool CStrike::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - m_pWriter->GetCurrentDocument()->WriteString(L"~~"); + m_pWriter->WriteString(L"~~", true); return true; } void CStrike::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; - m_pWriter->GetCurrentDocument()->WriteString(L"~~"); + m_pWriter->WriteString(L"~~", true); } CUnderline::CUnderline(CMDWriter* pWriter) @@ -131,22 +128,22 @@ CUnderline::CUnderline(CMDWriter* pWriter) bool CUnderline::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; if (m_pWriter->GetParametrs().m_bUseAlternativeHTMLTags) - m_pWriter->GetCurrentDocument()->WriteString(L""); + m_pWriter->WriteString(L"", true); return true; } void CUnderline::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; if (m_pWriter->GetParametrs().m_bUseAlternativeHTMLTags) - m_pWriter->GetCurrentDocument()->WriteString(L""); + m_pWriter->WriteString(L"", true); } CQuotation::CQuotation(CMDWriter* pWriter) @@ -155,10 +152,10 @@ CQuotation::CQuotation(CMDWriter* pWriter) bool CQuotation::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - m_pWriter->GetCurrentDocument()->AddCharSafe(L'>'); + // m_pWriter->WriteString(L"> ", true); return true; } @@ -172,20 +169,25 @@ CPreformatted::CPreformatted(CMDWriter* pWriter) bool CPreformatted::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - m_pWriter->GetCurrentDocument()->WriteString(L"```" + m_pWriter->GetParametrs().m_wsLineBreak); + m_pWriter->WriteBreakLine(); + m_pWriter->WriteString(L"```", true); + m_pWriter->EnteredPreformatted(); return true; } void CPreformatted::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; - m_pWriter->GetCurrentDocument()->WriteString(m_pWriter->GetParametrs().m_wsLineBreak + L"```" + m_pWriter->GetParametrs().m_wsLineBreak); + m_pWriter->WriteBreakLine(); + m_pWriter->WriteString(L"```", true); + m_pWriter->WriteBreakLine(false); + m_pWriter->OutPreformatted(); } CHeader::CHeader(CMDWriter* pWriter) @@ -194,17 +196,17 @@ CHeader::CHeader(CMDWriter* pWriter) bool CHeader::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; switch(arSelectors.back().m_wsName[1]) { - case L'1' : m_pWriter->GetCurrentDocument()->WriteString(L"# "); break; - case L'2' : m_pWriter->GetCurrentDocument()->WriteString(L"## "); break; - case L'3' : m_pWriter->GetCurrentDocument()->WriteString(L"### "); break; - case L'4' : m_pWriter->GetCurrentDocument()->WriteString(L"#### "); break; - case L'5' : m_pWriter->GetCurrentDocument()->WriteString(L"##### "); break; - case L'6' : m_pWriter->GetCurrentDocument()->WriteString(L"###### "); break; + case L'1' : m_pWriter->WriteString(L"# ", true); break; + case L'2' : m_pWriter->WriteString(L"## ", true); break; + case L'3' : m_pWriter->WriteString(L"### ", true); break; + case L'4' : m_pWriter->WriteString(L"#### ", true); break; + case L'5' : m_pWriter->WriteString(L"##### ", true); break; + case L'6' : m_pWriter->WriteString(L"###### ", true); break; default: return false; } @@ -213,7 +215,10 @@ bool CHeader::Open(const std::vector& arSelectors, cons } void CHeader::Close(const std::vector& arSelectors) -{} +{ + if (!ValidWriter()) + return; +} CImage::CImage(CMDWriter* pWriter) : CTag(pWriter) @@ -221,42 +226,47 @@ CImage::CImage(CMDWriter* pWriter) bool CImage::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; std::wstring wsAlt, wsSrc, wsTitle; - if (!arSelectors.back().GetAttributeValue(L"src", wsSrc) && - !arSelectors.back().GetAttributeValue(L"alt", wsAlt)) + if (!(arSelectors.back().GetAttributeValue(L"src", wsSrc) && + arSelectors.back().GetAttributeValue(L"alt", wsAlt))) return false; arSelectors.back().GetAttributeValue(L"title", wsTitle); - XmlString* pCurrentDocument{m_pWriter->GetCurrentDocument()}; - - pCurrentDocument->WriteString(L"![" + wsAlt + L"](" + wsSrc); + m_pWriter->WriteString(L"![" + wsAlt + L"](" + wsSrc); if (!wsTitle.empty()) - pCurrentDocument->WriteString(L" \"" + wsTitle + L'"'); + m_pWriter->WriteString(L" \"" + wsTitle + L'"'); - pCurrentDocument->AddCharSafe(L')'); + m_pWriter->WriteString(L")"); return true; } void CImage::Close(const std::vector& arSelectors) -{} +{ + if (!ValidWriter()) + return; + + m_pWriter->WriteBreakLine(); +} CHorizontalRule::CHorizontalRule(CMDWriter* pWriter) : CTag(pWriter) {} -bool HTML::CHorizontalRule::Open(const std::vector& arSelectors, const boost::any& oExtraData) +bool CHorizontalRule::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - m_pWriter->GetCurrentDocument()->WriteString(L"\n\n---\n\n"); + m_pWriter->WriteBreakLine(false); + m_pWriter->WriteString(L"---"); + m_pWriter->WriteBreakLine(false); return true; } @@ -265,29 +275,28 @@ void CHorizontalRule::Close(const std::vector& arSelect {} CBlockquote::CBlockquote(CMDWriter* pWriter) - : CTag(pWriter), m_unIndex(0) + : CTag(pWriter) {} bool CBlockquote::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; - ++m_unIndex; - - XmlString* pCurrentDocument{m_pWriter->GetCurrentDocument()}; - - pCurrentDocument->WriteString(m_pWriter->GetParametrs().m_wsLineBreak); - - for (UINT unIndex = 0; unIndex < m_unIndex; ++m_unIndex) - pCurrentDocument->WriteString(L"> "); + m_pWriter->WriteBreakLine(); + m_pWriter->EnteredBlockquote(); return true; } void CBlockquote::Close(const std::vector& arSelectors) { - --m_unIndex; + if (!ValidWriter()) + return; + + m_pWriter->OutBlockquote(); + m_pWriter->WriteBreakLine(); + m_pWriter->WriteBreakLine(false); } CTable::CTable(CMDWriter* pWriter) @@ -296,22 +305,22 @@ CTable::CTable(CMDWriter* pWriter) bool CTable::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter() || m_pWriter->InTable()) //В MD не поддерживаются вложенные таблицы return false; - //В MD не поддерживаются вложенные таблицы - for (std::vector::const_iterator itElement = arSelectors.cbegin(); itElement < arSelectors.cend() - 1; ++itElement) - if (L"table" == itElement->m_wsName) - return false; - - m_pWriter->GetCurrentDocument()->AddCharSafe(L'\n'); + m_pWriter->WriteBreakLine(); + m_pWriter->EnteredTable(); return true; } void CTable::Close(const std::vector& arSelectors) { - m_pWriter->GetCurrentDocument()->AddCharSafe(L'\n'); + if (!ValidWriter()) + return; + + m_pWriter->OutTable(); + m_pWriter->WriteBreakLine(); } CTableRow::CTableRow(CMDWriter* pWriter) @@ -320,69 +329,159 @@ CTableRow::CTableRow(CMDWriter* pWriter) bool CTableRow::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - using DataForRow = boost::tuple; + using DataForRow = boost::tuple; - if (!ValidInterpretator() || oExtraData.empty() || typeid(DataForRow) != oExtraData.type()) + if (!ValidWriter() || oExtraData.empty() || typeid(DataForRow) != oExtraData.type()) return false; const DataForRow& oDataForRow(boost::any_cast(oExtraData)); const CStorageTable& oStorageTable{boost::get<1>(oDataForRow)}; - XmlString* pCurrentDocument{m_pWriter->GetCurrentDocument()}; + + if (nullptr == boost::get<0>(oDataForRow) && ERowParseMode::Header == boost::get<2>(oDataForRow)) + { + for (UINT unIndex = 0; unIndex < oStorageTable.GetMaxColumns(); ++unIndex) + m_pWriter->WriteString(L"| "); + + m_pWriter->WriteString(L"|"); + m_pWriter->WriteBreakLine(); + m_unLastRowType = static_cast(ERowParseMode::Header); + return true; + } if (m_unLastRowType == static_cast(ERowParseMode::Header)) { for (UINT unIndex = 0; unIndex < oStorageTable.GetMaxColumns(); ++unIndex) - pCurrentDocument->WriteString(L"|-"); + m_pWriter->WriteString(L"|-"); - pCurrentDocument->WriteString(L"|\n"); - } - else if (ERowParseMode::Header != boost::get<2>(oDataForRow) && - ERowPosition::First == boost::get<3>(oDataForRow) && - m_unLastRowType == static_cast(ERowParseMode::Foother)) - { - for (UINT unIndex = 0; unIndex < oStorageTable.GetMaxColumns(); ++unIndex) - pCurrentDocument->WriteString(L"| "); - - pCurrentDocument->WriteString(L"|\n"); - - for (UINT unIndex = 0; unIndex < oStorageTable.GetMaxColumns(); ++unIndex) - pCurrentDocument->WriteString(L"|-"); - - pCurrentDocument->WriteString(L"|\n"); + m_pWriter->WriteString(L"|"); + m_pWriter->WriteBreakLine(); } + m_pWriter->WriteString(L"| "); m_unLastRowType = static_cast(boost::get<2>(oDataForRow)); - pCurrentDocument->WriteString(L"| "); - return true; } void CTableRow::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; - m_pWriter->GetCurrentDocument()->AddCharSafe(L'\n'); + m_pWriter->WriteBreakLine(); } CTableCell::CTableCell(CMDWriter* pWriter) - : CTag(pWriter) + : CTag(pWriter), m_unNeedEmptyCells(0) {} bool CTableCell::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + using DataForCell = boost::tuple; + + if (!ValidWriter() || oExtraData.empty() || typeid(DataForCell) != oExtraData.type()) return false; + const DataForCell& oDataForCell{boost::any_cast(oExtraData)}; + + m_unNeedEmptyCells = boost::get<0>(oDataForCell).GetColspan() - 1; + return true; } void CTableCell::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; - m_pWriter->GetCurrentDocument()->WriteString(L" | "); + for (UINT unIndex = 0; unIndex < m_unNeedEmptyCells; ++unIndex) + m_pWriter->WriteString(L" |"); + + m_unNeedEmptyCells = 0; + m_pWriter->WriteString(L" | "); } + +CList::CList(CMDWriter* pWriter) + : CTag(pWriter) +{} + +bool CList::Open(const std::vector& arSelectors, const boost::any& oExtraData) +{ + if (!ValidWriter()) + return false; + + m_pWriter->EnteredList(L"ol" == arSelectors.back().m_wsName); + + return true; +} + +void CList::Close(const std::vector& arSelectors) +{ + if (!ValidWriter()) + return; + + m_pWriter->OutList(); +} + +CListElement::CListElement(CMDWriter* pWriter) + : CTag(pWriter) +{} + +bool CListElement::Open(const std::vector& arSelectors, const boost::any& oExtraData) +{ + if (!ValidWriter()) + return false; + + for (UINT unLevelList = 0; unLevelList < m_pWriter->GetLevelList() - 1; ++unLevelList) + m_pWriter->WriteString(L" "); + + if (m_pWriter->InOrederedList()) + { + m_pWriter->IncreaseIndexOrderedList(); + m_pWriter->WriteString(std::to_wstring(m_pWriter->GetIndexOrderedList()) + m_pWriter->GetParametrs().m_wchOrderedList + L' '); + } + else + m_pWriter->WriteString({m_pWriter->GetParametrs().m_wchUnorderedList, L' '}); + + return true; +} + +void CListElement::Close(const std::vector& arSelectors) +{} + +CCode::CCode(CMDWriter* pWriter) + : CTag(pWriter) +{} + +bool CCode::Open(const std::vector& arSelectors, const boost::any& oExtraData) +{ + if (!ValidWriter()) + return false; + + m_pWriter->EnteredCode(); + + if (m_pWriter->InPreformatted()) + { + if (!arSelectors.back().m_wsClass.empty() && arSelectors.back().m_wsClass.size() >= 9 && + 0 == arSelectors.back().m_wsClass.compare(0, 9, L"language-")) + m_pWriter->WriteString(arSelectors.back().m_wsClass.substr(9, arSelectors.back().m_wsClass.size() - 9)); + m_pWriter->WriteBreakLine(false); + } + else + m_pWriter->WriteString(L"`", true); + + return true; +} + +void CCode::Close(const std::vector& arSelectors) +{ + if (!ValidWriter()) + return; + + if (!m_pWriter->InPreformatted()) + m_pWriter->WriteString(L"`", true); + + m_pWriter->OutCode(); +} + } diff --git a/HtmlFile2/Tags/MDTags.h b/HtmlFile2/Tags/MDTags.h index 6aca499b75..0186b55253 100644 --- a/HtmlFile2/Tags/MDTags.h +++ b/HtmlFile2/Tags/MDTags.h @@ -108,7 +108,6 @@ public: template<> class CBlockquote : public CTag { - UINT m_unIndex; public: CBlockquote(CMDWriter* pWriter); virtual bool Open(const std::vector& arSelectors, const boost::any& oExtraData = boost::any()) override; @@ -137,11 +136,40 @@ public: template<> class CTableCell : public CTag { + UINT m_unNeedEmptyCells; public: CTableCell(CMDWriter* pWriter); virtual bool Open(const std::vector& arSelectors, const boost::any& oExtraData = boost::any()) override; virtual void Close(const std::vector& arSelectors) override; }; + +template<> +class CList : public CTag +{ +public: + CList(CMDWriter* pWriter); + virtual bool Open(const std::vector& arSelectors, const boost::any& oExtraData = boost::any()) override; + virtual void Close(const std::vector& arSelectors) override; +}; + +template<> +class CListElement : public CTag +{ +public: + CListElement(CMDWriter* pWriter); + virtual bool Open(const std::vector& arSelectors, const boost::any& oExtraData = boost::any()) override; + virtual void Close(const std::vector& arSelectors) override; +}; + +template<> +class CCode : public CTag +{ +public: + CCode(CMDWriter* pWriter); + virtual bool Open(const std::vector& arSelectors, const boost::any& oExtraData = boost::any()) override; + virtual void Close(const std::vector& arSelectors) override; +}; + } #endif // MDTAGS_H diff --git a/HtmlFile2/Tags/OOXMLTags.cpp b/HtmlFile2/Tags/OOXMLTags.cpp index 355d1301a0..4ceebafbd5 100644 --- a/HtmlFile2/Tags/OOXMLTags.cpp +++ b/HtmlFile2/Tags/OOXMLTags.cpp @@ -39,7 +39,7 @@ CAnchor::CAnchor(COOXMLWriter* pWriter) bool CAnchor::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; std::wstring wsRef, wsAlt, wsName; @@ -73,7 +73,7 @@ bool CAnchor::Open(const std::vector& arSelectors, c void CAnchor::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; bool bCross = false; @@ -112,7 +112,7 @@ CAbbr::CAbbr(COOXMLWriter* pWriter) bool CAbbr::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; std::wstring wsTitle; @@ -134,7 +134,7 @@ bool CAbbr::Open(const std::vector& arSelectors, con void CAbbr::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; m_pWriter->GetCurrentDocument()->WriteString(L""); @@ -146,7 +146,7 @@ CBreak::CBreak(COOXMLWriter* pWriter) bool CBreak::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; m_pWriter->Break(arSelectors); @@ -163,7 +163,7 @@ CDivision::CDivision(COOXMLWriter* pWriter) bool CDivision::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; m_pWriter->UpdatePageStyle(arSelectors); @@ -199,7 +199,7 @@ bool CDivision::Open(const std::vector& arSelectors, void CDivision::Close(const std::vector& arSelectors) { - if (!ValidInterpretator() || m_arFootnoteIDs.empty()) + if (!ValidWriter() || m_arFootnoteIDs.empty()) return; if (m_arFootnoteIDs.top() >= 2) @@ -217,7 +217,7 @@ CImage::CImage(COOXMLWriter* pWriter) bool CImage::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; if (L"svg" == arSelectors.back().m_wsName) @@ -441,7 +441,7 @@ CFont::CFont(COOXMLWriter* pWriter) bool CFont::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; std::wstring wsValue; @@ -483,7 +483,7 @@ CInput::CInput(COOXMLWriter* pWriter) bool CInput::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; std::wstring wsValue{arSelectors.back().GetAttributeValue(L"value")}; @@ -519,7 +519,7 @@ CBaseFont::CBaseFont(COOXMLWriter* pWriter) bool CBaseFont::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; std::wstring wsFontStyles, wsValue; @@ -564,7 +564,7 @@ CBlockquote::CBlockquote(COOXMLWriter* pWriter) bool CBlockquote::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; const std::wstring wsKeyWord{arSelectors.back().m_wsName}; @@ -633,7 +633,7 @@ bool CBlockquote::Open(const std::vector& arSelector void CBlockquote::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; m_pWriter->RollBackDivId(); @@ -645,7 +645,7 @@ CHorizontalRule::CHorizontalRule(COOXMLWriter* pWriter) bool CHorizontalRule::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; for (const NSCSS::CNode& item : arSelectors) @@ -748,7 +748,7 @@ CList::CList(COOXMLWriter* pWriter) bool CList::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; m_pWriter->CloseP(); @@ -789,7 +789,7 @@ bool CList::Open(const std::vector& arSelectors, con void CList::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; m_pWriter->CloseP(); @@ -801,12 +801,12 @@ CListElement::CListElement(COOXMLWriter* pWriter) bool CListElement::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - return ValidInterpretator(); + return ValidWriter(); } void CListElement::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; m_pWriter->CloseP(); @@ -1068,7 +1068,7 @@ CCaption::CCaption(COOXMLWriter* pWriter) bool CCaption::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator()) + if (!ValidWriter()) return false; m_pWriter->WritePPr(arSelectors); @@ -1078,7 +1078,7 @@ bool CCaption::Open(const std::vector& arSelectors, void CCaption::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; m_pWriter->CloseP(); @@ -1156,7 +1156,7 @@ CTable::CTable(COOXMLWriter* pWriter) bool CTable::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - if (!ValidInterpretator() || oExtraData.empty() || typeid(CStorageTable*) != oExtraData.type()) + if (!ValidWriter() || oExtraData.empty() || typeid(CStorageTable*) != oExtraData.type()) return false; CStorageTable* pStorageTable{boost::any_cast(oExtraData)}; @@ -1248,7 +1248,7 @@ bool CTable::Open(const std::vector& arSelectors, co void CTable::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; m_pWriter->GetCurrentDocument()->WriteNodeEnd(L"w:tbl"); @@ -1260,9 +1260,9 @@ CTableRow::CTableRow(COOXMLWriter* pWriter) bool CTableRow::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - using DataForRow = boost::tuple; + using DataForRow = boost::tuple; - if (!ValidInterpretator() || oExtraData.empty() || typeid(DataForRow) != oExtraData.type()) + if (!ValidWriter() || oExtraData.empty() || typeid(DataForRow) != oExtraData.type()) return false; const DataForRow& oDataForRow(boost::any_cast(oExtraData)); @@ -1271,17 +1271,17 @@ bool CTableRow::Open(const std::vector& arSelectors, oCurrentDocument.WriteNodeBegin(L"w:tr"); const TTableStyles& oTableStyles{boost::get<1>(oDataForRow).GetTableStyles()}; - const TTableRowStyle oTableRowStyles{boost::get<0>(oDataForRow)}; + const TTableRowStyle* pTableRowStyles{boost::get<0>(oDataForRow)}; - if (!oTableRowStyles.Empty() || 0 < oTableStyles.m_nCellSpacing) + if (nullptr != pTableRowStyles && (!pTableRowStyles->Empty() || 0 < oTableStyles.m_nCellSpacing)) { oCurrentDocument.WriteNodeBegin(L"w:trPr"); - if (oTableRowStyles.m_bIsHeader) + if (pTableRowStyles->m_bIsHeader) oCurrentDocument += L""; - if (0 < oTableRowStyles.m_unMaxHeight) - oCurrentDocument += L""; + if (0 < pTableRowStyles->m_unMaxHeight) + oCurrentDocument += L"m_unMaxHeight) + L"\"/>"; if (0 < oTableStyles.m_nCellSpacing) oCurrentDocument += L""; @@ -1294,7 +1294,7 @@ bool CTableRow::Open(const std::vector& arSelectors, void HTML::CTableRow::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; m_pWriter->GetCurrentDocument()->WriteNodeEnd(L"w:tr"); @@ -1332,13 +1332,13 @@ std::wstring CalculateSidesToClean(UINT unColumnNumber, const std::vector::Open(const std::vector& arSelectors, const boost::any& oExtraData) { - using DataForCell = boost::tuple; + using DataForCell = boost::tuple; - if (!ValidInterpretator() || oExtraData.empty() || typeid(DataForCell) != oExtraData.type()) + if (!ValidWriter() || oExtraData.empty() || typeid(DataForCell) != oExtraData.type()) return false; const DataForCell& oDataForCell{boost::any_cast(oExtraData)}; - CStorageTableCell& oStorageTableCell{boost::get<0>(oDataForCell)}; + const CStorageTableCell& oStorageTableCell{boost::get<0>(oDataForCell)}; XmlString& oCurrentDocument{*m_pWriter->GetCurrentDocument()}; @@ -1450,7 +1450,7 @@ bool CTableCell::Open(const std::vector& arSelectors void HTML::CTableCell::Close(const std::vector& arSelectors) { - if (!ValidInterpretator()) + if (!ValidWriter()) return; m_pWriter->GetCurrentDocument()->WriteNodeEnd(L"w:tc"); diff --git a/HtmlFile2/Writers/IWriter.h b/HtmlFile2/Writers/IWriter.h index 8597478ecd..4b1ffcda76 100644 --- a/HtmlFile2/Writers/IWriter.h +++ b/HtmlFile2/Writers/IWriter.h @@ -16,7 +16,7 @@ public: virtual void Begin(const std::wstring& wsDst, const THtmlParams* pParams) = 0; virtual void End(const std::wstring& wsDst) = 0; - virtual bool WriteText(const std::wstring& wsText, const std::vector& arSelectors) = 0; + virtual bool WriteText(std::wstring wsText, const std::vector& arSelectors) = 0; virtual void WriteEmptyParagraph(bool bVahish = false, bool bInP = false) = 0; diff --git a/HtmlFile2/Writers/MDWriter.cpp b/HtmlFile2/Writers/MDWriter.cpp index 480031de38..d6ad897783 100644 --- a/HtmlFile2/Writers/MDWriter.cpp +++ b/HtmlFile2/Writers/MDWriter.cpp @@ -1,5 +1,10 @@ #include "MDWriter.h" +#include + +#include "../../DesktopEditor/common/File.h" +#include "../../Common/3dParty/html/css/src/CCompiledStyle.h" + namespace HTML { CMDWriter::CMDWriter(const TMDParametrs& oMDParametrs) @@ -16,27 +21,89 @@ void CMDWriter::Begin(const std::wstring& wsDst, const THtmlParams* pParams) void CMDWriter::End(const std::wstring& wsDst) { + NSFile::CFileBinary oDocument; + + if (!oDocument.CreateFileW(L"result.md")) + return; + + oDocument.WriteStringUTF8(m_oDocument.GetData()); + oDocument.CloseFile(); } -bool CMDWriter::WriteText(const std::wstring& wsText, const std::vector& arSelectors) +inline void ReplaceSpaces(std::wstring& wsValue) { - GetCurrentDocument()->WriteString(wsText); + // boost::wregex oRegex(L"\\s+"); + // wsValue = boost::regex_replace(wsValue, oRegex, L" "); + + std::wstring::const_iterator itBegin = std::find_if(wsValue.cbegin(), wsValue.cend(), [](wchar_t wchValue){ return std::iswspace(wchValue) && 0xa0 != wchValue; }); + std::wstring::const_iterator itEnd; + + while (wsValue.cend() != itBegin) + { + itEnd = std::find_if(itBegin, wsValue.cend(), [](wchar_t wchValue){ return !std::iswspace(wchValue) || 0xa0 == wchValue; }); + + wsValue.replace(itBegin, itEnd, L" "); + + itBegin = std::find_if(itBegin + 1, wsValue.cend(), [](wchar_t wchValue){ return std::iswspace(wchValue) && 0xa0 != wchValue; }); + } +} + +bool CMDWriter::WriteText(std::wstring wsText, const std::vector& arSelectors) +{ + bool bPreformatted{InPreformatted()}; + + const NSCSS::CCompiledStyle* pCompiledStyle{arSelectors.back().m_pCompiledStyle}; + + if (!bPreformatted && nullptr != arSelectors.back().m_pCompiledStyle) + { + // TODO::поведение должно быть немного разное (реализовать) + switch(pCompiledStyle->m_oDisplay.GetWhiteSpace().ToInt()) + { + case NSCSS::NSProperties::EWhiteSpace::Pre: + case NSCSS::NSProperties::EWhiteSpace::Pre_Wrap: + case NSCSS::NSProperties::EWhiteSpace::Pre_Line: + bPreformatted = true; + default: + break; + } + } + + if (!bPreformatted && wsText.end() == std::find_if_not(wsText.begin(), wsText.end(), [](wchar_t wchChar){ return iswspace(wchChar) && 0xa0 != wchChar;})) + return false; + + if (bPreformatted && !m_arStates.top().m_bEmptyLine) + GetCurrentDocument()->AddCharSafe(L'\n'); + + //Пока корректно работает только для текста (необходимо проверить и с другими нодами) + if (m_arStates.top().m_bEmptyLine) + { + for (UINT unIndex = 0; unIndex < GetLevelBlockquote(); ++unIndex) + WriteString(L"> ", true); + } + + if (!bPreformatted && !InCode()) + ReplaceSpaces(wsText); + + WriteString(wsText); + + if (L'\n' == wsText.back()) + m_arStates.top().m_bNeedBreakLine = false; + return true; } void CMDWriter::WriteEmptyParagraph(bool bVahish, bool bInP) { - } void CMDWriter::BeginBlock() { - + WriteBreakLine(); } void CMDWriter::EndBlock(bool bAddBlock) { - GetCurrentDocument()->WriteString(m_oMDParametrs.m_wsLineBreak); + WriteBreakLine(); } void CMDWriter::SetDataOutput(XmlString* pOutputData) @@ -47,13 +114,23 @@ void CMDWriter::SetDataOutput(XmlString* pOutputData) void CMDWriter::RevertDataOutput() { - RollBackState(); } TMDParametrs CMDWriter::GetParametrs() const { - return m_oMDParametrs;; + return m_oMDParametrs; +} + +void CMDWriter::WriteString(const std::wstring& wsString, bool bSpecialString) +{ + GetCurrentDocument()->WriteString(wsString); + + if (m_arStates.top().m_bEmptyLine) + m_arStates.top().m_bEmptyLine = wsString.empty(); + + if (!bSpecialString) + m_arStates.top().m_bNeedBreakLine = true; } XmlString* CMDWriter::GetCurrentDocument() const @@ -61,6 +138,110 @@ XmlString* CMDWriter::GetCurrentDocument() const return m_arStates.top().m_pCurrentDocument; } +void CMDWriter::WriteBreakLine(bool bNeedChecked) +{ + if (bNeedChecked && !m_arStates.top().m_bNeedBreakLine) + return; + + GetCurrentDocument()->WriteString(L" \n"); + m_arStates.top().m_bNeedBreakLine = false; + m_arStates.top().m_bEmptyLine = true; +} + +void CMDWriter::EnteredBlockquote() +{ + m_arStates.top().m_unLevelBlockquote++; +} + +void CMDWriter::OutBlockquote() +{ + if (m_arStates.top().m_unLevelBlockquote > 0) + m_arStates.top().m_unLevelBlockquote--; +} + +UINT CMDWriter::GetLevelBlockquote() +{ + return m_arStates.top().m_unLevelBlockquote; +} + +void CMDWriter::EnteredTable() +{ + m_arStates.top().m_bInTable = true; +} + +void CMDWriter::OutTable() +{ + m_arStates.top().m_bInTable = false; +} + +bool CMDWriter::InTable() const +{ + return m_arStates.top().m_bInTable; +} + +void CMDWriter::EnteredPreformatted() +{ + m_arStates.top().m_bInPreformatted = true; +} + +void CMDWriter::OutPreformatted() +{ + m_arStates.top().m_bInPreformatted = false; +} + +bool CMDWriter::InPreformatted() const +{ + return m_arStates.top().m_bInPreformatted; +} + +void CMDWriter::EnteredCode() +{ + m_arStates.top().m_bInCode = true; +} + +void CMDWriter::OutCode() +{ + m_arStates.top().m_bInCode = false; +} + +bool CMDWriter::InCode() const +{ + return m_arStates.top().m_bInCode; +} + +void CMDWriter::EnteredList(bool bOrderedList) +{ + SaveState(); + m_arStates.top().m_bInList = true; + m_arStates.top().m_bIsOrederedList = bOrderedList; + m_arStates.top().m_unLevelList++; +} + +void CMDWriter::OutList() +{ + RollBackState(); +} + +void CMDWriter::IncreaseIndexOrderedList() +{ + m_arStates.top().m_unIndexListElement++; +} + +bool CMDWriter::InOrederedList() const +{ + return m_arStates.top().m_bIsOrederedList; +} + +UINT CMDWriter::GetIndexOrderedList() const +{ + return m_arStates.top().m_unIndexListElement; +} + +UINT CMDWriter::GetLevelList() const +{ + return m_arStates.top().m_unLevelList; +} + void CMDWriter::SaveState() { m_arStates.push(m_arStates.top()); diff --git a/HtmlFile2/Writers/MDWriter.h b/HtmlFile2/Writers/MDWriter.h index 1a51d7da79..2f577842e7 100644 --- a/HtmlFile2/Writers/MDWriter.h +++ b/HtmlFile2/Writers/MDWriter.h @@ -9,7 +9,8 @@ namespace HTML struct TMDParametrs { bool m_bUseAlternativeHTMLTags = false; //Использовать html теги там, где нет стандартной реализации в md(например для подчеркиваний) - std::wstring m_wsLineBreak = L" "; // По умолчанию для переноса строки используем двойной пробел + WCHAR m_wchUnorderedList = L'-'; // Возможные варианты в md: -, +, * + WCHAR m_wchOrderedList = L'.'; // Возможные варианты в md: ., ) }; class CMDWriter : public IWriter @@ -18,7 +19,21 @@ class CMDWriter : public IWriter struct TState { - XmlString *m_pCurrentDocument; + XmlString *m_pCurrentDocument{nullptr}; + + bool m_bNeedBreakLine{false}; + bool m_bEmptyLine{true}; + + UINT m_unLevelBlockquote{0}; + + bool m_bInTable{false}; + bool m_bInPreformatted{false}; + bool m_bInCode{false}; + + bool m_bInList{false}; + bool m_bIsOrederedList{false}; + UINT m_unLevelList{0}; + UINT m_unIndexListElement{0}; }; std::stack m_arStates; @@ -29,7 +44,7 @@ public: void Begin(const std::wstring& wsDst, const THtmlParams* pParams) override; void End(const std::wstring& wsDst) override; - bool WriteText(const std::wstring& wsText, const std::vector& arSelectors) override; + bool WriteText(std::wstring wsText, const std::vector& arSelectors) override; void WriteEmptyParagraph(bool bVahish = false, bool bInP = false) override; @@ -40,7 +55,34 @@ public: void RevertDataOutput() override; TMDParametrs GetParametrs() const; + void WriteString(const std::wstring& wsString, bool bSpecialString = false); XmlString* GetCurrentDocument() const override; + + void WriteBreakLine(bool bNeedChecked = true); + + void EnteredBlockquote(); + void OutBlockquote(); + UINT GetLevelBlockquote(); + + void EnteredTable(); + void OutTable(); + bool InTable() const; + + void EnteredPreformatted(); + void OutPreformatted(); + bool InPreformatted() const; + + void EnteredCode(); + void OutCode(); + bool InCode() const; + + void EnteredList(bool bOrderedList); + void OutList(); + void IncreaseIndexOrderedList(); + + bool InOrederedList() const; + UINT GetIndexOrderedList() const; + UINT GetLevelList() const; private: void SaveState(); void RollBackState(); diff --git a/HtmlFile2/Writers/OOXMLWriter.cpp b/HtmlFile2/Writers/OOXMLWriter.cpp index f083f70203..d524981bc2 100644 --- a/HtmlFile2/Writers/OOXMLWriter.cpp +++ b/HtmlFile2/Writers/OOXMLWriter.cpp @@ -10,9 +10,6 @@ #include "../src/Languages.h" -#include -#include - namespace HTML { #ifndef VALUE2STR @@ -697,13 +694,11 @@ std::wstring COOXMLWriter::WriteRPr(XmlString& oXml, const std::vector& arSelectors) +bool COOXMLWriter::WriteText(std::wstring wsText, const std::vector& arSelectors) { if (wsText.empty()) return false; - std::wstring wsNormalizeText(wsText); - bool bBidirectional{false}, bPreformatted{false}, bQuotation{false}, bAddSpaces{true}, bMergedText{false}; for (const NSCSS::CNode& oNode : arSelectors) @@ -736,16 +731,16 @@ bool COOXMLWriter::WriteText(const std::wstring& wsText, const std::vectorWriteString(L"""); - if (!bPreformatted && bAddSpaces && m_arStates.top().m_bInP && !m_arStates.top().m_bInR && !iswspace(wsNormalizeText.front()) && !iswpunct(wsNormalizeText.front()) && !m_arStates.top().m_bWasSpace) + if (!bPreformatted && bAddSpaces && m_arStates.top().m_bInP && !m_arStates.top().m_bInR && !iswspace(wsText.front()) && !iswpunct(wsText.front()) && !m_arStates.top().m_bWasSpace) { if (pCompiledStyle->m_oDisplay.GetVAlign().Empty() || L"normal" == pCompiledStyle->m_oDisplay.GetVAlign().ToWString()) WriteSpace(); @@ -779,7 +774,7 @@ bool COOXMLWriter::WriteText(const std::wstring& wsText, const std::vectorWriteEncodeXmlString(wsNormalizeText.c_str() + unBegin, wsNormalizeText.length() - unBegin); + m_arStates.top().m_pCurrentDocument->WriteEncodeXmlString(wsText.c_str() + unBegin, wsText.length() - unBegin); break; } if (unBegin != unEnd) { - m_arStates.top().m_pCurrentDocument->WriteEncodeXmlString(wsNormalizeText.c_str() + unBegin, unEnd - unBegin); + m_arStates.top().m_pCurrentDocument->WriteEncodeXmlString(wsText.c_str() + unBegin, unEnd - unBegin); CloseT(); } - if (L'\n' == wsNormalizeText[unEnd]) + if (L'\n' == wsText[unEnd]) m_arStates.top().m_pCurrentDocument->WriteString(L""); - else if (L'\t' == wsNormalizeText[unEnd]) + else if (L'\t' == wsText[unEnd]) m_arStates.top().m_pCurrentDocument->WriteString(L""); unBegin = unEnd + 1; - unEnd = wsNormalizeText.find_first_of(L"\n\r\t", unBegin); + unEnd = wsText.find_first_of(L"\n\r\t", unBegin); } } else { - ReplaceSpaces(wsNormalizeText); + ReplaceSpaces(wsText); - if (!wsNormalizeText.empty() && L'\t' == wsNormalizeText[0]) + if (!wsText.empty() && L'\t' == wsText[0]) { m_arStates.top().m_pCurrentDocument->WriteString(L""); - wsNormalizeText.erase(0, 1); + wsText.erase(0, 1); } - if (!wsNormalizeText.empty() && std::iswspace(wsNormalizeText.front()) && m_arStates.top().m_bWasSpace) - wsNormalizeText.erase(0, 1); + if (!wsText.empty() && std::iswspace(wsText.front()) && m_arStates.top().m_bWasSpace) + wsText.erase(0, 1); OpenT(); if (bMergedText && !m_arStates.top().m_bWasSpace && bInT && !bPreformatted) m_arStates.top().m_pCurrentDocument->WriteEncodeXmlString(L" "); - if (!wsNormalizeText.empty()) + if (!wsText.empty()) { - m_arStates.top().m_bWasSpace = std::iswspace(wsNormalizeText.back()); - m_arStates.top().m_pCurrentDocument->WriteEncodeXmlString(wsNormalizeText); + m_arStates.top().m_bWasSpace = std::iswspace(wsText.back()); + m_arStates.top().m_pCurrentDocument->WriteEncodeXmlString(wsText); } } diff --git a/HtmlFile2/Writers/OOXMLWriter.h b/HtmlFile2/Writers/OOXMLWriter.h index 34170a33b5..d90b3b406c 100644 --- a/HtmlFile2/Writers/OOXMLWriter.h +++ b/HtmlFile2/Writers/OOXMLWriter.h @@ -78,9 +78,9 @@ class COOXMLWriter : public IWriter TState() : m_bInP(false), m_bInR(false), m_bInT(false), - m_bWasPStyle(false), m_bWasSpace(true), m_bInHyperlink(false), - m_bBanUpdatePageData(false), m_pCurrentDocument(nullptr), - m_bRemoveCurrentDocument(false)/*, m_eLastElement(HTML_TAG(UNKNOWN))*/ + m_bWasPStyle(false), m_bWasSpace(true), m_bInHyperlink(false), + m_bBanUpdatePageData(false), m_pCurrentDocument(nullptr), + m_bRemoveCurrentDocument(false)/*, m_eLastElement(HTML_TAG(UNKNOWN))*/ {} ~TState() @@ -150,7 +150,7 @@ public: std::wstring WritePPr(const std::vector& arSelectors); std::wstring WriteRPr(XmlString& oXml, const std::vector& arSelectors); - bool WriteText(const std::wstring& wsText, const std::vector& arSelectors) override; + bool WriteText(std::wstring wsText, const std::vector& arSelectors) override; void WriteEmptyParagraph(bool bVahish = false, bool bInP = false) override; void WriteSpace();