]> git.lyx.org Git - features.git/commitdiff
DocBook: make Paragraph::simpleDocBookOnePar return a list of paragraphs.
authorThibaut Cuvelier <tcuvelier@lyx.org>
Wed, 26 Aug 2020 19:19:38 +0000 (21:19 +0200)
committerThibaut Cuvelier <tcuvelier@lyx.org>
Sat, 19 Sep 2020 18:43:38 +0000 (20:43 +0200)
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
autotests/export/docbook/lists.xml
lib/doc/Customization.lyx
src/Paragraph.cpp
src/Paragraph.h
src/insets/InsetERT.cpp
src/insets/InsetNewline.cpp
src/output_docbook.cpp
src/xml.h

index f9033720841d325d3049439b3ea84784b162cbff..f4a58c2e100af464f70341889bb00703a94569a9 100644 (file)
@@ -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
index 4621e30937880334c5713660e9754856353e6edd..d7b24f6da765095488c06d3b82282f59057009ad 100644 (file)
@@ -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
index d6f5f1744b62490adff6342bc058a7e980bffe0b..357845a342973db4af2e79c194d894a25572abda 100644 (file)
@@ -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
index 24947f80dddf36aacbcfe526a7e56a509ba602d1..e87ef8817628918e226e4bea2a9b35932e4782a2 100644 (file)
@@ -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;
 }
 
 
index 58b276226356b0464b7a857f0fdce83fef4c110e..ee314031ba19adeb1051d3cfdd4a17739ba79fc5 100644 (file)
@@ -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.
index 8e69e8826043104b9ab19db658e5d0f3dbc23711..1af67e1e31d3b5c8e994fa1e1dffa17bf8cf4bbd 100644 (file)
@@ -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();
 }
index 7cba0f756abdbf1140f582c3ea1afc3630105185..b33cf007685807993bf53e031721cc6607956ead 100644 (file)
@@ -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.
 }
 
 
index ce3f6991b581681064a3ebd4c29a55cf0cba6788..0dc52578d3e1855ab26be885090f0fd07e473882 100644 (file)
@@ -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);
 }
index 69d582d0fd1203b21c271d204dea25dd4f834b30..9a7cf17f2849dbae17f9c3e3b479aa69c3ae080a 100644 (file)
--- 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 {