#include "support/debug.h"
#include "support/lassert.h"
#include "support/lstrings.h"
+#include "support/textutils.h"
#include <vector>
namespace html {
-docstring escapeChar(char_type c)
+docstring escapeChar(char_type c, XHTMLStream::EscapeSettings e)
{
docstring str;
- switch (c) {
- case ' ':
- str += " ";
- break;
- case '&':
- str += "&";
- break;
- case '<':
- str += "<";
- break;
- case '>':
- str += ">";
- break;
- default:
+ switch (e) {
+ case XHTMLStream::ESCAPE_NONE:
str += c;
break;
+ case XHTMLStream::ESCAPE_ALL:
+ if (c == '<') {
+ str += "<";
+ break;
+ } else if (c == '>') {
+ str += ">";
+ break;
+ }
+ // fall through
+ case XHTMLStream::ESCAPE_AND:
+ if (c == '&')
+ str += "&";
+ else
+ str +=c ;
+ break;
}
return str;
}
// escape what needs escaping
-docstring htmlize(docstring const & str) {
+docstring htmlize(docstring const & str, XHTMLStream::EscapeSettings e) {
odocstringstream d;
docstring::const_iterator it = str.begin();
docstring::const_iterator en = str.end();
for (; it != en; ++it)
- d << escapeChar(*it);
+ d << escapeChar(*it, e);
return d.str();
}
-string escapeChar(char c)
+string escapeChar(char c, XHTMLStream::EscapeSettings e)
{
string str;
- switch (c) {
- case ' ':
- str += " ";
- break;
- case '&':
- str += "&";
- break;
- case '<':
- str += "<";
- break;
- case '>':
- str += ">";
- break;
- default:
+ switch (e) {
+ case XHTMLStream::ESCAPE_NONE:
str += c;
break;
+ case XHTMLStream::ESCAPE_ALL:
+ if (c == '<') {
+ str += "<";
+ break;
+ } else if (c == '>') {
+ str += ">";
+ break;
+ }
+ // fall through
+ case XHTMLStream::ESCAPE_AND:
+ if (c == '&')
+ str += "&";
+ else
+ str +=c ;
+ break;
}
return str;
}
// escape what needs escaping
-string htmlize(string const & str) {
+string htmlize(string const & str, XHTMLStream::EscapeSettings e) {
ostringstream d;
string::const_iterator it = str.begin();
string::const_iterator en = str.end();
for (; it != en; ++it)
- d << escapeChar(*it);
+ d << escapeChar(*it, e);
return d.str();
}
docstring newname;
docstring::const_iterator it = str.begin();
docstring::const_iterator en = str.end();
- for (; it != en; ++it)
- if (isalnum(*it))
- newname += *it;
- else
- newname += '_';
+ for (; it != en; ++it) {
+ char_type const c = *it;
+ newname += isAlnumASCII(c) ? c : char_type('_');
+ }
return newname;
}
{
string output = "<" + tag_;
if (!attr_.empty())
- output += " " + html::htmlize(attr_);
+ output += " " + html::htmlize(attr_, XHTMLStream::ESCAPE_NONE);
output += ">";
return from_utf8(output);
}
{
string output = "<" + tag_;
if (!attr_.empty())
- output += " " + html::htmlize(attr_);
+ output += " " + html::htmlize(attr_, XHTMLStream::ESCAPE_NONE);
output += " />";
return from_utf8(output);
}
////////////////////////////////////////////////////////////////
XHTMLStream::XHTMLStream(odocstream & os)
- : os_(os), nextraw_(false)
+ : os_(os), escape_(ESCAPE_ALL)
{}
XHTMLStream & XHTMLStream::operator<<(docstring const & d)
{
clearTagDeque();
- if (nextraw_) {
- os_ << d;
- nextraw_ = false;
- } else
- os_ << html::htmlize(d);
+ os_ << html::htmlize(d, escape_);
+ escape_ = ESCAPE_ALL;
return *this;
}
{
clearTagDeque();
docstring const d = from_ascii(s);
- if (nextraw_) {
- os_ << d;
- nextraw_ = false;
- } else
- os_ << html::htmlize(d);
+ os_ << html::htmlize(d, escape_);
+ escape_ = ESCAPE_ALL;
return *this;
}
XHTMLStream & XHTMLStream::operator<<(char_type c)
{
clearTagDeque();
- if (nextraw_) {
- os_ << c;
- nextraw_ = false;
- } else
- os_ << html::escapeChar(c);
+ os_ << html::escapeChar(c, escape_);
+ escape_ = ESCAPE_ALL;
return *this;
}
XHTMLStream & XHTMLStream::operator<<(char c)
{
clearTagDeque();
- if (nextraw_) {
- os_ << c;
- nextraw_ = false;
- } else
- os_ << html::escapeChar(c);
+ string const d = html::escapeChar(c, escape_);
+ escape_ = ESCAPE_ALL;
return *this;
}
{
clearTagDeque();
os_ << i;
- nextraw_ = false;
+ escape_ = ESCAPE_ALL;
return *this;
}
-XHTMLStream & XHTMLStream::operator<<(NextRaw const &)
+XHTMLStream & XHTMLStream::operator<<(EscapeSettings e)
{
- nextraw_ = true;
+ escape_ = e;
return *this;
}
// to close.
// is this tag itself pending?
// non-const iterators because we may call erase().
- TagDeque::iterator dit = pending_tags_.begin();
- TagDeque::iterator const den = pending_tags_.end();
+ TagStack::iterator dit = pending_tags_.begin();
+ TagStack::iterator const den = pending_tags_.end();
for (; dit != den; ++dit) {
if (dit->tag_ == etag.tag_) {
// it was pending, so we just erase it
xs.cr();
}
if (!deferred.empty()) {
- xs << XHTMLStream::NextRaw() << deferred;
+ xs << XHTMLStream::ESCAPE_NONE << deferred;
xs.cr();
}
}
if (!style.counter.empty())
buf.params().documentClass().counters().step(style.counter, OutputUpdate);
- openTag(xs, style);
+ openTag(xs, style, pbegin->params());
// Label around sectioning number:
// FIXME Probably need to account for LABEL_MANUAL