+ // Generate the <info> tag if a section was just opened.
+ // Some sections may require abstracts (mostly parts, in books: DocBookForceAbstractTag will not be NONE),
+ // others can still have an abstract (it must be detected so that it can be output at the right place).
+ // TODO: docbookforceabstracttag is a bit contrived here, but it does the job. Having another field just for this would be cleaner, but that's just for <part> and <partintro>, so it's probably not worth the effort.
+ if (isLayoutSectioning(style)) {
+ // This abstract may be found between the next paragraph and the next title.
+ pit_type cpit = std::distance(text.paragraphs().begin(), par);
+ pit_type ppit = std::get<1>(hasDocumentSectioning(paragraphs, cpit + 1L, epit));
+
+ // Generate this abstract (this code corresponds to parts of outputDocBookInfo).
+ DocBookInfoTag secInfo = getParagraphsWithInfo(paragraphs, cpit, ppit, true,
+ style.docbookforceabstracttag() != "NONE");
+
+ if (!secInfo.mustBeInInfo.empty() || !secInfo.shouldBeInInfo.empty() || !secInfo.abstract.empty()) {
+ // Generate the <info>, if required. If DocBookForceAbstractTag != NONE, this abstract will not be in
+ // <info>, unlike other ("standard") abstracts.
+ bool hasStandardAbstract = !secInfo.abstract.empty() && style.docbookforceabstracttag() == "NONE";
+ bool needInfo = !secInfo.mustBeInInfo.empty() || hasStandardAbstract;
+
+ if (needInfo) {
+ xs.startDivision(false);
+ xs << xml::StartTag("info");
+ xs << xml::CR();
+ }
+
+ // Output the elements that should go in <info>, before and after the abstract.
+ for (auto pit : secInfo.shouldBeInInfo) // Typically, the title: these elements are so important and ubiquitous
+ // that mandating a wrapper like <info> would repel users. Thus, generate them first.
+ makeAny(text, buf, xs, ourparams, paragraphs.iterator_at(pit));
+ for (auto pit : secInfo.mustBeInInfo)
+ makeAny(text, buf, xs, ourparams, paragraphs.iterator_at(pit));
+
+ // Deal with the abstract in <info> if it is standard (i.e. its tag is <abstract>).
+ if (!secInfo.abstract.empty() && hasStandardAbstract) {
+ if (!secInfo.abstractLayout) {
+ xs << xml::StartTag("abstract");
+ xs << xml::CR();
+ }
+
+ for (auto const &p : secInfo.abstract)
+ makeAny(text, buf, xs, ourparams, paragraphs.iterator_at(p));
+
+ if (!secInfo.abstractLayout) {
+ xs << xml::EndTag("abstract");
+ xs << xml::CR();
+ }
+ }
+
+ // End the <info> tag if it was started.
+ if (needInfo) {
+ if (!xs.isLastTagCR())
+ xs << xml::CR();
+
+ xs << xml::EndTag("info");
+ xs << xml::CR();
+ xs.endDivision();
+ }
+
+ // Deal with the abstract outside <info> if it is not standard (i.e. its tag is layout-defined).
+ if (!secInfo.abstract.empty() && !hasStandardAbstract) {
+ // Assert: style.docbookforceabstracttag() != NONE.
+ xs << xml::StartTag(style.docbookforceabstracttag());
+ xs << xml::CR();
+ for (auto const &p : secInfo.abstract)
+ makeAny(text, buf, xs, ourparams, paragraphs.iterator_at(p));
+ xs << xml::EndTag(style.docbookforceabstracttag());
+ xs << xml::CR();
+ }
+
+ // Skip all the text that has just been generated.
+ par = paragraphs.iterator_at(secInfo.epit);
+ } else {
+ // No <info> tag to generate, proceed as for normal paragraphs.
+ par = makeAny(text, buf, xs, ourparams, par);
+ }
+ } else {
+ // Generate this paragraph, as it has nothing special.
+ par = makeAny(text, buf, xs, ourparams, par);
+ }