From 1f4b48537f52646f9e4d520c2b2c2425f3565fa2 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 4 Jan 2015 17:41:53 +0100 Subject: first draft for HTML Demo Output (still a lot of todos). --- src/plugins/html/DemoOutput.cpp | 187 ++++++++++++++++++++++++++++++++++++++++ src/plugins/html/DemoOutput.hpp | 85 ++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 src/plugins/html/DemoOutput.cpp create mode 100644 src/plugins/html/DemoOutput.hpp (limited to 'src/plugins/html') diff --git a/src/plugins/html/DemoOutput.cpp b/src/plugins/html/DemoOutput.cpp new file mode 100644 index 0000000..6b9b3a4 --- /dev/null +++ b/src/plugins/html/DemoOutput.cpp @@ -0,0 +1,187 @@ +/* + Ousía + Copyright (C) 2014 Benjamin Paaßen, Andreas Stöckel + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include + +#include "DemoOutput.hpp" + +namespace ousia { +namespace html { + +void DemoHTMLTransformer::writeHTML(Handle doc, + std::ostream &out) +{ + // write preamble + out << "\n"; + out << "\n"; + out << "\t\n"; + out << "\t\tTest HTML Output for" << doc->getName() << "\n"; + out << "\t\n"; + out << "\t\n"; + + // look for the book root node. + Rooted root = doc->getRoot(); + if (root->getDescriptor()->getName() != "book") { + throw OusiaException("The given documents root is no book node!"); + } + // write it to HTML. + writeSection(root, out); + // write end + out << "\t\n"; + out << "\n"; +} + +/** + * This is just for easier internal handling. + */ +enum class SectionType { BOOK, CHAPTER, SECTION, SUBSECTION, NONE }; + +SectionType getSectionType(const std::string &name) +{ + if (name == "book") { + return SectionType::BOOK; + } else if (name == "chapter") { + return SectionType::CHAPTER; + } else if (name == "section") { + return SectionType::SECTION; + } else if (name == "subsection") { + return SectionType::SUBSECTION; + } else { + return SectionType::NONE; + } +} + +void DemoHTMLTransformer::writeSection(Handle sec, + std::ostream &out) +{ + // check the section type. + SectionType type = getSectionType(sec->getDescriptor()->getName()); + if (type == SectionType::NONE) { + // if the input node is no section, we ignore it. + return; + } + // get the fields. + std::vector> &fields = sec->getFields(); + // check if we have a heading. + if (fields.size() > 1 && fields[1].size() > 0) { + out << "\t\t"; + switch (type) { + case SectionType::BOOK: + out << "

"; + break; + case SectionType::CHAPTER: + out << "

"; + break; + case SectionType::SECTION: + out << "

"; + break; + case SectionType::SUBSECTION: + out << "

"; + break; + case SectionType::NONE: + // this can not happen; + break; + } + // the second field marks the heading. So let's write it. + writeParagraph(fields[1][0], out, false); + // close the heading tag. + switch (type) { + case SectionType::BOOK: + out << "

"; + break; + case SectionType::CHAPTER: + out << ""; + break; + case SectionType::SECTION: + out << ""; + break; + case SectionType::SUBSECTION: + out << ""; + break; + case SectionType::NONE: + // this can not happen; + break; + } + out << "\n"; + } + + // then write the section content recursively. + for (auto &n : fields[0]) { + /* + * Strictly speaking this is the wrong mechanism, because we would have + * to make an "isa" call here because we can not rely on our knowledge + * that paragraphs can only be paragraphs or lists. There would have + * to be a listener structure of transformations that check if they can + * transform this specific node. + */ + std::string childDescriptorName = n->getDescriptor()->getName(); + if (childDescriptorName == "paragraph") { + writeParagraph(n, out); + // TODO: Implement + // } else if(childDescriptorName == "ul"){ + // writeList(n, out); + } else { + writeSection(n, out); + } + } +} + +void DemoHTMLTransformer::writeParagraph(Handle par, + std::ostream &out, bool writePTags) +{ + // validate descriptor. + if (par->getDescriptor()->getName() != "paragraph") { + throw OusiaException("Expected paragraph!"); + } + // get the fields. + std::vector> &fields = par->getFields(); + // write heading if its there. + // check if we have a heading. + if (fields.size() > 1 && fields[1].size() > 0) { + // start the heading tag + out << "\t\t
"; + // the second field marks the heading. So let's write it. + writeParagraph(fields[1][0], out, false); + // close the heading tag. + out << "
\n"; + } + // write start tag + if (writePTags) { + out << "\t\t

"; + } + // write content + // TODO: What about emphasis? + for (auto &text : fields[0]) { + if (text->getDescriptor()->getName() != "text") { + throw OusiaException("Expected text!"); + } + Handle primitive = + text->getFields()[0][0].cast(); + if (primitive == nullptr) { + throw OusiaException("Text field is not primitive!"); + } + out << primitive->getContent().asString(); + } + // write end tag + if (writePTags) { + out << "

\n"; + } +} +} +} diff --git a/src/plugins/html/DemoOutput.hpp b/src/plugins/html/DemoOutput.hpp new file mode 100644 index 0000000..ca9bcd2 --- /dev/null +++ b/src/plugins/html/DemoOutput.hpp @@ -0,0 +1,85 @@ +/* + Ousía + Copyright (C) 2014 Benjamin Paaßen, Andreas Stöckel + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file DemoOutput.hpp + * + * This implements a Demo HTML output for the following domains: + * * book + * * headings + * * emphasis + * * lists + * + * @author Benjamin Paassen - bpaassen@techfak.uni-bielefeld.de + */ +#ifndef _OUSIA_HTML_DEMO_OUTPUT_HPP_ +#define _OUSIA_HTML_DEMO_OUTPUT_HPP_ + +#include + +#include + +namespace ousia { +namespace html { + +class DemoHTMLTransformer { +private: + /** + * This method is to be called recursively to write a chapter, section or + * subsection to HTML. + */ + void writeSection(Handle sec, std::ostream& out); + /** + * This method is to be called recursively to write a paragraph to HTML. + */ + void writeParagraph(Handle par, std::ostream& out, + bool writePTags = true); + /** + * This method is to be called recursively to write a list to HTML. + * TODO: Implement + */ +// void writeList(Handle sec, std::ostream& out, +// int tabdepth); + + //TODO: Implement emphasis. + +public: + /** + * This writes a HTML representation of the given document to the given + * output stream. Note that this method lacks the generality of our Ousia + * approach with respect to two important points: + * 1.) It hardcodes the dependency to a certain set of domains in the C++ + * code. + * 2.) It does not use the proposed pipeline of first copying the document + * graph, then attaching style attributes and then transforming it to a + * specific output format but does all of these steps at once. + * 3.) It does not use different transformers for the different domains but + * does all transformations at once. + * Therefore this is not an adequate model of our algorithms but only a + * Demo. + * + * @param doc is a Document using concepts of the book, headings, emphasis + * and lists domains but no other. + * @param out is the output stream the data shall be written to. + */ + void writeHTML(Handle doc, std::ostream& out); +}; +} +} + +#endif -- cgit v1.2.3 From 319ad738f677a20403cc27192f1df7bb65ce8c0e Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 4 Jan 2015 19:40:21 +0100 Subject: corrected first draft of DemoOutput. Still some TODOs remain, but for the easy test document everything works. --- CMakeLists.txt | 13 +++++++++- src/plugins/html/DemoOutput.cpp | 26 +++++++++---------- test/plugins/html/DemoOutputTest.cpp | 49 ++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 test/plugins/html/DemoOutputTest.cpp (limited to 'src/plugins/html') diff --git a/CMakeLists.txt b/CMakeLists.txt index ddb087e..10e43ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,16 @@ IF(TEST) ousia_css ) + ADD_EXECUTABLE(ousia_test_html + test/plugins/html/DemoOutputTest + ) + + TARGET_LINK_LIBRARIES(ousia_test_html + ${GTEST_LIBRARIES} + ousia_core + ousia_html + ) + ADD_EXECUTABLE(ousia_test_xml test/plugins/xml/XmlParserTest ) @@ -264,8 +274,9 @@ IF(TEST) # Register the unit tests ADD_TEST(ousia_test_core ousia_test_core) ADD_TEST(ousia_test_boost ousia_test_boost) - ADD_TEST(ousia_test_xml ousia_test_xml) ADD_TEST(ousia_test_css ousia_test_css) + ADD_TEST(ousia_test_html ousia_test_html) + ADD_TEST(ousia_test_xml ousia_test_xml) # ADD_TEST(ousia_test_mozjs ousia_test_mozjs) ENDIF() diff --git a/src/plugins/html/DemoOutput.cpp b/src/plugins/html/DemoOutput.cpp index 6b9b3a4..463a5d2 100644 --- a/src/plugins/html/DemoOutput.cpp +++ b/src/plugins/html/DemoOutput.cpp @@ -31,7 +31,7 @@ void DemoHTMLTransformer::writeHTML(Handle doc, out << "\n"; out << "\n"; out << "\t\n"; - out << "\t\tTest HTML Output for" << doc->getName() << "\n"; + out << "\t\tTest HTML Output for " << doc->getName() << "\n"; out << "\t\n"; out << "\t\n"; @@ -76,10 +76,9 @@ void DemoHTMLTransformer::writeSection(Handle sec, // if the input node is no section, we ignore it. return; } - // get the fields. - std::vector> &fields = sec->getFields(); // check if we have a heading. - if (fields.size() > 1 && fields[1].size() > 0) { + if (sec->hasField("heading")) { + Rooted heading = sec->getField("heading")[0]; out << "\t\t"; switch (type) { case SectionType::BOOK: @@ -99,7 +98,7 @@ void DemoHTMLTransformer::writeSection(Handle sec, break; } // the second field marks the heading. So let's write it. - writeParagraph(fields[1][0], out, false); + writeParagraph(heading, out, false); // close the heading tag. switch (type) { case SectionType::BOOK: @@ -122,7 +121,8 @@ void DemoHTMLTransformer::writeSection(Handle sec, } // then write the section content recursively. - for (auto &n : fields[0]) { + NodeVector mainField = sec->getField(); + for (auto &n : mainField) { /* * Strictly speaking this is the wrong mechanism, because we would have * to make an "isa" call here because we can not rely on our knowledge @@ -149,15 +149,13 @@ void DemoHTMLTransformer::writeParagraph(Handle par, if (par->getDescriptor()->getName() != "paragraph") { throw OusiaException("Expected paragraph!"); } - // get the fields. - std::vector> &fields = par->getFields(); - // write heading if its there. // check if we have a heading. - if (fields.size() > 1 && fields[1].size() > 0) { + if (par->hasField("heading")) { + Rooted heading = par->getField("heading")[0]; // start the heading tag out << "\t\t
"; // the second field marks the heading. So let's write it. - writeParagraph(fields[1][0], out, false); + writeParagraph(heading, out, false); // close the heading tag. out << "
\n"; } @@ -167,13 +165,13 @@ void DemoHTMLTransformer::writeParagraph(Handle par, } // write content // TODO: What about emphasis? - for (auto &text : fields[0]) { + for (auto &text : par->getField()) { if (text->getDescriptor()->getName() != "text") { throw OusiaException("Expected text!"); } Handle primitive = - text->getFields()[0][0].cast(); - if (primitive == nullptr) { + text->getField()[0].cast(); + if (primitive.isNull()) { throw OusiaException("Text field is not primitive!"); } out << primitive->getContent().asString(); diff --git a/test/plugins/html/DemoOutputTest.cpp b/test/plugins/html/DemoOutputTest.cpp new file mode 100644 index 0000000..b81a001 --- /dev/null +++ b/test/plugins/html/DemoOutputTest.cpp @@ -0,0 +1,49 @@ +/* + Ousía + Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#include + +#include + +#include +#include + +#include +#include + +namespace ousia { +namespace html { + +TEST(DemoHTMLTransformer, writeHTML) +{ + // Construct Manager + Logger logger; + Manager mgr{1}; + // Get the domain. + Rooted domain = model::constructBookDomain(mgr, logger); + // Construct the document. + Rooted doc = model::constructBookDocument(mgr, domain); + + // print it + DemoHTMLTransformer transformer; + transformer.writeHTML(doc, std::cout); +} +} +} -- cgit v1.2.3