Skip to content

Commit ff6add5

Browse files
committed
Starting to implement docinfo
1 parent 28ede48 commit ff6add5

19 files changed

+450
-56
lines changed

src/bb2html.cpp

Lines changed: 288 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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
}

src/xml_parse.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ namespace quickbook
102102
std::make_pair(name.to_s(), value.to_s()));
103103
return attributes_.back().second;
104104
}
105+
106+
xml_element* get_child(quickbook::string_view name)
107+
{
108+
for (auto it = children(); it; it = it->next()) {
109+
if (it->type_ == element_node && it->name_ == name) {
110+
return it;
111+
}
112+
}
113+
114+
return 0;
115+
}
105116
};
106117

107118
struct xml_parse_error
@@ -120,4 +131,4 @@ namespace quickbook
120131
}
121132
}
122133

123-
#endif
134+
#endif

test/doc-info/author1.gold.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
<h3>
66
Document Information 4
77
</h3>
8-
Joe Blow
8+
<div class="authorgroup">
9+
<h3 class="author">
10+
Joe Blow
11+
</h3>
12+
</div>
913
</body>
1014
</html>

0 commit comments

Comments
 (0)