diff --git a/WsNovelParser/WsNovelParser.vcxproj.user b/WsNovelParser/WsNovelParser.vcxproj.user index 79d638e..737f5df 100644 --- a/WsNovelParser/WsNovelParser.vcxproj.user +++ b/WsNovelParser/WsNovelParser.vcxproj.user @@ -5,9 +5,9 @@ WindowsLocalDebugger - 2024-03-31T05:42:51.9907375Z + 2024-03-31T14:11:49.6878635Z - 2024-03-31T05:42:52.0532400Z + 2024-03-31T14:11:50.2019950Z \ No newline at end of file diff --git a/WsNovelParser/htmlprint.cpp b/WsNovelParser/htmlprint.cpp index 18dae35..cc33dbd 100644 --- a/WsNovelParser/htmlprint.cpp +++ b/WsNovelParser/htmlprint.cpp @@ -1,19 +1,29 @@ #include "htmlprint.h" #include +#include using namespace example_novel; using namespace printer; -Access::Access(std::shared_ptr handle) :access_handle(handle) {} +Access::Access(std::shared_ptr handle) + :access_handle(handle) {} std::shared_ptr Access::accessPeers() const { return access_handle; } -void Access::setHtmlRefer(const QString& href) { this->refers_store = href; } +void Access::setPageRefers(const QString& href) { this->summary_refer_store = href; } -QString Access::htmlRefer() const { return this->refers_store; } +QString Access::pageRefers() const { return this->summary_refer_store; } Element::Element(std::shared_ptr handle) :Access(handle) {} +void printer::Element::setPieceRefer(const QString& href) { + this->refer_store = href; +} + +QString printer::Element::pieceRefers() const { + return refer_store; +} + Group::Group(std::shared_ptr handle) : Access(handle) {} void Group::append(std::shared_ptr elm) @@ -26,29 +36,131 @@ QList> Group::elements() const return this->element_store; } +std::shared_ptr printer::Group::getElement(const QString& signature) const +{ + for (auto& it : elements()) { + if (it->accessPeers()->element()->signature() == signature) + return it; + } + return nullptr; +} + StoryLine::StoryLine(std::shared_ptr handle) :Group(handle) {} -QString StoryLine::toHTML() const -{ +QString StoryLine::getPageHTML(QDomElement& parent) const { + auto syntax_access = this->accessPeers(); + auto storyline_inst = std::dynamic_pointer_cast(syntax_access->element()); + + auto doc = parent.ownerDocument(); + auto dom_storyline = doc.createElement("div"); + parent.appendChild(dom_storyline); + + auto dom_title = doc.createElement("h1"); + dom_title.appendChild(doc.createTextNode(storyline_inst->name())); + dom_storyline.appendChild(dom_title); + + for (auto& inst_c : syntax_access->children()) { + switch ((NovelNode)inst_c->element()->typeMark()) { + case NovelNode::TextSection: { + auto text_inst = std::dynamic_pointer_cast(inst_c->element()); + auto dom_p = doc.createElement("p"); + dom_p.appendChild(doc.createTextNode(text_inst->content())); + dom_storyline.appendChild(dom_p); + }break; + case NovelNode::FragmentRefer: + case NovelNode::FragmentDefine: { + auto element_inst = this->getElement(inst_c->element()->signature()); + element_inst->getPieceHTML(dom_storyline); + }break; + default: + break; + } + } + return QString(); } StoryVolume::StoryVolume(std::shared_ptr handle) : Group(handle) {} -QString StoryVolume::toHTML() const +QString StoryVolume::getPageHTML(QDomElement& doc) const { return QString(); } FragmentRef::FragmentRef(std::shared_ptr handle) : Element(handle) {} -QString FragmentRef::toOutsideHTML() const +void printer::FragmentRef::setHost(std::shared_ptr frag_inst) { + this->host_inst = frag_inst; +} + +std::shared_ptr printer::FragmentRef::hostFragment() const +{ + return this->host_inst.lock(); +} + +QString FragmentRef::getPieceHTML(QDomElement& dom_parent) const { + auto syntax_element = this->accessPeers()->element(); + auto refer_element = std::dynamic_pointer_cast(syntax_element); + + auto jump_to_host = this->hostFragment()->pageRefers(); + auto doc = dom_parent.ownerDocument(); + + auto dom_reference = doc.createElement(u8"div"); + dom_parent.appendChild(dom_reference); + + auto dom_title = doc.createElement(u8"h2"); + dom_reference.appendChild(dom_title); + + auto dom_href = doc.createElement(u8"a"); + dom_href.appendChild(doc.createTextNode(refer_element->referSignature())); + dom_href.setAttribute("href", jump_to_host); + dom_title.appendChild(dom_href); + + for (auto child : this->accessPeers()->children()) { + if (child->element()->typeMark() == (int)NovelNode::TextSection) { + auto text_inst = std::dynamic_pointer_cast(child->element()); + auto dom_p = doc.createElement("p"); + dom_p.appendChild(doc.createTextNode(text_inst->content())); + dom_reference.appendChild(dom_p); + } + } + return QString(); } -QString FragmentRef::toDefinitionHTML() const -{ +QString FragmentRef::getPageHTML(QDomElement& parent) const { + auto syntax_access = this->accessPeers(); + auto refer_element = std::dynamic_pointer_cast(syntax_access->element()); + + auto doc = parent.ownerDocument(); + + auto refers_dom = doc.createElement(u8"div"); + parent.appendChild(refers_dom); + + auto title_block = doc.createElement(u8"h2"); + refers_dom.appendChild(title_block); + auto title_refer = doc.createElement(u8"a"); + title_refer.appendChild(doc.createTextNode(refer_element->signature())); + title_refer.setAttribute("href", this->pieceRefers()); + title_block.appendChild(title_refer); + + std::function>)> build_cascade = + [&](QList> children_items) { + for (auto child : children_items) { + if (child->element()->typeMark() == (int)NovelNode::TextSection) { + auto text_inst = std::dynamic_pointer_cast(child->element()); + auto p = doc.createElement("p"); + p.appendChild(doc.createTextNode(text_inst->content())); + refers_dom.appendChild(p); + } + else { + build_cascade(child->children()); + } + } + }; + + build_cascade(syntax_access->children()); return QString(); } @@ -56,26 +168,77 @@ Fragment::Fragment(std::shared_ptr handle) : Eleme void Fragment::appendRefers(std::shared_ptr inst) { this->additionals_store.append(inst); + inst->setHost(std::static_pointer_cast(this->shared_from_this())); } QList> Fragment::additionals() const { return this->additionals_store; } -QString Fragment::toOutsideHTML() const -{ +QString Fragment::getPieceHTML(QDomElement& parent) const { + auto syntax_access = this->accessPeers(); + auto fragment_inst = std::dynamic_pointer_cast(syntax_access->element()); + + auto doc = parent.ownerDocument(); + auto dom_fragment = doc.createElement("div"); + parent.appendChild(dom_fragment); + + auto dom_title = doc.createElement("h2"); + dom_fragment.appendChild(dom_title); + + auto dom_href = doc.createElement("a"); + dom_href.appendChild(doc.createTextNode(fragment_inst->name())); + dom_href.setAttribute("href", this->pageRefers()); + dom_title.appendChild(dom_href); + + for (auto& inst_c : syntax_access->children()) { + if (NovelNode::TextSection == (NovelNode)inst_c->element()->typeMark()) { + auto text_inst = std::dynamic_pointer_cast(inst_c->element()); + auto dom_p = doc.createElement("p"); + dom_p.appendChild(doc.createTextNode(text_inst->content())); + dom_fragment.appendChild(dom_p); + } + } + return QString(); } -QString Fragment::toDefinitionHTML() const -{ +QString Fragment::getPageHTML(QDomElement& parent) const { + auto syntax_access = this->accessPeers(); + auto fragment_inst = std::dynamic_pointer_cast(syntax_access->element()); + + auto doc = parent.ownerDocument(); + auto dom_fragment = doc.createElement("div"); + parent.appendChild(dom_fragment); + + auto dom_title = doc.createElement("h1"); + dom_fragment.appendChild(dom_title); + + auto dom_href = doc.createElement("a"); + dom_href.appendChild(doc.createTextNode(fragment_inst->signature())); + dom_href.setAttribute("href", this->pageRefers()); + dom_title.appendChild(dom_href); + + for (auto& inst_c : syntax_access->children()) { + if (NovelNode::TextSection == (NovelNode)inst_c->element()->typeMark()) { + auto text_inst = std::dynamic_pointer_cast(inst_c->element()); + auto dom_p = doc.createElement("p"); + dom_p.appendChild(doc.createTextNode(text_inst->content())); + dom_fragment.appendChild(dom_p); + } + } + + for (auto& it : this->additionals()) { + it->getPageHTML(dom_fragment); + } + return QString(); } #include void tools_printer::build_fragments(std::shared_ptr novel_root) { - if (novel_root->element()->typeMark() == (int)example_novel::NovelNode::FragmentDefine) { + if (novel_root->element()->typeMark() == (int)NovelNode::FragmentDefine) { auto inst = std::make_shared(novel_root); this->fragment_defines[novel_root->element()->signature()] = inst; } @@ -87,13 +250,13 @@ void tools_printer::build_fragments(std::shared_ptr novel_node) { - switch ((example_novel::NovelNode)novel_node->element()->typeMark()) { - case example_novel::NovelNode::StoryDefine: { + switch ((NovelNode)novel_node->element()->typeMark()) { + case NovelNode::StoryDefine: { auto storyinst = std::make_shared(novel_node); this->storyline_defines[novel_node->element()->signature()] = storyinst; build_storyline(storyinst); }return; - case example_novel::NovelNode::VolumeDefine: { + case NovelNode::VolumeDefine: { auto volumeinst = std::make_shared(novel_node); this->volume_defines[novel_node->element()->signature()] = volumeinst; build_volumeline(volumeinst); @@ -112,14 +275,14 @@ void tools_printer::build_storyline(std::shared_ptr line, std::shared } } else { - switch ((example_novel::NovelNode)novel_node->element()->typeMark()) + switch ((NovelNode)novel_node->element()->typeMark()) { - case example_novel::NovelNode::FragmentDefine: { + case NovelNode::FragmentDefine: { auto inst = this->fragment_defines[novel_node->element()->signature()]; line->append(inst); }return; - case example_novel::NovelNode::FragmentRefer: { - auto refer_node = std::dynamic_pointer_cast(novel_node->element()); + case NovelNode::FragmentRefer: { + auto refer_node = std::dynamic_pointer_cast(novel_node->element()); auto refer_fragment = this->fragment_defines[refer_node->referSignature()]; auto inst = std::make_shared(novel_node); refer_fragment->appendRefers(inst); @@ -139,8 +302,8 @@ void tools_printer::build_volumeline(std::shared_ptr volume, std::s build_volumeline(volume, inst_c); } else { - if (example_novel::NovelNode::FragmentRefer == (example_novel::NovelNode)novel_node->element()->typeMark()) { - auto refer_node = std::dynamic_pointer_cast(novel_node->element()); + if (NovelNode::FragmentRefer == (NovelNode)novel_node->element()->typeMark()) { + auto refer_node = std::dynamic_pointer_cast(novel_node->element()); auto refer_fragment = this->fragment_defines[refer_node->referSignature()]; auto inst = std::make_shared(novel_node); refer_fragment->appendRefers(inst); @@ -153,36 +316,50 @@ void tools_printer::build_volumeline(std::shared_ptr volume, std::s } } -void printer::tools_printer::fragments_anchors_define(const QList>& list, const QDir & destdir) { - for (auto &it : list) { +void tools_printer::fragments_anchors_define(const QList>& list, const QDir& root_dir) { + auto path = root_dir.filePath("fragments"); + if (!QDir(path).exists()) + root_dir.mkdir("fragments"); + QDir target_dir(path); + + for (auto& it : list) { auto address_x = QString::number((qulonglong)it->accessPeers()->element().get()); - it->setHtmlRefer(destdir.absoluteFilePath(QString("%1.html").arg(address_x))); + it->setPageRefers(target_dir.absoluteFilePath(QString("%1.html").arg(address_x))); } } -std::function>&, const QDir &)> refers_refresh = - [&](const QList> &items, const QDir &destdir){ - for (auto &item : items) { - auto refer = std::dynamic_pointer_cast(item); - if (refer) { - auto address_x = QString::number((qulonglong)refer->accessPeers()->element().get()); - refer->setHtmlRefer(destdir.absoluteFilePath(QString("%1.html").arg(address_x))); - } +std::function>&, const QString&)> refers_refresh = +[&](const QList>& items, const QString& summary_href) { + for (auto& item : items) { + auto element_addr = QString::number((qulonglong)item->accessPeers()->element().get()); + item->setPieceRefer(summary_href + u8"#" + element_addr); } -}; + }; -void printer::tools_printer::storylines_anchors_define(const QList>& list, const QDir & destdir) { - for (auto &it : list) { +void tools_printer::storylines_anchors_define(const QList>& list, const QDir& root_dir) { + auto path = root_dir.filePath("storylines"); + if (!QDir(path).exists()) + root_dir.mkdir("storylines"); + QDir target_dir(path); + + for (auto& it : list) { auto address_x = QString::number((qulonglong)it->accessPeers()->element().get()); - it->setHtmlRefer(destdir.absoluteFilePath(QString("%1.html").arg(address_x))); - refers_refresh(it->elements(), destdir); + auto page_address = target_dir.absoluteFilePath(QString("%1.html").arg(address_x)); + it->setPageRefers(page_address); + refers_refresh(it->elements(), page_address); } } -void printer::tools_printer::volumes_anchors_define(const QList>& list, const QDir & destdir) { - for (auto &it : list) { +void tools_printer::volumes_anchors_define(const QList>& list, const QDir& root_dir) { + auto path = root_dir.filePath("volumes"); + if (!QDir(path).exists()) + root_dir.mkdir("volumes"); + QDir target_dir(path); + + for (auto& it : list) { auto address_x = QString::number((qulonglong)it->accessPeers()->element().get()); - it->setHtmlRefer(destdir.absoluteFilePath(QString("%1.html").arg(address_x))); - refers_refresh(it->elements(), destdir); + auto page_address = target_dir.absoluteFilePath(QString("%1.html").arg(address_x)); + it->setPageRefers(page_address); + refers_refresh(it->elements(), page_address); } } diff --git a/WsNovelParser/htmlprint.h b/WsNovelParser/htmlprint.h index 8066360..1bc976f 100644 --- a/WsNovelParser/htmlprint.h +++ b/WsNovelParser/htmlprint.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include @@ -14,14 +15,27 @@ namespace printer { Access(std::shared_ptr handle); virtual ~Access() = default; + /* + * @brief 获取绑定的语法元素 + * @return 元素内存指针 + */ std::shared_ptr accessPeers() const; - void setHtmlRefer(const QString& href); - QString htmlRefer() const; + /* + * @brief 设置汇总页面路径 + * @param href 页面路径 + */ + void setPageRefers(const QString& href); + QString pageRefers() const; + + /* + * @brief 获取汇总页面的HTML + */ + virtual QString getPageHTML(QDomElement& doc) const = 0; private: std::shared_ptr access_handle; - QString refers_store; + QString summary_refer_store; }; /* @@ -32,8 +46,19 @@ namespace printer { Element(std::shared_ptr handle); virtual ~Element() = default; - virtual QString toOutsideHTML() const = 0; - virtual QString toDefinitionHTML() const = 0; + /* + * @brief 设置片段URL,从故事汇总页面跳转回出处页面 + */ + virtual void setPieceRefer(const QString& href); + virtual QString pieceRefers() const; + + /* + * @brief 获取故事片段出处的节点HTML + */ + virtual QString getPieceHTML(QDomElement &doc) const = 0; + + private: + QString refer_store; }; /* @@ -44,10 +69,9 @@ namespace printer { Group(std::shared_ptr handle); virtual ~Group() = default; - virtual QString toHTML() const = 0; - void append(std::shared_ptr elm); QList> elements() const; + std::shared_ptr getElement(const QString& signature) const; private: QList> element_store; @@ -58,7 +82,7 @@ namespace printer { StoryLine(std::shared_ptr handle); // 通过 Group 继承 - QString toHTML() const override; + QString getPageHTML(QDomElement& doc) const override; }; @@ -67,10 +91,10 @@ namespace printer { StoryVolume(std::shared_ptr handle); // 通过 Group 继承 - QString toHTML() const override; + QString getPageHTML(QDomElement& doc) const override; }; - + class Fragment; /* * @brief 情节片段引用定义 */ @@ -78,9 +102,17 @@ namespace printer { public: FragmentRef(std::shared_ptr handle); + void setHost(std::shared_ptr frag_inst); + std::shared_ptr hostFragment() const; + + // 通过 Access 继承 + QString getPageHTML(QDomElement& doc) const override; + // 通过 Element 继承 - QString toOutsideHTML() const override; - QString toDefinitionHTML() const override; + QString getPieceHTML(QDomElement& doc) const override; + + private: + std::weak_ptr host_inst; }; /* @@ -96,10 +128,11 @@ namespace printer { void appendRefers(std::shared_ptr inst); QList> additionals() const; + // 通过 Access 继承 + QString getPageHTML(QDomElement& doc) const override; // 通过 Element 继承 - QString toOutsideHTML() const override; - QString toDefinitionHTML() const override; + QString getPieceHTML(QDomElement& doc) const override; }; diff --git a/WsNovelParser/main.cpp b/WsNovelParser/main.cpp index d003ea2..27077dd 100644 --- a/WsNovelParser/main.cpp +++ b/WsNovelParser/main.cpp @@ -27,15 +27,10 @@ int main(int argc, char* argv[]) { printer::tools_printer tool; tool.build_fragments(novel_accesstree); tool.build_refers_network(novel_accesstree); - - auto dest = QDir::current(); - dest.mkdir("storylines"); - dest.mkdir("volumes"); - dest.mkdir("fragments"); - tool.fragments_anchors_define(tool.fragment_defines.values(), QDir(dest.filePath("fragments"))); - tool.storylines_anchors_define(tool.storyline_defines.values(), QDir(dest.filePath("storylines"))); - tool.volumes_anchors_define(tool.volume_defines.values(), QDir(dest.filePath("volumes"))); + tool.fragments_anchors_define(tool.fragment_defines.values(), QDir::current()); + tool.storylines_anchors_define(tool.storyline_defines.values(), QDir::current()); + tool.volumes_anchors_define(tool.volume_defines.values(), QDir::current()); std::function, int)> tnode_print = [&](std::shared_ptr node, int intend) { diff --git a/libParse/libParse.vcxproj.user b/libParse/libParse.vcxproj.user index 59cfff3..57e7254 100644 --- a/libParse/libParse.vcxproj.user +++ b/libParse/libParse.vcxproj.user @@ -5,9 +5,9 @@ WindowsLocalDebugger - 2024-03-31T05:42:52.1001219Z + 2024-03-31T14:11:50.6102543Z - 2024-03-31T05:42:52.1782463Z + 2024-03-31T14:11:50.7328441Z \ No newline at end of file diff --git a/libSyntax/libSyntax.vcxproj.user b/libSyntax/libSyntax.vcxproj.user index d396399..3545fe8 100644 --- a/libSyntax/libSyntax.vcxproj.user +++ b/libSyntax/libSyntax.vcxproj.user @@ -5,9 +5,9 @@ WindowsLocalDebugger - 2024-03-31T05:42:52.3344976Z + 2024-03-31T14:11:50.4238856Z - 2024-03-31T05:42:52.5226570Z + 2024-03-31T14:11:50.5434786Z \ No newline at end of file diff --git a/libToken/libToken.vcxproj.user b/libToken/libToken.vcxproj.user index 26e5b18..5e874a7 100644 --- a/libToken/libToken.vcxproj.user +++ b/libToken/libToken.vcxproj.user @@ -2,9 +2,9 @@ - 2024-03-31T05:42:52.2094883Z + 2024-03-31T14:11:50.7936395Z - 2024-03-31T05:42:52.3032378Z + 2024-03-31T14:11:50.9152358Z \ No newline at end of file