DocBook: add layout parameters to control the special case and argument positioning.

Only for flex insets.

Also add similar checks in InsetText to avoid bibliographies in paragraphs.
This commit is contained in:
Thibaut Cuvelier 2020-11-28 22:43:00 +01:00
parent a8de4d3296
commit 59acb375d1
11 changed files with 126 additions and 6 deletions

View File

@ -11,7 +11,7 @@
# This script will update a .layout file to current format # This script will update a .layout file to current format
# The latest layout format is also defined in src/TextClass.cpp # The latest layout format is also defined in src/TextClass.cpp
currentFormat = 87 currentFormat = 88
# Incremented to format 4, 6 April 2007, lasgouttes # Incremented to format 4, 6 April 2007, lasgouttes
@ -296,7 +296,10 @@ currentFormat = 87
# Incremented to format 86, 20 October 2020 by tcuvelier # Incremented to format 86, 20 October 2020 by tcuvelier
# New tag DocBookSection. # New tag DocBookSection.
# Incremeted to format 87, 2 November 2020 by rkh # Incremented to format 87, 2 November 2020 by rkh
# Incremented to format 88, 28 November 2020 by tcuvelier
# New tag DocBookNotInPara.
# Do not forget to document format change in Customization # Do not forget to document format change in Customization
# Manual (section "Declaring a new text class"). # Manual (section "Declaring a new text class").
@ -358,6 +361,7 @@ def concatenate_label(old, new):
else: else:
return b'"' + old + new + b'"' return b'"' + old + new + b'"'
# appends a string to a list unless it's already there # appends a string to a list unless it's already there
def addstring(s, l): def addstring(s, l):
if l.count(s) > 0: if l.count(s) > 0:
@ -547,6 +551,11 @@ def convert(lines, end_format):
i += 1 i += 1
continue continue
if 87 <= format <= 88:
# nothing to do.
i += 1
continue
if format == 86: if format == 86:
if lines[i].lstrip().lower().startswith(b"stepmastercounter"): if lines[i].lstrip().lower().startswith(b"stepmastercounter"):
pattern = re.compile(b"stepmastercounter", re.IGNORECASE) pattern = re.compile(b"stepmastercounter", re.IGNORECASE)

View File

@ -115,6 +115,7 @@ public:
docstring docbooktag; docstring docbooktag;
docstring docbooktagtype; docstring docbooktagtype;
docstring docbookattr; docstring docbookattr;
bool docbookargumentbeforemaintag = false;
}; };
/// ///
typedef std::map<std::string, latexarg> LaTeXArgMap; typedef std::map<std::string, latexarg> LaTeXArgMap;

View File

@ -26,6 +26,7 @@ class Encoding;
class ExportData; class ExportData;
class Font; class Font;
class Language; class Language;
class InsetArgument;
class OutputParams { class OutputParams {
public: public:
@ -382,6 +383,9 @@ public:
/// Should wrappers be ignored? Mostly useful to avoid generation of <abstract>. /// Should wrappers be ignored? Mostly useful to avoid generation of <abstract>.
bool docbook_ignore_wrapper = false; bool docbook_ignore_wrapper = false;
/// Some parameters are output before the rest of the paragraph, they should not be generated a second time.
std::set<InsetArgument const *> docbook_prepended_arguments = {};
/// Are we generating this material for inclusion in a TOC-like entity? /// Are we generating this material for inclusion in a TOC-like entity?
bool for_toc = false; bool for_toc = false;

View File

@ -865,6 +865,7 @@ int Paragraph::eraseChars(pos_type start, pos_type end, bool trackChanges)
return end - i; return end - i;
} }
// Handle combining characters // Handle combining characters
int Paragraph::Private::latexSurrogatePair(BufferParams const & bparams, int Paragraph::Private::latexSurrogatePair(BufferParams const & bparams,
otexstream & os, char_type c, char_type next, otexstream & os, char_type c, char_type next,

View File

@ -59,7 +59,7 @@ namespace lyx {
// You should also run the development/tools/updatelayouts.py script, // You should also run the development/tools/updatelayouts.py script,
// to update the format of all of our layout files. // to update the format of all of our layout files.
// //
int const LAYOUT_FORMAT = 87; // rkh: master --> parent for counters int const LAYOUT_FORMAT = 88; // tcuvelier: add DocBookNotInPara
// Layout format for the current lyx file format. Controls which format is // Layout format for the current lyx file format. Controls which format is

View File

@ -126,6 +126,7 @@ void InsetArgument::updateBuffer(ParIterator const & it, UpdateType utype, bool
docbooktag_ = (*lait).second.docbooktag; docbooktag_ = (*lait).second.docbooktag;
docbooktagtype_ = (*lait).second.docbooktagtype; docbooktagtype_ = (*lait).second.docbooktagtype;
docbookattr_ = (*lait).second.docbookattr; docbookattr_ = (*lait).second.docbookattr;
docbookargumentbeforemaintag_ = (*lait).second.docbookargumentbeforemaintag;
pass_thru_local_ = false; pass_thru_local_ = false;
if (lait->second.is_toc_caption) { if (lait->second.is_toc_caption) {
is_toc_caption_ = true; is_toc_caption_ = true;
@ -312,6 +313,10 @@ InsetLayout::InsetDecoration InsetArgument::decoration() const
void InsetArgument::docbook(XMLStream & xs, OutputParams const & rp) const { void InsetArgument::docbook(XMLStream & xs, OutputParams const & rp) const {
// Ignore arguments that have already been output.
if (rp.docbook_prepended_arguments.find(this) != rp.docbook_prepended_arguments.end())
return;
if (docbooktag_ != from_ascii("NONE") && docbooktag_ != from_ascii("IGNORE")) { if (docbooktag_ != from_ascii("NONE") && docbooktag_ != from_ascii("IGNORE")) {
// TODO: implement docbooktagtype_. // TODO: implement docbooktagtype_.
xs << xml::StartTag(docbooktag_, docbookattr_); xs << xml::StartTag(docbooktag_, docbookattr_);

View File

@ -39,6 +39,8 @@ public:
std::string name() const { return name_; } std::string name() const { return name_; }
bool docbookargumentbeforemaintag() const { return docbookargumentbeforemaintag_; }
/// \name Public functions inherited from Inset class /// \name Public functions inherited from Inset class
//@{ //@{
/// ///
@ -131,6 +133,8 @@ private:
docstring docbooktagtype_; docstring docbooktagtype_;
/// DocBook attributes. /// DocBook attributes.
docstring docbookattr_; docstring docbookattr_;
///
bool docbookargumentbeforemaintag_ = false;
protected: protected:
/// \name Protected functions inherited from Inset class /// \name Protected functions inherited from Inset class

View File

@ -95,6 +95,8 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
IL_DOCBOOKTAGTYPE, IL_DOCBOOKTAGTYPE,
IL_DOCBOOKSECTION, IL_DOCBOOKSECTION,
IL_DOCBOOKININFO, IL_DOCBOOKININFO,
IL_DOCBOOKARGUMENTBEFOREMAINTAG,
IL_DOCBOOKNOTINPARA,
IL_DOCBOOKWRAPPERTAG, IL_DOCBOOKWRAPPERTAG,
IL_DOCBOOKWRAPPERTAGTYPE, IL_DOCBOOKWRAPPERTAGTYPE,
IL_DOCBOOKWRAPPERATTR, IL_DOCBOOKWRAPPERATTR,
@ -148,6 +150,7 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
{ "custompars", IL_CUSTOMPARS }, { "custompars", IL_CUSTOMPARS },
{ "decoration", IL_DECORATION }, { "decoration", IL_DECORATION },
{ "display", IL_DISPLAY }, { "display", IL_DISPLAY },
{ "docbookargumentbeforemaintag", IL_DOCBOOKARGUMENTBEFOREMAINTAG },
{ "docbookattr", IL_DOCBOOKATTR }, { "docbookattr", IL_DOCBOOKATTR },
{ "docbookininfo", IL_DOCBOOKININFO }, { "docbookininfo", IL_DOCBOOKININFO },
{ "docbookitemattr", IL_DOCBOOKITEMATTR }, { "docbookitemattr", IL_DOCBOOKITEMATTR },
@ -156,6 +159,7 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
{ "docbookitemwrapperattr", IL_DOCBOOKITEMWRAPPERATTR }, { "docbookitemwrapperattr", IL_DOCBOOKITEMWRAPPERATTR },
{ "docbookitemwrappertag", IL_DOCBOOKITEMWRAPPERTAG }, { "docbookitemwrappertag", IL_DOCBOOKITEMWRAPPERTAG },
{ "docbookitemwrappertagtype", IL_DOCBOOKITEMWRAPPERTAGTYPE }, { "docbookitemwrappertagtype", IL_DOCBOOKITEMWRAPPERTAGTYPE },
{ "docbooknotinpara", IL_DOCBOOKNOTINPARA },
{ "docbooksection", IL_DOCBOOKSECTION }, { "docbooksection", IL_DOCBOOKSECTION },
{ "docbooktag", IL_DOCBOOKTAG }, { "docbooktag", IL_DOCBOOKTAG },
{ "docbooktagtype", IL_DOCBOOKTAGTYPE }, { "docbooktagtype", IL_DOCBOOKTAGTYPE },
@ -514,6 +518,12 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
case IL_DOCBOOKININFO: case IL_DOCBOOKININFO:
lex >> docbookininfo_; lex >> docbookininfo_;
break; break;
case IL_DOCBOOKARGUMENTBEFOREMAINTAG:
lex >> docbookargumentbeforemaintag_;
break;
case IL_DOCBOOKNOTINPARA:
lex >> docbooknotinpara_;
break;
case IL_DOCBOOKSECTION: case IL_DOCBOOKSECTION:
lex >> docbooksection_; lex >> docbooksection_;
break; break;
@ -819,6 +829,9 @@ void InsetLayout::readArgument(Lexer & lex)
} else if (tok == "docbooktagtype") { } else if (tok == "docbooktagtype") {
lex.next(); lex.next();
arg.docbooktagtype = lex.getDocString(); arg.docbooktagtype = lex.getDocString();
} else if (tok == "docbookargumentbeforemaintag") {
lex.next();
arg.docbookargumentbeforemaintag = lex.getBool();
} else { } else {
lex.printError("Unknown tag"); lex.printError("Unknown tag");
error = true; error = true;

View File

@ -158,6 +158,10 @@ public:
/// ///
bool docbooksection() const { return docbooksection_; } bool docbooksection() const { return docbooksection_; }
/// ///
bool docbooknotinpara() const { return docbooknotinpara_; }
///
bool docbookargumentbeforemaintag() const { return docbookargumentbeforemaintag_; }
///
std::string docbookwrappertag() const { return docbookwrappertag_; } std::string docbookwrappertag() const { return docbookwrappertag_; }
/// ///
std::string docbookwrappertagtype() const; std::string docbookwrappertagtype() const;
@ -311,6 +315,10 @@ private:
/// ///
mutable std::string docbookininfo_; mutable std::string docbookininfo_;
/// ///
bool docbooknotinpara_ = false;
///
bool docbookargumentbeforemaintag_ = false;
///
bool docbooksection_ = false; bool docbooksection_ = false;
/// ///
std::string docbookwrappertag_; std::string docbookwrappertag_;

View File

@ -621,8 +621,35 @@ void InsetText::docbook(XMLStream & xs, OutputParams const & rp, XHTMLOptions op
if (!rp.docbook_generate_info && il.docbookininfo() != "never") if (!rp.docbook_generate_info && il.docbookininfo() != "never")
return; return;
// In some cases, the input parameters must be overridden for outer tags.
bool writeOuterTag = opts & WriteOuterTag;
if (writeOuterTag) {
// For each paragraph, if there are only Bibitems and the corresponding text, don't write the outer tags.
bool allBibitems = std::all_of(text().paragraphs().begin(), text().paragraphs().end(), [](Paragraph const & par) {
auto nInsets = std::distance(par.insetList().begin(), par.insetList().end());
auto parSize = (size_t) par.size();
return nInsets == 1 && parSize > 1 && par.insetList().begin()->inset->lyxCode() == BIBITEM_CODE;
});
writeOuterTag = !allBibitems;
}
// Detect arguments that should be output before the paragraph.
// Don't reuse runparams.docbook_prepended_arguments, as the same object is used in InsetArgument to determine
// whether the inset should be output or not, whatever the context (i.e. position with respect to the wrapper).
std::set<InsetArgument const *> prependedArguments;
for (auto const & par : paragraphs()) {
for (pos_type i = 0; i < par.size(); ++i) {
if (par.getInset(i) && par.getInset(i)->lyxCode() == ARG_CODE) {
InsetArgument const *arg = par.getInset(i)->asInsetArgument();
if (arg->docbookargumentbeforemaintag())
prependedArguments.insert(par.getInset(i)->asInsetArgument());
}
}
}
// Start outputting this inset. // Start outputting this inset.
if (opts & WriteOuterTag) { // - First, wrapper around the inset and its main tag.
if (writeOuterTag) {
if (!il.docbookwrappertag().empty() && il.docbookwrappertag() != "NONE" && il.docbookwrappertag() != "IGNORE") if (!il.docbookwrappertag().empty() && il.docbookwrappertag() != "NONE" && il.docbookwrappertag() != "IGNORE")
xml::openTag(xs, il.docbookwrappertag(), il.docbookwrapperattr(), il.docbookwrappertagtype()); xml::openTag(xs, il.docbookwrappertag(), il.docbookwrapperattr(), il.docbookwrappertagtype());
@ -634,7 +661,19 @@ void InsetText::docbook(XMLStream & xs, OutputParams const & rp, XHTMLOptions op
attrs += from_ascii(" xlink:href=\"") + text_.asString() + from_ascii("\""); attrs += from_ascii(" xlink:href=\"") + text_.asString() + from_ascii("\"");
xml::openTag(xs, il.docbooktag(), attrs, il.docbooktagtype()); xml::openTag(xs, il.docbooktag(), attrs, il.docbooktagtype());
} }
}
// - Think about the arguments.
OutputParams np = runparams;
np.docbook_in_par = true;
for (auto const & arg : prependedArguments)
arg->docbook(xs, np);
// - Mark the newly generated arguments are not-to-be-generated-again.
runparams.docbook_prepended_arguments = std::move(prependedArguments);
// - Deal with the first item.
if (writeOuterTag) {
if (!il.docbookitemwrappertag().empty() && il.docbookitemwrappertag() != "NONE" && il.docbookitemwrappertag() != "IGNORE") if (!il.docbookitemwrappertag().empty() && il.docbookitemwrappertag() != "NONE" && il.docbookitemwrappertag() != "IGNORE")
xml::openTag(xs, il.docbookitemwrappertag(), il.docbookitemwrapperattr(), il.docbookitemwrappertagtype()); xml::openTag(xs, il.docbookitemwrappertag(), il.docbookitemwrapperattr(), il.docbookitemwrappertagtype());
@ -650,11 +689,13 @@ void InsetText::docbook(XMLStream & xs, OutputParams const & rp, XHTMLOptions op
if (il.isPassThru()) if (il.isPassThru())
runparams.pass_thru = true; runparams.pass_thru = true;
// - Write the main content of the inset.
xs.startDivision(false); xs.startDivision(false);
docbookParagraphs(text_, buffer(), xs, runparams); docbookParagraphs(text_, buffer(), xs, runparams);
xs.endDivision(); xs.endDivision();
if (opts & WriteOuterTag) { // - Close the required tags.
if (writeOuterTag) {
if (!il.docbookitemtag().empty() && il.docbookitemtag() != "NONE" && il.docbookitemtag() != "IGNORE") if (!il.docbookitemtag().empty() && il.docbookitemtag() != "NONE" && il.docbookitemtag() != "IGNORE")
xml::closeTag(xs, il.docbookitemtag(), il.docbookitemtagtype()); xml::closeTag(xs, il.docbookitemtag(), il.docbookitemtagtype());

View File

@ -347,7 +347,7 @@ void makeParagraph(
special_case = true; special_case = true;
} }
size_t nInsets = std::distance(par->insetList().begin(), par->insetList().end()); auto nInsets = std::distance(par->insetList().begin(), par->insetList().end());
auto parSize = (size_t) par->size(); auto parSize = (size_t) par->size();
// Plain layouts must be ignored. // Plain layouts must be ignored.
@ -377,6 +377,40 @@ void makeParagraph(
}; };
special_case |= nInsets == parSize && std::all_of(par->insetList().begin(), par->insetList().end(), isLyxCodeSpecialCase); special_case |= nInsets == parSize && std::all_of(par->insetList().begin(), par->insetList().end(), isLyxCodeSpecialCase);
// Flex elements (InsetLayout) have their own parameter to control the special case.
auto isFlexSpecialCase = [](InsetList::Element inset) {
if (inset.inset->lyxCode() != FLEX_CODE)
return false;
// Standard condition: check the parameter.
if (inset.inset->getLayout().docbooknotinpara())
return true;
// If the parameter is not set, maybe the flex inset only contains things that should match the standard
// condition. In this case, isLyxCodeSpecialCase must also check for bibitems...
auto isLyxCodeSpecialCase = [](InsetList::Element inset) {
return lyxCodeSpecialCases.find(inset.inset->lyxCode()) != lyxCodeSpecialCases.end() ||
inset.inset->lyxCode() == BIBITEM_CODE;
};
if (InsetText * text = inset.inset->asInsetText()) {
for (auto const & par : text->paragraphs()) {
auto nInsets = std::distance(par.insetList().begin(), par.insetList().end());
auto parSize = (size_t) par.size();
if (nInsets == 1 && par.insetList().begin()->inset->lyxCode() == BIBITEM_CODE)
return true;
if (nInsets != parSize)
return false;
if (!std::all_of(par.insetList().begin(), par.insetList().end(), isLyxCodeSpecialCase))
return false;
}
return true;
}
// No case matched: give up.
return false;
};
special_case |= nInsets == parSize && std::all_of(par->insetList().begin(), par->insetList().end(), isFlexSpecialCase);
// Open a paragraph if it is allowed, we are not already within a paragraph, and the insets in the paragraph do // Open a paragraph if it is allowed, we are not already within a paragraph, and the insets in the paragraph do
// not forbid paragraphs (aka special cases). // not forbid paragraphs (aka special cases).
bool const open_par = runparams.docbook_make_pars bool const open_par = runparams.docbook_make_pars