diff --git a/src/Layout.h b/src/Layout.h index 54d44df8e8..596c082b5d 100644 --- a/src/Layout.h +++ b/src/Layout.h @@ -122,6 +122,8 @@ public: /// std::string const & htmllabelattr() const; /// + std::string defaultCSSClass() const; + /// bool htmllabelfirst() const { return htmllabelfirst_; } /// docstring htmlstyle() const; @@ -254,8 +256,6 @@ private: /// generates the default CSS for this layout void makeDefaultCSS() const; /// - std::string defaultCSSClass() const; - /// std::string defaultCSSItemClass() const { return defaultCSSClass() + "_item"; } /// std::string defaultCSSLabelClass() const { return defaultCSSClass() + "_label"; } diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index 653c286487..f3ba6921cf 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -2394,6 +2394,7 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, XHTMLStream & xs, OutputParams const & runparams, Font const & outerfont, + bool fortoc, pos_type initial) const { docstring retval; @@ -2435,11 +2436,14 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, Inset const * inset = getInset(i); if (inset) { + InsetCommand const * ic = inset->asInsetCommand(); InsetLayout const & il = inset->getLayout(); - OutputParams np = runparams; - if (!il.htmlisblock()) - np.html_in_par = true; - retval += inset->xhtml(xs, np); + if (!fortoc || il.isInToc() || (ic && ic->isInToc())) { + OutputParams np = runparams; + if (!il.htmlisblock()) + np.html_in_par = true; + retval += inset->xhtml(xs, np); + } } else { char_type c = d->text_[i]; diff --git a/src/Paragraph.h b/src/Paragraph.h index 94a139ab5e..8bb275576f 100644 --- a/src/Paragraph.h +++ b/src/Paragraph.h @@ -166,6 +166,7 @@ public: XHTMLStream & xs, OutputParams const & runparams, Font const & outerfont, + bool fortoc = false, pos_type initial = 0) const; /// diff --git a/src/insets/Inset.h b/src/insets/Inset.h index 8d2f1f86df..66c2c40c01 100644 --- a/src/insets/Inset.h +++ b/src/insets/Inset.h @@ -37,6 +37,7 @@ class DocIterator; class FuncRequest; class FuncStatus; class InsetCollapsable; +class InsetCommand; class InsetIterator; class InsetLayout; class InsetList; @@ -138,6 +139,10 @@ public: virtual InsetTabular * asInsetTabular() { return 0; } /// is this inset based on the InsetTabular class? virtual InsetTabular const * asInsetTabular() const { return 0; } + /// is this inset based on the InsetCommand class? + virtual InsetCommand * asInsetCommand() { return 0; } + /// is this inset based on the InsetCommand class? + virtual InsetCommand const * asInsetCommand() const { return 0; } /// the real dispatcher void dispatch(Cursor & cur, FuncRequest & cmd); diff --git a/src/insets/InsetCommand.h b/src/insets/InsetCommand.h index 090a85abbb..fee67bf7be 100644 --- a/src/insets/InsetCommand.h +++ b/src/insets/InsetCommand.h @@ -58,6 +58,12 @@ public: docstring const getFirstNonOptParam() const { return p_.getFirstNonOptParam(); } /// update label and references. virtual void updateCommand(docstring const &, bool) {} + /// + virtual InsetCommand * asInsetCommand() { return this; } + /// + virtual InsetCommand const * asInsetCommand() const { return this; } + /// whether to include this inset in the strings generated for the TOC + virtual bool isInToc() const { return false; } protected: /// @@ -109,8 +115,6 @@ private: virtual docstring screenLabel() const = 0; /// bool showInsetDialog(BufferView * bv) const; - -private: /// InsetCommandParams p_; /// diff --git a/src/insets/InsetHyperlink.h b/src/insets/InsetHyperlink.h index 54850611ac..23fd4ad1d1 100644 --- a/src/insets/InsetHyperlink.h +++ b/src/insets/InsetHyperlink.h @@ -47,12 +47,14 @@ public: /// static ParamInfo const & findInfo(std::string const &); /// - static std::string defaultCommand() { return "href"; }; + static std::string defaultCommand() { return "href"; } /// static bool isCompatibleCommand(std::string const & s) { return s == "href"; } /// Force inset into LTR environment if surroundings are RTL? bool forceLTR() const { return true; } + /// + virtual bool isInToc() const { return true; } private: Inset * clone() const { return new InsetHyperlink(*this); } }; diff --git a/src/insets/InsetTOC.cpp b/src/insets/InsetTOC.cpp index 565fce3d6f..9f20ee5675 100644 --- a/src/insets/InsetTOC.cpp +++ b/src/insets/InsetTOC.cpp @@ -13,12 +13,18 @@ #include "InsetTOC.h" #include "Buffer.h" +#include "BufferParams.h" #include "DispatchResult.h" #include "FuncRequest.h" +#include "LaTeXFeatures.h" #include "MetricsInfo.h" #include "OutputParams.h" +#include "output_xhtml.h" +#include "Paragraph.h" +#include "TextClass.h" #include "TocBackend.h" +#include "support/debug.h" #include "support/gettext.h" #include @@ -67,4 +73,99 @@ int InsetTOC::docbook(odocstream & os, OutputParams const &) const } +docstring InsetTOC::xhtml(XHTMLStream &, OutputParams const & op) const +{ + // we'll use our own stream, because we are going to defer everything. + // that's how we deal with the fact that we're probably inside a standard + // paragraph, and we don't want to be. + odocstringstream ods; + XHTMLStream xs(ods); + // FIXME XHTML + // This is temporary. We'll get the main TOC working first. The rest will + // then be a fairly simple adapation of this code, I hope. + if (getCmdName() != "tableofcontents") + return docstring(); + Toc const & toc = buffer().tocBackend().toc("tableofcontents"); + if (toc.empty()) + return docstring(); + + xs << StartTag("div", "class='toc'"); + + // we want to figure out look like a chapter, section, or whatever. + // so we're going to look for the layout with the minimum toclevel + // number. we'll take the first one, just because. + DocumentClass const & dc = buffer().params().documentClass(); + TextClass::LayoutList::const_iterator lit = dc.begin(); + TextClass::LayoutList::const_iterator len = dc.end(); + int minlevel = 1000; + Layout const * lay = NULL; + for (; lit != len; ++lit) { + int const level = lit->toclevel; + if (level == Layout::NOT_IN_TOC || level >= minlevel) + continue; + lay = &*lit; + minlevel = level; + } + + string const tocclass = lay ? lay->defaultCSSClass() + " ": ""; + string const tocattr = "class='" + tocclass + "tochead'"; + + xs << StartTag("div", tocattr) + << _("Table of Contents") + << EndTag("div"); + Toc::const_iterator it = toc.begin(); + Toc::const_iterator const en = toc.end(); + int lastdepth = 0; + for (; it != en; ++it) { + Paragraph const & par = it->dit().innerParagraph(); + Font const dummy; + int const depth = it->depth(); + if (depth > lastdepth) { + xs.cr(); + // open as many tags as we need to open to get to this level + // this includes the tag for the current level + for (int i = lastdepth + 1; i <= depth; ++i) { + stringstream attr; + attr << "class='lyxtoc-" << i << "'"; + xs << StartTag("div", attr.str()); + } + lastdepth = depth; + } + else if (depth < lastdepth) { + // close as many as we have to close to get back to this level + // this includes closing the last tag at this level + for (int i = lastdepth; i >= depth; --i) + xs << EndTag("div"); + // now open our tag + stringstream attr; + attr << "class='lyxtoc-" << depth << "'"; + xs << StartTag("div", attr.str()); + lastdepth = depth; + } else { + // no change of level, so close and open + xs << EndTag("div"); + stringstream attr; + attr << "class='lyxtoc-" << depth << "'"; + xs << StartTag("div", attr.str()); + } + par.simpleLyXHTMLOnePar(buffer(), xs, op, dummy, true); + } + for (int i = lastdepth; i > 0; --i) + xs << EndTag("div"); + xs << EndTag("div"); + return ods.str(); +} + + +void InsetTOC::validate(LaTeXFeatures & features) const +{ + if (features.runparams().flavor != OutputParams::HTML) + return; + features.addPreambleSnippet(""); +} + } // namespace lyx diff --git a/src/insets/InsetTOC.h b/src/insets/InsetTOC.h index dc65b97ffb..95fbfcdf7c 100644 --- a/src/insets/InsetTOC.h +++ b/src/insets/InsetTOC.h @@ -34,12 +34,16 @@ public: /// int docbook(odocstream &, OutputParams const &) const; /// + docstring xhtml(XHTMLStream & xs, OutputParams const &) const; + /// static ParamInfo const & findInfo(std::string const &); /// - static std::string defaultCommand() { return "tableofcontents"; }; + static std::string defaultCommand() { return "tableofcontents"; } /// static bool isCompatibleCommand(std::string const & cmd) { return cmd == defaultCommand(); } + /// + void validate(LaTeXFeatures & features) const; private: Inset * clone() const { return new InsetTOC(*this); } }; diff --git a/src/output_xhtml.cpp b/src/output_xhtml.cpp index 27f36db5a0..eccc44e657 100644 --- a/src/output_xhtml.cpp +++ b/src/output_xhtml.cpp @@ -238,6 +238,7 @@ void XHTMLStream::clearTagDeque() StartTag const & tag = pending_tags_.front(); // tabs? os_ << tag.asTag(); + cr(); tag_stack_.push_back(tag); pending_tags_.pop_front(); } @@ -306,6 +307,7 @@ XHTMLStream & XHTMLStream::operator<<(CompTag const & tag) clearTagDeque(); // tabs? os_ << tag.asTag(); + cr(); return *this; } @@ -350,7 +352,8 @@ XHTMLStream & XHTMLStream::operator<<(EndTag const & etag) if (dit->tag_ == etag.tag_) { // it was pending, so we just erase it writeError("Tried to close pending tag `" + etag.tag_ - + "' when other tags were pending. Tag discarded."); + + "' when other tags were pending. Last pending tag is `" + + pending_tags_.back().tag_ + "'. Tag discarded."); pending_tags_.erase(dit); return *this; } @@ -378,6 +381,7 @@ XHTMLStream & XHTMLStream::operator<<(EndTag const & etag) if (etag.tag_ == tag_stack_.back().tag_) { // output it... os_ << etag.asEndTag(); + cr(); // ...and forget about it tag_stack_.pop_back(); return *this; @@ -420,12 +424,14 @@ XHTMLStream & XHTMLStream::operator<<(EndTag const & etag) TagStack fontstack; while (curtag.tag_ != etag.tag_) { os_ << curtag.asEndTag(); + cr(); fontstack.push_back(curtag); tag_stack_.pop_back(); curtag = tag_stack_.back(); } // now close our tag... os_ << etag.asEndTag(); + cr(); tag_stack_.pop_back(); // ...and restore the other tags. @@ -705,7 +711,7 @@ ParagraphList::const_iterator makeEnvironmentHtml(Buffer const & buf, openItemTag(xs, style); } par->simpleLyXHTMLOnePar(buf, xs, runparams, - text.outerFont(distance(begin, par)), sep); + text.outerFont(distance(begin, par)), false, sep); ++par; // We may not want to close the tag yet, in particular, // if we're not at the end...