MathML: let the user change the MathML version.

Discussed in https://www.lyx.org/trac/ticket/13058.
This commit is contained in:
Thibaut Cuvelier 2024-10-01 23:53:30 +02:00
parent df1ba8ee59
commit 7feffb89e9
15 changed files with 604 additions and 432 deletions

View File

@ -7,6 +7,11 @@ changes happened in particular if possible. A good example would be
----------------------- -----------------------
2024-09-29 Thibaut Cuvelier <tcuvelier@lyx.org>
* Format incremented to 631: Add support for MathML versions, which
are stored separately for DocBook and XHTML (\docbook_mathml_version,
which is new, and \html_math_output, which receives a new value).
2024-08-25 Jürgen Spitzmüller <spitz@lyx.org> 2024-08-25 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 630: Add support for a number of languages in * Format incremented to 630: Add support for a number of languages in
babel and polyglossia: babel and polyglossia:

View File

@ -1015,6 +1015,48 @@ def revert_new_babel_languages(document):
if document.language == "hebrew" or find_token(document.body, "\\lang oldrussian", 0) != -1: if document.language == "hebrew" or find_token(document.body, "\\lang oldrussian", 0) != -1:
add_to_preamble(document, ["\\PassOptionsToPackage{provide*=*}{babel}"]) add_to_preamble(document, ["\\PassOptionsToPackage{provide*=*}{babel}"])
def convert_mathml_version(document):
"""Add MathML version header for DocBook to use MathML 3 preferably.
For cleanliness, add this header close to other DocBook headers if present.
Leave XHTML alone, as the default value is still probably what the user wants (MathML Core)."""
i = find_token(document.header, "\\docbook", 0)
if i == -1:
document.header += ["\\docbook_mathml_version 0"]
else:
document.header.insert(i + 1, "\\docbook_mathml_version 0")
def revert_mathml_version(document):
"""Remove MathML version header.
For XHTML, only remove the value 4 for \html_math_output (MathML 3) and replace it with 0
(MathML Core with format 631+, MathML for 630-).
For DocBook, totally remove the header (the default with 630- is MathML)."""
while True:
i = find_token(document.header, "\\html_math_output", 0)
if i == -1:
# nothing to do
break
# remove XHTML header if using the new value, leave alone otherwise.
if "4" in document.header:
document.header[i] = "\\html_math_output 0"
while True:
i = find_token(document.header, "\\docbook_mathml_version", 0)
if i == -1:
# nothing to do
return
# remove header
del document.header[i]
## ##
# Conversion hub # Conversion hub
# #
@ -1030,11 +1072,13 @@ convert = [
[627, [convert_nomencl, convert_index_sc]], [627, [convert_nomencl, convert_index_sc]],
[628, []], [628, []],
[629, []], [629, []],
[630, []] [630, []],
[631, [convert_mathml_version]]
] ]
revert = [ revert = [
[630, [revert_mathml_version]],
[629, [revert_new_polyglossia_languages, revert_new_babel_languages]], [629, [revert_new_polyglossia_languages, revert_new_babel_languages]],
[628, [revert_langopts]], [628, [revert_langopts]],
[627, [revert_nomentbl]], [627, [revert_nomentbl]],

View File

@ -4472,8 +4472,11 @@ void Buffer::setMathFlavor(OutputParams & op) const
// In particular, this function has no impact on the DocBook code, as it // In particular, this function has no impact on the DocBook code, as it
// uses another mechanism to handle math flavours. // uses another mechanism to handle math flavours.
switch (params().html_math_output) { switch (params().html_math_output) {
case BufferParams::MathML: case BufferParams::MathMLCore:
op.math_flavor = OutputParams::MathAsMathML; op.math_flavor = OutputParams::MathAsMathMLCore;
break;
case BufferParams::MathML3:
op.math_flavor = OutputParams::MathAsMathML3;
break; break;
case BufferParams::HTML: case BufferParams::HTML:
op.math_flavor = OutputParams::MathAsHTML; op.math_flavor = OutputParams::MathAsHTML;

View File

@ -480,11 +480,12 @@ BufferParams::BufferParams()
// default index // default index
indiceslist().addDefault(B_("Index")); indiceslist().addDefault(B_("Index"));
html_be_strict = false; html_be_strict = false;
html_math_output = MathML; html_math_output = MathMLCore;
html_math_img_scale = 1.0; html_math_img_scale = 1.0;
html_css_as_file = false; html_css_as_file = false;
docbook_table_output = HTMLTable; docbook_table_output = HTMLTable;
docbook_mathml_prefix = MPrefix; docbook_mathml_prefix = MPrefix;
docbook_mathml_version = MathMLStream::mathml3;
display_pixel_ratio = 1.0; display_pixel_ratio = 1.0;
shell_escape = false; shell_escape = false;
@ -1226,6 +1227,10 @@ string BufferParams::readToken(Lexer & lex, string const & token,
int temp; int temp;
lex >> temp; lex >> temp;
docbook_mathml_prefix = static_cast<MathMLNameSpacePrefix>(temp); docbook_mathml_prefix = static_cast<MathMLNameSpacePrefix>(temp);
} else if (token == "\\docbook_mathml_version") {
int temp;
lex >> temp;
docbook_mathml_version = static_cast<MathMLStream::MathMLVersion>(temp);
} else if (token == "\\output_sync") { } else if (token == "\\output_sync") {
lex >> output_sync; lex >> output_sync;
} else if (token == "\\output_sync_macro") { } else if (token == "\\output_sync_macro") {
@ -1621,6 +1626,7 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const
os << "\\docbook_table_output " << docbook_table_output << '\n'; os << "\\docbook_table_output " << docbook_table_output << '\n';
os << "\\docbook_mathml_prefix " << docbook_mathml_prefix << '\n'; os << "\\docbook_mathml_prefix " << docbook_mathml_prefix << '\n';
os << "\\docbook_mathml_version " << docbook_mathml_version << '\n';
if (html_math_img_scale != 1.0) if (html_math_img_scale != 1.0)
os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n'; os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';

View File

@ -28,6 +28,8 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include "mathed/MathStream.h"
namespace lyx { namespace lyx {
namespace support { namespace support {
@ -587,7 +589,8 @@ public:
// do not change these values. we rely upon them. // do not change these values. we rely upon them.
enum MathOutput { enum MathOutput {
MathML = 0, MathMLCore = 0,
MathML3 = 4,
HTML = 1, HTML = 1,
Images = 2, Images = 2,
LaTeX = 3 LaTeX = 3
@ -625,6 +628,9 @@ public:
/// what prefix to use when outputting MathML. present choices are above /// what prefix to use when outputting MathML. present choices are above
MathMLNameSpacePrefix docbook_mathml_prefix; MathMLNameSpacePrefix docbook_mathml_prefix;
/// what version of MathML to use for DocBook output (likely different from the version used for XHTML)
MathMLStream::MathMLVersion docbook_mathml_version;
/// allow the LaTeX backend to run external programs /// allow the LaTeX backend to run external programs
bool shell_escape; bool shell_escape;
/// generate output usable for reverse/forward search /// generate output usable for reverse/forward search

View File

@ -658,7 +658,7 @@ void putClipboard(ParagraphList const & paragraphs,
// We don't want to produce images that are not used. Therefore, // We don't want to produce images that are not used. Therefore,
// output formulas as MathML. Even if this is not understood by all // output formulas as MathML. Even if this is not understood by all
// applications, the number that can parse it should go up in the future. // applications, the number that can parse it should go up in the future.
buffer->params().html_math_output = BufferParams::MathML; buffer->params().html_math_output = BufferParams::MathMLCore;
// Copy authors to the params. We need those pointers. // Copy authors to the params. We need those pointers.
for (Author const & a : bp.authors()) for (Author const & a : bp.authors())

View File

@ -54,7 +54,8 @@ class OutputParams {
public: public:
enum MathFlavor { enum MathFlavor {
NotApplicable, NotApplicable,
MathAsMathML, MathAsMathMLCore,
MathAsMathML3,
MathAsHTML, MathAsHTML,
MathAsImages, MathAsImages,
MathAsLaTeX MathAsLaTeX

View File

@ -952,6 +952,8 @@ GuiDocument::GuiDocument(GuiView & lv)
this, SLOT(change_adaptor())); this, SLOT(change_adaptor()));
connect(outputModule->mathmlprefixCB, SIGNAL(currentIndexChanged(int)), connect(outputModule->mathmlprefixCB, SIGNAL(currentIndexChanged(int)),
this, SLOT(change_adaptor())); this, SLOT(change_adaptor()));
connect(outputModule->mathmlverCB, SIGNAL(currentIndexChanged(int)),
this, SLOT(change_adaptor()));
connect(outputModule->shellescapeCB, SIGNAL(stateChanged(int)), connect(outputModule->shellescapeCB, SIGNAL(stateChanged(int)),
this, SLOT(shellescapeChanged())); this, SLOT(shellescapeChanged()));
@ -4076,6 +4078,12 @@ void GuiDocument::applyView()
auto const mp = static_cast<BufferParams::MathMLNameSpacePrefix>(mathmlprefix); auto const mp = static_cast<BufferParams::MathMLNameSpacePrefix>(mathmlprefix);
bp_.docbook_mathml_prefix = mp; bp_.docbook_mathml_prefix = mp;
int mathmlversion = outputModule->mathmlverCB->currentIndex();
if (mathmlversion == -1)
mathmlversion = 0;
auto const mv = static_cast<MathMLStream::MathMLVersion>(mathmlversion);
bp_.docbook_mathml_version = mv;
bp_.save_transient_properties = bp_.save_transient_properties =
outputModule->saveTransientPropertiesCB->isChecked(); outputModule->saveTransientPropertiesCB->isChecked();
bp_.postpone_fragile_content = bp_.postpone_fragile_content =

File diff suppressed because it is too large Load Diff

View File

@ -119,7 +119,8 @@ void InsetMathBox::validate(LaTeXFeatures & features) const
// FIXME XHTML // FIXME XHTML
// It'd be better to be able to get this from an InsetLayout, but at present // It'd be better to be able to get this from an InsetLayout, but at present
// InsetLayouts do not seem really to work for things that aren't InsetTexts. // InsetLayouts do not seem really to work for things that aren't InsetTexts.
if (features.runparams().math_flavor == OutputParams::MathAsMathML) if (features.runparams().math_flavor == OutputParams::MathAsMathMLCore ||
features.runparams().math_flavor == OutputParams::MathAsMathML3)
features.addCSSSnippet("mtext.mathbox { font-style: normal; }"); features.addCSSSnippet("mtext.mathbox { font-style: normal; }");
else if (features.runparams().math_flavor == OutputParams::MathAsHTML) else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
features.addCSSSnippet("span.mathbox { font-style: normal; }"); features.addCSSSnippet("span.mathbox { font-style: normal; }");
@ -204,7 +205,8 @@ void InsetMathFBox::validate(LaTeXFeatures & features) const
// FIXME XHTML // FIXME XHTML
// It'd be better to be able to get this from an InsetLayout, but at present // It'd be better to be able to get this from an InsetLayout, but at present
// InsetLayouts do not seem really to work for things that aren't InsetTexts. // InsetLayouts do not seem really to work for things that aren't InsetTexts.
if (features.runparams().math_flavor == OutputParams::MathAsMathML) if (features.runparams().math_flavor == OutputParams::MathAsMathMLCore ||
features.runparams().math_flavor == OutputParams::MathAsMathML3)
features.addCSSSnippet( features.addCSSSnippet(
"mtext.fbox { border: 1px solid black; font-style: normal; padding: 0.5ex; }"); "mtext.fbox { border: 1px solid black; font-style: normal; padding: 0.5ex; }");
else if (features.runparams().math_flavor == OutputParams::MathAsHTML) else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
@ -343,7 +345,8 @@ void InsetMathMakebox::validate(LaTeXFeatures & features) const
// FIXME XHTML // FIXME XHTML
// It'd be better to be able to get this from an InsetLayout, but at present // It'd be better to be able to get this from an InsetLayout, but at present
// InsetLayouts do not seem really to work for things that aren't InsetTexts. // InsetLayouts do not seem really to work for things that aren't InsetTexts.
if (features.runparams().math_flavor == OutputParams::MathAsMathML) if (features.runparams().math_flavor == OutputParams::MathAsMathMLCore ||
features.runparams().math_flavor == OutputParams::MathAsMathML3)
features.addCSSSnippet("mtext.framebox { border: 1px solid black; }"); features.addCSSSnippet("mtext.framebox { border: 1px solid black; }");
else if (features.runparams().math_flavor == OutputParams::MathAsHTML) else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
features.addCSSSnippet("span.framebox { border: 1px solid black; }"); features.addCSSSnippet("span.framebox { border: 1px solid black; }");
@ -423,7 +426,8 @@ void InsetMathBoxed::validate(LaTeXFeatures & features) const
// FIXME XHTML // FIXME XHTML
// It'd be better to be able to get this from an InsetLayout, but at present // It'd be better to be able to get this from an InsetLayout, but at present
// InsetLayouts do not seem really to work for things that aren't InsetTexts. // InsetLayouts do not seem really to work for things that aren't InsetTexts.
if (features.runparams().math_flavor == OutputParams::MathAsMathML) if (features.runparams().math_flavor == OutputParams::MathAsMathMLCore ||
features.runparams().math_flavor == OutputParams::MathAsMathML3)
features.addCSSSnippet("mtext.boxed { border: 1px solid black; }"); features.addCSSSnippet("mtext.boxed { border: 1px solid black; }");
else if (features.runparams().math_flavor == OutputParams::MathAsHTML) else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
features.addCSSSnippet("span.boxed { border: 1px solid black; }"); features.addCSSSnippet("span.boxed { border: 1px solid black; }");

View File

@ -98,7 +98,8 @@ void InsetMathEnsureMath::validate(LaTeXFeatures & features) const
// FIXME XHTML // FIXME XHTML
// It'd be better to be able to get this from an InsetLayout, but at present // It'd be better to be able to get this from an InsetLayout, but at present
// InsetLayouts do not seem really to work for things that aren't InsetTexts. // InsetLayouts do not seem really to work for things that aren't InsetTexts.
if (features.runparams().math_flavor == OutputParams::MathAsMathML) if (features.runparams().math_flavor == OutputParams::MathAsMathMLCore ||
features.runparams().math_flavor == OutputParams::MathAsMathML3)
features.addCSSSnippet("mstyle.math { font-style: italic; }"); features.addCSSSnippet("mstyle.math { font-style: italic; }");
else if (features.runparams().math_flavor == OutputParams::MathAsHTML) else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
features.addCSSSnippet("span.mathbox { font-style: italic; }"); features.addCSSSnippet("span.mathbox { font-style: italic; }");

View File

@ -2655,9 +2655,13 @@ docstring InsetMathHull::xhtml(XMLStream & xs, OutputParams const & op) const
} }
// FIXME Eventually we would like to do this inset by inset. // FIXME Eventually we would like to do this inset by inset.
if (mathtype == BufferParams::MathML) { if (mathtype == BufferParams::MathML3 || mathtype == BufferParams::MathMLCore) {
MathMLStream::MathMLVersion mathml_version = MathMLStream::mathmlCore;
if (mathtype == BufferParams::MathML3)
mathml_version = MathMLStream::mathml3;
odocstringstream os; odocstringstream os;
MathMLStream ms(os, "", MathMLStream::mathmlCore); MathMLStream ms(os, "", mathml_version);
try { try {
mathmlize(ms); mathmlize(ms);
success = true; success = true;

View File

@ -552,7 +552,7 @@ Preamble::Preamble() : one_language(true), explicit_babel(false),
// h_font_roman_opts; // h_font_roman_opts;
// h_font_sans_opts; // h_font_sans_opts;
// h_font_typewriter_opts; // h_font_typewriter_opts;
//h_font_cjk // h_font_cjk
h_is_mathindent = "0"; h_is_mathindent = "0";
h_math_numbering_side = "default"; h_math_numbering_side = "default";
h_graphics = "default"; h_graphics = "default";
@ -562,6 +562,7 @@ Preamble::Preamble() : one_language(true), explicit_babel(false),
h_html_math_output = "0"; h_html_math_output = "0";
h_docbook_table_output = "0"; h_docbook_table_output = "0";
h_docbook_mathml_prefix = "1"; h_docbook_mathml_prefix = "1";
h_docbook_mathml_version = "0";
h_index[0] = "Index"; h_index[0] = "Index";
h_index_command = "default"; h_index_command = "default";
h_inputencoding = "auto-legacy"; h_inputencoding = "auto-legacy";
@ -2168,6 +2169,7 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc, string const & outfiled
<< "\\html_be_strict " << h_html_be_strict << "\n" << "\\html_be_strict " << h_html_be_strict << "\n"
<< "\\docbook_table_output " << h_docbook_table_output << "\n" << "\\docbook_table_output " << h_docbook_table_output << "\n"
<< "\\docbook_mathml_prefix " << h_docbook_mathml_prefix << "\n" << "\\docbook_mathml_prefix " << h_docbook_mathml_prefix << "\n"
<< "\\docbook_mathml_version " << h_docbook_mathml_version << "\n"
<< authors_ << authors_
<< "\\end_header\n\n" << "\\end_header\n\n"
<< "\\begin_body\n"; << "\\begin_body\n";

View File

@ -199,6 +199,7 @@ private:
std::string h_html_math_output; std::string h_html_math_output;
std::string h_docbook_table_output; std::string h_docbook_table_output;
std::string h_docbook_mathml_prefix; std::string h_docbook_mathml_prefix;
std::string h_docbook_mathml_version;
std::string h_index[99]; std::string h_index[99];
std::string h_index_command; std::string h_index_command;
std::string h_inputencoding; 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 // Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own. // independent branches. Instead add your own.
#define LYX_FORMAT_LYX 630 // spitz: language updates #define LYX_FORMAT_LYX 631 // tcuvelier: add MathML version
#define LYX_FORMAT_TEX2LYX 630 #define LYX_FORMAT_TEX2LYX 631
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER #ifndef _MSC_VER