@@ -19,6 +19,7 @@ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
1919#include < boost/unordered_set.hpp>
2020#include " boostbook_chunker.hpp"
2121#include " files.hpp"
22+ #include " for.hpp"
2223#include " html_printer.hpp"
2324#include " path.hpp"
2425#include " post_process.hpp"
@@ -37,6 +38,7 @@ namespace quickbook
3738 {
3839 struct html_state ;
3940 struct html_gen ;
41+ struct docinfo_gen ;
4042 struct id_info ;
4143
4244 typedef boost::unordered_map<string_view, id_info> ids_type;
@@ -46,6 +48,23 @@ namespace quickbook
4648 node_parsers_type;
4749 static node_parsers_type node_parsers;
4850
51+ struct docinfo_node_parser
52+ {
53+ typedef void (*parser_type)(docinfo_gen&, xml_element*);
54+ enum docinfo_node_category
55+ {
56+ docinfo_general = 0 ,
57+ docinfo_author
58+ };
59+
60+ docinfo_node_category category;
61+ parser_type parser;
62+ };
63+ typedef boost::
64+ unordered_map<quickbook::string_view, docinfo_node_parser>
65+ docinfo_node_pasers_type;
66+ static docinfo_node_pasers_type docinfo_node_parsers;
67+
4968 void generate_chunked_documentation (
5069 chunk*, ids_type const &, html_options const &);
5170 void generate_chunks (html_state&, chunk*);
@@ -60,6 +79,7 @@ namespace quickbook
6079 void number_callouts (html_gen& gen, xml_element* x);
6180 void number_calloutlist_children (
6281 html_gen& gen, unsigned & count, xml_element* x);
82+ void generate_docinfo_html (html_gen&, xml_element*);
6383 void generate_tree_html (html_gen&, xml_element*);
6484 void generate_children_html (html_gen&, xml_element*);
6585 void write_file (
@@ -171,6 +191,19 @@ namespace quickbook
171191 }
172192 };
173193
194+ struct docinfo_gen
195+ {
196+ html_gen& gen;
197+ std::vector<std::string> copyrights;
198+ std::vector<std::string> pubdates;
199+ std::vector<std::string> legalnotices;
200+ std::vector<std::string> authors;
201+ std::vector<std::string> editors;
202+ std::vector<std::string> collabs;
203+
204+ docinfo_gen (html_gen& gen_) : gen(gen_) {}
205+ };
206+
174207 int boostbook_to_html (
175208 quickbook::string_view source, html_options const & options)
176209 {
@@ -412,7 +445,7 @@ namespace quickbook
412445 number_callouts (gen, x->contents_ .root ());
413446
414447 generate_tree_html (gen, x->title_ .root ());
415- generate_tree_html (gen, x->info_ .root ());
448+ generate_docinfo_html (gen, x->info_ .root ());
416449 generate_toc_html (gen, x);
417450 generate_tree_html (gen, x->contents_ .root ());
418451 }
@@ -595,6 +628,67 @@ namespace quickbook
595628 }
596629 }
597630
631+ void generate_docinfo_html_impl (docinfo_gen& d, xml_element* x)
632+ {
633+ for (xml_element* it = x->children (); it; it = it->next ()) {
634+ if (it->type_ == xml_element::element_node) {
635+ auto parser = docinfo_node_parsers.find (it->name_ );
636+ if (parser != docinfo_node_parsers.end ()) {
637+ parser->second .parser (d, it);
638+ }
639+ else {
640+ quickbook::detail::out ()
641+ << " Unsupported docinfo tag: " << x->name_
642+ << std::endl;
643+ generate_docinfo_html_impl (d, it);
644+ }
645+ }
646+ }
647+ }
648+
649+ void generate_docinfo_html (html_gen& gen, xml_element* x)
650+ {
651+ if (!x) {
652+ return ;
653+ }
654+
655+ docinfo_gen d (gen);
656+ generate_docinfo_html_impl (d, x);
657+
658+ if (!d.authors .empty () || !d.editors .empty () ||
659+ !d.collabs .empty ()) {
660+ gen.printer .html += " <div class=\" authorgroup\" >\n " ;
661+ QUICKBOOK_FOR (auto const & author, d.authors ) {
662+ gen.printer .html += " <h3 class=\" author\" >" ;
663+ gen.printer .html += author;
664+ gen.printer .html += " </h3>\n " ;
665+ }
666+ QUICKBOOK_FOR (auto const & editor, d.editors ) {
667+ gen.printer .html += " <h3 class=\" editor\" >" ;
668+ gen.printer .html += editor;
669+ gen.printer .html += " </h3>\n " ;
670+ }
671+ QUICKBOOK_FOR (auto const & collab, d.collabs ) {
672+ gen.printer .html += " <h3 class=\" collab\" >" ;
673+ gen.printer .html += collab;
674+ gen.printer .html += " </h3>\n " ;
675+ }
676+ gen.printer .html += " </div>\n " ;
677+ }
678+
679+ QUICKBOOK_FOR (auto const & copyright, d.copyrights ) {
680+ gen.printer .html += " <p class=\" copyright\" >" ;
681+ gen.printer .html += copyright;
682+ gen.printer .html += " </p>" ;
683+ }
684+
685+ QUICKBOOK_FOR (auto const & legalnotice, d.legalnotices ) {
686+ gen.printer .html += " <div class=\" legalnotice\" >" ;
687+ gen.printer .html += legalnotice;
688+ gen.printer .html += " </div>" ;
689+ }
690+ }
691+
598692 void write_file (
599693 html_state& state,
600694 std::string const & generic_path,
@@ -837,6 +931,21 @@ namespace quickbook
837931 } BOOST_PP_CAT(register_parser_, tag_name); \
838932 void BOOST_PP_CAT (parser_, tag_name)(html_gen & gen, xml_element * x)
839933
934+ #define DOCINFO_NODE_RULE (tag_name, category, gen, x ) \
935+ void BOOST_PP_CAT (docinfo_parser_, tag_name)(docinfo_gen&, xml_element*); \
936+ static struct BOOST_PP_CAT (register_docinfo_parser_type_, tag_name) \
937+ { \
938+ BOOST_PP_CAT (register_docinfo_parser_type_, tag_name)() \
939+ { \
940+ docinfo_node_parser p = { \
941+ docinfo_node_parser::category, \
942+ &BOOST_PP_CAT (docinfo_parser_, tag_name)}; \
943+ docinfo_node_parsers.emplace (BOOST_PP_STRINGIZE (tag_name), p); \
944+ } \
945+ } BOOST_PP_CAT(register_docinfo_parser_, tag_name); \
946+ void BOOST_PP_CAT (docinfo_parser_, tag_name)( \
947+ docinfo_gen & gen, xml_element * x)
948+
840949#define NODE_MAP (tag_name, html_name ) \
841950 NODE_RULE (tag_name, gen, x) { tag (gen, BOOST_PP_STRINGIZE (html_name), x); }
842951
@@ -1335,5 +1444,183 @@ namespace quickbook
13351444
13361445 gen.chunk .footnotes .push_back (x);
13371446 }
1447+
1448+ std::string docinfo_get_contents (docinfo_gen& d, xml_element* x)
1449+ {
1450+ html_gen gen2 (d.gen );
1451+ generate_children_html (gen2, x);
1452+ return gen2.printer .html ;
1453+ }
1454+
1455+ std::string docinfo_get_author (docinfo_gen& d, xml_element* x)
1456+ {
1457+ auto personname = x->get_child (" personname" );
1458+ if (personname) {
1459+ return docinfo_get_author (d, personname);
1460+ }
1461+
1462+ std::string name;
1463+
1464+ char const * name_parts[] = {" honorific" , " firstname" , " surname" };
1465+ std::size_t const length =
1466+ sizeof (name_parts) / sizeof (name_parts[0 ]);
1467+ for (std::size_t i = 0 ; i < length; ++i) {
1468+ auto child = x->get_child (name_parts[i]);
1469+ if (child) {
1470+ if (name.size ()) {
1471+ name += " " ;
1472+ }
1473+ name += docinfo_get_contents (d, child);
1474+ }
1475+ }
1476+
1477+ return name;
1478+ }
1479+
1480+ // docinfo parsers
1481+
1482+ // No support for:
1483+ //
1484+ // graphic, mediaobject
1485+ // modespec
1486+ // subjectset, keywordset
1487+ // itermset, indexterm
1488+ // abbrev
1489+ // abstract
1490+ // address
1491+ // artpagenums
1492+ // authorinitials
1493+ // bibliomisc, biblioset
1494+ // confgroup
1495+ // contractnum, contractsponsor
1496+ // corpname
1497+ // date
1498+ // edition
1499+ // invpartnumber, isbn, issn, issuenum, biblioid
1500+ // orgname
1501+ // citebiblioid, citetitle
1502+ // bibliosource, bibliorelation, bibliocoverage - Dublin core
1503+ // pagenums
1504+ // printhistory
1505+ // productname, productnumber
1506+ // pubdate ***
1507+ // publisher, publishername, pubsnumber
1508+ // releaseinfo
1509+ // revhistory
1510+ // seriesvolnums
1511+ // title, subtitle, titleabbrev - *** extract into parent?
1512+ // volumenum
1513+ // personname, honorific, firstname, surname, lineage, othername,
1514+ // affiliation, authorblurb, contrib - add to authors?
1515+
1516+ DOCINFO_NODE_RULE (copyright, docinfo_general, d, x)
1517+ {
1518+ std::vector<xml_element*> years;
1519+ std::vector<xml_element*> holders;
1520+
1521+ for (auto child = x->children (); child; child = child->next ()) {
1522+ if (child->type_ == xml_element::element_node) {
1523+ if (child->name_ == " year" ) {
1524+ years.push_back (child);
1525+ }
1526+ else if (child->name_ == " holder" ) {
1527+ holders.push_back (child);
1528+ }
1529+ else {
1530+ quickbook::detail::out ()
1531+ << " Unsupported copyright tag: " << x->name_
1532+ << std::endl;
1533+ }
1534+ }
1535+ }
1536+
1537+ // TODO: Format years, e.g. 2005 2006 2007 2010 => 2005-2007, 2010
1538+
1539+ std::string copyright;
1540+ QUICKBOOK_FOR (auto year, years) {
1541+ if (!copyright.empty ()) {
1542+ copyright += " , " ;
1543+ }
1544+ copyright += docinfo_get_contents (d, year);
1545+ }
1546+ bool first = true ;
1547+ QUICKBOOK_FOR (auto holder, holders) {
1548+ if (first) {
1549+ if (!copyright.empty ()) {
1550+ copyright += " " ;
1551+ }
1552+ first = false ;
1553+ }
1554+ else {
1555+ copyright += " , " ;
1556+ }
1557+ copyright += docinfo_get_contents (d, holder);
1558+ }
1559+ d.copyrights .push_back (copyright);
1560+ }
1561+
1562+ DOCINFO_NODE_RULE (legalnotice, docinfo_general, d, x)
1563+ {
1564+ d.legalnotices .push_back (docinfo_get_contents (d, x));
1565+ }
1566+
1567+ DOCINFO_NODE_RULE (pubdate, docinfo_general, d, x)
1568+ {
1569+ d.pubdates .push_back (docinfo_get_contents (d, x));
1570+ }
1571+
1572+ DOCINFO_NODE_RULE (authorgroup, docinfo_general, d, x)
1573+ {
1574+ // TODO: Check children are docinfo_author
1575+ generate_docinfo_html_impl (d, x);
1576+ }
1577+
1578+ DOCINFO_NODE_RULE (author, docinfo_author, d, x)
1579+ {
1580+ d.authors .push_back (docinfo_get_author (d, x));
1581+ }
1582+
1583+ DOCINFO_NODE_RULE (editor, docinfo_author, d, x)
1584+ {
1585+ d.editors .push_back (docinfo_get_author (d, x));
1586+ }
1587+
1588+ DOCINFO_NODE_RULE (collab, docinfo_author, d, x)
1589+ {
1590+ // Ignoring affiliation.
1591+ auto collabname = x->get_child (" collabname" );
1592+ if (collabname) {
1593+ d.collabs .push_back (docinfo_get_contents (d, collabname));
1594+ }
1595+ }
1596+
1597+ DOCINFO_NODE_RULE (corpauthor, docinfo_author, d, x)
1598+ {
1599+ d.authors .push_back (docinfo_get_contents (d, x));
1600+ }
1601+
1602+ DOCINFO_NODE_RULE (corpcredit, docinfo_author, d, x)
1603+ {
1604+ std::string text = docinfo_get_contents (d, x);
1605+
1606+ string_view class_ = x->get_attribute (" class" );
1607+ if (!class_.empty ()) {
1608+ text = class_.to_s () + " : " + text;
1609+ }
1610+
1611+ d.authors .push_back (text);
1612+ }
1613+
1614+ DOCINFO_NODE_RULE (othercredit, docinfo_author, d, x)
1615+ {
1616+ std::string text = docinfo_get_author (d, x);
1617+
1618+ string_view class_ = x->get_attribute (" class" );
1619+ if (!class_.empty ()) {
1620+ text = class_.to_s () + " : " + text;
1621+ }
1622+
1623+ d.authors .push_back (text);
1624+ }
13381625 }
13391626}
0 commit comments