summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/context.cpp114
-rw-r--r--src/htmlgen.cpp13
-rw-r--r--src/resourcemgr.cpp10
-rw-r--r--src/resourcemgr.h2
-rwxr-xr-xsrc/template.cpp235
-rw-r--r--src/template.h5
6 files changed, 262 insertions, 117 deletions
diff --git a/src/context.cpp b/src/context.cpp
index 2ae62a0..fc7a586 100644
--- a/src/context.cpp
+++ b/src/context.cpp
@@ -9377,61 +9377,82 @@ class SymbolContext::Private
const Definition *prevScope = prev ? prev->getOuterScope() : 0;
const MemberDef *md = toMemberDef(m_def);
bool isFunctionLike = md && (md->isFunction() || md->isSlot() || md->isSignal());
- bool overloadedFunction = isFunctionLike &&
- ((prevScope!=0 && scope==prevScope) || (scope && scope==nextScope));
- QCString prefix;
- if (md) prefix=md->localName();
- if (overloadedFunction) // overloaded member function
- {
- prefix+=md->argsString();
- // show argument list to disambiguate overloaded functions
- }
- else if (md && isFunctionLike) // unique member function
- {
- prefix+="()"; // only to show it is a function
- }
- bool found=FALSE;
+ bool overloadedFunction = ((prevScope!=0 && scope==prevScope) || (scope && scope==nextScope)) &&
+ md && (md->isFunction() || md->isSlot());
+
QCString name;
- if (m_def->definitionType()==Definition::TypeClass)
+ if (prev==0 && next==0) // unique name
{
- name = m_def->displayName();
- found = TRUE;
- }
- else if (m_def->definitionType()==Definition::TypeNamespace)
- {
- name = m_def->displayName();
- found = TRUE;
- }
- else if (scope==0 || scope==Doxygen::globalScope) // in global scope
- {
- if (md)
+ if (scope!=Doxygen::globalScope)
+ {
+ name = scope->name();
+ }
+ else if (md)
{
const FileDef *fd = md->getBodyDef();
if (fd==0) fd = md->getFileDef();
if (fd)
{
- if (!prefix.isEmpty()) prefix+=": ";
- name = prefix + convertToXML(fd->localName());
- found = TRUE;
+ name = fd->localName();
}
}
}
- else if (md && (md->getClassDef() || md->getNamespaceDef()))
- // member in class or namespace scope
- {
- SrcLangExt lang = md->getLanguage();
- name = m_def->getOuterScope()->qualifiedName()
- + getLanguageSpecificSeparator(lang) + prefix;
- found = TRUE;
- }
- else if (scope) // some thing else? -> show scope
- {
- name = prefix + convertToXML(scope->name());
- found = TRUE;
- }
- if (!found) // fallback
+ else
{
- name = prefix + "("+theTranslator->trGlobalNamespace()+")";
+
+ QCString prefix;
+ if (md) prefix=md->localName();
+ if (overloadedFunction) // overloaded member function
+ {
+ prefix+=md->argsString();
+ // show argument list to disambiguate overloaded functions
+ }
+ else if (md && isFunctionLike) // unique member function
+ {
+ prefix+="()"; // only to show it is a function
+ }
+ bool found=FALSE;
+ if (m_def->definitionType()==Definition::TypeClass)
+ {
+ name = m_def->displayName();
+ found = TRUE;
+ }
+ else if (m_def->definitionType()==Definition::TypeNamespace)
+ {
+ name = m_def->displayName();
+ found = TRUE;
+ }
+ else if (scope==0 || scope==Doxygen::globalScope) // in global scope
+ {
+ if (md)
+ {
+ const FileDef *fd = md->getBodyDef();
+ if (fd==0) fd = md->getFileDef();
+ if (fd)
+ {
+ if (!prefix.isEmpty()) prefix+=": ";
+ name = prefix + convertToXML(fd->localName());
+ found = TRUE;
+ }
+ }
+ }
+ else if (md && (md->resolveAlias()->getClassDef() || md->resolveAlias()->getNamespaceDef()))
+ // member in class or namespace scope
+ {
+ SrcLangExt lang = md->getLanguage();
+ name = m_def->getOuterScope()->qualifiedName()
+ + getLanguageSpecificSeparator(lang) + prefix;
+ found = TRUE;
+ }
+ else if (scope) // some thing else? -> show scope
+ {
+ name = prefix + convertToXML(scope->name());
+ found = TRUE;
+ }
+ if (!found) // fallback
+ {
+ name = prefix + "("+theTranslator->trGlobalNamespace()+")";
+ }
}
return name;
}
@@ -9600,7 +9621,10 @@ class SymbolGroupListContext::Private : public GenericNodeListContext
QCString name = searchName(*it);
if (name!=lastName)
{
- append(SymbolGroupContext::alloc(it_begin,it));
+ if (it!=it_begin)
+ {
+ append(SymbolGroupContext::alloc(it_begin,it));
+ }
it_begin = it;
lastName = name;
}
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
index ad8782b..cde7ef2 100644
--- a/src/htmlgen.cpp
+++ b/src/htmlgen.cpp
@@ -999,13 +999,7 @@ void HtmlGenerator::init()
t << mgr.getAsString("dynsections.js");
if (Config_getBool(SOURCE_BROWSER) && Config_getBool(SOURCE_TOOLTIPS))
{
- t <<
- "\n$(document).ready(function() {\n"
- " $('.code,.codeRef').each(function() {\n"
- " $(this).data('powertip',$('#a'+$(this).attr('href').replace(/.*\\//,'').replace(/[^a-z_A-Z0-9]/g,'_')).html());\n"
- " $(this).powerTip({ placement: 's', smartPlacement: true, mouseOnToPopup: true });\n"
- " });\n"
- "});\n";
+ t << mgr.getAsString("dynsections_tooltips.js");
}
}
}
@@ -2501,7 +2495,7 @@ static void writeDefaultQuickLinks(TextStream &t,bool compact,
t << "<script type=\"text/javascript\" src=\"" << relPath << "menudata.js\"></script>\n";
t << "<script type=\"text/javascript\" src=\"" << relPath << "menu.js\"></script>\n";
t << "<script type=\"text/javascript\">\n";
- t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */\n";
+ t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */\n";
t << "$(function() {\n";
t << " initMenu('" << relPath << "',"
<< (searchEngine?"true":"false") << ","
@@ -2516,14 +2510,13 @@ static void writeDefaultQuickLinks(TextStream &t,bool compact,
}
else
{
- t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */\n";
t << " $(document).ready(function() {\n"
<< " if ($('.searchresults').length > 0) { searchBox.DOMSearchField().focus(); }\n"
<< " });\n";
}
}
t << "});\n";
- t << "/* @license-end */";
+ t << "/* @license-end */\n";
t << "</script>\n";
t << "<div id=\"main-nav\"></div>\n";
}
diff --git a/src/resourcemgr.cpp b/src/resourcemgr.cpp
index 161e480..fb52d99 100644
--- a/src/resourcemgr.cpp
+++ b/src/resourcemgr.cpp
@@ -76,9 +76,11 @@ bool ResourceMgr::writeCategory(const QCString &categoryName,const QCString &tar
return TRUE;
}
-bool ResourceMgr::copyResourceAs(const QCString &name,const QCString &targetDir,const QCString &targetName) const
+bool ResourceMgr::copyResourceAs(const QCString &name,const QCString &targetDir,const QCString &targetName,bool append) const
{
std::string pathName = targetDir.str()+"/"+targetName.str();
+ std::ios_base::openmode mode = std::ofstream::out | std::ofstream::binary;
+ if (append) mode |= std::ofstream::app;
const Resource *res = get(name);
if (res)
{
@@ -86,7 +88,7 @@ bool ResourceMgr::copyResourceAs(const QCString &name,const QCString &targetDir,
{
case Resource::Verbatim:
{
- std::ofstream f(pathName,std::ofstream::out | std::ofstream::binary);
+ std::ofstream f(pathName,mode);
bool ok=false;
if (f.is_open())
{
@@ -137,7 +139,7 @@ bool ResourceMgr::copyResourceAs(const QCString &name,const QCString &targetDir,
break;
case Resource::CSS:
{
- std::ofstream t(pathName,std::ofstream::out | std::ofstream::binary);
+ std::ofstream t(pathName,mode);
if (t.is_open())
{
QCString buf(res->size+1);
@@ -157,7 +159,7 @@ bool ResourceMgr::copyResourceAs(const QCString &name,const QCString &targetDir,
break;
case Resource::SVG:
{
- std::ofstream t(pathName,std::ostream::out | std::ofstream::binary);
+ std::ofstream t(pathName,mode);
if (t.is_open())
{
QCString buf(res->size+1);
diff --git a/src/resourcemgr.h b/src/resourcemgr.h
index 7978e09..3c4c1b3 100644
--- a/src/resourcemgr.h
+++ b/src/resourcemgr.h
@@ -48,7 +48,7 @@ class ResourceMgr
bool copyResource(const QCString &name,const QCString &targetDir) const;
/** Copies a registered resource to a given target directory under a given target name */
- bool copyResourceAs(const QCString &name,const QCString &targetDir,const QCString &targetName) const;
+ bool copyResourceAs(const QCString &name,const QCString &targetDir,const QCString &targetName, bool append=false) const;
/** Gets the resource data as a C string */
QCString getAsString(const QCString &name) const;
diff --git a/src/template.cpp b/src/template.cpp
index 82b35f7..13ce7ef 100755
--- a/src/template.cpp
+++ b/src/template.cpp
@@ -98,30 +98,33 @@ static std::vector<QCString> split(const QCString &str,const QCString &sep,
/** Strips spaces surrounding `=` from string \a in, so
* `foo = 10 bar=5 baz= 'hello'` will become `foo=10 bar=5 baz='hello'`
*/
-static QCString removeSpacesAroundEquals(const QCString &s)
+static void removeSpacesAroundEquals(QCString &s)
{
- if (s.isEmpty()) return s;
- QCString result(s);
- const char *p=s.data();
- char *q = result.rawData();
- char c;
- while ((c=*p++))
+ //printf(">removeSpacesAroundEquals(%s)\n",qPrint(s));
+ uint i=0, dstIdx=0, l=s.length();
+ while (i<l)
{
- if (c==' ') // found a space, see if there is a = as well
+ char c = s[i++];
+ if (c==' ')
{
- const char *t = p;
- bool found=FALSE;
- while (*t==' ' || *t=='=') { if (*t++=='=') found=TRUE; }
- if (found)
+ bool found=false;
+ // look ahead for space or '='
+ uint j=i;
+ while (j<l && (s[j]==' '|| s[j]=='='))
+ {
+ if (s[j]=='=') found=true;
+ j++;
+ }
+ if (found) // found a '=', write it without spaces
{
- c='=';
- p=t; // move p to end of '\s*=\s*' sequence
+ c = '=';
+ i=j;
}
}
- *q++=c;
+ s[dstIdx++]=c;
}
- if (q<p) result.resize(static_cast<uint>(q-result.data())+1);
- return result;
+ s.resize(dstIdx+1);
+ //printf("<removeSpacesAroundEquals(%s)\n",qPrint(s));
}
//----------------------------------------------------------------------------
@@ -130,9 +133,9 @@ static QCString removeSpacesAroundEquals(const QCString &s)
static QCString replace(const QCString &s,char csrc,char cdst)
{
QCString result = s;
- for (char *p=result.data();*p;p++)
+ for (uint i=0;i<result.length();i++)
{
- if (*p==csrc) *p=cdst;
+ if (result[i]==csrc) result[i]=cdst;
}
return result;
}
@@ -514,6 +517,7 @@ class TemplateContextImpl : public TemplateContext
void push();
void pop();
void set(const QCString &name,const TemplateVariant &v);
+ void update(const QCString &name,const TemplateVariant &v);
TemplateVariant get(const QCString &name) const;
const TemplateVariant *getRef(const QCString &name) const;
void setOutputDirectory(const QCString &dir)
@@ -1078,14 +1082,14 @@ class FilterAlphaIndex
private:
struct ListElem
{
- ListElem(uint k,const TemplateVariant &v) : key(k), value(v) {}
- QCString key;
+ ListElem(std::string k,const TemplateVariant &v) : key(k), value(v) {}
+ std::string key;
TemplateVariant value;
};
- static QCString keyToLabel(const QCString &startLetter)
+ static QCString keyToLabel(const char *startLetter)
{
- if (startLetter.isEmpty()) return startLetter;
- const char *p = startLetter.data();
+ //printf(">keyToLabel(%s)\n",qPrint(startLetter));
+ const char *p = startLetter;
char c = *p;
QCString result;
if (c<127 && c>31) // printable ASCII character
@@ -1102,16 +1106,14 @@ class FilterAlphaIndex
result+=hex[((unsigned char)c)&0xf];
}
}
+ //printf("<keyToLabel(%s)\n",qPrint(result));
return result;
}
- static uint determineSortKey(TemplateStructIntf *s,const QCString &attribName)
+ static std::string determineSortKey(TemplateStructIntf *s,const QCString &attribName)
{
TemplateVariant v = s->get(attribName);
int index = getPrefixIndex(v.toString());
- return getUnicodeForUTF8CharAt(
- convertUTF8ToUpper(
- getUTF8CharAt(v.toString().str(),index)
- ),0);
+ return convertUTF8ToUpper(getUTF8CharAt(v.toString().str(),index));
}
public:
@@ -1134,7 +1136,7 @@ class FilterAlphaIndex
TemplateStructIntf *s = item.toStruct();
if (s)
{
- uint sortKey = determineSortKey(s,args.toString());
+ std::string sortKey = determineSortKey(s,args.toString());
sortList.emplace_back(sortKey,item);
//printf("sortKey=%s\n",qPrint(sortKey));
}
@@ -1147,7 +1149,7 @@ class FilterAlphaIndex
[](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; });
// create an index from the sorted list
- QCString letter;
+ std::string letter;
TemplateStruct *indexNode = 0;
TemplateList *indexList = 0;
for (const auto &elem : sortList)
@@ -1158,7 +1160,7 @@ class FilterAlphaIndex
indexNode = TemplateStruct::alloc();
indexList = TemplateList::alloc();
indexNode->set("letter", elem.key);
- indexNode->set("label", keyToLabel(elem.key));
+ indexNode->set("label", keyToLabel(elem.key.c_str()));
indexNode->set("items",indexList);
result->append(indexNode);
letter=elem.key;
@@ -1282,6 +1284,55 @@ class FilterIsAbsoluteURL
//--------------------------------------------------------------------
+/** @brief The implementation of the "lower" filter */
+class FilterLower
+{
+ public:
+ static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &)
+ {
+ if (v.isValid() && v.type()==TemplateVariant::String)
+ {
+ return v.toString().lower();
+ }
+ return v;
+ }
+};
+
+//--------------------------------------------------------------------
+
+/** @brief The implementation of the "upper" filter */
+class FilterUpper
+{
+ public:
+ static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &)
+ {
+ if (v.isValid() && v.type()==TemplateVariant::String)
+ {
+ return v.toString().upper();
+ }
+ return v;
+ }
+};
+
+//--------------------------------------------------------------------
+
+/** @brief The implementation of the "e" filter */
+class FilterHtmlEscape
+{
+ public:
+ static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &)
+ {
+ if (v.isValid() && v.type()==TemplateVariant::String)
+ {
+ return convertToHtml(v.toString());
+ }
+ return v;
+ }
+};
+
+
+//--------------------------------------------------------------------
+
/** @brief The implementation of the "decodeURL" filter
* The leading character is removed from the value in case it is a ^ or !.
* - ^ is used to encode a absolute URL
@@ -1359,7 +1410,10 @@ static TemplateFilterFactory::AutoRegister<FilterAdd> fAdd("add")
static TemplateFilterFactory::AutoRegister<FilterGet> fGet("get");
static TemplateFilterFactory::AutoRegister<FilterRaw> fRaw("raw");
static TemplateFilterFactory::AutoRegister<FilterList> fList("list");
+static TemplateFilterFactory::AutoRegister<FilterLower> fLower("lower");
+static TemplateFilterFactory::AutoRegister<FilterUpper> fUpper("upper");
static TemplateFilterFactory::AutoRegister<FilterAppend> fAppend("append");
+static TemplateFilterFactory::AutoRegister<FilterHtmlEscape> fEscape("e");
static TemplateFilterFactory::AutoRegister<FilterLength> fLength("length");
static TemplateFilterFactory::AutoRegister<FilterNoWrap> fNoWrap("nowrap");
static TemplateFilterFactory::AutoRegister<FilterFlatten> fFlatten("flatten");
@@ -1409,7 +1463,7 @@ class ExprAstVariable : public ExprAst
{
public:
ExprAstVariable(const QCString &name) : m_name(name)
- { TRACE(("ExprAstVariable(%s)\n",name)); }
+ { TRACE(("ExprAstVariable(%s)\n",name.data())); }
const QCString &name() const { return m_name; }
virtual TemplateVariant resolve(TemplateContext *c)
{
@@ -1461,7 +1515,7 @@ class ExprAstFilter : public ExprAst
{
public:
ExprAstFilter(const QCString &name,ExprAst *arg) : m_name(name), m_arg(arg)
- { TRACE(("ExprAstFilter(%s)\n",name)); }
+ { TRACE(("ExprAstFilter(%s)\n",name.data())); }
~ExprAstFilter() { delete m_arg; }
const QCString &name() const { return m_name; }
TemplateVariant apply(const TemplateVariant &v,TemplateContext *c)
@@ -1506,7 +1560,7 @@ class ExprAstLiteral : public ExprAst
{
public:
ExprAstLiteral(const QCString &lit) : m_literal(lit)
- { TRACE(("ExprAstLiteral(%s)\n",lit)); }
+ { TRACE(("ExprAstLiteral(%s)\n",lit.data())); }
const QCString &literal() const { return m_literal; }
virtual TemplateVariant resolve(TemplateContext *) { return TemplateVariant(m_literal); }
private:
@@ -1969,6 +2023,7 @@ class ExpressionParser
{
warn(m_parser->templateName(),m_line,"unexpected operator '%s' in expression",
Operator::toString(m_curToken.op));
+ abort();
}
break;
default:
@@ -2261,8 +2316,8 @@ class ExpressionParser
m_curToken.id = s;
p++;
}
- //TRACE(("token type=%d op=%d num=%d id=%s\n",
- // m_curToken.type,m_curToken.op,m_curToken.num,qPrint(m_curToken.id)));
+ TRACE(("token type=%d op=%d num=%d id=%s\n",
+ m_curToken.type,m_curToken.op,m_curToken.num,qPrint(m_curToken.id)));
m_tokenStream = p;
return TRUE;
@@ -2382,6 +2437,23 @@ void TemplateContextImpl::set(const QCString &name,const TemplateVariant &v)
ctx.insert(std::make_pair(name.str(),v));
}
+void TemplateContextImpl::update(const QCString &name,const TemplateVariant &v)
+{
+ int depth=0;
+ for (auto &ctx : m_contextStack)
+ {
+ auto it = ctx.find(name.str());
+ if (it!=ctx.end())
+ {
+ ctx.erase(it);
+ ctx.insert(std::make_pair(name.str(),v));
+ return;
+ }
+ depth++;
+ }
+ warn(m_templateName,m_line,"requesting update for non-existing variable '%s'",qPrint(name));
+}
+
TemplateVariant TemplateContextImpl::get(const QCString &name) const
{
int i=name.find('.');
@@ -3544,21 +3616,16 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude>
static void stripLeadingWhiteSpace(QCString &s)
{
- const char *src = s.data();
- if (src)
+ uint i=0, dstIdx=0, l=s.length();
+ bool skipSpaces=true;
+ while (i<l)
{
- char *dst = s.rawData();
- char c;
- bool skipSpaces=TRUE;
- while ((c=*src++))
- {
- if (c=='\n') { *dst++=c; skipSpaces=TRUE; }
- else if (c==' ' && skipSpaces) {}
- else { *dst++=c; skipSpaces=FALSE; }
- }
- *dst='\0';
- s.resize( (int)(dst - src) + 1 );
+ char c = s[i++];
+ if (c=='\n') { s[dstIdx++]=c; skipSpaces=true; }
+ else if (c==' ' && skipSpaces) {}
+ else { s[dstIdx++] = c; skipSpaces=false; }
}
+ s.resize(dstIdx+1);
}
/** @brief Class representing an 'create' tag in a template */
@@ -3945,7 +4012,8 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
{
TRACE(("{TemplateNodeWith(%s)\n",qPrint(data)));
ExpressionParser expParser(parser,line);
- QCString filteredData = removeSpacesAroundEquals(data);
+ QCString filteredData = data;
+ removeSpacesAroundEquals(filteredData);
std::vector<QCString> args = split(filteredData," ");
auto it = args.begin();
while (it!=args.end())
@@ -4114,6 +4182,52 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
//----------------------------------------------------------
+/** @brief Class representing an 'update' tag in a template */
+class TemplateNodeUpdate : public TemplateNodeCreator<TemplateNodeUpdate>
+{
+ struct Mapping
+ {
+ Mapping(const QCString &n,ExprAst *e) : name(n), value(e) {}
+ ~Mapping() { }
+ QCString name;
+ ExprAst *value = 0;
+ };
+ public:
+ TemplateNodeUpdate(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
+ : TemplateNodeCreator<TemplateNodeUpdate>(parser,parent,line)
+ {
+ TRACE(("{TemplateNodeUpdate(%s)\n",qPrint(data)));
+ ExpressionParser expParser(parser,line);
+ // data format: name=expression
+ int j=data.find('=');
+ ExprAst *expr = 0;
+ if (j>0 && (expr = expParser.parse(data.mid(j+1))))
+ {
+ m_mapping = std::make_unique<Mapping>(data.left(j),expr);
+ }
+ TRACE(("}TemplateNodeUpdate(%s)\n",qPrint(data)));
+ }
+ ~TemplateNodeUpdate()
+ {
+ }
+ void render(TextStream &, TemplateContext *c)
+ {
+ TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
+ if (ci==0) return; // should not happen
+ ci->setLocation(m_templateName,m_line);
+ if (m_mapping)
+ {
+ TemplateVariant value = m_mapping->value->resolve(c);
+ ci->update(m_mapping->name,value);
+ }
+ }
+ private:
+ std::unique_ptr<Mapping> m_mapping;
+};
+
+
+//----------------------------------------------------------
+
/** @brief Class representing an 'spaceless' tag in a template */
class TemplateNodeSpaceless : public TemplateNodeCreator<TemplateNodeSpaceless>
{
@@ -4313,6 +4427,12 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource>
m_resExpr = ep.parse(data.left(i)); // part before as
m_asExpr = ep.parse(data.mid(i+4)); // part after as
}
+ else if ((i=data.find(" append "))!=-1) // resource a appends to b
+ {
+ m_resExpr = ep.parse(data.left(i)); // part before append
+ m_asExpr = ep.parse(data.mid(i+8)); // part after append
+ m_append = true;
+ }
else // resource a
{
m_resExpr = ep.parse(data);
@@ -4345,11 +4465,12 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource>
QCString targetFile = m_asExpr->resolve(c).toString();
mkpath(ci,targetFile.str());
if (targetFile.isEmpty())
- { ci->warn(m_templateName,m_line,"invalid parameter at right side of 'as' for resource command\n");
+ {
+ ci->warn(m_templateName,m_line,"invalid parameter at right side of '%s' for resource command\n", m_append ? "append" : "as");
}
else
{
- ResourceMgr::instance().copyResourceAs(resourceFile,outputDirectory,targetFile);
+ ResourceMgr::instance().copyResourceAs(resourceFile,outputDirectory,targetFile,m_append);
}
}
else
@@ -4362,6 +4483,7 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource>
private:
ExprAst *m_resExpr = 0;
ExprAst *m_asExpr = 0;
+ bool m_append = false;
};
//----------------------------------------------------------
@@ -4477,6 +4599,7 @@ static TemplateNodeFactory::AutoRegister<TemplateNodeRange> autoRefRange
static TemplateNodeFactory::AutoRegister<TemplateNodeExtend> autoRefExtend("extend");
static TemplateNodeFactory::AutoRegister<TemplateNodeCreate> autoRefCreate("create");
static TemplateNodeFactory::AutoRegister<TemplateNodeRepeat> autoRefRepeat("repeat");
+static TemplateNodeFactory::AutoRegister<TemplateNodeUpdate> autoRefUpdate("update");
static TemplateNodeFactory::AutoRegister<TemplateNodeInclude> autoRefInclude("include");
static TemplateNodeFactory::AutoRegister<TemplateNodeMarkers> autoRefMarkers("markers");
static TemplateNodeFactory::AutoRegister<TemplateNodeTabbing> autoRefTabbing("tabbing");
@@ -4797,7 +4920,7 @@ void TemplateLexer::addToken(TemplateTokenStream &tokens,
{
if (startPos<endPos)
{
- int len = endPos-startPos+1;
+ int len = endPos-startPos;
QCString text = data.mid(startPos,len);
if (type!=TemplateToken::Text) text = text.stripWhiteSpace();
tokens.push_back(std::make_unique<TemplateToken>(type,text,line));
@@ -4822,8 +4945,8 @@ void TemplateParser::parse(
while (hasNextToken())
{
auto tok = takeNextToken();
- //printf("%p:Token type=%d data='%s' line=%d\n",
- // parent,tok->type,qPrint(tok->data),tok->line);
+ TRACE(("%p:Token type=%d data='%s' line=%d\n",
+ (void*)parent,tok->type,qPrint(tok->data),tok->line));
switch(tok->type)
{
case TemplateToken::Text:
diff --git a/src/template.h b/src/template.h
index dee063d..18e8b06 100644
--- a/src/template.h
+++ b/src/template.h
@@ -28,7 +28,7 @@ class TextStream;
/** @defgroup template_api Template API
*
* This is the API for a
- * <a href="https://docs.djangoproject.com/en/1.6/topics/templates/">Django</a>
+ * <a href="https://www.djangoproject.com/">Django</a>
* compatible template system written in C++.
* It is somewhat inspired by Stephen Kelly's
* <a href="http://www.gitorious.org/grantlee/pages/Home">Grantlee</a>.
@@ -175,6 +175,9 @@ class TemplateVariant
/** Constructs a new variant with a string value \a s. */
TemplateVariant(const QCString &s,bool raw=FALSE) : m_type(String), m_strVal(s), m_strukt(0), m_raw(raw) {}
+ /** Constructs a new variant with a string value \a s. */
+ TemplateVariant(const std::string &s,bool raw=FALSE) : m_type(String), m_strVal(s), m_strukt(0), m_raw(raw) {}
+
/** Constructs a new variant with a struct value \a s.
* @note. The variant will hold a reference to the object.
*/