commit e70cdfd3a222f12ab25a8c7296b180018bc06381
Author: Thibaut Cuvelier <[email protected]>
Date: Sun Jan 8 02:27:36 2023 +0100
InsetMathBox: split the boxed text into <mtext> and other tags, while
boxing the whole inset within an <mrow>.
Rationales:
- previously, <mstyle> was used, but it's being deprecated for MathML 4
Core in favour of CSS and <mrow> (not a big deal in itself)
- the whole box cannot be hosted within the same tag, because neither
<mstyle> nor <mrow> can have text, they need an intermediate container, <mtext>
(which cannot hold anything else that pure text)
- new behaviour: always output a container for the whole box that has the
right attributes, i.e. an <mrow>; split the content of the cell to have text
and other tags set apart (text in <mtext>, other tags left as they were)
Old behaviour, invalid MathML (2 to 4):
<mstyle XXX>text<mn>.</mn></mstyle>
New behaviour, valid MathML:
<mrow XXX><mtext>text</mtext><mn>.</mn></mrow>
---
src/mathed/InsetMathBox.cpp | 89 +++++++++++++++++++++++++++++++++++-------
1 files changed, 74 insertions(+), 15 deletions(-)
diff --git a/src/mathed/InsetMathBox.cpp b/src/mathed/InsetMathBox.cpp
index f3ba7a7..30cbd14 100644
--- a/src/mathed/InsetMathBox.cpp
+++ b/src/mathed/InsetMathBox.cpp
@@ -25,6 +25,7 @@
#include "frontends/Painter.h"
#include <algorithm>
+#include <iostream>
#include <ostream>
using namespace lyx::support;
@@ -57,16 +58,82 @@ void InsetMathBox::normalize(NormalStream & os) const
}
+namespace {
+void splitAndWrapInMText(MathMLStream & ms, MathData const & cell,
+ const std::string & attributes)
+{
+ // First, generate the inset into a string of its own.
+ docstring inset_contents;
+ {
+ odocstringstream ostmp;
+ MathMLStream mstmp(ostmp, ms.xmlns());
+
+ SetMode textmode(mstmp, true);
+ mstmp << cell;
+
+ inset_contents = ostmp.str();
+ }
+
+ std::cout << '"' << to_ascii(inset_contents) << '"' << std::endl;
+
+ // No tags are allowed within <m:mtext>: split the string if there are
tags.
+ std::vector<docstring> parts;
+ while (true) {
+ std::size_t angle_pos = inset_contents.find('<');
+ if (angle_pos == docstring::npos)
+ break;
+
+ // String structure:
+ // - prefix: pure text, no tag
+ // - tag to split: something like <m:mn>1</m:mn> or more
complicated
+ // (like nested tags), with or without name space
+ // - rest to be taken care of in the next iteration
+
+ // Push the part before the tag.
+ parts.emplace_back(inset_contents.substr(0, angle_pos));
+ inset_contents = inset_contents.substr(angle_pos);
+ // Now, inset_contents starts with the tag to isolate, so that
+ // inset_contents[0] == '<'
+
+ // Push the tag, up to its end. Process: find the tag name
(either
+ // before > or the first attribute of the tag), then the
matching end
+ // tag, then proceed with pushing.
+ const std::size_t tag_name_end =
+ std::min(inset_contents.find(' ', 1),
inset_contents.find('>', 1));
+ const std::size_t tag_name_length = tag_name_end - 1;
+ const docstring tag_name = inset_contents.substr(1,
tag_name_length);
+
+ const std::size_t end_tag_start =
+ inset_contents.find(tag_name, tag_name_end + 1);
+ const std::size_t end_tag = inset_contents.find('>',
end_tag_start);
+
+ parts.emplace_back(inset_contents.substr(0, end_tag + 1));
+ inset_contents = inset_contents.substr(end_tag + 1);
+ }
+ parts.emplace_back(inset_contents);
+
+ // Finally, output the complete inset: escape the test in <m:mtext>,
leave
+ // the other tags untouched.
+ ms << MTag("mrow", attributes);
+ for (int i = 0; i < parts.size(); i += 2) {
+ ms << MTag("mtext")
+ << parts[i]
+ << ETag("mtext");
+ if (parts.size() > i + 1)
+ ms << parts[i + 1];
+ }
+ ms << ETag("mrow");
+}
+}
+
+
void InsetMathBox::mathmlize(MathMLStream & ms) const
{
// FIXME XHTML
// Need to do something special for tags here.
// Probably will have to involve deferring them, which
// means returning something from this routine.
- SetMode textmode(ms, true);
- ms << MTag("mtext", "class='mathbox'")
- << cell(0)
- << ETag("mtext");
+ splitAndWrapInMText(ms, cell(0), "class='mathbox'");
}
@@ -165,10 +232,7 @@ void InsetMathFBox::normalize(NormalStream & os) const
void InsetMathFBox::mathmlize(MathMLStream & ms) const
{
- SetMode textmode(ms, true);
- ms << MTag("mtext", "class='fbox'")
- << cell(0)
- << ETag("mtext");
+ splitAndWrapInMText(ms, cell(0), "class='fbox'");
}
@@ -311,10 +375,7 @@ void InsetMathMakebox::mathmlize(MathMLStream & ms) const
{
// FIXME We could do something with the other arguments.
std::string const cssclass = framebox_ ? "framebox" : "makebox";
- SetMode textmode(ms, true);
- ms << MTag("mtext", "class='" + cssclass + "'")
- << cell(2)
- << ETag("mtext");
+ splitAndWrapInMText(ms, cell(2), "class='" + cssclass + "'");
}
@@ -393,9 +454,7 @@ void InsetMathBoxed::infoize(odocstream & os) const
void InsetMathBoxed::mathmlize(MathMLStream & ms) const
{
- ms << MTag("mtext", "class='boxed'")
- << cell(0)
- << ETag("mtext");
+ splitAndWrapInMText(ms, cell(0), "class='boxed'");
}
--
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs