From: Richard Heck Date: Mon, 29 Mar 2010 22:52:13 +0000 (+0000) Subject: The beginnings of pure HTML output of math, for our internal XHTML X-Git-Tag: 2.0.0~3644 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=30b18aec37da1355c8947cfeb8d181e7b5a9a4f9;p=features.git The beginnings of pure HTML output of math, for our internal XHTML output routines. The idea is that in some cases people may not want to use MathML, so we are going to try to give options. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@33936 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/mathed/InsetMath.cpp b/src/mathed/InsetMath.cpp index a1cc8d8049..943ca90263 100644 --- a/src/mathed/InsetMath.cpp +++ b/src/mathed/InsetMath.cpp @@ -130,6 +130,16 @@ void InsetMath::mathmlize(MathStream & os) const } +void InsetMath::htmlize(HtmlStream & os) const +{ + os << ""; + os << MTag("span", "style='color: red;'"); + NormalStream ns(os.os()); + normalize(ns); + os << ETag("span"); +} + + HullType InsetMath::getType() const { return hullNone; diff --git a/src/mathed/InsetMath.h b/src/mathed/InsetMath.h index 555762c8c7..e043a733fb 100644 --- a/src/mathed/InsetMath.h +++ b/src/mathed/InsetMath.h @@ -73,6 +73,7 @@ class InsetMathUnknown; class InsetMathRef; +class HtmlStream; class NormalStream; class OctaveStream; class MapleStream; @@ -186,8 +187,13 @@ public: virtual void maxima(MaximaStream &) const; /// write content as something readable by Mathematica virtual void mathematica(MathematicaStream &) const; - /// write content as something resembling MathML + /// write content as MathML virtual void mathmlize(MathStream &) const; + /// write content as HTML, best we can. + /// the idea for this, and some of the details, come from + /// eLyXer, written by Alex Fernandez. no code is borrowed. rather, + /// we try to mimic how eLyXer outputs some math. + virtual void htmlize(HtmlStream &) const; /// write content as something readable by Octave virtual void octave(OctaveStream &) const; diff --git a/src/mathed/InsetMathGrid.cpp b/src/mathed/InsetMathGrid.cpp index 7ce5858145..14f9ba87dd 100644 --- a/src/mathed/InsetMathGrid.cpp +++ b/src/mathed/InsetMathGrid.cpp @@ -998,6 +998,27 @@ void InsetMathGrid::mathmlize(MathStream & os) const } +void InsetMathGrid::htmlize(HtmlStream & os) const +{ + bool const havetable = nrows() > 1 || ncols() > 1; + if (!havetable) { + os << cell(index(0, 0)); + return; + } + os << MTag("table", "class='mathtable'"); + for (row_type row = 0; row < nrows(); ++row) { + os << MTag("tr");; + for (col_type col = 0; col < ncols(); ++col) { + os << MTag("td"); + os << cell(index(row, col)); + os << ETag("td"); + } + os << ETag("tr");; + } + os << ETag("table"); +} + + void InsetMathGrid::write(WriteStream & os) const { write(os, 0, 0, nrows(), ncols()); diff --git a/src/mathed/InsetMathGrid.h b/src/mathed/InsetMathGrid.h index 17e9650124..cd86b6b7f6 100644 --- a/src/mathed/InsetMathGrid.h +++ b/src/mathed/InsetMathGrid.h @@ -222,6 +222,8 @@ public: //void maple(MapleStream &) const; /// void mathmlize(MathStream &) const; + /// + void htmlize(HtmlStream &) const; /// //void octave(OctaveStream &) const; diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index 35e4186e2b..f977dacb97 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -1810,14 +1810,38 @@ int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) cons docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const &) const { - if (getType() == hullSimple) - xs << html::StartTag("math", "xmlns=\"http://www.w3.org/1998/Math/MathML\"", true); - else - xs << html::StartTag("math", - "display=\"block\" xmlns=\"http://www.w3.org/1998/Math/MathML\"", true); - MathStream ms(xs.os()); - InsetMathGrid::mathmlize(ms); - xs << html::EndTag("math"); + BufferParams::MathOutput mathtype = buffer().params().html_math_output; + // FIXME Eventually we would like to do this inset by inset. + switch (mathtype) { + case BufferParams::MathML: { + if (getType() == hullSimple) + xs << html::StartTag("math", + "xmlns=\"http://www.w3.org/1998/Math/MathML\"", true); + else + xs << html::StartTag("math", + "display=\"block\" xmlns=\"http://www.w3.org/1998/Math/MathML\"", true); + MathStream ms(xs.os()); + InsetMathGrid::mathmlize(ms); + xs << html::EndTag("math"); + break; + } + case BufferParams::HTML: { + string tag = (getType() == hullSimple) ? "span" : "div"; + xs << html::StartTag(tag, "class='formula'", true); + HtmlStream ms(xs.os()); + InsetMathGrid::htmlize(ms); + xs << html::EndTag(tag); + break; + } + case BufferParams::Images: { + LYXERR0("Image output for math presently unsupported."); + break; + } + case BufferParams::LaTeX: { + // FIXME Obviously, the only real question is how to wrap this. + LYXERR0("LaTeX output for math presently unsupported."); + } + } // end switch return docstring(); } diff --git a/src/mathed/MathExtern.cpp b/src/mathed/MathExtern.cpp index fb0ed20517..f394183965 100644 --- a/src/mathed/MathExtern.cpp +++ b/src/mathed/MathExtern.cpp @@ -54,6 +54,7 @@ namespace lyx { namespace { enum ExternalMath { + HTML, MAPLE, MAXIMA, MATHEMATICA, @@ -120,7 +121,7 @@ MathData::iterator extractArgument(MathData & ar, // leave out delimiters if this is a function argument // unless we are doing MathML, in which case we do want // the delimiters - if (function && kind != MATHML) { + if (function && kind != MATHML && kind != HTML) { MathData const & arg = (*pos)->asDelimInset()->cell(0); MathData::const_iterator cur = arg.begin(); MathData::const_iterator end = arg.end(); @@ -948,16 +949,16 @@ void extractLims(MathData & ar) void extractStructure(MathData & ar, ExternalMath kind) { //lyxerr << "\nStructure from: " << ar << endl; - if (kind != MATHML) + if (kind != MATHML && kind != HTML) splitScripts(ar); extractDelims(ar); extractIntegrals(ar, kind); - if (kind != MATHML) + if (kind != MATHML && kind != HTML) extractSums(ar); extractNumbers(ar); extractMatrices(ar); extractFunctions(ar, kind); - if (kind != MATHML) { + if (kind != MATHML && kind != HTML) { extractDets(ar); extractDiff(ar); extractExps(ar); @@ -1434,6 +1435,21 @@ void mathmlize(MathData const & dat, MathStream & os) } +void htmlize(MathData const & dat, HtmlStream & os) +{ + MathData ar = dat; + extractStructure(ar, HTML); + if (ar.size() == 0) + return; + if (ar.size() == 1) { + os << ar.front(); + return; + } + for (MathData::const_iterator it = ar.begin(); it != ar.end(); ++it) + (*it)->htmlize(os); +} + + // convert this inset somehow to a number bool extractNumber(MathData const & ar, int & i) { diff --git a/src/mathed/MathExtern.h b/src/mathed/MathExtern.h index 199295ae96..fba3ecbe9e 100644 --- a/src/mathed/MathExtern.h +++ b/src/mathed/MathExtern.h @@ -16,6 +16,7 @@ namespace lyx { +class HtmlStream; class NormalStream; class MapleStream; class MaximaStream; @@ -26,6 +27,7 @@ class WriteStream; class MathData; void write(MathData const &, WriteStream &); +void htmlize(MathData const &, HtmlStream &); void normalize(MathData const &, NormalStream &); void maple(MathData const &, MapleStream &); void maxima(MathData const &, MaximaStream &); diff --git a/src/mathed/MathStream.cpp b/src/mathed/MathStream.cpp index 2d2be81254..bcd7160bc0 100644 --- a/src/mathed/MathStream.cpp +++ b/src/mathed/MathStream.cpp @@ -346,6 +346,99 @@ MathStream & operator<<(MathStream & ms, docstring const & s) } +////////////////////////////////////////////////////////////////////// + + +HtmlStream::HtmlStream(odocstream & os) + : os_(os), tab_(0), line_(0), lastchar_(0), in_text_(false) +{} + + +void HtmlStream::defer(docstring const & s) +{ + deferred_ << s; +} + + +void HtmlStream::defer(string const & s) +{ + deferred_ << from_utf8(s); +} + + +docstring HtmlStream::deferred() const +{ + return deferred_.str(); +} + + +HtmlStream & operator<<(HtmlStream & ms, MathAtom const & at) +{ + at->htmlize(ms); + return ms; +} + + +HtmlStream & operator<<(HtmlStream & ms, MathData const & ar) +{ + htmlize(ar, ms); + return ms; +} + + +HtmlStream & operator<<(HtmlStream & ms, char const * s) +{ + ms.os() << s; + return ms; +} + + +HtmlStream & operator<<(HtmlStream & ms, char c) +{ + ms.os() << c; + return ms; +} + + +HtmlStream & operator<<(HtmlStream & ms, char_type c) +{ + ms.os().put(c); + return ms; +} + + +HtmlStream & operator<<(HtmlStream & ms, MTag const & t) +{ + ++ms.tab(); + ms.os() << "\n"; + ms.os() << '<' << from_ascii(t.tag_); + if (!t.attr_.empty()) + ms.os() << " " << from_ascii(t.attr_); + ms << '>'; + return ms; +} + + +HtmlStream & operator<<(HtmlStream & ms, ETag const & t) +{ + ms.os() << "\n"; + if (ms.tab() > 0) + --ms.tab(); + ms.os() << "'; + return ms; +} + + +HtmlStream & operator<<(HtmlStream & ms, docstring const & s) +{ + ms.os() << s; + return ms; +} + + +////////////////////////////////////////////////////////////////////// + + SetMode::SetMode(MathStream & os, bool text) : os_(os), opened_(false) { diff --git a/src/mathed/MathStream.h b/src/mathed/MathStream.h index 6fb8f8265f..cf08afe23c 100644 --- a/src/mathed/MathStream.h +++ b/src/mathed/MathStream.h @@ -352,6 +352,67 @@ private: }; +class HtmlStream { +public: + /// + explicit HtmlStream(odocstream & os); + /// + void cr(); + /// + odocstream & os() { return os_; } + /// + int line() const { return line_; } + /// + int & tab() { return tab_; } + /// + friend HtmlStream & operator<<(HtmlStream &, char const *); + /// + void defer(docstring const &); + /// + void defer(std::string const &); + /// + docstring deferred() const; + /// + bool inText() const { return in_text_; } +private: + /// + void setTextMode() { in_text_ = true; } + /// + void setMathMode() { in_text_ = false; } + /// + odocstream & os_; + /// + int tab_; + /// + int line_; + /// + char lastchar_; + /// + bool in_text_; + /// + odocstringstream deferred_; + /// + friend class SetMode; +}; + +/// +HtmlStream & operator<<(HtmlStream &, MathAtom const &); +/// +HtmlStream & operator<<(HtmlStream &, MathData const &); +/// +HtmlStream & operator<<(HtmlStream &, docstring const &); +/// +HtmlStream & operator<<(HtmlStream &, char const *); +/// +HtmlStream & operator<<(HtmlStream &, char); +/// +HtmlStream & operator<<(HtmlStream &, char_type); +/// +HtmlStream & operator<<(HtmlStream &, MTag const &); +/// +HtmlStream & operator<<(HtmlStream &, ETag const &); + + // // Debugging //