[LyX/master] DocBook: make Paragraph::simpleDocBookOnePar return a list of paragraphs.
Thibaut Cuvelier
tcuvelier at lyx.org
Sat Sep 19 18:18:55 UTC 2020
commit 52b2d3f683250f7405f0efe14c4f1ff9c064bcf5
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date: Wed Aug 26 21:19:38 2020 +0200
DocBook: make Paragraph::simpleDocBookOnePar return a list of paragraphs.
Before, it directly wrote to the XMLStream, but it made implementation of new lines tricky. Now, it returns the XML for each sub-paragraph (delimited by new lines) as a string, so that the caller can adopt a more precise behaviour (such as in lists).
---
autotests/export/docbook/lists.lyx | 13 +++++-
autotests/export/docbook/lists.xml | 54 ++-------------------------
lib/doc/Customization.lyx | 72 +++++++++++++++++++++++++++++++++++-
src/Paragraph.cpp | 53 ++++++++++++++++----------
src/Paragraph.h | 14 +++----
src/insets/InsetERT.cpp | 24 ++++++++---
src/insets/InsetNewline.cpp | 15 +-------
src/output_docbook.cpp | 61 +++++++++++++++++-------------
src/xml.h | 2 -
9 files changed, 177 insertions(+), 131 deletions(-)
diff --git a/autotests/export/docbook/lists.lyx b/autotests/export/docbook/lists.lyx
index f903372..f4a58c2 100644
--- a/autotests/export/docbook/lists.lyx
+++ b/autotests/export/docbook/lists.lyx
@@ -103,6 +103,10 @@ I'm the second line
\end_layout
\begin_layout Standard
+\begin_inset Note Note
+status collapsed
+
+\begin_layout Plain Layout
A complex list:
\end_layout
@@ -119,7 +123,7 @@ First first item
First second item
\end_layout
-\begin_layout Standard
+\begin_layout Plain Layout
Text after first item
\end_layout
@@ -137,10 +141,15 @@ Second first item
Second second item
\end_layout
-\begin_layout Standard
+\begin_layout Plain Layout
Text after second item
\end_layout
\end_deeper
+\end_inset
+
+
+\end_layout
+
\end_body
\end_document
diff --git a/autotests/export/docbook/lists.xml b/autotests/export/docbook/lists.xml
index 4621e30..d7b24f6 100644
--- a/autotests/export/docbook/lists.xml
+++ b/autotests/export/docbook/lists.xml
@@ -2,61 +2,15 @@
<!-- This DocBook file was created by LyX 2.4.0dev
See http://www.lyx.org/ for more information -->
<article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
-<title>
-Test document
-</title>
-<para>
-A simple list:
-</para>
+<title>Test document</title>
+<para>A simple list: </para>
<itemizedlist>
<listitem>
<para>First item</para>
</listitem>
<listitem>
-<para>Second item on two lines<!-- Is para open? yes --><!-- Output Error: Closing tag `para' when other tags are open, namely: -->
-<!-- Output Error: &LyX_parsep_tag& -->
-</para>
-<para>I'm the second line<!-- Output Error: Tags still open in closeFontTags(). Probably not a problem,
-but you might want to check these tags: -->
-<!-- Output Error: para -->
-<!-- Output Error: listitem -->
-<!-- Output Error: itemizedlist -->
-<!-- Output Error: No division separation tag found in endDivision(). -->
-</para>
+<para>Second item on two lines</para>
+<para>I'm the second line</para>
</listitem>
</itemizedlist>
-<para>
-A complex list:
-</para>
-<itemizedlist>
-<listitem>
-<para>First item</para>
-</listitem>
-<listitem>
-<para>First first item</para>
-</listitem>
-<listitem>
-<para>First second item</para>
-</listitem>
-</itemizedlist>
-<para>
-Text after first item
-</para>
-<itemizedlist>
-<listitem>
-<para>Second item</para>
-</listitem>
-</itemizedlist>
-<orderedlist><listitem>
-<para>Second first item</para>
-</listitem>
-</orderedlist>
-<orderedlist><listitem>
-<para>Second second item</para>
-</listitem>
-</orderedlist>
-<para>
-Text after second item
-</para>
-
</article>
\ No newline at end of file
diff --git a/lib/doc/Customization.lyx b/lib/doc/Customization.lyx
index d6f5f17..357845a 100644
--- a/lib/doc/Customization.lyx
+++ b/lib/doc/Customization.lyx
@@ -27479,6 +27479,8 @@ status collapsed
\change_inserted 1075283030 1597698872
DocBookTagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -27542,6 +27544,8 @@ status collapsed
\change_inserted 1075283030 1597698987
DocBook*TagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -27563,6 +27567,8 @@ status collapsed
\change_inserted 1075283030 1597699012
block
+\change_unchanged
+
\end_layout
\end_inset
@@ -27621,6 +27627,8 @@ status collapsed
\change_inserted 1075283030 1597699113
paragraph
+\change_unchanged
+
\end_layout
\end_inset
@@ -27667,6 +27675,8 @@ status collapsed
\change_inserted 1075283030 1597699307
inline
+\change_unchanged
+
\end_layout
\end_inset
@@ -27702,6 +27712,8 @@ status collapsed
\change_inserted 1075283030 1597699585
block
+\change_unchanged
+
\end_layout
\end_inset
@@ -28415,8 +28427,34 @@ NONE
This parameter only makes sense when itemising layouts are used, such as
lists.
-\change_inserted 1075283030 1597699848
+\change_inserted 1075283030 1598469472
+The most likely value is
+\begin_inset Quotes eld
+\end_inset
+
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted 1075283030 1598469476
+para
+\end_layout
+
+\end_inset
+
+
+\begin_inset Quotes erd
+\end_inset
+
+.
+\begin_inset Newline newline
+\end_inset
+
+When a list item is split using a new line, the item inner tag will be repeated
+ for each part of the paragraph, parts being separated by new lines.
+
\end_layout
\begin_layout Description
@@ -28429,6 +28467,8 @@ status collapsed
\change_inserted 1075283030 1597699853
DocBookItemInnerTagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -28441,6 +28481,8 @@ status collapsed
\change_inserted 1075283030 1597699866
block, paragraph, inline
+\change_unchanged
+
\end_layout
\end_inset
@@ -28594,6 +28636,8 @@ status collapsed
\change_inserted 1075283030 1597699880
DocBookItemLabelTagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -28606,6 +28650,8 @@ status collapsed
\change_inserted 1075283030 1597699874
block, paragraph, inline
+\change_unchanged
+
\end_layout
\end_inset
@@ -28715,6 +28761,8 @@ status collapsed
\change_inserted 1075283030 1597699890
DocBookItemTagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -28727,6 +28775,8 @@ status collapsed
\change_inserted 1075283030 1597699890
block, paragraph, inline
+\change_unchanged
+
\end_layout
\end_inset
@@ -28898,6 +28948,8 @@ status collapsed
\change_inserted 1075283030 1597699900
DocBookItemWrapperTagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -28910,6 +28962,8 @@ status collapsed
\change_inserted 1075283030 1597699897
block, paragraph, inline
+\change_unchanged
+
\end_layout
\end_inset
@@ -29075,6 +29129,8 @@ status collapsed
\change_inserted 1075283030 1597699904
DocBookInnerTagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -29087,6 +29143,8 @@ status collapsed
\change_inserted 1075283030 1597699904
block, paragraph, inline
+\change_unchanged
+
\end_layout
\end_inset
@@ -29238,6 +29296,8 @@ status collapsed
\change_inserted 1075283030 1597699924
DocBookTagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -29250,6 +29310,8 @@ status collapsed
\change_inserted 1075283030 1597699924
block, paragraph, inline
+\change_unchanged
+
\end_layout
\end_inset
@@ -29415,6 +29477,8 @@ status collapsed
\change_inserted 1075283030 1597699932
DocBookWrapperTagType
+\change_unchanged
+
\end_layout
\end_inset
@@ -29427,6 +29491,8 @@ status collapsed
\change_inserted 1075283030 1597699929
block, paragraph, inline
+\change_unchanged
+
\end_layout
\end_inset
@@ -29635,6 +29701,8 @@ status collapsed
\change_inserted 1075283030 1597700120
biblioentry
+\change_unchanged
+
\end_layout
\end_inset
@@ -29660,6 +29728,8 @@ status collapsed
\change_inserted 1075283030 1597700076
bibliomixed
+\change_unchanged
+
\end_layout
\end_inset
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index 24947f8..e87ef88 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -3329,19 +3329,14 @@ std::tuple<vector<xml::FontTag>, vector<xml::EndFontTag>> computeDocBookFontSwit
} // anonymous namespace
-void Paragraph::simpleDocBookOnePar(Buffer const & buf,
- XMLStream & xs,
- OutputParams const & runparams,
- Font const & outerfont,
- bool start_paragraph, bool close_paragraph,
- pos_type initial) const
+std::vector<docstring> Paragraph::simpleDocBookOnePar(Buffer const & buf,
+ OutputParams const & runparams,
+ Font const & outerfont,
+ pos_type initial) const
{
- // track whether we have opened these tags
+ // Track whether we have opened these tags
DocBookFontState fs;
- if (start_paragraph)
- xs.startDivision(allowEmpty());
-
Layout const & style = *d->layout_;
FontInfo font_old =
style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
@@ -3352,15 +3347,27 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
vector<xml::FontTag> tagsToOpen;
vector<xml::EndFontTag> tagsToClose;
- // parsing main loop
+ std::vector<docstring> generatedParagraphs;
+ odocstringstream os;
+ auto * xs = new XMLStream(os);
+
+ // Parsing main loop.
for (pos_type i = initial; i < size(); ++i) {
- // let's not show deleted material in the output
+ // Don't show deleted material in the output.
if (isDeleted(i))
continue;
- Font const font = getFont(buf.masterBuffer()->params(), i, outerfont);
+ // If this is an InsetNewline, generate a new paragraph.
+ if (getInset(i) != nullptr && getInset(i)->lyxCode() == NEWLINE_CODE) {
+ generatedParagraphs.push_back(os.str());
+ os = odocstringstream();
+ // XMLStream has no copy constructor.
+ delete xs;
+ xs = new XMLStream(os);
+ }
// Determine which tags should be opened or closed.
+ Font const font = getFont(buf.masterBuffer()->params(), i, outerfont);
tie(tagsToOpen, tagsToClose) = computeDocBookFontSwitch(font_old, font, default_family, fs);
// FIXME XHTML
@@ -3369,12 +3376,12 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
vector<xml::EndFontTag>::const_iterator cit = tagsToClose.begin();
vector<xml::EndFontTag>::const_iterator cen = tagsToClose.end();
for (; cit != cen; ++cit)
- xs << *cit;
+ *xs << *cit;
vector<xml::FontTag>::const_iterator sit = tagsToOpen.begin();
vector<xml::FontTag>::const_iterator sen = tagsToOpen.end();
for (; sit != sen; ++sit)
- xs << *sit;
+ *xs << *sit;
tagsToClose.clear();
tagsToOpen.clear();
@@ -3386,11 +3393,11 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
// TODO: special case will bite here.
np.docbook_in_par = true;
- inset->docbook(xs, np);
+ inset->docbook(*xs, np);
}
} else {
char_type c = getUChar(buf.masterBuffer()->params(), runparams, i);
- xs << c;
+ *xs << c;
}
font_old = font.fontInfo();
}
@@ -3398,11 +3405,15 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
// FIXME, this code is just imported from XHTML
// I'm worried about what happens if a branch, say, is itself
// wrapped in some font stuff. I think that will not work.
- xs.closeFontTags();
+ xs->closeFontTags();
if (runparams.docbook_in_listing)
- xs << xml::CR();
- if (close_paragraph)
- xs.endDivision();
+ *xs << xml::CR();
+
+ // Finalise the last (and most likely only) paragraph.
+ generatedParagraphs.push_back(os.str());
+ delete xs;
+
+ return generatedParagraphs;
}
diff --git a/src/Paragraph.h b/src/Paragraph.h
index 58b2762..ee31403 100644
--- a/src/Paragraph.h
+++ b/src/Paragraph.h
@@ -24,6 +24,7 @@
#include "support/types.h"
#include <set>
+#include <vector>
namespace lyx {
@@ -208,14 +209,11 @@ public:
/// Output the first word of a paragraph, return the position where it left.
pos_type firstWordLyXHTML(XMLStream & xs, OutputParams const & runparams) const;
- /// Writes to stream the DocBook representation
- void simpleDocBookOnePar(Buffer const & buf,
- XMLStream &,
- OutputParams const & runparams,
- Font const & outerfont,
- bool start_paragraph = true,
- bool close_paragraph = true,
- pos_type initial = 0) const;
+ /// Outputs to stream the DocBook representation, one element per paragraph.
+ std::vector<docstring> simpleDocBookOnePar(Buffer const & buf,
+ OutputParams const & runparams,
+ Font const & outerfont,
+ pos_type initial = 0) const;
/// \return any material that has had to be deferred until after the
/// paragraph has closed.
diff --git a/src/insets/InsetERT.cpp b/src/insets/InsetERT.cpp
index 8e69e88..1af67e1 100644
--- a/src/insets/InsetERT.cpp
+++ b/src/insets/InsetERT.cpp
@@ -98,23 +98,33 @@ void InsetERT::docbook(XMLStream & xs, OutputParams const & runparams) const
auto par = begin;
auto const end = paragraphs().end();
- odocstringstream os2;
- XMLStream xs2(os2);
+ odocstringstream os; // No need for XML handling here.
// Recreate the logic of makeParagraph in output_docbook.cpp, but much simplified: never open <para>
// in an ERT, use simple line breaks.
- while (par != end) {
- par->simpleDocBookOnePar(buffer(), xs2, runparams, text().outerFont(distance(begin, par)));
+ // New line after each paragraph of the ERT, save the last one.
+ while (true) { // For each paragraph in the ERT...
+ auto pars = par->simpleDocBookOnePar(buffer(), runparams, text().outerFont(distance(begin, par)));
+ auto p = pars.begin();
+ while (true) { // For each line of this ERT paragraph...
+ os << *p;
+ ++p;
+ if (p != pars.end())
+ os << "\n";
+ else
+ break;
+ }
- // New line after each paragraph of the ERT, save the last one.
++par;
if (par != end)
- xs << "\n";
+ os << "\n";
+ else
+ break;
}
// Output the ERT as a comment with the appropriate escaping.
xs << XMLStream::ESCAPE_NONE << "<!-- ";
- xs << XMLStream::ESCAPE_COMMENTS << os2.str();
+ xs << XMLStream::ESCAPE_COMMENTS << os.str();
xs << XMLStream::ESCAPE_NONE << " -->";
xs << xml::CR();
}
diff --git a/src/insets/InsetNewline.cpp b/src/insets/InsetNewline.cpp
index 7cba0f7..b33cf00 100644
--- a/src/insets/InsetNewline.cpp
+++ b/src/insets/InsetNewline.cpp
@@ -174,20 +174,7 @@ int InsetNewline::plaintext(odocstringstream & os,
void InsetNewline::docbook(XMLStream & xs, OutputParams const & runparams) const
{
- if (runparams.docbook_in_par) {
- xs.closeFontTags();
-
- // TODO: what if within a list item, and docbookiteminnertag is not para? This would require information
- // about the paragraph's layout... Good for now, though, this should not happen in DocBook, only maybe
- // extensions.
- xs << XMLStream::ESCAPE_NONE << from_utf8("<!-- Is para open? " + string((xs.isTagOpen(xml::StartTag("para"))) ? "yes" : "no") +" -->");
- xs << XMLStream::ESCAPE_NONE << from_utf8("</para>\n<para>");
- // TODO: that's a hack...
-// xs << xml::EndTag("para");
-// xs << xml::CR();
-// xs << xml::StartTag("para");
- }
- // Outside a paragraph, no need to handle new lines.
+ // New lines are handled by Paragraph::simpleDocBookOnePar.
}
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index ce3f699..0dc5257 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -382,9 +382,11 @@ void makeParagraphBibliography(
}
xs << xml::StartTag(from_utf8("bibliomixed"), attr);
- // Generate the entry.
+ // Generate the entry. Concatenate the different parts of the paragraph if any.
auto const begin = text.paragraphs().begin();
- par->simpleDocBookOnePar(buf, xs, runparams, text.outerFont(std::distance(begin, par)), true, true, 0);
+ auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(begin, par)), 0);
+ for (auto & parXML : pars)
+ xs << XMLStream::ESCAPE_NONE << parXML;
// End the precooked bibliography entry.
xs << xml::EndTag("bibliomixed");
@@ -488,21 +490,19 @@ void makeParagraph(
// Determine if this paragraph has some real content. Things like new pages are not caught
// by Paragraph::empty(), even though they do not generate anything useful in DocBook.
// Thus, remove all spaces (including new lines: \r, \n) before checking for emptiness.
- odocstringstream os2;
- XMLStream xs2(os2);
- par->simpleDocBookOnePar(buf, xs2, runparams, text.outerFont(distance(begin, par)), open_par, close_par, 0);
-
- docstring cleaned = os2.str();
- cleaned.erase(std::remove_if(cleaned.begin(), cleaned.end(), ::isspace), cleaned.end());
-
- if (!cleaned.empty()) {
- if (open_par)
- openParTag(xs, &*par, prevpar);
-
- xs << XMLStream::ESCAPE_NONE << os2.str();
-
- if (close_par)
- closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr);
+ // std::all_of allows doing this check without having to copy the string.
+ // Open and close tags around each contained paragraph.
+ auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(distance(begin, par)), 0);
+ for (auto & parXML : pars) {
+ if (!std::all_of(parXML.begin(), parXML.end(), ::isspace)) {
+ if (open_par)
+ openParTag(xs, &*par, prevpar);
+
+ xs << XMLStream::ESCAPE_NONE << parXML;
+
+ if (close_par)
+ closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr);
+ }
}
}
@@ -529,10 +529,8 @@ void makeEnvironment(
style.latextype == LATEX_LIST_ENVIRONMENT ||
style.latextype == LATEX_ITEM_ENVIRONMENT) {
// Open a wrapper tag if needed.
- if (style.docbookitemwrappertag() != "NONE") {
- xs << xml::StartTag(style.docbookitemwrappertag(), style.docbookitemwrapperattr());
- xs << xml::CR();
- }
+ if (style.docbookitemwrappertag() != "NONE")
+ 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
// character after the label.
@@ -580,9 +578,18 @@ void makeEnvironment(
// TODO: this always worked only by magic...
xs << ' ';
} else {
- // Generate the rest of the paragraph, if need be.
- par->simpleDocBookOnePar(buf, xs, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)),
- true, true, sep);
+ // Generate the rest of the paragraph, if need be. Open as many inner tags as necessary.
+ auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), sep);
+ auto p = pars.begin();
+ while (true) {
+ xs << XMLStream::ESCAPE_NONE << *p;
+ ++p;
+ if (p != pars.end()) {
+ closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
+ openTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(), par->layout().docbookiteminnertagtype());
+ } else
+ break;
+ }
}
} else {
makeAny(text, buf, xs, runparams, par);
@@ -612,8 +619,10 @@ void makeCommand(
auto prevpar = text.paragraphs().getParagraphBefore(par);
openParTag(xs, &*par, prevpar);
- par->simpleDocBookOnePar(buf, xs, runparams,
- text.outerFont(distance(begin, par)));
+ auto pars = par->simpleDocBookOnePar(buf, runparams,text.outerFont(distance(begin, par)));
+ for (auto & parXML : pars)
+ // TODO: decide what to do with openParTag/closeParTag in new lines.
+ xs << XMLStream::ESCAPE_NONE << parXML;
closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr);
}
diff --git a/src/xml.h b/src/xml.h
index 69d582d..9a7cf17 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -132,8 +132,6 @@ private:
TagDeque tag_stack_;
///
bool is_last_tag_cr_;
-public:
- bool pending_tags_empty() { return pending_tags_.empty();};
};
namespace xml {
More information about the lyx-cvs
mailing list