Add support for CALS tables in DocBook.

This commit is contained in:
Thibaut Cuvelier 2020-07-13 03:31:48 +02:00
parent 3b740d0c8f
commit e302757476
11 changed files with 292 additions and 64 deletions

View File

@ -7,6 +7,10 @@ changes happened in particular if possible. A good example would be
-----------------------
2020-07-14 Thibaut Cuvelier <tcuvelier@lyx.org>
* Format incremented to 598: DocBook can export to HTML and CALS tables, with the parameter
\docbook_table_output (0: HTML, only choice previously; CALS: 1).
2020-03-13 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 593: Buffer param \maintain_unincluded_children is not longer a bool
(true|false) but has three states: "no" (formerly "false"), "strict" (formerly "true") and

View File

@ -3922,6 +3922,20 @@ def revert_libertinus_sftt_fonts(document):
add_to_preamble(document, ["\\renewcommand*{\\LibertinusMono@scale}{" + str(tt_scale / 100.0) + "}"])
def convert_docbook_table_output(document):
if find_token(document.header, '\\docbook_table_output') != -1:
document.warning("Malformed LyX file: \\docbook_table_output found before format 598!")
else:
document.header.append('\\docbook_table_output 0')
def revert_docbook_table_output(document):
i = find_token(document.header, '\\docbook_table_output 0')
i = find_token(document.header, '\\docbook_table_output 1') if i == -1 else i
if i != -1:
del document.header[i]
##
# Conversion hub
#
@ -3980,10 +3994,12 @@ convert = [
[594, []],
[595, []],
[596, [convert_parskip]],
[597, [convert_libertinus_rm_fonts]]
[597, [convert_libertinus_rm_fonts]],
[598, [convert_docbook_table_output]]
]
revert = [[595, [revert_libertinus_rm_fonts,revert_libertinus_sftt_fonts]],
revert = [[597, [revert_docbook_table_output]],
[595, [revert_libertinus_rm_fonts,revert_libertinus_sftt_fonts]],
[595, [revert_parskip,revert_line_vspaces]],
[594, [revert_ams_spaces]],
[593, [revert_counter_inset]],

View File

@ -471,6 +471,7 @@ BufferParams::BufferParams()
html_math_output = MathML;
html_math_img_scale = 1.0;
html_css_as_file = false;
docbook_table_output = HTMLTable;
display_pixel_ratio = 1.0;
shell_escape = false;
@ -1134,6 +1135,10 @@ string BufferParams::readToken(Lexer & lex, string const & token,
} else if (token == "\\html_latex_end") {
lex.eatLine();
html_latex_end = lex.getString();
} else if (token == "\\docbook_table_output") {
int temp;
lex >> temp;
docbook_table_output = static_cast<TableOutput>(temp);
} else if (token == "\\output_sync") {
lex >> output_sync;
} else if (token == "\\output_sync_macro") {
@ -1491,6 +1496,8 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const
<< "\\html_css_as_file " << html_css_as_file << '\n'
<< "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
os << "\\docbook_table_output " << docbook_table_output << '\n';
if (html_math_img_scale != 1.0)
os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
if (!html_latex_start.empty())

View File

@ -558,6 +558,15 @@ public:
std::string html_latex_end;
///
bool html_css_as_file;
// do not change these values. we rely upon them.
enum TableOutput {
HTMLTable = 0,
CALSTable = 1
};
/// what format to use for table output in DocBook. present choices are above
TableOutput docbook_table_output;
/// allow the LaTeX backend to run external programs
bool shell_escape;
/// generate output usable for reverse/forward search

View File

@ -925,6 +925,8 @@ GuiDocument::GuiDocument(GuiView & lv)
this, SLOT(change_adaptor()));
connect(outputModule->mathoutCB, SIGNAL(currentIndexChanged(int)),
this, SLOT(change_adaptor()));
connect(outputModule->tableoutCB, SIGNAL(currentIndexChanged(int)),
this, SLOT(change_adaptor()));
connect(outputModule->shellescapeCB, SIGNAL(stateChanged(int)),
this, SLOT(shellescapeChanged()));
@ -3718,6 +3720,13 @@ void GuiDocument::applyView()
bp_.html_math_img_scale = outputModule->mathimgSB->value();
bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
int tablefmt = outputModule->tableoutCB->currentIndex();
if (tablefmt == -1)
tablefmt = 0;
BufferParams::TableOutput const to =
static_cast<BufferParams::TableOutput>(tablefmt);
bp_.docbook_table_output = to;
bp_.save_transient_properties =
outputModule->saveTransientPropertiesCB->isChecked();
bp_.postpone_fragile_content =
@ -4355,6 +4364,8 @@ void GuiDocument::paramsToDialog()
outputModule->strictCB->setChecked(bp_.html_be_strict);
outputModule->cssCB->setChecked(bp_.html_css_as_file);
outputModule->tableoutCB->setCurrentIndex(bp_.docbook_table_output);
outputModule->saveTransientPropertiesCB
->setChecked(bp_.save_transient_properties);
outputModule->postponeFragileCB

View File

@ -14,6 +14,95 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="0">
<widget class="QGroupBox" name="docbookGB">
<property name="title">
<string>DocBook Output Options</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="outDBGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="tableoutLA">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>&amp;Table output:</string>
</property>
<property name="buddy">
<cstring>tableoutCB</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="tableoutCB">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Format to use for math output.</string>
</property>
<item>
<property name="text">
<string>HTML</string>
</property>
</item>
<item>
<property name="text">
<string>CALS</string>
</property>
</item>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<widget class="QGroupBox" name="savingGB">
<property name="title">
<string>LyX Format</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout7">
<item row="0" column="0">
<widget class="QCheckBox" name="saveTransientPropertiesCB">
<property name="toolTip">
<string>Save all parameters in the LyX file, including ones that are frequently switched or that are specific to the user (such as the output of the tracked changes, or the document directory path). Disabling this option plays nicer in collaborative settings and with version control systems.</string>
</property>
<property name="text">
<string>Save &amp;transient properties</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="outputFormatGB">
<property name="title">
@ -93,16 +182,6 @@
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="shellescapeCB">
<property name="toolTip">
<string>Runs the LaTeX backend with the -shell-escape option (Warning: use only when really necessary)</string>
</property>
<property name="text">
<string>&amp;Allow running external programs</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="xhtmlGB">
<property name="title">
@ -164,7 +243,7 @@
<string>&amp;Math output:</string>
</property>
<property name="buddy">
<cstring>mathoutCB</cstring>
<cstring>tableoutCB</cstring>
</property>
</widget>
</item>
@ -235,44 +314,16 @@
</layout>
</widget>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="savingGB">
<property name="title">
<string>LyX Format</string>
<item row="1" column="0">
<widget class="QCheckBox" name="shellescapeCB">
<property name="toolTip">
<string>Runs the LaTeX backend with the -shell-escape option (Warning: use only when really necessary)</string>
</property>
<property name="flat">
<bool>true</bool>
<property name="text">
<string>&amp;Allow running external programs</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout7">
<item row="0" column="0">
<widget class="QCheckBox" name="saveTransientPropertiesCB">
<property name="toolTip">
<string>Save all parameters in the LyX file, including ones that are frequently switched or that are specific to the user (such as the output of the tracked changes, or the document directory path). Disabling this option plays nicer in collaborative settings and with version control systems.</string>
</property>
<property name="text">
<string>Save &amp;transient properties</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="latexOutputGB">
<property name="title">
@ -359,6 +410,19 @@
</layout>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<includes>

View File

@ -3501,6 +3501,20 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
void Tabular::docbookRow(XMLStream & xs, row_type row,
OutputParams const & runparams, bool header) const
{
switch (buffer().params().docbook_table_output) {
case BufferParams::HTMLTable:
docbookRowAsHTML(xs, row, runparams, header);
break;
case BufferParams::CALSTable:
docbookRowAsCALS(xs, row, runparams);
break;
}
}
void Tabular::docbookRowAsHTML(XMLStream & xs, row_type row,
OutputParams const & runparams, bool header) const
{
string const celltag = header ? "th" : "td";
idx_type cell = getFirstCellInRow(row);
@ -3565,7 +3579,77 @@ void Tabular::docbookRow(XMLStream & xs, row_type row,
++cell;
}
xs << xml::EndTag("tr");
xs<< xml::CR();
xs << xml::CR();
}
void Tabular::docbookRowAsCALS(XMLStream & xs, row_type row,
OutputParams const & runparams) const
{
idx_type cell = getFirstCellInRow(row);
xs << xml::StartTag("row");
xs << xml::CR();
for (col_type c = 0; c < ncols(); ++c) {
if (isPartOfMultiColumn(row, c) || isPartOfMultiRow(row, c))
continue;
stringstream attr;
attr << "align='";
switch (getAlignment(cell)) {
case LYX_ALIGN_BLOCK:
attr << "justify";
break;
case LYX_ALIGN_DECIMAL: {
Language const *tlang = buffer().paragraphs().front().getParLanguage(buffer().params());
attr << "char' char='" << to_utf8(tlang->decimalSeparator());
}
break;
case LYX_ALIGN_LEFT:
attr << "left";
break;
case LYX_ALIGN_RIGHT:
attr << "right";
break;
default:
attr << "center";
break;
}
attr << "'";
attr << " valign='";
switch (getVAlignment(cell)) {
case LYX_VALIGN_TOP:
attr << "top";
break;
case LYX_VALIGN_BOTTOM:
attr << "bottom";
break;
case LYX_VALIGN_MIDDLE:
attr << "middle";
}
attr << "'";
if (isMultiColumn(cell))
attr << " colspan='" << columnSpan(cell) << "'";
else if (isMultiRow(cell))
attr << " rowspan='" << rowSpan(cell) << "'";
else
attr << " colname='c" << (c + 1) << "'"; // Column numbering starts at 1.
// All cases where there should be a line *below* this row.
if (row_info[row].bottom_space_default)
attr << " rowsep='1'";
xs << xml::StartTag("entry", attr.str(), true);
cellInset(cell)->docbook(xs, runparams);
xs << xml::EndTag("entry");
xs << xml::CR();
++cell;
}
xs << xml::EndTag("row");
xs << xml::CR();
}
@ -3580,35 +3664,57 @@ void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const
xs << xml::CR();
}
// "Formal" tables have a caption and use the tag <table>; the distinction with <informaltable> is done outside.
// "Formal" tables have a title and use the tag <table>; the distinction with <informaltable> is done outside.
// HTML has the caption first with titles forbidden, and CALS has a title first.
if (haveLTCaption()) {
xs << xml::StartTag("caption");
std::string tag = ((buffer().params().docbook_table_output) == BufferParams::HTMLTable) ? "caption" : "title";
xs << xml::StartTag(tag);
for (row_type r = 0; r < nrows(); ++r)
if (row_info[r].caption)
docbookRow(xs, r, runparams);
xs << xml::EndTag("caption");
xs << xml::EndTag(tag);
xs << xml::CR();
}
// output header info
// CALS header: describe all columns in this table. For names, take 'c' then the ID of the column.
// Start at one, as is customary with CALS!
if (buffer().params().docbook_table_output == BufferParams::CALSTable) {
for (col_type c = 0; c < ncols(); ++c) {
std::stringstream attr;
attr << "colnum='" << (c + 1) << "' ";
attr << "colname='c" << (c + 1) << "' ";
Length const cwidth = column_info[c].p_width;
if (!cwidth.zero())
attr << "colwidth='" << cwidth.asHTMLString() << "' ";
attr << "rowheader='norowheader'"; // Last attribute, hence no space at the end.
xs << xml::CompTag("colspec", attr.str());
xs << xml::CR();
}
}
// Output the header of the table. For both HTML and CALS, this is surrounded by a thead.
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.
// in DocBook. 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 (((havefirsthead && row_info[r].endfirsthead) ||
(havehead && row_info[r].endhead)) &&
!row_info[r].caption) {
docbookRow(xs, r, runparams, true);
(havehead && row_info[r].endhead)) &&
!row_info[r].caption) {
docbookRow(xs, r, runparams, true); // TODO: HTML vs CALS
}
}
xs << xml::EndTag("thead");
xs << xml::CR();
}
// output footer info
// Output the footer of the table. For both HTML and CALS, this is surrounded by a tfoot and output just after
// the header (and before the body).
bool const havelastfoot = haveLTLastFoot(false);
// as before.
bool const havefoot = !havelastfoot && haveLTFoot(false);
@ -3616,15 +3722,17 @@ void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const
xs << xml::StartTag("tfoot") << xml::CR();
for (row_type r = 0; r < nrows(); ++r) {
if (((havelastfoot && row_info[r].endlastfoot) ||
(havefoot && row_info[r].endfoot)) &&
!row_info[r].caption) {
docbookRow(xs, r, runparams);
(havefoot && row_info[r].endfoot)) &&
!row_info[r].caption) {
docbookRow(xs, r, runparams); // TODO: HTML vs CALS
}
}
xs << xml::EndTag("tfoot");
xs << xml::CR();
}
// Output the main part of the table. The tbody container is mandatory for CALS, but optional for HTML (only if
// there is no header and no footer). It never hurts to have it, though.
xs << xml::StartTag("tbody");
xs << xml::CR();
for (row_type r = 0; r < nrows(); ++r)
@ -3633,6 +3741,7 @@ void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const
xs << xml::EndTag("tbody");
xs << xml::CR();
// If this method started the table tag, also make it close it.
if (!hasTableStarted) {
xs << xml::EndTag("informaltable");
xs << xml::CR();

View File

@ -572,7 +572,7 @@ public:
void read(Lexer &);
///
void latex(otexstream &, OutputParams const &) const;
///
/// serialise the table in DocBook, according to buffer parameters
void docbook(XMLStream &, OutputParams const &) const;
///
docstring xhtml(XMLStream &, OutputParams const &) const;
@ -907,9 +907,14 @@ public:
idx_type cell, row_type row, col_type column,
std::vector<unsigned int> const &,
bool onlydata, size_t max_length) const;
/// auxiliary function for docbook
/// auxiliary function for DocBook
void docbookRow(XMLStream &, row_type, OutputParams const &,
bool header = false) const;
/// auxiliary function for DocBook: export this row as HTML
void docbookRowAsHTML(XMLStream &, row_type, OutputParams const &,
bool header) const;
/// auxiliary function for DocBook: export this row as CALS
void docbookRowAsCALS(XMLStream &, row_type, OutputParams const &) const;
///
docstring xhtmlRow(XMLStream & xs, row_type, OutputParams const &,
bool header = false) const;

View File

@ -543,6 +543,7 @@ Preamble::Preamble() : one_language(true), explicit_babel(false),
h_html_be_strict = "false";
h_html_css_as_file = "0";
h_html_math_output = "0";
h_docbook_table_output = "0";
h_index[0] = "Index";
h_index_command = "default";
h_inputencoding = "auto-legacy";
@ -2117,6 +2118,7 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc, string const & outfiled
<< "\\html_math_output " << h_html_math_output << "\n"
<< "\\html_css_as_file " << h_html_css_as_file << "\n"
<< "\\html_be_strict " << h_html_be_strict << "\n"
<< "\\docbook_table_output " << h_docbook_table_output << "\n"
<< authors_
<< "\\end_header\n\n"
<< "\\begin_body\n";

View File

@ -190,6 +190,7 @@ private:
std::string h_html_be_strict;
std::string h_html_css_as_file;
std::string h_html_math_output;
std::string h_docbook_table_output;
std::string h_index[99];
std::string h_index_command;
std::string h_inputencoding;

View File

@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
#define LYX_FORMAT_LYX 597 // spitz: libertinus fonts
#define LYX_FORMAT_TEX2LYX 597
#define LYX_FORMAT_LYX 598 // tcuvelier: DocBook tables
#define LYX_FORMAT_TEX2LYX 598
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER