#include #include #include #include #include #include #include #include #include #include #include #include #include "novelparser.h" #include "htmlprint.h" using namespace example_novel; std::function, int)> tnode_print = [&](std::shared_ptr node, int intend) { auto name = node->element()->signature(); auto text = QString(intend * 2, ' ') + name; /*for (auto& t : node->tokens()) { text += " " + t->token()->content(); }*/ qDebug() << text; for (auto& c_n : node->children()) { tnode_print(c_n, intend + 1); } }; /* * nsc --help * nsc [opts] --path path-to-dir * opts: * -p print-struct 输出整体结构 * -s service 常驻服务启动 */ int main(int argc, char* argv[]) { QCoreApplication a(argc, argv); QStringList args; for (int idx = 0; idx < argc; idx++) { args += QString::fromLocal8Bit(argv[idx]); } // 帮助特殊用法 if (args.contains(u8"--help")) { std::cout << "nsc(WsNovelStoryCompiler:故事线编译器)" << std::endl; std::cout << "版本:V1.0.0" << std::endl; std::cout << "nsc -path path-to-dir" << std::endl; exit(0); } auto source_dir = QDir::current(); auto index = args.indexOf(u8"--path"); if (index < 0) { std::cout << "参数错误:必须指定 --path 参数" << endl; exit(1); } if (index + 1 >= args.size()) { std::cout << "参数错误:--path 后面应该续接story文件的父文件夹路径。" << std::endl; exit(1); } else { auto tdir = QDir(args[index+1]); if (tdir.exists()) { source_dir = tdir; } else { std::cout << "参数错误:传入的story文件父文件夹路径无效。"<< std::endl; exit(1); } } auto files = source_dir.entryInfoList(QStringList() << "*.story"); if (files.size()) { try { auto parser = std::make_shared(); auto novel_accesstree = parser->parse(files); printer::tools_printer tool; tool.build_fragments(novel_accesstree); tool.build_refers_network(novel_accesstree); 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)> html_output = [](std::shared_ptr inst) { auto target_path = inst->pageRefers(); QFile tfile(target_path); if (tfile.open(QIODevice::WriteOnly | QIODevice::Text)) { QDomDocument doc_inst(QDomImplementation().createDocumentType(u8"html", QString(), QString())); auto html = doc_inst.createElement(u8"html"); doc_inst.appendChild(html); auto body = doc_inst.createElement(u8"body"); html.appendChild(body); inst->buildPageHTML(body); QTextStream tout(&tfile); doc_inst.save(tout, 2); tout.flush(); } }; for (auto& node : tool.fragment_defines) html_output(node); for (auto& node : tool.storyline_defines) html_output(node); for (auto& node : tool.volume_defines) html_output(node); auto dot_src = tool.storylines_paint(tool.storyline_defines.values()); QFile dot_file(QDir::current().filePath(u8"relates.dot")); if (dot_file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream txt(&dot_file); txt.setCodec(u8"UTF-8"); txt << dot_src; txt.flush(); } system("dot -Tsvg relates.dot -o relates.svg"); auto vols_src = tool.volumes_paint(tool.volume_defines.values(), tool.storyline_defines.values()); QFile vols_file(QDir::current().filePath(u8"volumes_group.dot")); if (vols_file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream txt(&vols_file); txt.setCodec(u8"UTF-8"); txt << vols_src; txt.flush(); } system("fdp -Tsvg volumes_group.dot -o volumes_group.svg"); { QFile tfile("./index.html"); if (tfile.open(QIODevice::WriteOnly | QIODevice::Text)) { QDomDocument doc_inst(QDomImplementation().createDocumentType(u8"html", QString(), QString())); auto html = doc_inst.createElement(u8"html"); doc_inst.appendChild(html); auto body = doc_inst.createElement(u8"body"); html.appendChild(body); auto dom_storyline = doc_inst.createElement("div"); auto dom_storyline_title = doc_inst.createElement("h2"); dom_storyline_title.appendChild(doc_inst.createTextNode(u8"故事脉络")); dom_storyline.appendChild(dom_storyline_title); body.appendChild(dom_storyline); auto lines = tool.storyline_defines.values(); std::sort(lines.begin(), lines.end(), [](std::shared_ptr a, std::shared_ptr b)->bool { auto a_elm = std::dynamic_pointer_cast(a->accessPeers()->element()); auto b_elm = std::dynamic_pointer_cast(b->accessPeers()->element()); return a_elm->sort() < b_elm->sort(); }); for (auto& inst_line : lines) { auto dom_line = doc_inst.createElement("p"); dom_storyline.appendChild(dom_line); auto line_href = doc_inst.createElement("a"); line_href.setAttribute(u8"href", u8"file:///" + inst_line->pageRefers()); auto a_elm = std::dynamic_pointer_cast(inst_line->accessPeers()->element()); line_href.appendChild(doc_inst.createTextNode(QString(u8"%1.%2").arg(a_elm->sort()).arg(a_elm->signature()))); dom_line.appendChild(line_href); } auto dom_volume = doc_inst.createElement("div"); auto dom_volume_title = doc_inst.createElement("h2"); dom_volume_title.appendChild(doc_inst.createTextNode(u8"分卷内容")); dom_volume.appendChild(dom_volume_title); body.appendChild(dom_volume); for (auto& inst_volume : tool.volume_defines) { auto dom_volume_ref = doc_inst.createElement("p"); dom_volume.appendChild(dom_volume_ref); auto volume_href = doc_inst.createElement("a"); volume_href.setAttribute(u8"href", u8"file:///" + inst_volume->pageRefers()); volume_href.appendChild(doc_inst.createTextNode(inst_volume->accessPeers()->element()->signature())); dom_volume_ref.appendChild(volume_href); } auto dom_fragment = doc_inst.createElement("div"); auto dom_fragment_title = doc_inst.createElement("h2"); dom_fragment_title.appendChild(doc_inst.createTextNode(u8"情节集合")); dom_fragment.appendChild(dom_fragment_title); body.appendChild(dom_fragment); for (auto& inst_frag : tool.fragment_defines) { auto dom_fragment_ref = doc_inst.createElement("p"); dom_fragment.appendChild(dom_fragment_ref); auto frag_href = doc_inst.createElement("a"); frag_href.setAttribute(u8"href", u8"file:///" + inst_frag->pageRefers()); frag_href.appendChild(doc_inst.createTextNode(inst_frag->accessPeers()->element()->signature())); dom_fragment_ref.appendChild(frag_href); } auto dom_relate = doc_inst.createElement(u8"div"); auto dom_relate_title = doc_inst.createElement(u8"h2"); dom_relate_title.appendChild(doc_inst.createTextNode(u8"联系图")); dom_relate.appendChild(dom_relate_title); body.appendChild(dom_relate); auto img = doc_inst.createElement(u8"img"); img.setAttribute(u8"src", u8"file:///" + QDir::current().filePath(u8"relates.svg")); dom_relate.appendChild(img); dom_relate.appendChild(doc_inst.createElement("br")); img = doc_inst.createElement(u8"img"); img.setAttribute(u8"src", u8"file:///" + QDir::current().filePath(u8"volumes_group.svg")); dom_relate.appendChild(img); QTextStream tout(&tfile); doc_inst.save(tout, 2); tout.flush(); } } //tnode_print(novel_accesstree, 0); qDebug() << u8"编译成功:" << QDir::current().absoluteFilePath(u8"index.html"); } catch (lib_syntax::SyntaxException* e) { qDebug().noquote() << e->message(); delete e; } catch (lib_parse::CheckException* e) { qDebug().noquote() << e->message(); delete e; } } return 0; //return a.exec(); }