if (!ip)
continue;
if (const auto * bibitem = dynamic_cast<const InsetBibitem*>(ip)) {
- attr = from_utf8("xml:id='") + bibitem->getParam("key") + from_utf8("'");
+ auto id = xml::cleanID(bibitem->getParam("key"));
+ attr = from_utf8("xml:id='") + id + from_utf8("'");
break;
}
}
// Handle the content of the list environment, item by item.
while (par != envend) {
- Layout const & style = par->layout();
+ // Skip this paragraph if it is both empty and the last one (otherwise, there may be deeper paragraphs after).
+ auto nextpar = par;
+ ++nextpar;
+ if (par->empty() && nextpar == envend)
+ break;
// Open the item wrapper.
+ Layout const & style = par->layout();
openTag(xs, style.docbookitemwrappertag(), style.docbookitemwrapperattr(), style.docbookitemwrappertagtype());
// Generate the label, if need be. If it is taken from the text, sep != 0 and corresponds to the first
docstring abstract;
if (hasAbstract) {
// Generate the abstract XML into a string before further checks.
+ // Usually, makeAny only generates one paragraph at a time. However, for the specific case of lists, it might
+ // generate more than one paragraph, as indicated in the return value.
odocstringstream os2;
XMLStream xs2(os2);
- for (auto const & p : info.abstract)
- makeAny(text, buf, xs2, runparams, paragraphs.iterator_at(p));
+
+ set<pit_type> doneParas;
+ for (auto const & p : info.abstract) {
+ if (doneParas.find(p) == doneParas.end()) {
+ auto oldPar = paragraphs.iterator_at(p);
+ auto newPar = makeAny(text, buf, xs2, runparams, oldPar);
+
+ // Insert the indices of all the paragraphs that were just generated (typically, one).
+ // **Make the hypothesis that, when an abstract has a list, all its items are consecutive.**
+ pit_type id = p;
+ while (oldPar != newPar) {
+ doneParas.emplace(id);
+ ++oldPar;
+ ++id;
+ }
+ }
+ }
// Actually output the abstract if there is something to do. Don't count line feeds or spaces in this,
// even though they must be properly output if there is some abstract.