New DocBook support

This commit is contained in:
Thibaut Cuvelier 2020-06-08 23:27:49 +02:00 committed by Pavel Sanda
parent 70776ba667
commit 3883b85f49
104 changed files with 3190 additions and 1070 deletions

View File

@ -22,7 +22,7 @@
#include "Encoding.h"
#include "InsetIterator.h"
#include "Language.h"
#include "output_xhtml.h"
#include "xml.h"
#include "Paragraph.h"
#include "TextClass.h"
#include "TocBackend.h"
@ -1591,4 +1591,77 @@ string citationStyleToString(const CitationStyle & cs, bool const latex)
return cmd;
}
docstring authorsToDocBookAuthorGroup(docstring const & authorsString, XMLStream & xs, Buffer const & buf)
{
// This function closely mimics getAuthorList, but produces DocBook instead of text.
// It has been greatly simplified, as the complete list of authors is always produced. No separators are required,
// as the output has a database-like shape.
// constructName has also been merged within, as it becomes really simple and leads to no copy-paste.
if (authorsString.empty()) {
return docstring();
}
// Split the input list of authors into individual authors.
vector<docstring> const authors = getAuthors(authorsString);
// Retrieve the "et al." variation.
string const etal = buf.params().documentClass().getCiteMacro(buf.params().citeEngineType(), "_etal");
// Output the list of authors.
xs << xml::StartTag("authorgroup");
auto it = authors.cbegin();
auto en = authors.cend();
for (size_t i = 0; it != en; ++it, ++i) {
xs << xml::StartTag("author");
xs << xml::CR();
xs << xml::StartTag("personname");
xs << xml::CR();
docstring name = *it;
// All authors go in a <personname>. If more structure is known, use it; otherwise (just "et al."), print it as such.
if (name == "others") {
xs << buf.B_(etal);
} else {
name_parts parts = nameParts(name);
if (! parts.prefix.empty()) {
xs << xml::StartTag("honorific");
xs << parts.prefix;
xs << xml::EndTag("honorific");
xs << xml::CR();
}
if (! parts.prename.empty()) {
xs << xml::StartTag("firstname");
xs << parts.prename;
xs << xml::EndTag("firstname");
xs << xml::CR();
}
if (! parts.surname.empty()) {
xs << xml::StartTag("surname");
xs << parts.surname;
xs << xml::EndTag("surname");
xs << xml::CR();
}
if (! parts.suffix.empty()) {
xs << xml::StartTag("othername", "role=\"suffix\"");
xs << parts.suffix;
xs << xml::EndTag("othername");
xs << xml::CR();
}
}
xs << xml::EndTag("personname");
xs << xml::CR();
xs << xml::EndTag("author");
xs << xml::CR();
// Could add an affiliation after <personname>, but not stored in BibTeX.
}
xs << xml::EndTag("authorgroup");
xs << xml::CR();
return docstring();
}
} // namespace lyx

View File

@ -35,6 +35,9 @@ CitationStyle citationStyleFromString(std::string const & latex_str,
/// the other way round
std::string citationStyleToString(CitationStyle const &, bool const latex = false);
/// Transforms the information about authors into a <authorgroup> (directly written to a XMLStream).
docstring authorsToDocBookAuthorGroup(docstring const & authorsString, XMLStream & xs, Buffer const & buf);
/// Class to represent information about a BibTeX or
/// bibliography entry.

View File

@ -46,11 +46,11 @@
#include "LyX.h"
#include "LyXRC.h"
#include "LyXVC.h"
#include "output_docbook.h"
#include "output.h"
#include "output_latex.h"
#include "output_xhtml.h"
#include "output_docbook.h"
#include "output_plaintext.h"
#include "output_xhtml.h"
#include "Paragraph.h"
#include "ParagraphParameters.h"
#include "ParIterator.h"
@ -2112,7 +2112,7 @@ Buffer::ExportStatus Buffer::makeDocBookFile(FileName const & fname,
updateMacroInstances(OutputUpdate);
ExportStatus const retval =
writeDocBookSource(ofs, fname.absFileName(), runparams, output);
writeDocBookSource(ofs, runparams, output);
if (retval == ExportKilled)
return ExportKilled;
@ -2123,85 +2123,56 @@ Buffer::ExportStatus Buffer::makeDocBookFile(FileName const & fname,
}
Buffer::ExportStatus Buffer::writeDocBookSource(odocstream & os, string const & fname,
Buffer::ExportStatus Buffer::writeDocBookSource(odocstream & os,
OutputParams const & runparams,
OutputWhat output) const
{
LaTeXFeatures features(*this, params(), runparams);
validate(features);
d->bibinfo_.makeCitationLabels(*this);
d->texrow.reset();
DocumentClass const & tclass = params().documentClass();
string const & top_element = tclass.latexname();
bool const output_preamble =
output == FullSource || output == OnlyPreamble;
bool const output_body =
output == FullSource || output == OnlyBody;
XMLStream xs(os);
if (output_preamble) {
if (runparams.flavor == OutputParams::DOCBOOK5)
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
// XML preamble, no doctype needed.
// Not using XMLStream for this, as the root tag would be in the tag stack and make troubles with the error
// detection mechanisms (these are called before the end tag is output, and thus interact with the canary
// parsep in output_docbook.cpp).
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<!-- This DocBook file was created by LyX " << lyx_version
<< "\n See http://www.lyx.org/ for more information -->\n";
// FIXME UNICODE
os << "<!DOCTYPE " << from_ascii(top_element) << ' ';
// Directly output the root tag, based on the current type of document.
string languageCode = params().language->code();
string params = "xml:lang=\"" + languageCode + '"'
+ " 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\"";
// FIXME UNICODE
if (! tclass.class_header().empty())
os << from_ascii(tclass.class_header());
else if (runparams.flavor == OutputParams::DOCBOOK5)
os << "PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\" "
<< "\"https://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\"";
else
os << " PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\"";
docstring preamble = params().preamble;
if (runparams.flavor != OutputParams::DOCBOOK5 ) {
preamble += "<!ENTITY % output.print.png \"IGNORE\">\n";
preamble += "<!ENTITY % output.print.pdf \"IGNORE\">\n";
preamble += "<!ENTITY % output.print.eps \"IGNORE\">\n";
preamble += "<!ENTITY % output.print.bmp \"IGNORE\">\n";
}
string const name = runparams.nice
? changeExtension(absFileName(), ".sgml") : fname;
preamble += features.getIncludedFiles(name);
preamble += features.getLyXSGMLEntities();
if (!preamble.empty()) {
os << "\n [ " << preamble << " ]";
}
os << ">\n\n";
os << "<" << from_ascii(tclass.docbookroot()) << " " << from_ascii(params) << ">\n";
}
if (output_body) {
string top = top_element;
top += " lang=\"";
if (runparams.flavor == OutputParams::DOCBOOK5)
top += params().language->code();
else
top += params().language->code().substr(0, 2);
top += '"';
if (!params().options.empty()) {
top += ' ';
top += params().options;
}
os << "<!-- " << ((runparams.flavor == OutputParams::DOCBOOK5)? "XML" : "SGML")
<< " file was created by LyX " << lyx_version
<< "\n See https://www.lyx.org/ for more information -->\n";
params().documentClass().counters().reset();
xml::openTag(os, top);
os << '\n';
try {
docbookParagraphs(text(), *this, os, runparams);
}
catch (ConversionException const &) { return ExportKilled; }
xml::closeTag(os, top_element);
// Start to output the document.
docbookParagraphs(text(), *this, xs, runparams);
}
if (output_preamble) {
// Close the root element.
os << "\n</" << from_ascii(tclass.docbookroot()) << ">";
}
return ExportSuccess;
}
@ -4132,8 +4103,9 @@ unique_ptr<TexRow> Buffer::getSourceCode(odocstream & os, string const & format,
// Probably should have some routine with a signature like them.
writePlaintextParagraph(*this,
text().paragraphs()[par_begin], os, runparams, dummy);
} else if (params().isDocBook()) {
docbookParagraphs(text(), *this, os, runparams);
} else if (runparams.flavor == OutputParams::DOCBOOK5) {
XMLStream xs{os};
docbookParagraphs(text(), *this, xs, runparams);
} else {
// If we are previewing a paragraph, even if this is the
// child of some other buffer, let's cut the link here,
@ -4185,8 +4157,8 @@ unique_ptr<TexRow> Buffer::getSourceCode(odocstream & os, string const & format,
os << "% "<< _("Plain text does not have a preamble.");
} else
writePlaintextFile(*this, os, runparams);
} else if (params().isDocBook()) {
writeDocBookSource(os, absFileName(), runparams, output);
} else if (runparams.flavor == OutputParams::DOCBOOK5) {
writeDocBookSource(os, runparams, output);
} else {
// latex or literate
otexstream ots(os);
@ -4495,8 +4467,9 @@ Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir
return ExportKilled;
} else if (backend_format == "lyx")
writeFile(FileName(filename));
// Docbook backend
else if (params().isDocBook()) {
// DocBook backend
else if (backend_format == "docbook5") {
runparams.flavor = OutputParams::DOCBOOK5;
runparams.nice = !put_in_tempdir;
if (makeDocBookFile(FileName(filename), runparams) == ExportKilled)
return ExportKilled;

View File

@ -335,7 +335,7 @@ public:
OutputParams const & runparams_in,
OutputWhat output = FullSource) const;
///
ExportStatus writeDocBookSource(odocstream & os, std::string const & filename,
ExportStatus writeDocBookSource(odocstream & os,
OutputParams const & runparams_in,
OutputWhat output = FullSource) const;
///

View File

@ -105,7 +105,7 @@ private:
Converter::Converter(string const & f, string const & t,
string const & c, string const & l)
: from_(f), to_(t), command_(c), flags_(l),
From_(nullptr), To_(nullptr), latex_(false), xml_(false),
From_(nullptr), To_(nullptr), latex_(false), docbook_(false),
need_aux_(false), nice_(false), need_auth_(false)
{}
@ -122,7 +122,7 @@ void Converter::readFlags()
latex_flavor_ = flag_value.empty() ?
"latex" : flag_value;
} else if (flag_name == "xml")
xml_ = true;
docbook_ = true;
else if (flag_name == "needaux") {
need_aux_ = true;
latex_flavor_ = flag_value.empty() ?
@ -276,7 +276,7 @@ OutputParams::FLAVOR Converters::getFlavor(Graph::EdgePath const & path,
if (conv.latex_flavor() == "pdflatex")
return OutputParams::PDFLATEX;
}
if (conv.xml())
if (conv.docbook())
return OutputParams::DOCBOOK5;
}
return buffer ? buffer->params().getOutputFlavor()

View File

@ -74,7 +74,7 @@ public:
///
std::string const latex_flavor() const { return latex_flavor_; }
///
bool xml() const { return xml_; }
bool docbook() const { return docbook_; }
///
bool need_aux() const { return need_aux_; }
/// Return whether or not the needauth option is set for this converter
@ -108,8 +108,8 @@ private:
bool latex_;
/// The latex derivate
trivstring latex_flavor_;
/// The converter is xml
bool xml_;
/// The converter is DocBook
bool docbook_;
/// This converter needs the .aux files
bool need_aux_;
/// we need a "nice" file from the backend, c.f. OutputParams.nice.

View File

@ -30,7 +30,8 @@ Floating::Floating(string const & type, string const & placement,
string const & listName, std::string const & listCmd,
string const & refPrefix, std::string const & allowedplacement,
string const & htmlTag, string const & htmlAttrib,
docstring const & htmlStyle, string const & required,
docstring const & htmlStyle, string const & docbookTag,
string const & docbookAttr, string const & required,
bool usesfloat, bool ispredefined,
bool allowswide, bool allowssideways)
: floattype_(type), placement_(placement), ext_(ext), within_(within),
@ -38,7 +39,8 @@ Floating::Floating(string const & type, string const & placement,
refprefix_(refPrefix), allowedplacement_(allowedplacement), required_(required),
usesfloatpkg_(usesfloat), ispredefined_(ispredefined),
allowswide_(allowswide), allowssideways_(allowssideways),
html_tag_(htmlTag), html_attrib_(htmlAttrib), html_style_(htmlStyle)
html_tag_(htmlTag), html_attrib_(htmlAttrib), html_style_(htmlStyle),
docbook_tag_(docbookTag), docbook_attr_(docbookAttr)
{}
@ -80,4 +82,42 @@ string Floating::defaultCSSClass() const
}
string const & Floating::docbookAttr() const
{
return docbook_attr_;
}
string const & Floating::docbookTag(bool hasTitle) const
{
docbook_tag_ = "";
if (floattype_ == "figure") {
docbook_tag_ = hasTitle ? "figure" : "informalfigure";
} else if (floattype_ == "table") {
docbook_tag_ = hasTitle ? "table" : "informaltable";
} else if (floattype_ == "algorithm") {
// TODO: no good translation for now! Figures are the closest match, as they can contain text.
// Solvable as soon as https://github.com/docbook/docbook/issues/157 has a definitive answer.
docbook_tag_ = "figure";
}
return docbook_tag_;
}
string const & Floating::docbookCaption() const
{
docbook_caption_ = "";
if (floattype_ == "figure") {
docbook_caption_ = "title";
} else if (floattype_ == "table") {
docbook_caption_ = "caption";
} else if (floattype_ == "algorithm") {
// TODO: no good translation for now! Figures are the closest match, as they can contain text.
// Solvable as soon as https://github.com/docbook/docbook/issues/157 has a definitive answer.
docbook_caption_ = "title";
}
return docbook_caption_;
}
} // namespace lyx

View File

@ -37,9 +37,9 @@ public:
std::string const & listName, std::string const & listCmd,
std::string const & refPrefix, std::string const & allowedplacement,
std::string const & htmlType, std::string const & htmlClass,
docstring const & htmlStyle, std::string const & required,
bool usesfloat, bool isprefined,
bool allowswide, bool allowssideways);
docstring const & htmlStyle, std::string const & docbookTag,
std::string const & docbookAttr, std::string const & required,
bool usesfloat, bool isprefined, bool allowswide, bool allowssideways);
///
std::string const & floattype() const { return floattype_; }
///
@ -79,6 +79,12 @@ public:
std::string const & htmlAttrib() const;
/// tag type, defaults to "div"
std::string const & htmlTag() const;
///
std::string const & docbookTag(bool hasTitle = false) const;
///
std::string const & docbookAttr() const;
///
std::string const & docbookCaption() const;
private:
///
std::string defaultCSSClass() const;
@ -120,6 +126,12 @@ private:
mutable std::string defaultcssclass_;
///
docstring html_style_;
/// DocBook tag
mutable std::string docbook_tag_;
/// attribute (mostly, role)
mutable std::string docbook_caption_;
/// caption tag (mostly, either caption or title)
std::string docbook_attr_;
};

View File

@ -31,7 +31,7 @@ using namespace lyx::support;
namespace lyx {
/// Special value of toclevel for layouts that to not belong in a TOC
/// Special value of toclevel for layouts that do not belong to a TOC
const int Layout::NOT_IN_TOC = -1000;
// The order of the LayoutTags enum is no more important. [asierra300396]
@ -104,6 +104,21 @@ enum LayoutTags {
LT_HTMLPREAMBLE,
LT_HTMLSTYLE,
LT_HTMLFORCECSS,
LT_DOCBOOKTAG,
LT_DOCBOOKATTR,
LT_DOCBOOKININFO,
LT_DOCBOOKWRAPPERTAG,
LT_DOCBOOKWRAPPERATTR,
LT_DOCBOOKSECTIONTAG,
LT_DOCBOOKITEMWRAPPERTAG,
LT_DOCBOOKITEMWRAPPERATTR,
LT_DOCBOOKITEMTAG,
LT_DOCBOOKITEMATTR,
LT_DOCBOOKITEMLABELTAG,
LT_DOCBOOKITEMLABELATTR,
LT_DOCBOOKITEMINNERTAG,
LT_DOCBOOKITEMINNERATTR,
LT_DOCBOOKFORCEABSTRACTTAG,
LT_INPREAMBLE,
LT_HTMLTITLE,
LT_SPELLCHECK,
@ -204,6 +219,21 @@ bool Layout::readIgnoreForcelocal(Lexer & lex, TextClass const & tclass)
{ "commanddepth", LT_COMMANDDEPTH },
{ "copystyle", LT_COPYSTYLE },
{ "dependson", LT_DEPENDSON },
{ "docbookattr", LT_DOCBOOKATTR },
{ "docbookforceabstracttag", LT_DOCBOOKFORCEABSTRACTTAG },
{ "docbookininfo", LT_DOCBOOKININFO },
{ "docbookitemattr", LT_DOCBOOKITEMATTR },
{ "docbookiteminnerattr", LT_DOCBOOKITEMINNERATTR },
{ "docbookiteminnertag", LT_DOCBOOKITEMINNERTAG },
{ "docbookitemlabelattr", LT_DOCBOOKITEMLABELATTR },
{ "docbookitemlabeltag", LT_DOCBOOKITEMLABELTAG },
{ "docbookitemtag", LT_DOCBOOKITEMTAG },
{ "docbookitemwrapperattr", LT_DOCBOOKITEMWRAPPERATTR },
{ "docbookitemwrappertag", LT_DOCBOOKITEMWRAPPERTAG },
{ "docbooksectiontag", LT_DOCBOOKSECTIONTAG },
{ "docbooktag", LT_DOCBOOKTAG },
{ "docbookwrapperattr", LT_DOCBOOKWRAPPERATTR },
{ "docbookwrappertag", LT_DOCBOOKWRAPPERTAG },
{ "end", LT_END },
{ "endlabelstring", LT_ENDLABELSTRING },
{ "endlabeltype", LT_ENDLABELTYPE },
@ -689,6 +719,66 @@ bool Layout::readIgnoreForcelocal(Lexer & lex, TextClass const & tclass)
lex >> htmltitle_;
break;
case LT_DOCBOOKTAG:
lex >> docbooktag_;
break;
case LT_DOCBOOKATTR:
lex >> docbookattr_;
break;
case LT_DOCBOOKFORCEABSTRACTTAG:
lex >> docbookforceabstracttag_;
break;
case LT_DOCBOOKININFO:
lex >> docbookininfo_;
break;
case LT_DOCBOOKWRAPPERTAG:
lex >> docbookwrappertag_;
break;
case LT_DOCBOOKWRAPPERATTR:
lex >> docbookwrapperattr_;
break;
case LT_DOCBOOKSECTIONTAG:
lex >> docbooksectiontag_;
break;
case LT_DOCBOOKITEMWRAPPERTAG:
lex >> docbookitemwrappertag_;
break;
case LT_DOCBOOKITEMWRAPPERATTR:
lex >> docbookitemwrapperattr_;
break;
case LT_DOCBOOKITEMTAG:
lex >> docbookitemtag_;
break;
case LT_DOCBOOKITEMATTR:
lex >> docbookitemattr_;
break;
case LT_DOCBOOKITEMLABELTAG:
lex >> docbookitemlabeltag_;
break;
case LT_DOCBOOKITEMLABELATTR:
lex >> docbookitemlabelattr_;
break;
case LT_DOCBOOKITEMINNERTAG:
lex >> docbookiteminnertag_;
break;
case LT_DOCBOOKITEMINNERATTR:
lex >> docbookiteminnerattr_;
break;
case LT_SPELLCHECK:
lex >> spellcheck;
break;
@ -1499,8 +1589,38 @@ void Layout::write(ostream & os) const
os << "\tHTMLPreamble\n"
<< to_utf8(rtrim(htmlpreamble_, "\n"))
<< "\n\tEndPreamble\n";
os << "\tHTMLTitle " << htmltitle_ << "\n"
"\tSpellcheck " << spellcheck << "\n"
os << "\tHTMLTitle " << htmltitle_ << "\n";
if(!docbooktag_.empty())
os << "\tDocBookTag " << docbooktag_ << '\n';
if(!docbookattr_.empty())
os << "\tDocBookAttr " << docbookattr_ << '\n';
if(!docbookininfo_.empty())
os << "\tDocBookInInfo " << docbookininfo_ << '\n';
if(!docbookwrappertag_.empty())
os << "\tDocBookWrapperTag " << docbookwrappertag_ << '\n';
if(!docbookwrapperattr_.empty())
os << "\tDocBookWrapperAttr " << docbookwrapperattr_ << '\n';
if(!docbooksectiontag_.empty())
os << "\tDocBookSectionTag " << docbooksectiontag_ << '\n';
if(!docbookitemtag_.empty())
os << "\tDocBookItemTag " << docbookitemtag_ << '\n';
if(!docbookitemattr_.empty())
os << "\tDocBookItemAttr " << docbookitemattr_ << '\n';
if(!docbookitemwrappertag_.empty())
os << "\tDocBookItemTag " << docbookitemwrappertag_ << '\n';
if(!docbookitemwrapperattr_.empty())
os << "\tDocBookItemWrapperAttr " << docbookitemwrapperattr_ << '\n';
if(!docbookitemlabeltag_.empty())
os << "\tDocBookItemLabelTag " << docbookitemlabeltag_ << '\n';
if(!docbookitemlabelattr_.empty())
os << "\tDocBookItemLabelAttr " << docbookitemlabelattr_ << '\n';
if(!docbookiteminnertag_.empty())
os << "\tDocBookItemInnerTag " << docbookiteminnertag_ << '\n';
if(!docbookiteminnerattr_.empty())
os << "\tDocBookItemInnerAttr " << docbookiteminnerattr_ << '\n';
if(!docbookforceabstracttag_.empty())
os << "\tDocBookForceAbstractTag " << docbookforceabstracttag_ << '\n';
os << "\tSpellcheck " << spellcheck << "\n"
"\tForceLocal " << forcelocal << "\n"
"End\n";
}
@ -1648,6 +1768,116 @@ string Layout::defaultCSSClass() const
}
string const & Layout::docbooktag() const
{
// No sensible default value, unhappily...
if (docbooktag_.empty())
docbooktag_ = to_utf8(name_);
return docbooktag_;
}
string const & Layout::docbookattr() const
{
// Perfectly OK to return no attributes, so docbookattr_ does not need to be filled.
return docbookattr_;
}
string const & Layout::docbookininfo() const
{
// Indeed, a trilean. Only titles should be "maybe": otherwise, metadata is "always", content is "never".
if (docbookininfo_.empty() || (docbookininfo_ != "never" && docbookininfo_ != "always" && docbookininfo_ != "maybe"))
docbookininfo_ = "never";
return docbookininfo_;
}
string const & Layout::docbookwrappertag() const
{
if (docbookwrappertag_.empty())
docbookwrappertag_ = "NONE";
return docbookwrappertag_;
}
string const & Layout::docbookwrapperattr() const
{
return docbookwrapperattr_;
}
string const & Layout::docbooksectiontag() const
{
if (docbooksectiontag_.empty())
docbooksectiontag_ = "section";
return docbooksectiontag_;
}
string const & Layout::docbookitemwrappertag() const
{
if (docbookitemwrappertag_.empty())
docbookitemwrappertag_ = "NONE";
return docbookitemwrappertag_;
}
string const & Layout::docbookitemwrapperattr() const
{
return docbookitemwrapperattr_;
}
string const & Layout::docbookitemtag() const
{
return docbookitemtag_;
}
string const & Layout::docbookitemattr() const
{
return docbookitemattr_;
}
string const & Layout::docbookitemlabeltag() const
{
if (docbookitemlabeltag_.empty())
docbookitemlabeltag_ = "NONE";
return docbookitemlabeltag_;
}
string const & Layout::docbookitemlabelattr() const
{
return docbookitemlabelattr_;
}
string const & Layout::docbookiteminnertag() const
{
if (docbookiteminnertag_.empty())
docbookiteminnertag_ = "NONE";
return docbookiteminnertag_;
}
string const & Layout::docbookiteminnerattr() const
{
return docbookiteminnerattr_;
}
std::string const & Layout::docbookforceabstracttag() const
{
if (docbookforceabstracttag_.empty())
docbookforceabstracttag_ = "NONE";
return docbookforceabstracttag_;
}
namespace {
string makeMarginValue(char const * side, double d)

View File

@ -193,6 +193,36 @@ public:
///
bool htmltitle() const { return htmltitle_; }
///
std::string const & docbooktag() const;
///
std::string const & docbookattr() const;
///
std::string const & docbookininfo() const;
///
std::string const & docbookwrappertag() const;
///
std::string const & docbookwrapperattr() const;
///
std::string const & docbooksectiontag() const;
///
std::string const & docbookitemwrappertag() const;
///
std::string const & docbookitemwrapperattr() const;
///
std::string const & docbookitemlabeltag() const;
///
std::string const & docbookitemlabelattr() const;
///
std::string const & docbookiteminnertag() const;
///
std::string const & docbookiteminnerattr() const;
///
std::string const & docbookitemtag() const;
///
std::string const & docbookitemattr() const;
///
std::string const & docbookforceabstracttag() const;
///
bool isParagraph() const { return latextype == LATEX_PARAGRAPH; }
///
bool isCommand() const { return latextype == LATEX_COMMAND; }
@ -457,6 +487,39 @@ private:
bool htmllabelfirst_;
/// CSS information needed by this layout.
docstring htmlstyle_;
/// DocBook tag corresponding to this layout.
mutable std::string docbooktag_;
/// Roles to add to docbooktag_, if any (default: none).
mutable std::string docbookattr_;
/// DocBook tag corresponding to this item (mainly for lists).
mutable std::string docbookitemtag_;
/// Roles to add to docbookitemtag_, if any (default: none).
mutable std::string docbookitemattr_;
/// DocBook tag corresponding to the wrapper around an item (mainly for lists).
mutable std::string docbookitemwrappertag_;
/// Roles to add to docbookitemwrappertag_, if any (default: none).
mutable std::string docbookitemwrapperattr_;
/// DocBook tag corresponding to this label (only for description lists;
/// labels in the common sense do not exist with DocBook).
mutable std::string docbookitemlabeltag_;
/// Roles to add to docbooklabeltag_, if any (default: none).
mutable std::string docbookitemlabelattr_;
/// DocBook tag to add within the item, around its direct content (mainly for lists).
mutable std::string docbookiteminnertag_;
/// Roles to add to docbookiteminnertag_, if any (default: none).
mutable std::string docbookiteminnerattr_;
/// DocBook tag corresponding to this wrapper around the main tag.
mutable std::string docbookwrappertag_;
/// Roles to add to docbookwrappertag_, if any (default: none).
mutable std::string docbookwrapperattr_;
/// Outer tag for this section, only if this layout represent a sectionning item, including chapters (default: section).
mutable std::string docbooksectiontag_;
/// Whether this tag must/can/can't go into an <info> tag (default: never, as it only makes sense for metadata).
mutable std::string docbookininfo_;
/// whether this element (root or not) does not accept text without a section(i.e. the first text that is met
/// in LyX must be considered as the abstract if this is true); this text must be output with the specific tag
/// held by this attribute
mutable std::string docbookforceabstracttag_;
/// Should we generate the default CSS for this layout, even if HTMLStyle
/// has been given? Default is false.
/// Note that the default CSS is output first, then the user CSS, so it is

View File

@ -33,7 +33,9 @@ OutputParams::OutputParams(Encoding const * enc)
par_begin(0), par_end(0), lastid(-1), lastpos(0), isLastPar(false),
dryrun(false), silent(false), pass_thru(false),
html_disable_captions(false), html_in_par(false),
html_make_pars(true), for_toc(false), for_tooltip(false),
html_make_pars(true), docbook_in_par(false), docbook_make_pars(true),
docbook_force_pars(false), docbook_in_float(false), docbook_anchors_to_ignore(std::unordered_set<docstring>()),
docbook_in_listing(false), for_toc(false), for_tooltip(false),
for_search(false), for_preview(false), includeall(false)
{
// Note: in PreviewLoader::Impl::dumpPreamble

View File

@ -16,6 +16,7 @@
#include "Changes.h"
#include <memory>
#include <unordered_set>
namespace lyx {
@ -350,6 +351,24 @@ public:
/// Does the present context even permit paragraphs?
bool html_make_pars;
/// Are we already in a paragraph?
bool docbook_in_par;
/// Does the present context even permit paragraphs?
bool docbook_make_pars;
/// Are paragraphs mandatory in this context?
bool docbook_force_pars;
/// Anchors that should not be output (LyX-side identifier, not DocBook-side).
std::unordered_set<docstring> docbook_anchors_to_ignore;
/// Is the current context a float (such as a table or a figure)?
bool docbook_in_float;
/// Is the current context a listing?
bool docbook_in_listing;
/// Are we generating this material for inclusion in a TOC-like entity?
bool for_toc;

View File

@ -64,6 +64,7 @@
#include "support/lassert.h"
#include "support/lstrings.h"
#include "support/textutils.h"
#include "output_docbook.h"
#include <atomic>
#include <sstream>
@ -2054,13 +2055,6 @@ docstring Paragraph::expandLabel(Layout const & layout,
}
docstring Paragraph::expandDocBookLabel(Layout const & layout,
BufferParams const & bparams) const
{
return expandParagraphLabel(layout, bparams, false);
}
docstring Paragraph::expandParagraphLabel(Layout const & layout,
BufferParams const & bparams, bool process_appendix) const
{
@ -2952,18 +2946,17 @@ string Paragraph::getID(Buffer const &, OutputParams const &)
}
pos_type Paragraph::firstWordDocBook(odocstream & os, OutputParams const & runparams)
const
pos_type Paragraph::firstWordDocBook(XMLStream & xs, OutputParams const & runparams) const
{
pos_type i;
for (i = 0; i < size(); ++i) {
if (Inset const * inset = getInset(i)) {
inset->docbook(os, runparams);
inset->docbook(xs, runparams);
} else {
char_type c = d->text_[i];
if (c == ' ')
break;
os << xml::escapeChar(c, XMLStream::ESCAPE_ALL);
xs << c;
}
}
return i;
@ -3005,57 +2998,312 @@ bool Paragraph::Private::onlyText(Buffer const & buf, Font const & outerfont, po
}
void Paragraph::simpleDocBookOnePar(Buffer const & buf,
odocstream & os,
OutputParams const & runparams,
Font const & outerfont,
pos_type initial) const
namespace {
void doFontSwitchDocBook(vector<xml::FontTag> & tagsToOpen,
vector<xml::EndFontTag> & tagsToClose,
bool & flag, FontState curstate, xml::FontTypes type)
{
bool emph_flag = false;
if (curstate == FONT_ON) {
tagsToOpen.push_back(docbookStartFontTag(type));
flag = true;
} else if (flag) {
tagsToClose.push_back(docbookEndFontTag(type));
flag = false;
}
}
Layout const & style = *d->layout_;
FontInfo font_old =
style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
class OptionalFontType {
public:
bool has_value;
xml::FontTypes ft;
if (style.pass_thru && !d->onlyText(buf, outerfont, initial))
os << "]]>";
OptionalFontType(): has_value(false), ft(xml::FT_EMPH) {} // A possible value at random for ft.
OptionalFontType(xml::FontTypes ft): has_value(true), ft(ft) {}
};
// parsing main loop
for (pos_type i = initial; i < size(); ++i) {
Font font = getFont(buf.params(), i, outerfont);
OptionalFontType fontShapeToXml(FontShape fs)
{
switch (fs) {
case ITALIC_SHAPE:
return {xml::FT_ITALIC};
case SLANTED_SHAPE:
return {xml::FT_SLANTED};
case SMALLCAPS_SHAPE:
return {xml::FT_SMALLCAPS};
case UP_SHAPE:
case INHERIT_SHAPE:
return {};
default:
// the other tags are for internal use
LATTEST(false);
return {};
}
}
// handle <emphasis> tag
if (font_old.emph() != font.fontInfo().emph()) {
if (font.fontInfo().emph() == FONT_ON) {
os << "<emphasis>";
emph_flag = true;
} else if (i != initial) {
os << "</emphasis>";
emph_flag = false;
OptionalFontType fontFamilyToXml(FontFamily fm)
{
switch (fm) {
case ROMAN_FAMILY:
return {xml::FT_ROMAN};
break;
case SANS_FAMILY:
return {xml::FT_SANS};
break;
case TYPEWRITER_FAMILY:
return {xml::FT_TYPE};
break;
case INHERIT_FAMILY:
return {};
default:
// the other tags are for internal use
LATTEST(false);
return {};
}
}
OptionalFontType fontSizeToXml(FontSize fs)
{
switch (fs) {
case TINY_SIZE:
return {xml::FT_SIZE_TINY};
case SCRIPT_SIZE:
return {xml::FT_SIZE_SCRIPT};
case FOOTNOTE_SIZE:
return {xml::FT_SIZE_FOOTNOTE};
case SMALL_SIZE:
return {xml::FT_SIZE_SMALL};
case LARGE_SIZE:
return {xml::FT_SIZE_LARGE};
case LARGER_SIZE:
return {xml::FT_SIZE_LARGER};
case LARGEST_SIZE:
return {xml::FT_SIZE_LARGEST};
case HUGE_SIZE:
return {xml::FT_SIZE_HUGE};
case HUGER_SIZE:
return {xml::FT_SIZE_HUGER};
case INCREASE_SIZE:
return {xml::FT_SIZE_INCREASE};
case DECREASE_SIZE:
return {xml::FT_SIZE_DECREASE};
case INHERIT_SIZE:
case NORMAL_SIZE:
return {};
default:
// the other tags are for internal use
LATTEST(false);
return {};
}
}
}// 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
{
// track whether we have opened these tags
bool emph_flag = false;
bool bold_flag = false;
bool noun_flag = false;
bool ubar_flag = false;
bool dbar_flag = false;
bool sout_flag = false;
bool wave_flag = false;
// shape tags
bool shap_flag = false;
// family tags
bool faml_flag = false;
// size tags
bool size_flag = false;
Layout const & style = *d->layout_;
if (start_paragraph)
xs.startDivision(allowEmpty());
FontInfo font_old =
style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
FontShape curr_fs = INHERIT_SHAPE;
FontFamily curr_fam = INHERIT_FAMILY;
FontSize curr_size = INHERIT_SIZE;
string const default_family =
buf.masterBuffer()->params().fonts_default_family;
vector<xml::FontTag> tagsToOpen;
vector<xml::EndFontTag> tagsToClose;
// parsing main loop
for (pos_type i = initial; i < size(); ++i) {
// let's not show deleted material in the output
if (isDeleted(i))
continue;
Font const font = getFont(buf.masterBuffer()->params(), i, outerfont);
// emphasis
FontState curstate = font.fontInfo().emph();
if (font_old.emph() != curstate)
doFontSwitchDocBook(tagsToOpen, tagsToClose, emph_flag, curstate, xml::FT_EMPH);
// noun
curstate = font.fontInfo().noun();
if (font_old.noun() != curstate)
doFontSwitchDocBook(tagsToOpen, tagsToClose, noun_flag, curstate, xml::FT_NOUN);
// underbar
curstate = font.fontInfo().underbar();
if (font_old.underbar() != curstate)
doFontSwitchDocBook(tagsToOpen, tagsToClose, ubar_flag, curstate, xml::FT_UBAR);
// strikeout
curstate = font.fontInfo().strikeout();
if (font_old.strikeout() != curstate)
doFontSwitchDocBook(tagsToOpen, tagsToClose, sout_flag, curstate, xml::FT_SOUT);
// double underbar
curstate = font.fontInfo().uuline();
if (font_old.uuline() != curstate)
doFontSwitchDocBook(tagsToOpen, tagsToClose, dbar_flag, curstate, xml::FT_DBAR);
// wavy line
curstate = font.fontInfo().uwave();
if (font_old.uwave() != curstate)
doFontSwitchDocBook(tagsToOpen, tagsToClose, wave_flag, curstate, xml::FT_WAVE);
// bold
// a little hackish, but allows us to reuse what we have.
curstate = (font.fontInfo().series() == BOLD_SERIES ? FONT_ON : FONT_OFF);
if (font_old.series() != font.fontInfo().series())
doFontSwitchDocBook(tagsToOpen, tagsToClose, bold_flag, curstate, xml::FT_BOLD);
// Font shape
curr_fs = font.fontInfo().shape();
FontShape old_fs = font_old.shape();
if (old_fs != curr_fs) {
if (shap_flag) {
OptionalFontType tag = fontShapeToXml(old_fs);
if (tag.has_value) {
tagsToClose.push_back(docbookEndFontTag(tag.ft));
}
shap_flag = false;
}
}
if (Inset const * inset = getInset(i)) {
inset->docbook(os, runparams);
} else {
char_type c = d->text_[i];
OptionalFontType tag = fontShapeToXml(curr_fs);
if (tag.has_value) {
tagsToOpen.push_back(docbookStartFontTag(tag.ft));
}
}
if (style.pass_thru)
os.put(c);
else
os << xml::escapeChar(c, XMLStream::EscapeSettings::ESCAPE_ALL);
}
font_old = font.fontInfo();
}
// Font family
curr_fam = font.fontInfo().family();
FontFamily old_fam = font_old.family();
if (old_fam != curr_fam) {
if (faml_flag) {
OptionalFontType tag = fontFamilyToXml(old_fam);
if (tag.has_value) {
tagsToClose.push_back(docbookEndFontTag(tag.ft));
}
faml_flag = false;
}
switch (curr_fam) {
case ROMAN_FAMILY:
// we will treat a "default" font family as roman, since we have
// no other idea what to do.
if (default_family != "rmdefault" && default_family != "default") {
tagsToOpen.push_back(docbookStartFontTag(xml::FT_ROMAN));
faml_flag = true;
}
break;
case SANS_FAMILY:
if (default_family != "sfdefault") {
tagsToOpen.push_back(docbookStartFontTag(xml::FT_SANS));
faml_flag = true;
}
break;
case TYPEWRITER_FAMILY:
if (default_family != "ttdefault") {
tagsToOpen.push_back(docbookStartFontTag(xml::FT_TYPE));
faml_flag = true;
}
break;
case INHERIT_FAMILY:
break;
default:
// the other tags are for internal use
LATTEST(false);
break;
}
}
if (emph_flag) {
os << "</emphasis>";
}
// Font size
curr_size = font.fontInfo().size();
FontSize old_size = font_old.size();
if (old_size != curr_size) {
if (size_flag) {
OptionalFontType tag = fontSizeToXml(old_size);
if (tag.has_value) {
tagsToClose.push_back(docbookEndFontTag(tag.ft));
}
size_flag = false;
}
if (style.free_spacing)
os << '\n';
if (style.pass_thru && !d->onlyText(buf, outerfont, initial))
os << "<![CDATA[";
OptionalFontType tag = fontSizeToXml(curr_size);
if (tag.has_value) {
tagsToOpen.push_back(docbookStartFontTag(tag.ft));
size_flag = true;
}
}
// FIXME XHTML
// Other such tags? What about the other text ranges?
vector<xml::EndFontTag>::const_iterator cit = tagsToClose.begin();
vector<xml::EndFontTag>::const_iterator cen = tagsToClose.end();
for (; cit != cen; ++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;
tagsToClose.clear();
tagsToOpen.clear();
if (Inset const * inset = getInset(i)) {
if (!runparams.for_toc || inset->isInToc()) {
OutputParams np = runparams;
np.local_font = &font;
// If the paragraph has size 1, then we are in the "special
// case" where we do not output the containing paragraph info.
if (!inset->getLayout().htmlisblock() && size() != 1) // TODO: htmlisblock here too!
np.docbook_in_par = true;
inset->docbook(xs, np);
}
} else {
char_type c = getUChar(buf.masterBuffer()->params(), runparams, i);
xs << c;
}
font_old = font.fontInfo();
}
// FIXME 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();
if (runparams.docbook_in_listing)
xs << xml::CR();
if (close_paragraph)
xs.endDivision();
}

View File

@ -200,27 +200,29 @@ public:
std::string getID(Buffer const & buf, OutputParams const & runparams) const;
/// Output the first word of a paragraph, return the position where it left.
pos_type firstWordDocBook(odocstream & os, OutputParams const & runparams) const;
pos_type firstWordDocBook(XMLStream & xs, OutputParams const & runparams) const;
/// 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
/// Writes to stream the DocBook representation
void simpleDocBookOnePar(Buffer const & buf,
odocstream &,
OutputParams const & runparams,
Font const & outerfont,
pos_type initial = 0) const;
XMLStream &,
OutputParams const & runparams,
Font const & outerfont,
bool start_paragraph = true,
bool close_paragraph = true,
pos_type initial = 0) const;
/// \return any material that has had to be deferred until after the
/// paragraph has closed.
docstring simpleLyXHTMLOnePar(Buffer const & buf,
XMLStream & xs,
OutputParams const & runparams,
Font const & outerfont,
bool start_paragraph = true,
bool close_paragraph = true,
pos_type initial = 0) const;
XMLStream & xs,
OutputParams const & runparams,
Font const & outerfont,
bool start_paragraph = true,
bool close_paragraph = true,
pos_type initial = 0) const;
///
bool hasSameLayout(Paragraph const & par) const;
@ -307,8 +309,6 @@ public:
///
docstring expandLabel(Layout const &, BufferParams const &) const;
///
docstring expandDocBookLabel(Layout const &, BufferParams const &) const;
///
docstring const & labelString() const;
/// the next two functions are for the manual labels
docstring const getLabelWidthString() const;

View File

@ -62,7 +62,7 @@ namespace lyx {
// You should also run the development/tools/updatelayouts.py script,
// to update the format of all of our layout files.
//
int const LAYOUT_FORMAT = 81; // rikiheck: GuiName for counters
int const LAYOUT_FORMAT = 82; // dourouc05: DocBook additions.
// Layout format for the current lyx file format. Controls which format is
@ -143,7 +143,7 @@ TextClass::TextClass()
outputFormat_("latex"), has_output_format_(false), defaultfont_(sane_font),
titletype_(TITLE_COMMAND_AFTER), titlename_("maketitle"),
min_toclevel_(0), max_toclevel_(0), maxcitenames_(2),
cite_full_author_list_(true), bibintoc_(false)
cite_full_author_list_(true), bibintoc_(false), docbookroot_("article"), docbookforceabstract_(false)
{
}
@ -216,7 +216,9 @@ enum TextClassTags {
TC_FULLAUTHORLIST,
TC_OUTLINERNAME,
TC_TABLESTYLE,
TC_BIBINTOC
TC_BIBINTOC,
TC_DOCBOOKROOT,
TC_DOCBOOKFORCEABSTRACT
};
@ -239,6 +241,8 @@ LexerKeyword textClassTags[] = {
{ "defaultfont", TC_DEFAULTFONT },
{ "defaultmodule", TC_DEFAULTMODULE },
{ "defaultstyle", TC_DEFAULTSTYLE },
{ "docbookforceabstract", TC_DOCBOOKFORCEABSTRACT },
{ "docbookroot", TC_DOCBOOKROOT },
{ "excludesmodule", TC_EXCLUDESMODULE },
{ "float", TC_FLOAT },
{ "format", TC_FORMAT },
@ -868,10 +872,20 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
error = !readOutlinerName(lexrc);
break;
case TC_TABLESTYLE:
case TC_TABLESTYLE:
lexrc.next();
tablestyle_ = rtrim(lexrc.getString());
break;
case TC_DOCBOOKROOT:
if (lexrc.next())
docbookroot_ = lexrc.getString();
break;
case TC_DOCBOOKFORCEABSTRACT:
if (lexrc.next())
docbookforceabstract_ = lexrc.getBool();
break;
} // end of switch
}
@ -994,7 +1008,6 @@ void TextClass::readClassOptions(Lexer & lexrc)
CO_PAGESIZE_FORMAT,
CO_PAGESTYLE,
CO_OTHER,
CO_HEADER,
CO_END
};
@ -1002,7 +1015,6 @@ void TextClass::readClassOptions(Lexer & lexrc)
{"end", CO_END },
{"fontsize", CO_FONTSIZE },
{"fontsizeformat", CO_FONTSIZE_FORMAT },
{"header", CO_HEADER },
{"other", CO_OTHER },
{"pagesize", CO_PAGESIZE },
{"pagesizeformat", CO_PAGESIZE_FORMAT },
@ -1048,10 +1060,6 @@ void TextClass::readClassOptions(Lexer & lexrc)
else
options_ += ',' + lexrc.getString();
break;
case CO_HEADER:
lexrc.next();
class_header_ = subst(lexrc.getString(), "&quot;", "\"");
break;
case CO_END:
getout = true;
break;
@ -1373,6 +1381,8 @@ bool TextClass::readFloat(Lexer & lexrc)
FT_HTMLSTYLE,
FT_HTMLATTR,
FT_HTMLTAG,
FT_DOCBOOKATTR,
FT_DOCBOOKTAG,
FT_LISTCOMMAND,
FT_REFPREFIX,
FT_ALLOWED_PLACEMENT,
@ -1386,6 +1396,8 @@ bool TextClass::readFloat(Lexer & lexrc)
{ "allowedplacement", FT_ALLOWED_PLACEMENT },
{ "allowssideways", FT_ALLOWS_SIDEWAYS },
{ "allowswide", FT_ALLOWS_WIDE },
{ "docbookattr", FT_DOCBOOKATTR },
{ "docbooktag", FT_DOCBOOKTAG },
{ "end", FT_END },
{ "extension", FT_EXT },
{ "guiname", FT_NAME },
@ -1410,6 +1422,8 @@ bool TextClass::readFloat(Lexer & lexrc)
string htmlattr;
docstring htmlstyle;
string htmltag;
string docbookattr;
string docbooktag;
string listname;
string listcommand;
string name;
@ -1523,6 +1537,14 @@ bool TextClass::readFloat(Lexer & lexrc)
lexrc.next();
htmltag = lexrc.getString();
break;
case FT_DOCBOOKATTR:
lexrc.next();
docbookattr = lexrc.getString();
break;
case FT_DOCBOOKTAG:
lexrc.next();
docbooktag = lexrc.getString();
break;
case FT_END:
getout = true;
break;
@ -1550,8 +1572,9 @@ bool TextClass::readFloat(Lexer & lexrc)
}
Floating fl(type, placement, ext, within, style, name,
listname, listcommand, refprefix, allowed_placement,
htmltag, htmlattr, htmlstyle, required, usesfloat,
ispredefined, allowswide, allowssideways);
htmltag, htmlattr, htmlstyle, docbooktag, docbookattr,
required, usesfloat, ispredefined, allowswide,
allowssideways);
floatlist_.newFloat(fl);
// each float has its own counter
counters_.newCounter(from_ascii(type), from_ascii(within),

View File

@ -303,8 +303,13 @@ protected:
docstring htmlpreamble_;
/// same, but specifically for CSS information
docstring htmlstyles_;
/// the paragraph style to use for TOCs, Bibliography, etc
/// the paragraph style to use for TOCs, bibliography, etc.
mutable docstring html_toc_section_;
/// root element when exporting as DocBook
std::string docbookroot_;
/// whether this root element does not accept text without a section (i.e. the first text that is met in LyX must
/// be considered as the abstract if this is true); this text must be output within <info> and <abstract>
bool docbookforceabstract_;
/// latex packages loaded by document class.
std::set<std::string> provides_;
/// latex packages requested by document class.
@ -484,6 +489,10 @@ public:
docstring const & htmlpreamble() const { return htmlpreamble_; }
///
docstring const & htmlstyles() const { return htmlstyles_; }
///
bool const & docbookforceabstract() const { return docbookforceabstract_; }
///
std::string const & docbookroot() const { return docbookroot_; }
/// Looks for the layout of "highest level", other than Part (or other
/// layouts with a negative toc number), for use in constructing TOCs and
/// similar information.

View File

@ -29,6 +29,7 @@
#include "FuncStatus.h"
#include "MetricsInfo.h"
#include "output_xhtml.h"
#include "xml.h"
#include "Text.h"
#include "TextClass.h"
#include "TocBackend.h"
@ -466,9 +467,9 @@ bool Inset::idxUpDown(Cursor &, bool) const
}
int Inset::docbook(odocstream &, OutputParams const &) const
void Inset::docbook(XMLStream & xs, OutputParams const &) const
{
return 0;
xs << "[[Inset: " << from_ascii(insetName(lyxCode())) << "]]";
}

View File

@ -341,7 +341,7 @@ public:
virtual int plaintext(odocstringstream &, OutputParams const &,
size_t max_length = INT_MAX) const = 0;
/// docbook output
virtual int docbook(odocstream & os, OutputParams const &) const;
virtual void docbook(XMLStream &, OutputParams const &) const;
/// XHTML output
/// the inset is expected to write XHTML to the XMLStream
/// \return any "deferred" material that should be written outside the

View File

@ -54,7 +54,7 @@ public:
///
int plaintext(odocstringstream &, OutputParams const &, size_t) const { return 0; }
///
int docbook(odocstream &, OutputParams const &) const { return 0; }
void docbook(XMLStream &, OutputParams const &) const { return; }
///
docstring xhtml(XMLStream &, OutputParams const &) const
{ return docstring(); }

View File

@ -27,7 +27,6 @@
#include "FuncStatus.h"
#include "LaTeXFeatures.h"
#include "output_latex.h"
#include "output_xhtml.h"
#include "xml.h"
#include "OutputParams.h"
#include "PDFOptions.h"
@ -44,6 +43,7 @@
#include "support/ExceptionMessage.h"
#include "support/FileNameList.h"
#include "support/filetools.h"
#include "support/regex.h"
#include "support/gettext.h"
#include "support/lstrings.h"
#include "support/os.h"
@ -51,6 +51,10 @@
#include "support/textutils.h"
#include <limits>
#include <map>
#include <utility>
#include <iostream>
using namespace std;
using namespace lyx::support;
@ -1075,6 +1079,342 @@ docstring InsetBibtex::xhtml(XMLStream & xs, OutputParams const &) const
}
void InsetBibtex::docbook(XMLStream & xs, OutputParams const &) const
{
BiblioInfo const & bibinfo = buffer().masterBibInfo();
bool const all_entries = getParam("btprint") == "btPrintAll";
vector<docstring> const & cites =
all_entries ? bibinfo.getKeys() : bibinfo.citedEntries();
docstring const reflabel = buffer().B_("References");
// Tell BiblioInfo our purpose (i.e. generate HTML rich text).
CiteItem ci;
ci.context = CiteItem::Export;
ci.richtext = true;
ci.max_key_size = UINT_MAX;
// Header for bibliography (title required).
xs << xml::StartTag("bibliography");
xs << xml::CR();
xs << xml::StartTag("title");
xs << reflabel;
xs << xml::EndTag("title") << xml::CR();
// Translation between keys in each entry and DocBook tags.
// IDs for publications; list: http://tdg.docbook.org/tdg/5.2/biblioid.html.
vector<pair<string, string>> biblioId = { // <bibtex, docbook>
make_pair("doi", "doi"),
make_pair("isbn", "isbn"),
make_pair("issn", "issn"),
make_pair("isrn", "isrn"),
make_pair("istc", "istc"),
make_pair("lccn", "libraryofcongress"),
make_pair("number", "pubsnumber"),
make_pair("url", "uri")
};
// Relations between documents.
vector<pair<string, string>> relations = { // <bibtex, docbook biblioset relation>
make_pair("journal", "journal"),
make_pair("booktitle", "book"),
make_pair("series", "series")
};
// Various things that do not fit DocBook.
vector<string> misc = { "language", "school", "note" };
// Store the mapping between BibTeX and DocBook.
map<string, string> toDocBookTag;
toDocBookTag["fullnames:author"] = "SPECIFIC"; // No direct translation to DocBook: <authorgroup>.
toDocBookTag["publisher"] = "SPECIFIC"; // No direct translation to DocBook: <publisher>.
toDocBookTag["address"] = "SPECIFIC"; // No direct translation to DocBook: <publisher>.
toDocBookTag["editor"] = "editor";
toDocBookTag["institution"] = "SPECIFIC"; // No direct translation to DocBook: <org>.
toDocBookTag["title"] = "title";
toDocBookTag["volume"] = "volumenum";
toDocBookTag["edition"] = "edition";
toDocBookTag["pages"] = "artpagenums";
toDocBookTag["abstract"] = "SPECIFIC"; // No direct translation to DocBook: <abstract>.
toDocBookTag["keywords"] = "SPECIFIC"; // No direct translation to DocBook: <keywordset>.
toDocBookTag["year"] = "SPECIFIC"; // No direct translation to DocBook: <pubdate>.
toDocBookTag["month"] = "SPECIFIC"; // No direct translation to DocBook: <pubdate>.
toDocBookTag["journal"] = "SPECIFIC"; // No direct translation to DocBook: <biblioset>.
toDocBookTag["booktitle"] = "SPECIFIC"; // No direct translation to DocBook: <biblioset>.
toDocBookTag["series"] = "SPECIFIC"; // No direct translation to DocBook: <biblioset>.
for (auto const & id: biblioId)
toDocBookTag[id.first] = "SPECIFIC"; // No direct translation to DocBook: <biblioid>.
for (auto const & id: relations)
toDocBookTag[id.first] = "SPECIFIC"; // No direct translation to DocBook: <biblioset>.
for (auto const & id: misc)
toDocBookTag[id] = "SPECIFIC"; // No direct translation to DocBook: <bibliomisc>.
// Loop over the entries. If there are no entries, add a comment to say so.
auto vit = cites.begin();
auto ven = cites.end();
if (vit == ven) {
xs << XMLStream::ESCAPE_NONE << "<!-- No entry in the bibliography. -->";
}
for (; vit != ven; ++vit) {
BiblioInfo::const_iterator const biit = bibinfo.find(*vit);
if (biit == bibinfo.end())
continue;
BibTeXInfo const & entry = biit->second;
string const attr = "xml:id=\"" + to_utf8(xml::cleanID(entry.key())) + "\"";
xs << xml::StartTag("biblioentry", attr);
xs << xml::CR();
// FIXME Right now, we are calling BibInfo::getInfo on the key,
// which will give us all the cross-referenced info. But for every
// entry, so there's a lot of repetition. This should be fixed.
// Parse the results of getInfo and emit the corresponding DocBook tags. Interesting pieces have the form
// "<span class="bib-STH">STH</span>", the rest of the text may be discarded.
// Could have written a DocBook version of expandFormat (that parses a citation into HTML), but it implements
// some kind of recursion. Still, a (static) conversion step between the citation format and DocBook would have
// been required. All in all, both codes approaches would have been similar, but this parsing allows relying
// on existing building blocks.
string html = to_utf8(bibinfo.getInfo(entry.key(), buffer(), ci));
regex tagRegex("<span class=\"bib-([^\"]*)\">([^<]*)</span>");
smatch match;
auto tagIt = std::sregex_iterator(html.cbegin(), html.cend(), tagRegex, regex_constants::match_default);
auto tagEnd = std::sregex_iterator();
map<string, string> delayedTags;
// Read all tags from HTML and convert those that have a 1:1 matching.
while (tagIt != tagEnd) {
string tag = tagIt->str(); // regex_match cannot work with temporary strings.
++tagIt;
std::regex_match(tag, match, tagRegex);
if (toDocBookTag.find(match[1]) == toDocBookTag.end()) {
LYXERR0("The BibTeX field " << match[1].str() << " is unknown.");
xs << XMLStream::ESCAPE_NONE << from_utf8("<!-- Output Error: The BibTeX field " + match[1].str() + " is unknown -->\n");
continue;
}
if (toDocBookTag[match[1]] == "SPECIFIC") {
delayedTags[match[1]] = match[2];
} else {
xs << xml::StartTag(toDocBookTag[match[1]]);
xs << from_utf8(match[2].str());
xs << xml::EndTag(toDocBookTag[match[1]]);
}
}
// Type of document (book, journal paper, etc.).
xs << xml::StartTag("bibliomisc", "role=\"type\"");
xs << entry.entryType();
xs << xml::EndTag("bibliomisc");
xs << xml::CR();
// Handle tags that have complex transformations.
if (! delayedTags.empty()) {
unsigned long remainingTags = delayedTags.size(); // Used as a workaround. With GCC 7, when erasing all
// elements one by one, some elements may still pop in later on (even though they were deleted previously).
auto hasTag = [&delayedTags](string key) { return delayedTags.find(key) != delayedTags.end(); };
auto getTag = [&delayedTags](string key) { return from_utf8(delayedTags[key]); };
auto eraseTag = [&delayedTags, &remainingTags](string key) {
remainingTags -= 1;
delayedTags.erase(key);
};
// Notes on order of checks.
// - address goes with publisher if there is one, so check this first. Otherwise, the address goes with
// the entry without other details.
// <publisher>
if (hasTag("publisher")) {
xs << xml::StartTag("publisher");
xs << xml::CR();
xs << xml::StartTag("publishername");
xs << getTag("publisher");
xs << xml::EndTag("publishername");
xs << xml::CR();
if (hasTag("address")) {
xs << xml::StartTag("address");
xs << getTag("address");
xs << xml::EndTag("address");
eraseTag("address");
}
xs << xml::EndTag("publisher");
xs << xml::CR();
eraseTag("publisher");
}
if (hasTag("address")) {
xs << xml::StartTag("address");
xs << getTag("address");
xs << xml::EndTag("address");
eraseTag("address");
}
// <keywordset>
if (hasTag("keywords")) {
// Split the keywords on comma.
docstring keywordSet = getTag("keywords");
vector<docstring> keywords;
if (keywordSet.find(from_utf8(",")) == string::npos) {
keywords = { keywordSet };
} else {
size_t pos = 0;
while ((pos = keywordSet.find(from_utf8(","))) != string::npos) {
keywords.push_back(keywordSet.substr(0, pos));
keywordSet.erase(0, pos + 1);
}
keywords.push_back(keywordSet);
}
xs << xml::StartTag("keywordset") << xml::CR();
for (auto & kw: keywords) {
kw.erase(kw.begin(), std::find_if(kw.begin(), kw.end(),
[](int c) {return !std::isspace(c);}));
xs << xml::StartTag("keyword");
xs << kw;
xs << xml::EndTag("keyword");
xs << xml::CR();
}
xs << xml::EndTag("keywordset") << xml::CR();
eraseTag("keywords");
}
// <copyright>
// Example: http://tdg.docbook.org/tdg/5.1/biblioset.html
if (hasTag("year")) {
docstring value = getTag("year");
eraseTag("year");
// Follow xsd:gYearMonth format (http://books.xmlschemata.org/relaxng/ch19-77135.html).
if (hasTag("month")) {
value += "-" + getTag("month");
eraseTag("month");
}
xs << xml::StartTag("pubdate");
xs << value;
xs << xml::EndTag("pubdate");
xs << xml::CR();
}
// <institution>
if (hasTag("institution")) {
xs << xml::StartTag("org");
xs << xml::CR();
xs << xml::StartTag("orgname");
xs << getTag("institution");
xs << xml::EndTag("orgname");
xs << xml::CR();
xs << xml::EndTag("org");
xs << xml::CR();
eraseTag("institution");
}
// <biblioset>
// Example: http://tdg.docbook.org/tdg/5.1/biblioset.html
for (auto const & id: relations) {
if (hasTag(id.first)) {
xs << xml::StartTag("biblioset", "relation=\"" + id.second + "\"");
xs << xml::CR();
xs << xml::StartTag("title");
xs << getTag(id.first);
xs << xml::EndTag("title");
xs << xml::CR();
xs << xml::EndTag("biblioset");
xs << xml::CR();
eraseTag(id.first);
}
}
// <authorgroup>
// Example: http://tdg.docbook.org/tdg/5.1/authorgroup.html
if (hasTag("fullnames:author")) {
// Perform full parsing of the BibTeX string, dealing with the many corner cases that might
// be encountered.
authorsToDocBookAuthorGroup(getTag("fullnames:author"), xs, buffer());
eraseTag("fullnames:author");
}
// <abstract>
if (hasTag("abstract")) {
// Split the paragraphs on new line.
docstring abstract = getTag("abstract");
vector<docstring> paragraphs;
if (abstract.find(from_utf8("\n")) == string::npos) {
paragraphs = { abstract };
} else {
size_t pos = 0;
while ((pos = abstract.find(from_utf8(","))) != string::npos) {
paragraphs.push_back(abstract.substr(0, pos));
abstract.erase(0, pos + 1);
}
paragraphs.push_back(abstract);
}
xs << xml::StartTag("abstract");
xs << xml::CR();
for (auto const & para: paragraphs) {
if (para.empty())
continue;
xs << xml::StartTag("para");
xs << para;
xs << xml::EndTag("para");
}
xs << xml::CR();
xs << xml::EndTag("abstract");
xs << xml::CR();
eraseTag("abstract");
}
// <biblioid>
for (auto const & id: biblioId) {
if (hasTag(id.first)) {
xs << xml::StartTag("biblioid", "class=\"" + id.second + "\"");
xs << getTag(id.first);
xs << xml::EndTag("biblioid");
xs << xml::CR();
eraseTag(id.first);
}
}
// <bibliomisc>
for (auto const & id: misc) {
if (hasTag(id)) {
xs << xml::StartTag("bibliomisc", "role=\"" + id + "\"");
xs << getTag(id);
xs << xml::EndTag("bibliomisc");
xs << xml::CR();
eraseTag(id);
}
}
// After all tags are processed, check for errors.
if (remainingTags > 0) {
LYXERR0("Still delayed tags not yet handled.");
xs << XMLStream::ESCAPE_NONE << from_utf8("<!-- Output Error: still delayed tags not yet handled.\n");
for (auto const & item: delayedTags) {
xs << from_utf8(" " + item.first + ": " + item.second + "\n");
}
xs << XMLStream::ESCAPE_NONE << from_utf8(" -->\n");
}
}
xs << xml::EndTag("biblioentry");
xs << xml::CR();
}
// Footer for bibliography.
xs << xml::EndTag("bibliography");
}
void InsetBibtex::write(ostream & os) const
{
params().Write(os, &buffer());

View File

@ -66,6 +66,8 @@ public:
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///
void docbook(XMLStream &, OutputParams const &) const;
///
std::string contextMenuName() const;
//@}

View File

@ -715,9 +715,9 @@ int InsetBox::plaintext(odocstringstream & os,
}
int InsetBox::docbook(odocstream & os, OutputParams const & runparams) const
void InsetBox::docbook(XMLStream & xs, OutputParams const & runparams) const
{
return InsetText::docbook(os, runparams);
InsetText::docbook(xs, runparams);
}

View File

@ -133,7 +133,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -24,6 +24,7 @@
#include "Lexer.h"
#include "LyX.h"
#include "OutputParams.h"
#include "output_docbook.h"
#include "output_xhtml.h"
#include "TextClass.h"
#include "TocBackend.h"
@ -329,10 +330,14 @@ int InsetBranch::plaintext(odocstringstream & os,
}
int InsetBranch::docbook(odocstream & os,
OutputParams const & runparams) const
void InsetBranch::docbook(XMLStream & xs, OutputParams const & runparams) const
{
return producesOutput() ? InsetText::docbook(os, runparams) : 0;
if (producesOutput()) {
OutputParams rp = runparams;
rp.par_begin = 0;
rp.par_end = text().paragraphs().size();
docbookParagraphs(text(), buffer(), xs, rp);
}
}

View File

@ -76,7 +76,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -27,6 +27,7 @@
#include "Language.h"
#include "LyXRC.h"
#include "MetricsInfo.h"
#include "xml.h"
#include "output_latex.h"
#include "output_xhtml.h"
#include "OutputParams.h"
@ -291,14 +292,9 @@ int InsetCaption::plaintext(odocstringstream & os,
}
int InsetCaption::docbook(odocstream & os,
OutputParams const & runparams) const
void InsetCaption::docbook(XMLStream &, OutputParams const &) const
{
int ret;
os << "<title>";
ret = InsetText::docbook(os, runparams);
os << "</title>\n";
return ret;
// This function should never be called (rather InsetFloat::docbook, the titles should be skipped in floats).
}
@ -364,6 +360,19 @@ int InsetCaption::getCaptionAsPlaintext(odocstream & os,
}
void InsetCaption::getCaptionAsDocBook(XMLStream & xs,
OutputParams const & runparams) const
{
if (runparams.docbook_in_float)
return;
// Ignore full_label_, as the DocBook processor will deal with the numbering.
InsetText::XHTMLOptions const opts =
InsetText::WriteLabel | InsetText::WriteInnerTag;
InsetText::docbook(xs, runparams, opts);
}
docstring InsetCaption::getCaptionAsHTML(XMLStream & xs,
OutputParams const & runparams) const
{

View File

@ -30,6 +30,8 @@ public:
void getArgument(otexstream & os, OutputParams const &) const;
/// return the caption text
int getCaptionAsPlaintext(odocstream & os, OutputParams const &) const;
/// write the caption text as DocBook in os
void getCaptionAsDocBook(XMLStream & os, OutputParams const &) const;
/// return the caption text as HTML
docstring getCaptionAsHTML(XMLStream & os, OutputParams const &) const;
///
@ -76,7 +78,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream & os, OutputParams const & runparams) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream & os, OutputParams const & runparams) const;
///

View File

@ -80,6 +80,19 @@ docstring InsetCaptionable::getCaptionText(OutputParams const & runparams) const
}
docstring InsetCaptionable::getCaptionDocBook(OutputParams const & runparams) const
{
InsetCaption const * ins = getCaptionInset();
if (ins == nullptr)
return docstring();
odocstringstream ods;
XMLStream xs(ods);
ins->getCaptionAsDocBook(xs, runparams);
return ods.str();
}
docstring InsetCaptionable::getCaptionHTML(OutputParams const & runparams) const
{
InsetCaption const * ins = getCaptionInset();

View File

@ -38,6 +38,8 @@ protected:
///
docstring getCaptionHTML(OutputParams const &) const;
///
docstring getCaptionDocBook(OutputParams const &) const;
///
virtual void setCaptionType(std::string const & type);
/// are our captions subcaptions?
virtual bool hasSubCaptions(ParIterator const &) const { return false; }

View File

@ -24,6 +24,7 @@
#include "FuncStatus.h"
#include "LaTeXFeatures.h"
#include "output_xhtml.h"
#include <output_docbook.h>
#include "ParIterator.h"
#include "texstream.h"
#include "TocBackend.h"
@ -545,19 +546,33 @@ static docstring const cleanupWhitespace(docstring const & citelist)
}
int InsetCitation::docbook(odocstream & os, OutputParams const &) const
void InsetCitation::docbook(XMLStream & xs, OutputParams const &) const
{
os << from_ascii("<citation>")
<< cleanupWhitespace(getParam("key"))
<< from_ascii("</citation>");
return 0;
if (getCmdName() == "nocite")
return;
// Split the different citations (on ","), so that one tag can be output for each of them.
string citations = to_utf8(getParam("key")); // Citation strings are not supposed to be too fancy.
if (citations.find(',') == string::npos) {
xs << xml::CompTag("biblioref", "endterm=\"" + citations + "\"");
} else {
size_t pos = 0;
while (pos != string::npos) {
pos = citations.find(',');
xs << xml::CompTag("biblioref", "endterm=\"" + citations.substr(0, pos) + "\"");
citations.erase(0, pos + 1);
if (pos != string::npos) {
xs << ", ";
}
}
}
}
docstring InsetCitation::xhtml(XMLStream & xs, OutputParams const &) const
{
string const & cmd = getCmdName();
if (cmd == "nocite")
if (getCmdName() == "nocite")
return docstring();
// have to output this raw, because generateLabel() will include tags

View File

@ -56,7 +56,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -162,9 +162,9 @@ int InsetCommand::plaintext(odocstringstream & os,
}
int InsetCommand::docbook(odocstream &, OutputParams const &) const
void InsetCommand::docbook(XMLStream &, OutputParams const &) const
{
return 0;
return;
}

View File

@ -89,7 +89,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const & runparams) const;
void docbook(XMLStream &, OutputParams const &) const;
///
void validate(LaTeXFeatures & features) const;
///

View File

@ -184,13 +184,12 @@ void InsetCounter::trackCounters(string const & cmd) const
}
}
int InsetCounter::docbook(odocstream &, OutputParams const &) const
void InsetCounter::docbook(odocstream &, OutputParams const &) const
{
// Here, we need to track counter values ourselves,
// since unlike in the LaTeX case, there is no external
// mechanism for doing that.
trackCounters(getCmdName());
return 0;
}

View File

@ -39,7 +39,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(odocstream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -25,6 +25,7 @@
#include "Lexer.h"
#include "LyXAction.h"
#include "OutputParams.h"
#include "xml.h"
#include "ParagraphParameters.h"
#include "Paragraph.h"
@ -90,25 +91,24 @@ int InsetERT::plaintext(odocstringstream & os,
}
int InsetERT::docbook(odocstream & os, OutputParams const &) const
void InsetERT::docbook(XMLStream & xs, OutputParams const &) const
{
// FIXME can we do the same thing here as for LaTeX?
ParagraphList::const_iterator par = paragraphs().begin();
ParagraphList::const_iterator end = paragraphs().end();
int lines = 0;
xs << XMLStream::ESCAPE_NONE << "<!-- ";
while (par != end) {
pos_type siz = par->size();
for (pos_type i = 0; i < siz; ++i)
os.put(par->getChar(i));
for (pos_type i = 0; i < siz; ++i) {
xs << par->getChar(i);
}
++par;
if (par != end) {
os << "\n";
++lines;
xs << "\n";
}
}
return lines;
xs << XMLStream::ESCAPE_NONE << " -->";
}

View File

@ -52,7 +52,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -770,42 +770,35 @@ int InsetExternal::plaintext(odocstringstream & os,
}
int InsetExternal::docbook(odocstream & os,
OutputParams const & runparams) const
void InsetExternal::generateXML(XMLStream & xs, OutputParams const & runparams, std::string const & format) const
{
bool const external_in_tmpdir = !runparams.nice;
bool const dryrun = runparams.dryrun || runparams.inComment;
odocstringstream ods;
otexstream ots(ods);
external::RetVal retval =
external::writeExternal(params_, "DocBook", buffer(), ots,
*(runparams.exportdata), external_in_tmpdir, dryrun);
if (retval == external::KILLED) {
LYXERR0("External template preparation killed.");
if (buffer().isClone() && buffer().isExporting())
throw ConversionException();
}
os << ods.str();
return int(count(ods.str().begin(), ods.str().end(), '\n'));
}
docstring InsetExternal::xhtml(XMLStream & xs,
OutputParams const & runparams) const
{
bool const external_in_tmpdir = !runparams.nice;
bool const dryrun = runparams.dryrun || runparams.inComment;
odocstringstream ods;
otexstream ots(ods);
external::RetVal retval =
external::writeExternal(params_, "XHTML", buffer(), ots,
*(runparams.exportdata), external_in_tmpdir, dryrun);
external::writeExternal(params_, format, buffer(), ots,
*(runparams.exportdata), external_in_tmpdir, dryrun);
if (retval == external::KILLED) {
LYXERR0("External template preparation killed.");
if (buffer().isClone() && buffer().isExporting())
throw ConversionException();
}
xs << XMLStream::ESCAPE_NONE << ods.str();
}
void InsetExternal::docbook(XMLStream & xs,
OutputParams const & runparams) const
{
generateXML(xs, runparams, "DocBook");
}
docstring InsetExternal::xhtml(XMLStream & xs,
OutputParams const & runparams) const
{
generateXML(xs, runparams, "XHTML");
return docstring();
}

View File

@ -146,7 +146,9 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void generateXML(XMLStream &, OutputParams const &, std::string const &) const;
///
void docbook(XMLStream &, OutputParams const &) const;
/// For now, this does nothing. Someone who knows about this
/// should see what needs doing for XHTML output.
docstring xhtml(XMLStream &, OutputParams const &) const;

View File

@ -10,11 +10,17 @@
* Full author contact details are available in file CREDITS.
*/
#include <typeinfo>
#include <config.h>
#include <output_docbook.h>
#include <xml.h>
#include "InsetFloat.h"
#include "InsetBox.h"
#include "InsetCaption.h"
#include "InsetFloat.h"
#include "InsetGraphics.h"
#include "InsetLabel.h"
#include "Buffer.h"
#include "BufferParams.h"
@ -480,15 +486,193 @@ int InsetFloat::plaintext(odocstringstream & os, OutputParams const & runparams,
}
int InsetFloat::docbook(odocstream & os, OutputParams const & runparams) const
std::vector<const InsetBox *> findSubfiguresInParagraph(const Paragraph &par)
{
// FIXME Implement subfloat!
// FIXME UNICODE
os << '<' << from_ascii(params_.type) << '>';
int const i = InsetText::docbook(os, runparams);
os << "</" << from_ascii(params_.type) << '>';
return i;
// Don't make the hypothesis that all subfigures are in the same paragraph.
// Similarly, there may be several subfigures in the same paragraph (most likely case, based on the documentation).
// Any box is considered as a subfigure, even though the most likely case is \minipage.
std::vector<const InsetBox *> subfigures;
for (pos_type pos = 0; pos < par.size(); ++pos) {
const Inset *inset = par.getInset(pos);
if (!inset)
continue;
if (const auto box = dynamic_cast<const InsetBox *>(inset))
subfigures.push_back(box);
}
return subfigures;
}
const InsetLabel* findLabelInParagraph(const Paragraph &par)
{
for (pos_type pos = 0; pos < par.size(); ++pos) {
// If this inset is a subfigure, skip it.
const Inset *inset = par.getInset(pos);
if (dynamic_cast<const InsetBox *>(inset)) {
continue;
}
// Maybe an inset is directly a label, in which case no more work is needed.
if (inset && dynamic_cast<const InsetLabel *>(inset))
return dynamic_cast<const InsetLabel *>(inset);
// More likely, the label is hidden in an inset of a paragraph (only if a subtype of InsetText).
if (!dynamic_cast<const InsetText *>(inset))
continue;
auto insetAsText = dynamic_cast<const InsetText *>(inset);
auto itIn = insetAsText->paragraphs().begin();
auto endIn = insetAsText->paragraphs().end();
for (; itIn != endIn; ++itIn) {
for (pos_type posIn = 0; posIn < itIn->size(); ++posIn) {
const Inset *insetIn = itIn->getInset(posIn);
if (insetIn && dynamic_cast<const InsetLabel *>(insetIn)) {
return dynamic_cast<const InsetLabel *>(insetIn);
}
}
}
// Obviously, this solution does not scale with more levels of paragraphs-insets, but this should be enough.
}
return nullptr;
}
const InsetCaption* findCaptionInParagraph(const Paragraph &par)
{
// Don't dive too deep, otherwise, this could be a subfigure caption.
for (pos_type pos = 0; pos < par.size(); ++pos) {
// If this inset is a subfigure, skip it.
const Inset *inset = par.getInset(pos);
if (dynamic_cast<const InsetBox *>(inset))
continue;
if (inset && dynamic_cast<const InsetCaption *>(inset))
return dynamic_cast<const InsetCaption *>(inset);
}
return nullptr;
}
void InsetFloat::docbook(XMLStream & xs, OutputParams const & runparams) const
{
// Determine whether the float has a title or not. For this, iterate through the paragraphs and look
// for an InsetCaption. Do the same for labels and subfigures.
// The caption and the label for each subfigure is handled by recursive calls.
const InsetCaption* caption = nullptr;
const InsetLabel* label = nullptr;
std::vector<const InsetBox *> subfigures;
auto end = paragraphs().end();
for (auto it = paragraphs().begin(); it != end; ++it) {
std::vector<const InsetBox *> foundSubfigures = findSubfiguresInParagraph(*it);
if (!foundSubfigures.empty()) {
subfigures.reserve(subfigures.size() + foundSubfigures.size());
subfigures.insert(subfigures.end(), foundSubfigures.begin(), foundSubfigures.end());
}
if (!caption)
caption = findCaptionInParagraph(*it);
if (!label)
label = findLabelInParagraph(*it);
}
// Gather a few things from global environment that are shared between all following cases.
FloatList const &floats = buffer().params().documentClass().floats();
Floating const &ftype = floats.getType(params_.type);
string const &titleTag = ftype.docbookCaption();
// Ensure there is no label output, it is supposed to be handled as xml:id.
OutputParams rpNoLabel = runparams;
if (label)
rpNoLabel.docbook_anchors_to_ignore.emplace(label->screenLabel());
// Ensure the float does not output its caption, as it is handled here (DocBook mandates a specific place for
// captions, they cannot appear at the end of the float, albeit LyX is happy with that).
OutputParams rpNoTitle = runparams;
rpNoTitle.docbook_in_float = true;
// Deal with subfigures.
if (!subfigures.empty()) {
// First, open the formal group.
docstring attr = docstring();
if (label)
attr += "xml:id=\"" + xml::cleanID(label->screenLabel()) + "\"";
xs.startDivision(false);
xs << xml::StartTag("formalgroup", attr);
xs << xml::CR();
xs << xml::StartTag("title", attr);
if (caption) {
caption->getCaptionAsDocBook(xs, rpNoLabel);
} else {
xs << "No caption";
// No caption has been detected, but this tag is required for the document to be valid DocBook.
}
xs << xml::EndTag("title");
xs << xml::CR();
// Deal with each subfigure individually. This should also deal with their caption and their label.
// This should be a recursive call to InsetFloat.
for (const InsetBox *subfigure: subfigures) {
// If there is no InsetFloat in the paragraphs, output a warning.
bool foundInsetFloat = false;
for (auto it = subfigure->paragraphs().begin(); it != subfigure->paragraphs().end(); ++it) {
for (pos_type posIn = 0; posIn < it->size(); ++posIn) {
const Inset *inset = it->getInset(posIn);
if (inset && dynamic_cast<const InsetFloat*>(inset)) {
foundInsetFloat = true;
break;
}
}
if (foundInsetFloat)
break;
}
if (!foundInsetFloat)
xs << XMLStream::ESCAPE_NONE << "Error: no float found in the box. "
"To use subfigures in DocBook, elements must be wrapped in a float "
"inset and have a title/caption.";
// TODO: could also output a table, that would ensure that the document is correct and *displays* correctly (but without the right semantics), instead of just an error.
// Finally, recurse.
subfigure->docbook(xs, runparams);
}
// Every subfigure is done: close the formal group.
xs << xml::EndTag("formalgroup");
xs << xml::CR();
xs.endDivision();
}
// Here, ensured not to have subfigures.
// Organisation: <float> <title if any/> <contents without title/> </float>
docstring attr = docstring();
if (label)
attr += "xml:id=\"" + xml::cleanID(label->screenLabel()) + "\"";
if (!ftype.docbookAttr().empty()) {
if (!attr.empty())
attr += " ";
attr += from_utf8(ftype.docbookAttr());
}
xs << xml::StartTag(ftype.docbookTag(caption != nullptr), attr);
xs << xml::CR();
if (caption != nullptr) {
xs << xml::StartTag(titleTag);
caption->getCaptionAsDocBook(xs, rpNoLabel);
xs << xml::EndTag(titleTag);
xs << xml::CR();
}
InsetText::docbook(xs, rpNoTitle);
xs << xml::EndTag(ftype.docbookTag(caption != nullptr));
xs << xml::CR();
}

View File

@ -99,7 +99,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -40,7 +40,7 @@ public:
///
void latex(otexstream &, OutputParams const &) const;
///
int docbook(odocstream &, OutputParams const &) const { return 0; }
void docbook(XMLStream &, OutputParams const &) const { return; }
///
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;

View File

@ -10,6 +10,7 @@
*/
#include <config.h>
#include <output_docbook.h>
#include "InsetFoot.h"
#include "InsetBox.h"
@ -122,13 +123,12 @@ int InsetFoot::plaintext(odocstringstream & os,
}
int InsetFoot::docbook(odocstream & os, OutputParams const & runparams) const
void InsetFoot::docbook(XMLStream & xs, OutputParams const & runparams) const
{
os << "<footnote>";
int const i = InsetText::docbook(os, runparams);
os << "</footnote>";
return i;
OutputParams rp = runparams;
rp.docbook_force_pars = true;
rp.docbook_in_par = false;
InsetText::docbook(xs, rp);
}

View File

@ -35,7 +35,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
void validate(LaTeXFeatures & features) const;
/// Update the counters of this inset and of its contents

View File

@ -95,7 +95,7 @@ TODO
#include <algorithm>
#include <sstream>
#include <tuple>
#include <output_docbook.h>
using namespace std;
using namespace lyx::support;
@ -125,8 +125,9 @@ string findTargetFormat(string const & format, OutputParams const & runparams)
// Convert everything else to png
return "png";
}
// for HTML, we leave the known formats and otherwise convert to png
if (runparams.flavor == OutputParams::HTML) {
// for HTML and DocBook, we leave the known formats and otherwise convert to png
if (runparams.flavor == OutputParams::HTML || runparams.flavor == OutputParams::DOCBOOK5) {
Format const * const f = theFormats().getFormat(format);
// Convert vector graphics to svg
if (f && f->vectorFormat() && theConverters().isReachable(format, "svg"))
@ -522,7 +523,6 @@ docstring InsetGraphics::createDocBookAttributes() const
}
}
if (!params().special.empty())
options << from_ascii(params().special) << " ";
@ -935,62 +935,24 @@ int InsetGraphics::plaintext(odocstringstream & os,
}
static int writeImageObject(char const * format, odocstream & os,
OutputParams const & runparams, docstring const & graphic_label,
docstring const & attributes)
{
if (runparams.flavor != OutputParams::DOCBOOK5)
os << "<![ %output.print." << format
<< "; [" << endl;
os <<"<imageobject><imagedata fileref=\"&"
<< graphic_label
<< ";."
<< format
<< "\" "
<< attributes;
if (runparams.flavor == OutputParams::DOCBOOK5)
os << " role=\"" << format << "\"/>" ;
else
os << " format=\"" << format << "\">" ;
os << "</imageobject>";
if (runparams.flavor != OutputParams::DOCBOOK5)
os << endl << "]]>" ;
return runparams.flavor == OutputParams::DOCBOOK5 ? 0 : 2;
}
// For explanation on inserting graphics into DocBook checkout:
// http://en.tldp.org/LDP/LDP-Author-Guide/html/inserting-pictures.html
// See also the docbook guide at http://www.docbook.org/
int InsetGraphics::docbook(odocstream & os,
OutputParams const & runparams) const
void InsetGraphics::docbook(XMLStream & xs, OutputParams const & runparams) const
{
// In DocBook v5.0, the graphic tag will be eliminated from DocBook, will
// need to switch to MediaObject. However, for now this is sufficient and
// easier to use.
if (runparams.flavor == OutputParams::DOCBOOK5)
runparams.exportdata->addExternalFile("docbook-xml",
params().filename);
else
runparams.exportdata->addExternalFile("docbook",
params().filename);
string fn = params().filename.relFileName(runparams.export_folder);
string tag = runparams.docbook_in_float ? "mediaobject" : "inlinemediaobject";
os << "<inlinemediaobject>";
int r = 0;
docstring attributes = createDocBookAttributes();
r += writeImageObject("png", os, runparams, graphic_label, attributes);
r += writeImageObject("pdf", os, runparams, graphic_label, attributes);
r += writeImageObject("eps", os, runparams, graphic_label, attributes);
r += writeImageObject("bmp", os, runparams, graphic_label, attributes);
os << "</inlinemediaobject>";
return r;
xs << xml::StartTag(tag);
xs << xml::CR();
xs << xml::StartTag("imageobject");
xs << xml::CR();
xs << xml::CompTag("imagedata", "fileref=\"" + fn + "\" " + to_utf8(createDocBookAttributes()));
xs << xml::CR();
xs << xml::EndTag("imageobject");
xs << xml::CR();
xs << xml::EndTag(tag);
xs << xml::CR();
}

View File

@ -78,7 +78,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream & os, OutputParams const &) const;
/** Tell LyX what the latex features you need i.e. what latex packages

View File

@ -10,6 +10,7 @@
*/
#include <config.h>
#include <output_docbook.h>
#include "InsetHyperlink.h"
@ -213,14 +214,11 @@ int InsetHyperlink::plaintext(odocstringstream & os,
}
int InsetHyperlink::docbook(odocstream & os, OutputParams const &) const
void InsetHyperlink::docbook(XMLStream & xs, OutputParams const &) const
{
os << "<ulink url=\""
<< subst(getParam("target"), from_ascii("&"), from_ascii("&amp;"))
<< "\">"
<< xml::escapeString(getParam("name"))
<< "</ulink>";
return 0;
xs << xml::StartTag("link", "xlink:href=\"" + subst(getParam("target"), from_ascii("&"), from_ascii("&amp;")) + "\"");
xs << xml::escapeString(getParam("name"));
xs << xml::EndTag("link");
}

View File

@ -51,7 +51,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
//@}

View File

@ -233,6 +233,14 @@ void InsetIPA::latex(otexstream & os, OutputParams const & runparams_in) const
}
void InsetIPA::docbook(XMLStream & xs, OutputParams const & runparams) const
{
OutputParams rp(runparams);
rp.inIPA = true;
InsetText::docbook(xs, rp);
}
docstring InsetIPA::xhtml(XMLStream & xs, OutputParams const & runparams_in) const
{
OutputParams runparams(runparams_in);

View File

@ -77,6 +77,8 @@ public:
///
void latex(otexstream &, OutputParams const &) const;
///
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream & xs, OutputParams const &) const;
///
void validate(LaTeXFeatures & features) const;

View File

@ -22,7 +22,7 @@
#include "LaTeXFeatures.h"
#include "Lexer.h"
#include "MetricsInfo.h"
#include "output_xhtml.h"
#include "xml.h"
#include "texstream.h"
#include "frontends/FontMetrics.h"
@ -305,10 +305,22 @@ int InsetIPADeco::plaintext(odocstringstream & os,
}
int InsetIPADeco::docbook(odocstream & os, OutputParams const & runparams) const
void InsetIPADeco::docbook(XMLStream & xs, OutputParams const & runparams) const
{
// FIXME: Any docbook option here?
return InsetCollapsible::docbook(os, runparams);
// The special combining character must be put in the middle, between the two other characters.
// It will not work if there is anything else than two pure characters, so going back to plaintext.
odocstringstream ods;
int h = (int)(InsetText::plaintext(ods, runparams) / 2);
docstring result = ods.str();
docstring const before = result.substr(0, h);
docstring const after = result.substr(h, result.size());
xs << XMLStream::ESCAPE_NONE << before;
if (params_.type == InsetIPADecoParams::Toptiebar)
xs << XMLStream::ESCAPE_NONE << "&#x0361;";
else if (params_.type == InsetIPADecoParams::Bottomtiebar)
xs << XMLStream::ESCAPE_NONE << "&#x035c;";
xs << XMLStream::ESCAPE_NONE << after;
}
@ -540,19 +552,31 @@ int InsetIPAChar::plaintext(odocstringstream & os, OutputParams const &, size_t)
}
int InsetIPAChar::docbook(odocstream & /*os*/, OutputParams const &) const
void InsetIPAChar::docbook(XMLStream & xs, OutputParams const &) const
{
switch (kind_) {
case TONE_FALLING:
case TONE_RISING:
case TONE_HIGH_RISING:
case TONE_LOW_RISING:
case TONE_HIGH_RISING_FALLING:
// FIXME
LYXERR0("IPA tone macros not yet implemented with DocBook!");
break;
}
return 0;
switch (kind_) {
case TONE_FALLING:
xs << XMLStream::ESCAPE_NONE << "&#x2e5;";
xs << XMLStream::ESCAPE_NONE << "&#x2e9;";
break;
case TONE_RISING:
xs << XMLStream::ESCAPE_NONE << "&#x2e9;";
xs << XMLStream::ESCAPE_NONE << "&#x2e5;";
break;
case TONE_HIGH_RISING:
xs << XMLStream::ESCAPE_NONE << "&#x2e7;";
xs << XMLStream::ESCAPE_NONE << "&#x2e5;";
break;
case TONE_LOW_RISING:
xs << XMLStream::ESCAPE_NONE << "&#x2e9;";
xs << XMLStream::ESCAPE_NONE << "&#x2e7;";
break;
case TONE_HIGH_RISING_FALLING:
xs << XMLStream::ESCAPE_NONE << "&#x2e8;";
xs << XMLStream::ESCAPE_NONE << "&#x2e5;";
xs << XMLStream::ESCAPE_NONE << "&#x2e8;";
break;
}
}

View File

@ -79,7 +79,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///
@ -150,7 +150,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -987,12 +987,11 @@ docstring InsetInclude::xhtml(XMLStream & xs, OutputParams const & rp) const
op.par_begin = 0;
op.par_end = 0;
ibuf->writeLyXHTMLSource(xs.os(), op, Buffer::IncludedFile);
} else
xs << XMLStream::ESCAPE_NONE
<< "<!-- Included file: "
<< from_utf8(included_file.absFileName())
<< XMLStream::ESCAPE_NONE
<< " -->";
} else {
xs << XMLStream::ESCAPE_NONE << "<!-- Included file: ";
xs << from_utf8(included_file.absFileName());
xs << XMLStream::ESCAPE_NONE << " -->";
}
return docstring();
}
@ -1037,56 +1036,68 @@ int InsetInclude::plaintext(odocstringstream & os,
}
int InsetInclude::docbook(odocstream & os, OutputParams const & runparams) const
void InsetInclude::docbook(XMLStream & xs, OutputParams const & rp) const
{
string incfile = ltrim(to_utf8(params()["filename"]));
if (rp.inComment)
return;
// Do nothing if no file name has been specified
if (incfile.empty())
return 0;
// For verbatim and listings, we just include the contents of the file as-is.
bool const verbatim = isVerbatim(params());
bool const listing = isListings(params());
if (listing || verbatim) {
if (listing)
xs << xml::StartTag("programlisting");
else if (verbatim)
xs << xml::StartTag("literallayout");
string const included_file = includedFileName(buffer(), params()).absFileName();
string exppath = incfile;
if (!runparams.export_folder.empty()) {
exppath = makeAbsPath(exppath, runparams.export_folder).realPath();
FileName(exppath).onlyPath().createPath();
// FIXME: We don't know the encoding of the file, default to UTF-8.
xs << includedFileName(buffer(), params()).fileContents("UTF-8");
if (listing)
xs << xml::EndTag("programlisting");
else if (verbatim)
xs << xml::EndTag("literallayout");
return;
}
// write it to a file (so far the complete file)
string const exportfile = changeExtension(exppath, ".sgml");
DocFileName writefile(changeExtension(included_file, ".sgml"));
Buffer * tmp = loadIfNeeded();
if (tmp) {
if (recursion_error_)
return 0;
string const mangled = writefile.mangledFileName();
writefile = makeAbsPath(mangled,
buffer().masterBuffer()->temppath());
if (!runparams.nice)
incfile = mangled;
LYXERR(Debug::LATEX, "incfile:" << incfile);
LYXERR(Debug::LATEX, "exportfile:" << exportfile);
LYXERR(Debug::LATEX, "writefile:" << writefile);
tmp->makeDocBookFile(writefile, runparams, Buffer::OnlyBody);
// We don't (yet) know how to Input or Include non-LyX files.
// (If we wanted to get really arcane, we could run some tex2html
// converter on the included file. But that's just masochistic.)
FileName const included_file = includedFileName(buffer(), params());
if (!isLyXFileName(included_file.absFileName())) {
if (!rp.silent)
frontend::Alert::warning(_("Unsupported Inclusion"),
bformat(_("LyX does not know how to include non-LyX files when "
"generating DocBook output. Offending file:\n%1$s"),
ltrim(params()["filename"])));
return;
}
runparams.exportdata->addExternalFile("docbook", writefile,
exportfile);
runparams.exportdata->addExternalFile("docbook-xml", writefile,
exportfile);
// In the other cases, we will generate the HTML and include it.
Buffer const * const ibuf = loadIfNeeded();
if (!ibuf)
return;
if (isVerbatim(params()) || isListings(params())) {
os << "<inlinegraphic fileref=\""
<< '&' << include_label << ';'
<< "\" format=\"linespecific\">";
if (recursion_error_)
return;
// are we generating only some paragraphs, or all of them?
bool const all_pars = !rp.dryrun ||
(rp.par_begin == 0 &&
rp.par_end == (int) buffer().text().paragraphs().size());
OutputParams op = rp;
if (all_pars) {
op.par_begin = 0;
op.par_end = 0;
ibuf->writeDocBookSource(xs.os(), op, Buffer::IncludedFile);
} else
os << '&' << include_label << ';';
return 0;
xs << XMLStream::ESCAPE_NONE
<< "<!-- Included file: "
<< from_utf8(included_file.absFileName())
<< XMLStream::ESCAPE_NONE
<< " -->";
}

View File

@ -94,7 +94,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -40,8 +40,11 @@
#include "frontends/alert.h"
#include <algorithm>
#include <set>
#include <ostream>
#include <QThreadStorage>
using namespace std;
using namespace lyx::support;
@ -182,12 +185,181 @@ void InsetIndex::latex(otexstream & ios, OutputParams const & runparams_in) cons
}
int InsetIndex::docbook(odocstream & os, OutputParams const & runparams) const
void InsetIndex::docbook(XMLStream & xs, OutputParams const & runparams) const
{
os << "<indexterm><primary>";
int const i = InsetText::docbook(os, runparams);
os << "</primary></indexterm>";
return i;
// Get the content of the inset as LaTeX, as some things may be encoded as ERT (like {}).
odocstringstream odss;
otexstream ots(odss);
InsetText::latex(ots, runparams);
docstring latexString = trim(odss.str());
// Check whether there are unsupported things.
if (latexString.find(from_utf8("@")) != latexString.npos) {
docstring error = from_utf8("Unsupported feature: an index entry contains an @. "
"Complete entry: \"") + latexString + from_utf8("\"");
LYXERR0(error);
xs << XMLStream::ESCAPE_NONE << (from_utf8("<!-- Output Error: ") + error + from_utf8(" -->\n"));
}
// Handle several indices.
docstring indexType = from_utf8("");
if (buffer().masterBuffer()->params().use_indices) {
indexType += " type=\"" + params_.index + "\"";
}
// Split the string into its main constituents: terms, and command (see, see also, range).
size_t positionVerticalBar = latexString.find(from_ascii("|")); // What comes before | is (sub)(sub)entries.
docstring indexTerms = latexString.substr(0, positionVerticalBar);
docstring command = latexString.substr(positionVerticalBar + 1);
// Handle primary, secondary, and tertiary terms (entries, subentries, and subsubentries, for LaTeX).
vector<docstring> terms = getVectorFromString(indexTerms, from_ascii("!"), false);
// Handle ranges. Happily, (| and |) can only be at the end of the string! However, | may be trapped by the
bool hasStartRange = latexString.find(from_ascii("|(")) != latexString.npos;
bool hasEndRange = latexString.find(from_ascii("|)")) != latexString.npos;
if (hasStartRange || hasEndRange) {
// Remove the ranges from the command if they do not appear at the beginning.
size_t index = 0;
while ((index = command.find(from_utf8("|("), index)) != std::string::npos)
command.erase(index, 1);
index = 0;
while ((index = command.find(from_utf8("|)"), index)) != std::string::npos)
command.erase(index, 1);
// Remove the ranges when they are the only vertical bar in the complete string.
if (command[0] == '(' || command[0] == ')')
command.erase(0, 1);
}
// Handle see and seealso. As "see" is a prefix of "seealso", the order of the comparisons is important.
// Both commands are mutually exclusive!
docstring see = from_utf8("");
vector<docstring> seeAlsoes;
if (command.substr(0, 3) == "see") {
// Unescape brackets.
size_t index = 0;
while ((index = command.find(from_utf8("\\{"), index)) != std::string::npos)
command.erase(index, 1);
index = 0;
while ((index = command.find(from_utf8("\\}"), index)) != std::string::npos)
command.erase(index, 1);
// Retrieve the part between brackets, and remove the complete seealso.
size_t positionOpeningBracket = command.find(from_ascii("{"));
size_t positionClosingBracket = command.find(from_ascii("}"));
docstring list = command.substr(positionOpeningBracket + 1, positionClosingBracket - positionOpeningBracket - 1);
// Parse the list of referenced entries (or a single one for see).
if (command.substr(0, 7) == "seealso") {
seeAlsoes = getVectorFromString(list, from_ascii(","), false);
} else {
see = list;
if (see.find(from_ascii(",")) != see.npos) {
docstring error = from_utf8("Several index terms found as \"see\"! Only one is acceptable. "
"Complete entry: \"") + latexString + from_utf8("\"");
LYXERR0(error);
xs << XMLStream::ESCAPE_NONE << (from_utf8("<!-- Output Error: ") + error + from_utf8(" -->\n"));
}
}
// Remove the complete see/seealso from the commands, in case there is something else to parse.
command = command.substr(positionClosingBracket + 1);
}
// Some parts of the strings are not parsed, as they do not have anything matching in DocBook: things like
// formatting the entry or the page number, other strings for sorting. https://wiki.lyx.org/Tips/Indexing
// If there are such things in the index entry, then this code may miserably fail. For example, for "Peter|(textbf",
// no range will be detected.
// TODO: Could handle formatting as significance="preferred"?
// Write all of this down.
if (terms.empty() && !hasEndRange) {
docstring error = from_utf8("No index term found! Complete entry: \"") + latexString + from_utf8("\"");
LYXERR0(error);
xs << XMLStream::ESCAPE_NONE << (from_utf8("<!-- Output Error: ") + error + from_utf8(" -->\n"));
} else {
// Generate the attributes for ranges. It is based on the terms that are indexed, but the ID must be unique
// to this indexing area (xml::cleanID does not guarantee this: for each call with the same arguments,
// the same legal ID is produced; here, as the input would be the same, the output must be, by design).
// Hence the thread-local storage, as the numbers must strictly be unique, and thus cannot be shared across
// a paragraph (making the solution used for HTML worthless). This solution is very similar to the one used in
// xml::cleanID.
docstring attrs = indexType;
if (hasStartRange || hasEndRange) {
// Append an ID if uniqueness is not guaranteed across the document.
static QThreadStorage<set<docstring>> tKnownTermLists;
static QThreadStorage<int> tID;
set<docstring> & knownTermLists = tKnownTermLists.localData();
int & ID = tID.localData();
if (!tID.hasLocalData()) {
tID.localData() = 0;
}
// Modify the index terms to add the unique ID if needed.
docstring newIndexTerms = indexTerms;
if (knownTermLists.find(indexTerms) != knownTermLists.end()) {
newIndexTerms += from_ascii(string("-") + to_string(ID));
// Only increment for the end of range, so that the same number is used for the start of range.
if (hasEndRange) {
ID++;
}
}
// Term list not yet known: add it to the set AFTER the end of range. After
if (knownTermLists.find(indexTerms) == knownTermLists.end() && hasEndRange) {
knownTermLists.insert(indexTerms);
}
// Generate the attributes.
docstring id = xml::cleanID(newIndexTerms);
if (hasStartRange) {
attrs += " class=\"startofrange\" xml:id=\"" + id + "\"";
} else {
attrs += " class=\"endofrange\" startref=\"" + id + "\"";
}
}
// Handle the index terms (including the specific index for this entry).
xs << xml::StartTag("indexterm", attrs);
if (terms.size() > 0) { // hasEndRange has no content.
xs << xml::StartTag("primary");
xs << terms[0];
xs << xml::EndTag("primary");
}
if (terms.size() > 1) {
xs << xml::StartTag("secondary");
xs << terms[1];
xs << xml::EndTag("secondary");
}
if (terms.size() > 2) {
xs << xml::StartTag("tertiary");
xs << terms[2];
xs << xml::EndTag("tertiary");
}
// Handle see and see also.
if (!see.empty()) {
xs << xml::StartTag("see");
xs << see;
xs << xml::EndTag("see");
}
if (!seeAlsoes.empty()) {
for (auto & entry : seeAlsoes) {
xs << xml::StartTag("seealso");
xs << entry;
xs << xml::EndTag("seealso");
}
}
// Close the entry.
xs << xml::EndTag("indexterm");
}
}

View File

@ -57,7 +57,7 @@ private:
///
void read(Lexer & lex);
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -25,7 +25,6 @@
#include "InsetIterator.h"
#include "Language.h"
#include "LyX.h"
#include "output_xhtml.h"
#include "ParIterator.h"
#include "xml.h"
#include "texstream.h"
@ -351,12 +350,13 @@ int InsetLabel::plaintext(odocstringstream & os,
}
int InsetLabel::docbook(odocstream & os, OutputParams const &) const
void InsetLabel::docbook(XMLStream & xs, OutputParams const & runparams) const
{
os << "<!-- anchor id=\""
<< xml::cleanID(getParam("name"))
<< "\" -->";
return 0;
// Output an anchor only if it has not been processed before.
if (runparams.docbook_anchors_to_ignore.find(getParam("name")) == runparams.docbook_anchors_to_ignore.end()) {
docstring attr = from_utf8("xml:id=\"") + xml::cleanID(getParam("name")) + from_utf8("\"");
xs << xml::CompTag("anchor", to_utf8(attr));
}
}

View File

@ -53,7 +53,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -37,6 +37,7 @@
#include "support/lstrings.h"
#include <cstdlib>
#include <output_docbook.h>
using namespace std;
@ -183,10 +184,9 @@ int InsetLine::plaintext(odocstringstream & os,
}
int InsetLine::docbook(odocstream & os, OutputParams const &) const
void InsetLine::docbook(XMLStream & xs, OutputParams const &) const
{
os << '\n';
return 0;
xs << xml::CR();
}

View File

@ -41,8 +41,7 @@ private:
/// Inset inherited methods.
//@{
InsetCode lyxCode() const { return LINE_CODE; }
int docbook(odocstream &, OutputParams const &) const;
/// Does nothing at the moment.
void docbook(XMLStream &, OutputParams const &) const;
docstring xhtml(XMLStream &, OutputParams const &) const;
bool hasSettings() const { return true; }
void metrics(MetricsInfo &, Dimension &) const;

View File

@ -27,6 +27,7 @@
#include "LaTeXFeatures.h"
#include "Lexer.h"
#include "output_latex.h"
#include "output_docbook.h"
#include "output_xhtml.h"
#include "OutputParams.h"
#include "TextClass.h"
@ -480,6 +481,45 @@ docstring InsetListings::xhtml(XMLStream & os, OutputParams const & rp) const
}
void InsetListings::docbook(XMLStream & xs, OutputParams const & rp) const
{
InsetLayout const & il = getLayout();
// Forge the attributes.
string attrs;
if (!il.docbookattr().empty())
attrs += " role=\"" + il.docbookattr() + "\"";
string const lang = params().getParamValue("language");
if (!lang.empty())
attrs += " language=\"" + lang + "\"";
xs << xml::StartTag(il.docbooktag(), attrs);
xs.startDivision(false);
// Deal with the caption.
docstring caption = getCaptionDocBook(rp);
if (!caption.empty()) {
xs << xml::StartTag("bridgehead");
xs << XMLStream::ESCAPE_NONE;
xs << caption;
xs << xml::EndTag("bridgehead");
}
// Deal with the content of the listing.
OutputParams newrp = rp;
newrp.pass_thru = true;
newrp.docbook_make_pars = false;
newrp.par_begin = 0;
newrp.par_end = text().paragraphs().size();
newrp.docbook_in_listing = true;
docbookParagraphs(text(), buffer(), xs, newrp);
// Done with the listing.
xs.endDivision();
xs << xml::EndTag(il.docbooktag());
}
string InsetListings::contextMenuName() const
{
return "context-listings";

View File

@ -58,6 +58,8 @@ private:
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///
void docbook(XMLStream &, OutputParams const &) const;
///
void validate(LaTeXFeatures &) const;
///
bool showInsetDialog(BufferView *) const;

View File

@ -10,6 +10,7 @@
*/
#include <config.h>
#include <output_docbook.h>
#include "InsetMarginal.h"
@ -41,14 +42,15 @@ int InsetMarginal::plaintext(odocstringstream & os,
}
int InsetMarginal::docbook(odocstream & os,
OutputParams const & runparams) const
void InsetMarginal::docbook(XMLStream & xs, OutputParams const & runparams) const
{
os << "<note role=\"margin\">";
int const i = InsetText::docbook(os, runparams);
os << "</note>";
return i;
// Implementation as per http://www.sagehill.net/docbookxsl/SideFloats.html
// Unfortunately, only for XSL-FO output with the default style sheets, hence the role.
xs << xml::StartTag("sidebar", "role=\"margin\"");
xs << xml::CR();
xs << "<?dbfo float-type=\"margin.note\"?>";
InsetText::docbook(xs, runparams);
xs << xml::EndTag("sidebar");
}

View File

@ -34,7 +34,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const & runparams) const;
void docbook(XMLStream &, OutputParams const & runparams) const;
/// Is the content of this inset part of the immediate (visible) text sequence?
bool isPartOfTextSequence() const { return false; }
private:

View File

@ -10,6 +10,7 @@
*/
#include <config.h>
#include <output_docbook.h>
#include "InsetNewline.h"
@ -171,10 +172,13 @@ int InsetNewline::plaintext(odocstringstream & os,
}
int InsetNewline::docbook(odocstream & os, OutputParams const &) const
void InsetNewline::docbook(XMLStream & xs, OutputParams const & runparams) const
{
os << '\n';
return 0;
if (runparams.docbook_in_par) {
xs.closeFontTags();
xs << xml::EndTag("para");
xs << xml::StartTag("para");
}
}

View File

@ -65,7 +65,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -19,7 +19,7 @@
#include "Lexer.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "xml.h"
#include "texstream.h"
#include "Text.h"
#include "TextMetrics.h"
@ -248,10 +248,9 @@ int InsetNewpage::plaintext(odocstringstream & os,
}
int InsetNewpage::docbook(odocstream & os, OutputParams const &) const
void InsetNewpage::docbook(XMLStream & os, OutputParams const &) const
{
os << '\n';
return 0;
os << xml::CR();
}

View File

@ -66,7 +66,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -29,7 +29,6 @@
#include "Length.h"
#include "LyX.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "xml.h"
#include "texstream.h"
#include "TocBackend.h"
@ -105,12 +104,12 @@ int InsetNomencl::plaintext(odocstringstream & os,
}
int InsetNomencl::docbook(odocstream & os, OutputParams const &) const
void InsetNomencl::docbook(XMLStream & xs, OutputParams const &) const
{
os << "<glossterm linkend=\"" << nomenclature_entry_id << "\">"
<< xml::escapeString(getParam("symbol"))
<< "</glossterm>";
return 0;
docstring attr = "linkend=\"" + nomenclature_entry_id + "\"";
xs << xml::StartTag("glossterm", attr);
xs << xml::escapeString(getParam("symbol"));
xs << xml::EndTag("glossterm");
}
@ -120,20 +119,6 @@ docstring InsetNomencl::xhtml(XMLStream &, OutputParams const &) const
}
int InsetNomencl::docbookGlossary(odocstream & os) const
{
os << "<glossentry id=\"" << nomenclature_entry_id << "\">\n"
<< "<glossterm>"
<< xml::escapeString(getParam("symbol"))
<< "</glossterm>\n"
<< "<glossdef><para>"
<< xml::escapeString(getParam("description"))
<< "</para></glossdef>\n"
<<"</glossentry>\n";
return 4;
}
void InsetNomencl::validate(LaTeXFeatures & features) const
{
features.require("nomencl");
@ -316,29 +301,75 @@ bool InsetPrintNomencl::getStatus(Cursor & cur, FuncRequest const & cmd,
}
// FIXME This should be changed to use the TOC. Perhaps
// that could be done when XHTML output is added.
int InsetPrintNomencl::docbook(odocstream & os, OutputParams const &) const
void InsetPrintNomencl::docbook(XMLStream & xs, OutputParams const & runparams) const
{
os << "<glossary>\n";
int newlines = 2;
InsetIterator it = inset_iterator_begin(buffer().inset());
while (it) {
if (it->lyxCode() == NOMENCL_CODE) {
newlines += static_cast<InsetNomencl const &>(*it).docbookGlossary(os);
++it;
} else if (!it->producesOutput()) {
// Ignore contents of insets that are not in output
size_t const depth = it.depth();
++it;
while (it.depth() > depth)
++it;
} else {
++it;
}
shared_ptr<Toc const> toc = buffer().tocBackend().toc("nomencl");
EntryMap entries;
Toc::const_iterator it = toc->begin();
Toc::const_iterator const en = toc->end();
for (; it != en; ++it) {
DocIterator dit = it->dit();
Paragraph const & par = dit.innerParagraph();
Inset const * inset = par.getInset(dit.top().pos());
if (!inset)
return;
InsetCommand const * ic = inset->asInsetCommand();
if (!ic)
return;
// FIXME We need a link to the paragraph here, so we
// need some kind of struct.
docstring const symbol = ic->getParam("symbol");
docstring const desc = ic->getParam("description");
docstring const prefix = ic->getParam("prefix");
docstring const sortas = prefix.empty() ? symbol : prefix;
entries[sortas] = NomenclEntry(symbol, desc, &par);
}
os << "</glossary>\n";
return newlines;
if (entries.empty())
return;
// As opposed to XHTML, no need to defer everything until the end of time, so write directly to xs.
// TODO: At least, that's what was done before...
docstring toclabel = translateIfPossible(from_ascii("Nomenclature"),
runparams.local_font->language()->lang());
xs << xml::StartTag("glossary");
xs << xml::CR();
xs << xml::StartTag("title");
xs << toclabel;
xs << xml::EndTag("title");
xs << xml::CR();
EntryMap::const_iterator eit = entries.begin();
EntryMap::const_iterator const een = entries.end();
for (; eit != een; ++eit) {
NomenclEntry const & ne = eit->second;
string const parid = ne.par->magicLabel();
xs << xml::StartTag("glossentry", "xml:id=\"" + parid + "\"");
xs << xml::CR();
xs << xml::StartTag("glossterm");
xs << ne.symbol;
xs << xml::EndTag("glossterm");
xs << xml::CR();
xs << xml::StartTag("glossdef");
xs << xml::CR();
xs << xml::StartTag("para");
xs << ne.desc;
xs << xml::EndTag("para");
xs << xml::CR();
xs << xml::EndTag("glossdef");
xs << xml::CR();
xs << xml::EndTag("glossentry");
xs << xml::CR();
}
xs << xml::EndTag("glossary");
xs << xml::CR();
}

View File

@ -28,9 +28,6 @@ public:
///
InsetNomencl(Buffer * buf, InsetCommandParams const &);
///
int docbookGlossary(odocstream &) const;
/// \name Public functions inherited from Inset class
//@{
///
@ -48,7 +45,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
/// Does nothing at the moment.
docstring xhtml(XMLStream &, OutputParams const &) const;
//@}
@ -92,7 +89,7 @@ public:
/// Updates needed features for this inset.
void validate(LaTeXFeatures & features) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -42,6 +42,7 @@
#include <algorithm>
#include <sstream>
#include <output_docbook.h>
using namespace std;
@ -260,27 +261,28 @@ int InsetNote::plaintext(odocstringstream & os,
}
int InsetNote::docbook(odocstream & os, OutputParams const & runparams_in) const
void InsetNote::docbook(XMLStream & xs, OutputParams const & runparams_in) const
{
if (params_.type == InsetNoteParams::Note)
return 0;
return;
OutputParams runparams(runparams_in);
if (params_.type == InsetNoteParams::Comment) {
os << "<remark>\n";
xs << xml::StartTag("remark");
xs << xml::CR();
runparams.inComment = true;
// Ignore files that are exported inside a comment
runparams.exportdata.reset(new ExportData);
}
// Greyed out text is output as such (no way to mark text as greyed out with DocBook).
int const n = InsetText::docbook(os, runparams);
InsetText::docbook(xs, runparams);
if (params_.type == InsetNoteParams::Comment)
os << "\n</remark>\n";
// Return how many newlines we issued.
//return int(count(str.begin(), str.end(), '\n'));
return n + 1 + 2;
if (params_.type == InsetNoteParams::Comment) {
xs << xml::CR();
xs << xml::EndTag("remark");
xs << xml::CR();
}
}

View File

@ -86,7 +86,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -348,22 +348,9 @@ int InsetPhantom::plaintext(odocstringstream & os,
}
int InsetPhantom::docbook(odocstream & os, OutputParams const & runparams) const
void InsetPhantom::docbook(XMLStream &, OutputParams const &) const
{
docstring cmdname;
switch (params_.type) {
case InsetPhantomParams::Phantom:
case InsetPhantomParams::HPhantom:
case InsetPhantomParams::VPhantom:
default:
cmdname = from_ascii("phantom");
break;
}
os << "<" + cmdname + ">";
int const i = InsetCollapsible::docbook(os, runparams);
os << "</" + cmdname + ">";
return i;
return;
}

View File

@ -79,7 +79,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
/// Makes no sense for XHTML.
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -28,10 +28,10 @@
#include "LyXRC.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "Paragraph.h"
#include "ParIterator.h"
#include "texstream.h"
#include "xml.h"
#include "frontends/FontMetrics.h"
#include "frontends/Painter.h"
@ -1041,10 +1041,9 @@ docstring InsetQuotes::getQuoteEntity(bool isHTML) const {
}
int InsetQuotes::docbook(odocstream & os, OutputParams const &) const
void InsetQuotes::docbook(XMLStream & xs, OutputParams const &) const
{
os << getQuoteEntity(false);
return 0;
xs << XMLStream::ESCAPE_NONE << getQuoteEntity(false);
}

View File

@ -146,7 +146,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;

View File

@ -309,28 +309,59 @@ int InsetRef::plaintext(odocstringstream & os,
}
int InsetRef::docbook(odocstream & os, OutputParams const & runparams) const
void InsetRef::docbook(XMLStream & xs, OutputParams const &) const
{
docstring const & ref = getParam("reference");
InsetLabel const * il = buffer().insetLabel(ref, true);
string const & cmd = params().getCmdName();
docstring linkend = xml::cleanID(ref);
// A name is provided, LyX will provide it. This is supposed to be a very rare case.
// Link with linkend, as is it within the document (not outside, in which case xlink:href is better suited).
docstring const & name = getParam("name");
if (name.empty()) {
if (runparams.flavor == OutputParams::DOCBOOK5) {
os << "<xref linkend=\""
<< xml::cleanID(getParam("reference"))
<< "\" />";
} else {
os << "<xref linkend=\""
<< xml::cleanID(getParam("reference"))
<< "\">";
}
} else {
os << "<link linkend=\""
<< xml::cleanID(getParam("reference"))
<< "\">"
<< getParam("name")
<< "</link>";
if (!name.empty()) {
docstring attr = from_utf8("linkend=\"") + linkend + from_utf8("\"");
xs << xml::StartTag("link", to_utf8(attr));
xs << name;
xs << xml::EndTag("link");
return;
}
return 0;
// The DocBook processor will generate the name when required.
docstring display_before;
docstring display_after;
docstring role;
if (il && !il->counterValue().empty()) {
// Try to construct a label from the InsetLabel we reference.
if (cmd == "vref" || cmd == "pageref" || cmd == "vpageref" || cmd == "nameref" || cmd == "formatted") {
// "ref on page #", "on page #", etc. The DocBook processor deals with generating the right text,
// including in the right language.
role = from_ascii(cmd);
if (cmd == "formatted") {
// A formatted reference may have many parameters. Generate all of them as roles, the only
// way arbitrary parameters can be passed into DocBook.
if (buffer().params().use_refstyle && getParam("caps") == "true")
role += " refstyle-caps";
if (buffer().params().use_refstyle && getParam("plural") == "true")
role += " refstyle-plural";
}
} else if (cmd == "eqref") {
display_before = from_ascii("(");
display_after = from_ascii(")");
}
// TODO: what about labelonly? I don't get how this is supposed to work...
}
// No name, ask DocBook to generate one.
docstring attr = from_utf8("linkend=\"") + ref + from_utf8("\"");
if (!role.empty())
attr += " role=\"" + role + "\"";
xs << display_before;
xs << xml::CompTag("xref", to_utf8(attr));
xs << display_after;
}

View File

@ -61,7 +61,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -40,6 +40,7 @@
#include "frontends/Painter.h"
#include <algorithm>
#include <output_docbook.h>
using namespace std;
@ -354,7 +355,7 @@ int InsetScript::plaintext(odocstringstream & os,
}
int InsetScript::docbook(odocstream & os, OutputParams const & runparams) const
void InsetScript::docbook(XMLStream & xs, OutputParams const & runparams) const
{
docstring cmdname;
switch (params_.type) {
@ -365,11 +366,10 @@ int InsetScript::docbook(odocstream & os, OutputParams const & runparams) const
cmdname = from_ascii("superscript");
break;
}
os << '<' + cmdname + '>';
int const i = InsetText::docbook(os, runparams);
os << "</" + cmdname + '>';
return i;
xs << xml::StartTag(cmdname);
InsetText::docbook(xs, runparams);
xs << xml::EndTag(cmdname);
}

View File

@ -99,7 +99,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
void edit(Cursor & cur, bool front,
EntryDirection entry_from = ENTRY_DIRECTION_IGNORE);

View File

@ -9,6 +9,7 @@
*/
#include <config.h>
#include <output_docbook.h>
#include "InsetSeparator.h"
@ -167,10 +168,9 @@ int InsetSeparator::plaintext(odocstringstream & os,
}
int InsetSeparator::docbook(odocstream & os, OutputParams const &) const
void InsetSeparator::docbook(XMLStream & xs, OutputParams const &) const
{
os << '\n';
return 0;
xs << xml::CR();
}

View File

@ -79,7 +79,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -26,8 +26,8 @@
#include "Lexer.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "texstream.h"
#include "xml.h"
#include "support/debug.h"
#include "support/docstream.h"
@ -741,68 +741,57 @@ int InsetSpace::plaintext(odocstringstream & os,
}
int InsetSpace::docbook(odocstream & os, OutputParams const &) const
void InsetSpace::docbook(XMLStream & xs, OutputParams const &) const
{
switch (params_.kind) {
case InsetSpaceParams::NORMAL:
os << " ";
xs << XMLStream::ESCAPE_NONE << " ";
break;
case InsetSpaceParams::QUAD:
os << "&emsp;";
xs << XMLStream::ESCAPE_NONE << "&#x2003;"; // HTML: &emsp;
break;
case InsetSpaceParams::QQUAD:
os << "&emsp;&emsp;";
xs << XMLStream::ESCAPE_NONE << "&#x2003;&#x2003;"; // HTML: &emsp;&emsp;
break;
case InsetSpaceParams::ENSKIP:
os << "&ensp;";
xs << XMLStream::ESCAPE_NONE << "&#x2002;"; // HTML: &ensp;
break;
case InsetSpaceParams::PROTECTED:
os << "&nbsp;";
xs << XMLStream::ESCAPE_NONE << "&#xA0;"; // HTML: &nbsp;
break;
case InsetSpaceParams::VISIBLE:
os << "&#x2423;";
xs << XMLStream::ESCAPE_NONE << "&#x2423;";
break;
case InsetSpaceParams::ENSPACE:
os << "&#x2060;&ensp;&#x2060;";
case InsetSpaceParams::ENSPACE: // HTML: &#x2060;&ensp;&#x2060; (word joiners)
xs << XMLStream::ESCAPE_NONE << "&#x2060;&#x2002;&#x2060;";
break;
case InsetSpaceParams::THIN:
os << "&thinsp;";
xs << XMLStream::ESCAPE_NONE << "&#x2009;"; // HTML: &thinspace;
break;
case InsetSpaceParams::MEDIUM:
os << "&emsp14;";
xs << XMLStream::ESCAPE_NONE << "&#x2005;"; // HTML: &emsp14;
break;
case InsetSpaceParams::THICK:
os << "&emsp13;";
xs << XMLStream::ESCAPE_NONE << "&#x2004;"; // HTML: &emsp13;
break;
case InsetSpaceParams::NEGTHIN:
case InsetSpaceParams::NEGMEDIUM:
case InsetSpaceParams::NEGTHICK:
// FIXME
os << "&nbsp;";
xs << XMLStream::ESCAPE_NONE << "&#xA0;"; // HTML: &nbsp;
break;
case InsetSpaceParams::HFILL:
case InsetSpaceParams::HFILL_PROTECTED:
os << '\n';
break;
case InsetSpaceParams::DOTFILL:
// FIXME
os << '\n';
break;
case InsetSpaceParams::HRULEFILL:
// FIXME
os << '\n';
break;
case InsetSpaceParams::LEFTARROWFILL:
case InsetSpaceParams::RIGHTARROWFILL:
case InsetSpaceParams::UPBRACEFILL:
case InsetSpaceParams::DOWNBRACEFILL:
case InsetSpaceParams::CUSTOM:
case InsetSpaceParams::CUSTOM_PROTECTED:
// FIXME
os << '\n';
xs << '\n';
break;
}
return 0;
}

View File

@ -129,7 +129,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -22,6 +22,7 @@
#include "Lexer.h"
#include "MetricsInfo.h"
#include "output_xhtml.h"
#include "xml.h"
#include "texstream.h"
#include "frontends/FontMetrics.h"
@ -529,48 +530,54 @@ int InsetSpecialChar::plaintext(odocstringstream & os,
}
int InsetSpecialChar::docbook(odocstream & os, OutputParams const &) const
void InsetSpecialChar::docbook(XMLStream & xs, OutputParams const &) const
{
switch (kind_) {
case HYPHENATION:
break;
case ALLOWBREAK:
// U+200B ZERO WIDTH SPACE (ZWSP)
os.put(0x200b);
break;
case HYPHENATION:
// Soft hyphen.
xs << XMLStream::ESCAPE_NONE << "&#xAD;";
break;
case ALLOWBREAK:
// Zero-width space
xs << XMLStream::ESCAPE_NONE << "&#x200B;";
break;
case LIGATURE_BREAK:
// Zero width non-joiner
xs << XMLStream::ESCAPE_NONE << "&#x200C;";
break;
case END_OF_SENTENCE:
os << '.';
xs << '.';
break;
case LDOTS:
os << "&hellip;";
// &hellip;
xs << XMLStream::ESCAPE_NONE << "&#x2026;";
break;
case MENU_SEPARATOR:
os << "&lyxarrow;";
// &rArr;, right arrow.
xs << XMLStream::ESCAPE_NONE << "&#x21D2;";
break;
case SLASH:
os << '/';
// &frasl;, fractional slash.
xs << XMLStream::ESCAPE_NONE << "&#x2044;";
break;
// Non-breaking hyphen.
case NOBREAKDASH:
os << '-';
xs << XMLStream::ESCAPE_NONE << "&#x2011;";
break;
case PHRASE_LYX:
os << "LyX";
xs << "LyX";
break;
case PHRASE_TEX:
os << "TeX";
xs << "TeX";
break;
case PHRASE_LATEX2E:
os << "LaTeX2";
// ε U+03B5 GREEK SMALL LETTER EPSILON
os.put(0x03b5);
// Lower-case epsilon.
xs << "LaTeX2" << XMLStream::ESCAPE_NONE << "&#x03b5;";
break;
case PHRASE_LATEX:
os << "LaTeX";
xs << "LaTeX";
break;
}
return 0;
}

View File

@ -78,7 +78,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -128,11 +128,10 @@ int InsetTOC::plaintext(odocstringstream & os,
}
int InsetTOC::docbook(odocstream & os, OutputParams const &) const
void InsetTOC::docbook(XMLStream &, OutputParams const &) const
{
if (getCmdName() == "tableofcontents")
os << "<toc></toc>";
return 0;
// TOC are generated automatically by the DocBook processor.
return;
}

View File

@ -44,7 +44,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream & xs, OutputParams const &) const;
///

View File

@ -42,6 +42,7 @@
#include "LyXRC.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "xml.h"
#include "output_xhtml.h"
#include "Paragraph.h"
#include "ParagraphParameters.h"
@ -3498,154 +3499,136 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
}
int Tabular::docbookRow(odocstream & os, row_type row,
OutputParams const & runparams) const
void Tabular::docbookRow(XMLStream & xs, row_type row,
OutputParams const & runparams, bool header) const
{
int ret = 0;
string const celltag = header ? "th" : "td";
idx_type cell = getFirstCellInRow(row);
os << "<row>\n";
xs << xml::StartTag("tr");
xs << xml::CR();
for (col_type c = 0; c < ncols(); ++c) {
if (isPartOfMultiColumn(row, c))
if (isPartOfMultiColumn(row, c) || isPartOfMultiRow(row, c))
continue;
os << "<entry align=\"";
stringstream attr;
Length const cwidth = column_info[c].p_width;
if (!cwidth.zero()) {
string const hwidth = cwidth.asHTMLString();
attr << "style =\"width: " << hwidth << ";\" ";
}
attr << "align='";
switch (getAlignment(cell)) {
case LYX_ALIGN_LEFT:
os << "left";
attr << "left";
break;
case LYX_ALIGN_RIGHT:
os << "right";
attr << "right";
break;
default:
os << "center";
attr << "center";
break;
}
os << "\" valign=\"";
attr << "'";
attr << " valign='";
switch (getVAlignment(cell)) {
case LYX_VALIGN_TOP:
os << "top";
attr << "top";
break;
case LYX_VALIGN_BOTTOM:
os << "bottom";
attr << "bottom";
break;
case LYX_VALIGN_MIDDLE:
os << "middle";
attr << "middle";
}
os << '"';
attr << "'";
if (isMultiColumn(cell)) {
os << " namest=\"col" << c << "\" ";
os << "nameend=\"col" << c + columnSpan(cell) - 1 << '"';
}
if (isMultiColumn(cell))
attr << " colspan='" << columnSpan(cell) << "'";
else if (isMultiRow(cell))
attr << " rowspan='" << rowSpan(cell) << "'";
os << '>';
ret += cellInset(cell)->docbook(os, runparams);
os << "</entry>\n";
xs << xml::StartTag(celltag, attr.str(), true);
cellInset(cell)->docbook(xs, runparams);
xs << xml::EndTag(celltag);
xs << xml::CR();
++cell;
}
os << "</row>\n";
return ret;
xs << xml::EndTag("tr");
xs<< xml::CR();
}
int Tabular::docbook(odocstream & os, OutputParams const & runparams) const
void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const
{
int ret = 0;
docstring ret;
//+---------------------------------------------------------------------
//+ first the opening preamble +
//+---------------------------------------------------------------------
os << "<tgroup cols=\"" << ncols()
<< "\" colsep=\"1\" rowsep=\"1\">\n";
for (col_type c = 0; c < ncols(); ++c) {
os << "<colspec colname=\"col" << c << "\" align=\"";
switch (column_info[c].alignment) {
case LYX_ALIGN_LEFT:
os << "left";
break;
case LYX_ALIGN_RIGHT:
os << "right";
break;
default:
os << "center";
break;
}
os << '"';
if (runparams.flavor == OutputParams::DOCBOOK5)
os << '/';
os << ">\n";
++ret;
// Some tables are inline. Likely limitation: cannot output a table within a table; is that really a limitation?
bool hasTableStarted = xs.isTagOpen(xml::StartTag("informaltable")) || xs.isTagOpen(xml::StartTag("table"));
if (!hasTableStarted) {
xs << xml::StartTag("informaltable");
xs << xml::CR();
}
//+---------------------------------------------------------------------
//+ Long Tabular case +
//+---------------------------------------------------------------------
// output caption info
// The caption flag wins over head/foot
// "Formal" tables have a caption and use the tag <table>; the distinction with <informaltable> is done outside.
if (haveLTCaption()) {
os << "<caption>\n";
++ret;
for (row_type r = 0; r < nrows(); ++r) {
if (row_info[r].caption) {
ret += docbookRow(os, r, runparams);
}
}
os << "</caption>\n";
++ret;
xs << xml::StartTag("caption");
for (row_type r = 0; r < nrows(); ++r)
if (row_info[r].caption)
docbookRow(xs, r, runparams);
xs << xml::EndTag("caption");
xs << xml::CR();
}
// output header info
if (haveLTHead(false) || haveLTFirstHead(false)) {
os << "<thead>\n";
++ret;
bool const havefirsthead = haveLTFirstHead(false);
// if we have a first head, then we are going to ignore the
// headers for the additional pages, since there aren't any
// in XHTML. this test accomplishes that.
bool const havehead = !havefirsthead && haveLTHead(false);
if (havehead || havefirsthead) {
xs << xml::StartTag("thead") << xml::CR();
for (row_type r = 0; r < nrows(); ++r) {
if ((row_info[r].endhead || row_info[r].endfirsthead) &&
!row_info[r].caption) {
ret += docbookRow(os, r, runparams);
if (((havefirsthead && row_info[r].endfirsthead) ||
(havehead && row_info[r].endhead)) &&
!row_info[r].caption) {
docbookRow(xs, r, runparams, true);
}
}
os << "</thead>\n";
++ret;
xs << xml::EndTag("thead");
xs << xml::CR();
}
// output footer info
if (haveLTFoot(false) || haveLTLastFoot(false)) {
os << "<tfoot>\n";
++ret;
bool const havelastfoot = haveLTLastFoot(false);
// as before.
bool const havefoot = !havelastfoot && haveLTFoot(false);
if (havefoot || havelastfoot) {
xs << xml::StartTag("tfoot") << xml::CR();
for (row_type r = 0; r < nrows(); ++r) {
if ((row_info[r].endfoot || row_info[r].endlastfoot) &&
!row_info[r].caption) {
ret += docbookRow(os, r, runparams);
if (((havelastfoot && row_info[r].endlastfoot) ||
(havefoot && row_info[r].endfoot)) &&
!row_info[r].caption) {
docbookRow(xs, r, runparams);
}
}
os << "</tfoot>\n";
++ret;
xs << xml::EndTag("tfoot");
xs << xml::CR();
}
//+---------------------------------------------------------------------
//+ the single row and columns (cells) +
//+---------------------------------------------------------------------
xs << xml::StartTag("tbody");
xs << xml::CR();
for (row_type r = 0; r < nrows(); ++r)
if (isValidRow(r))
docbookRow(xs, r, runparams);
xs << xml::EndTag("tbody");
xs << xml::CR();
os << "<tbody>\n";
++ret;
for (row_type r = 0; r < nrows(); ++r) {
if (isValidRow(r)) {
ret += docbookRow(os, r, runparams);
}
if (!hasTableStarted) {
xs << xml::EndTag("informaltable");
xs << xml::CR();
}
os << "</tbody>\n";
++ret;
//+---------------------------------------------------------------------
//+ the closing of the tabular +
//+---------------------------------------------------------------------
os << "</tgroup>";
++ret;
return ret;
}
@ -3728,20 +3711,22 @@ docstring Tabular::xhtml(XMLStream & xs, OutputParams const & runparams) const
align = "right";
break;
}
xs << xml::StartTag("div", "class='longtable' style='text-align: " + align + ";'")
<< xml::CR();
xs << xml::StartTag("div", "class='longtable' style='text-align: " + align + ";'");
xs << xml::CR();
// The caption flag wins over head/foot
if (haveLTCaption()) {
xs << xml::StartTag("div", "class='longtable-caption' style='text-align: " + align + ";'")
<< xml::CR();
xs << xml::StartTag("div", "class='longtable-caption' style='text-align: " + align + ";'");
xs << xml::CR();
for (row_type r = 0; r < nrows(); ++r)
if (row_info[r].caption)
ret += xhtmlRow(xs, r, runparams);
xs << xml::EndTag("div") << xml::CR();
xs << xml::EndTag("div");
xs << xml::CR();
}
}
xs << xml::StartTag("table") << xml::CR();
xs << xml::StartTag("table");
xs << xml::CR();
// output header info
bool const havefirsthead = haveLTFirstHead(false);
@ -3750,7 +3735,8 @@ docstring Tabular::xhtml(XMLStream & xs, OutputParams const & runparams) const
// in XHTML. this test accomplishes that.
bool const havehead = !havefirsthead && haveLTHead(false);
if (havehead || havefirsthead) {
xs << xml::StartTag("thead") << xml::CR();
xs << xml::StartTag("thead");
xs << xml::CR();
for (row_type r = 0; r < nrows(); ++r) {
if (((havefirsthead && row_info[r].endfirsthead) ||
(havehead && row_info[r].endhead)) &&
@ -3758,7 +3744,8 @@ docstring Tabular::xhtml(XMLStream & xs, OutputParams const & runparams) const
ret += xhtmlRow(xs, r, runparams, true);
}
}
xs << xml::EndTag("thead") << xml::CR();
xs << xml::EndTag("thead");
xs << xml::CR();
}
// output footer info
bool const havelastfoot = haveLTLastFoot(false);
@ -3773,21 +3760,22 @@ docstring Tabular::xhtml(XMLStream & xs, OutputParams const & runparams) const
ret += xhtmlRow(xs, r, runparams);
}
}
xs << xml::EndTag("tfoot") << xml::CR();
xs << xml::EndTag("tfoot");
xs << xml::CR();
}
xs << xml::StartTag("tbody") << xml::CR();
for (row_type r = 0; r < nrows(); ++r) {
if (isValidRow(r)) {
for (row_type r = 0; r < nrows(); ++r)
if (isValidRow(r))
ret += xhtmlRow(xs, r, runparams);
}
xs << xml::EndTag("tbody");
xs << xml::CR();
xs << xml::EndTag("table");
xs << xml::CR();
if (is_long_tabular) {
xs << xml::EndTag("div");
xs << xml::CR();
}
xs << xml::EndTag("tbody")
<< xml::CR()
<< xml::EndTag("table")
<< xml::CR();
if (is_long_tabular)
xs << xml::EndTag("div") << xml::CR();
return ret;
}
@ -4175,6 +4163,12 @@ docstring InsetTableCell::xhtml(XMLStream & xs, OutputParams const & rp) const
}
void InsetTableCell::docbook(XMLStream & xs, OutputParams const & runparams) const
{
InsetText::docbook(xs, runparams);
}
void InsetTableCell::metrics(MetricsInfo & mi, Dimension & dim) const
{
TextMetrics & tm = mi.base.bv->textMetrics(&text());
@ -6010,30 +6004,9 @@ int InsetTabular::plaintext(odocstringstream & os,
}
int InsetTabular::docbook(odocstream & os, OutputParams const & runparams) const
void InsetTabular::docbook(XMLStream & xs, OutputParams const & runparams) const
{
int ret = 0;
Inset * master = 0;
// FIXME: Why not pass a proper DocIterator here?
#if 0
// if the table is inside a float it doesn't need the informaltable
// wrapper. Search for it.
for (master = owner(); master; master = master->owner())
if (master->lyxCode() == FLOAT_CODE)
break;
#endif
if (!master) {
os << "<informaltable>";
++ret;
}
ret += tabular.docbook(os, runparams);
if (!master) {
os << "</informaltable>";
++ret;
}
return ret;
tabular.docbook(xs, runparams);
}

View File

@ -74,6 +74,8 @@ public:
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///
void docbook(XMLStream &, OutputParams const &) const;
///
void addToToc(DocIterator const & di, bool output_active,
UpdateType utype, TocBackend & backend) const;
///
@ -571,7 +573,7 @@ public:
///
void latex(otexstream &, OutputParams const &) const;
///
int docbook(odocstream & os, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///
@ -906,7 +908,8 @@ public:
std::vector<unsigned int> const &,
bool onlydata, size_t max_length) const;
/// auxiliary function for docbook
int docbookRow(odocstream & os, row_type, OutputParams const &) const;
void docbookRow(XMLStream &, row_type, OutputParams const &,
bool header = false) const;
///
docstring xhtmlRow(XMLStream & xs, row_type, OutputParams const &,
bool header = false) const;
@ -979,7 +982,7 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -38,14 +38,13 @@
#include "MetricsInfo.h"
#include "output_docbook.h"
#include "output_latex.h"
#include "output_plaintext.h"
#include "output_xhtml.h"
#include "OutputParams.h"
#include "output_plaintext.h"
#include "Paragraph.h"
#include "ParagraphParameters.h"
#include "ParIterator.h"
#include "Row.h"
#include "xml.h"
#include "TexRow.h"
#include "texstream.h"
#include "TextClass.h"
@ -589,20 +588,52 @@ int InsetText::plaintext(odocstringstream & os,
}
int InsetText::docbook(odocstream & os, OutputParams const & runparams) const
void InsetText::docbook(XMLStream & xs, OutputParams const & rp) const
{
ParagraphList::const_iterator const beg = paragraphs().begin();
docbook(xs, rp, WriteEverything);
}
if (!undefined())
xml::openTag(os, getLayout().latexname(),
beg->getID(buffer(), runparams) + getLayout().latexparam());
docbookParagraphs(text_, buffer(), os, runparams);
void InsetText::docbook(XMLStream & xs, OutputParams const & rp, XHTMLOptions opts) const
{
// we will always want to output all our paragraphs when we are
// called this way.
OutputParams runparams = rp;
runparams.par_begin = 0;
runparams.par_end = text().paragraphs().size();
if (!undefined())
xml::closeTag(os, getLayout().latexname());
if (undefined()) {
xs.startDivision(false);
docbookParagraphs(text_, buffer(), xs, runparams);
xs.endDivision();
return;
}
return 0;
InsetLayout const & il = getLayout();
if (opts & WriteOuterTag && !il.docbooktag().empty() && il.docbooktag() != "NONE") {
docstring attrs = docstring();
if (!il.docbookattr().empty())
attrs += from_ascii(il.docbookattr());
if (il.docbooktag() == "link")
attrs += from_ascii(" xlink:href=\"") + text_.asString() + from_ascii("\"");
xs << xml::StartTag(il.docbooktag(), attrs);
}
// No need for labels that are generated from counters.
// With respect to XHTML, paragraphs are still allowed here.
if (!allowMultiPar())
runparams.docbook_make_pars = false;
if (il.isPassThru())
runparams.pass_thru = true;
xs.startDivision(false);
docbookParagraphs(text_, buffer(), xs, runparams);
xs.endDivision();
if (opts & WriteOuterTag)
xs << xml::EndTag(il.docbooktag());
}

View File

@ -81,8 +81,6 @@ public:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///
enum XHTMLOptions {
@ -96,6 +94,10 @@ public:
docstring insetAsXHTML(XMLStream &, OutputParams const &,
XHTMLOptions) const;
///
void docbook(XMLStream &, OutputParams const &, XHTMLOptions opts) const;
///
void docbook(XMLStream &, OutputParams const &) const;
///
void validate(LaTeXFeatures & features) const;
/// return the argument(s) only

View File

@ -23,7 +23,7 @@
#include "Lexer.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "xml.h"
#include "texstream.h"
#include "Text.h"
@ -224,10 +224,9 @@ int InsetVSpace::plaintext(odocstringstream & os,
}
int InsetVSpace::docbook(odocstream & os, OutputParams const &) const
void InsetVSpace::docbook(XMLStream & xs, OutputParams const &) const
{
os << '\n';
return 1;
xs << xml::CR();
}

View File

@ -50,7 +50,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
/// Note that this returns the inset rather than writing it,
/// so it will actually be written after the present paragraph.
/// The normal case is that this inset will be on a line by

View File

@ -26,7 +26,7 @@
#include "FuncStatus.h"
#include "LaTeXFeatures.h"
#include "Lexer.h"
#include "output_xhtml.h"
#include "xml.h"
#include "texstream.h"
#include "TextClass.h"
@ -207,13 +207,13 @@ int InsetWrap::plaintext(odocstringstream & os,
}
int InsetWrap::docbook(odocstream & os, OutputParams const & runparams) const
void InsetWrap::docbook(XMLStream & xs, OutputParams const & runparams) const
{
// FIXME UNICODE
os << '<' << from_ascii(params_.type) << '>';
int const i = InsetText::docbook(os, runparams);
os << "</" << from_ascii(params_.type) << '>';
return i;
InsetLayout const & il = getLayout();
xs << xml::StartTag(il.docbooktag(), il.docbookattr()); // TODO: Detect when there is a title.
InsetText::docbook(xs, runparams);
xs << xml::EndTag(il.docbooktag());
}

View File

@ -72,7 +72,7 @@ private:
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -38,7 +38,7 @@
#include "InsetMathMacro.h"
#include "InsetMathMacroTemplate.h"
#include "MetricsInfo.h"
#include "output_xhtml.h"
#include "xml.h"
#include "Paragraph.h"
#include "ParIterator.h"
#include "xml.h"
@ -2404,13 +2404,12 @@ int InsetMathHull::plaintext(odocstringstream & os,
}
int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) const
void InsetMathHull::docbook(XMLStream & xs, OutputParams const & runparams) const
{
// With DocBook 5, MathML must be within its own namespace; defined in Buffer.cpp::writeDocBookSource as "m".
// Output everything in a separate stream so that this does not interfere with the standard flow of DocBook tags.
odocstringstream osmath;
MathStream ms(osmath, "m", true);
int res = 0;
// Choose the tag around the MathML equation.
docstring name;
@ -2419,6 +2418,8 @@ int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) cons
else
name = from_ascii("informalequation");
// DocBook also has <equation>, but it comes with a title.
docstring bname = name;
for (row_type i = 0; i < nrows(); ++i) {
if (!label(i).empty()) {
@ -2429,44 +2430,44 @@ int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) cons
++ms.tab(); ms.cr(); ms.os() << '<' << bname << '>';
// Output the MathML subtree.
odocstringstream ls;
otexstream ols(ls);
if (runparams.flavor == OutputParams::DOCBOOK5) {
ms << MTag("alt role='tex' ");
// Workaround for db2latex: db2latex always includes equations with
// \ensuremath{} or \begin{display}\end{display}
// so we strip LyX' math environment
WriteStream wi(ols, false, false, WriteStream::wsDefault, runparams.encoding);
InsetMathGrid::write(wi);
ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&amp;"), "<", "&lt;"));
ms << ETag("alt");
ms << MTag("math");
ms << ETag("alt");
ms << MTag("math");
InsetMathGrid::mathmlize(ms);
ms << ETag("math");
} else {
ms << MTag("alt role='tex'");
latex(ols, runparams);
res = ols.texrow().rows();
ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&amp;"), "<", "&lt;"));
ms << ETag("alt");
// TeX transcription. Avoid MTag/ETag so that there are no extraneous spaces.
ms << "<" << from_ascii("alt") << " role='tex'" << ">";
// Workaround for db2latex: db2latex always includes equations with
// \ensuremath{} or \begin{display}\end{display}
// so we strip LyX' math environment
WriteStream wi(ols, false, false, WriteStream::wsDefault, runparams.encoding);
InsetMathGrid::write(wi);
ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&amp;"), "<", "&lt;"));
ms << "</" << from_ascii("alt") << ">";
// Actual transformation of the formula into MathML. This translation may fail (for example, due to custom macros).
// The new output stream is required to deal with the errors: first write completely the formula into this
// temporary stream; then, if it is possible without error, then copy it back to the "real" stream. Otherwise,
// some incomplete tags might be put into the real stream.
try {
// First, generate the MathML expression.
odocstringstream ostmp;
MathStream mstmp(ostmp, ms.xmlns(), ms.xmlMode());
InsetMathGrid::mathmlize(mstmp);
// Then, output it (but only if the generation can be done without errors!).
ms << MTag("math");
ms.cr();
osmath << ostmp.str(); // osmath is not a XMLStream, so no need for XMLStream::ESCAPE_NONE.
ms << ETag("math");
} catch (MathExportException const &) {
osmath << "MathML export failed. Please report this as a bug.";
}
ms << from_ascii("<graphic fileref=\"eqn/");
if (!label(0).empty())
ms << xml::cleanID(label(0));
else
ms << xml::uniqueID(from_ascii("anon"));
if (runparams.flavor == OutputParams::DOCBOOK5)
ms << from_ascii("\"/>");
else
ms << from_ascii("\">");
// Close the DocBook tag enclosing the formula.
ms.cr(); --ms.tab(); ms.os() << "</" << name << '>';
return ms.line() + res;
// Output the complete tag to the DocBook stream.
xs << XMLStream::ESCAPE_NONE << osmath.str();
}

View File

@ -144,7 +144,7 @@ public:
int plaintext(odocstringstream &, OutputParams const &,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
///

View File

@ -182,24 +182,18 @@ void InsetMathRef::validate(LaTeXFeatures & features) const
}
int InsetMathRef::docbook(odocstream & os, OutputParams const & runparams) const
void InsetMathRef::docbook(XMLStream & xs, OutputParams const &) const
{
if (cell(1).empty()) {
os << "<xref linkend=\""
<< xml::cleanID(asString(cell(0)));
if (runparams.flavor == OutputParams::DOCBOOK5)
os << "\"/>";
else
os << "\">";
docstring attr = from_utf8("linkend=\"") + xml::cleanID(asString(cell(0))) + from_utf8("\"");
xs << xml::CompTag("xref", to_utf8(attr));
} else {
os << "<link linkend=\""
<< xml::cleanID(asString(cell(0)))
<< "\">"
// Link with linkend, as is it within the document (not outside, in which case xlink:href is better suited).
docstring attr = from_utf8("linkend=\"") + xml::cleanID(asString(cell(0))) + from_utf8("\"");
xs << xml::StartTag("link", to_utf8(attr))
<< asString(cell(1))
<< "</link>";
<< xml::EndTag("link");
}
return 0;
}

View File

@ -48,7 +48,7 @@ public:
virtual InsetMathRef * asRefInset() { return this; }
/// docbook output
int docbook(odocstream & os, OutputParams const &) const;
void docbook(XMLStream &, OutputParams const &) const;
/// generate something that will be understood by the Dialogs.
std::string const createDialogStr() const;

Some files were not shown because too many files have changed in this diff Show More