dynamic logic based control inside html files using mustash syntax

{{%bool1 && bool2 || (bool3 && !bool4)}}
must be closed exactly as stated!!
{{/bool1 && bool2 || (bool3 && !bool4)}}
main
Brett 2023-08-23 15:27:27 -04:00
parent cd3e660765
commit 429b39cf08
4 changed files with 52 additions and 18 deletions

View File

@ -18,8 +18,16 @@
<div class="center"> <div class="center">
HAXsdsad HAXsdsad
{{#_admin}} {{%_admin}}
Admin detected <p>Admin detected</p>
{{/_admin}}
{{%_admin && _create_posts}}
<p>Admin and can read!</p>
{{/_admin && _create_posts}}
{{%_admin}}
{{%_read_files}}
Nested time!
{{/_read_files}}
{{/_admin}} {{/_admin}}
</div> </div>
</div> </div>

@ -1 +1 @@
Subproject commit 34536e2a633050ed241b951c292aca58c55435b9 Subproject commit 1b4e36416ae67d3a3789333ff965866ae45bb98b

View File

@ -9,6 +9,7 @@
#include <algorithm> #include <algorithm>
#include <blt/std/time.h> #include <blt/std/time.h>
#include <optional> #include <optional>
#include <blt/std/assert.h>
namespace cs namespace cs
{ {
@ -65,9 +66,7 @@ namespace cs
while (!hasTemplateSuffix()) while (!hasTemplateSuffix())
{ {
if (!hasNext()) if (!hasNext())
{ blt_throw(LexerSyntaxError());
throw LexerSyntaxError();
}
token += consume(); token += consume();
} }
consumeTemplateSuffix(); consumeTemplateSuffix();
@ -195,12 +194,12 @@ namespace cs
{ {
case '&': case '&':
if (consume() != '&') if (consume() != '&')
throw LexerSyntaxError("Unable to parse logical expression. Found single '&' missing second '&'"); blt_throw(LexerSyntaxError("Unable to parse logical expression. Found single '&' missing second '&'"));
tokens.emplace_back(TokenType::AND); tokens.emplace_back(TokenType::AND);
break; break;
case '|': case '|':
if (consume() != '|') if (consume() != '|')
throw LexerSyntaxError("Unable to parse logical expression. Found single '|' missing second '|'"); blt_throw(LexerSyntaxError("Unable to parse logical expression. Found single '|' missing second '|'"));
tokens.emplace_back(TokenType::OR); tokens.emplace_back(TokenType::OR);
break; break;
case '!': case '!':
@ -225,19 +224,19 @@ namespace cs
static inline bool isTrue(const RuntimeContext& context, const std::string& token) static inline bool isTrue(const RuntimeContext& context, const std::string& token)
{ {
BLT_DEBUG("isTrue for token '%s' contains? %s", token.c_str(), context.contains(token) ? "True" : "False"); //BLT_DEBUG("isTrue for token '%s' contains? %s", token.c_str(), context.contains(token) ? "True" : "False");
return context.contains(token) && !context.at(token).empty(); return context.contains(token) && !context.at(token).empty();
} }
// http://www.cs.unb.ca/~wdu/cs4613/a2ans.htm // http://www.cs.unb.ca/~wdu/cs4613/a2ans.htm
bool factor(const RuntimeContext& context) bool factor(const RuntimeContext& context)
{ {
if (!hasNextToken()) if (!hasNextToken())
throw LexerSyntaxError("Processing boolean factor but no token was found!"); blt_throw(LexerSyntaxError("Processing boolean factor but no token was found!"));
auto next = consumeToken(); auto next = consumeToken();
switch (next.type){ switch (next.type){
case TokenType::IDENT: case TokenType::IDENT:
if (!next.value.has_value()) if (!next.value.has_value())
throw LexerSyntaxError("Token identifier does not have a value!"); blt_throw(LexerSyntaxError("Token identifier does not have a value!"));
return isTrue(context, next.value.value()); return isTrue(context, next.value.value());
case TokenType::NOT: case TokenType::NOT:
return !factor(context); return !factor(context);
@ -245,11 +244,11 @@ namespace cs
{ {
// auto ret = ; // auto ret = ;
// if (consume() != ')') // if (consume() != ')')
// throw LexerSyntaxError("Found token '(', parsed expression, but not ')' was found!"); // blt_throw( LexerSyntaxError("Found token '(', parsed expression, but not ')' was found!");
return expr(context); return expr(context);
} }
default: default:
throw LexerSyntaxError("Weird token found while parsing tokens, type: " + decodeName(next.type)); blt_throw(LexerSyntaxError("Weird token found while parsing tokens, type: " + decodeName(next.type)));
} }
} }
@ -299,9 +298,7 @@ namespace cs
} }
static size_t findLastTagLocation(const std::string& tag, const std::string& data) static void getTagLocations(std::vector<size_t>& tagLocations, const std::string& tag, const std::string& data){
{
std::vector<size_t> tagLocations{};
RuntimeLexer lexer(data); RuntimeLexer lexer(data);
while (lexer.hasNext()) while (lexer.hasNext())
{ {
@ -315,10 +312,22 @@ namespace cs
lexer.consume(); lexer.consume();
} }
if (tagLocations.empty()) if (tagLocations.empty())
throw LexerSearchFailure(tag); blt_throw( LexerSearchFailure(tag));
}
static size_t findLastTagLocation(const std::string& tag, const std::string& data)
{
std::vector<size_t> tagLocations{};
getTagLocations(tagLocations, tag, data);
return tagLocations[tagLocations.size() - 1]; return tagLocations[tagLocations.size() - 1];
} }
static size_t findNextTagLocation(const std::string& tag, const std::string& data) {
std::vector<size_t> tagLocations{};
getTagLocations(tagLocations, tag, data);
return tagLocations[0];
}
static std::string searchAndReplace(const std::string& data, const RuntimeContext& context) static std::string searchAndReplace(const std::string& data, const RuntimeContext& context)
{ {
RuntimeLexer lexer(data); RuntimeLexer lexer(data);
@ -329,8 +338,21 @@ namespace cs
{ {
auto token = lexer.consumeToken(); auto token = lexer.consumeToken();
auto searchField = lexer.str.substr(lexer.index); auto searchField = lexer.str.substr(lexer.index);
auto endTokenLoc = RuntimeLexer::findLastTagLocation(token, searchField); auto endTokenLoc = RuntimeLexer::findNextTagLocation(token, searchField);
auto internalData = searchField.substr(0, endTokenLoc);
LogicalEval eval(token);
if (eval.eval(context)) {
results += searchAndReplace(internalData, context);
}
lexer.index += endTokenLoc;
if (lexer.hasTemplatePrefix('/'))
lexer.consumeToken();
else {
blt_throw(LexerSyntaxError("Ending token not found!"));
}
} else } else
results += lexer.consume(); results += lexer.consume();

View File

@ -10,6 +10,7 @@
#include <crowsite/site/auth.h> #include <crowsite/site/auth.h>
#include <crow/middlewares/session.h> #include <crow/middlewares/session.h>
#include <crow/middlewares/cookie_parser.h> #include <crow/middlewares/cookie_parser.h>
#include "blt/std/assert.h"
using Session = crow::SessionMiddleware<crow::FileStore>; using Session = crow::SessionMiddleware<crow::FileStore>;
using CrowApp = crow::App<crow::CookieParser, Session>; using CrowApp = crow::App<crow::CookieParser, Session>;
@ -152,6 +153,8 @@ crow::response handle_root_page(const site_params& params)
crow::mustache::context ctx; crow::mustache::context ctx;
cs::RuntimeContext context; cs::RuntimeContext context;
generateRuntimeContext(params, context);
// pass perms in // pass perms in
if (user_perms & cs::PERM_ADMIN) if (user_perms & cs::PERM_ADMIN)
ctx["_admin"] = true; ctx["_admin"] = true;
@ -189,6 +192,7 @@ int main(int argc, const char** argv)
blt::logging::setLogOutputFormat( blt::logging::setLogOutputFormat(
"\033[94m[${{FULL_TIME}}]${{RC}} ${{LF}}[${{LOG_LEVEL}}]${{RC}} \033[35m(${{FILE}}:${{LINE}})${{RC}} ${{CNR}}${{STR}}${{RC}}\n" "\033[94m[${{FULL_TIME}}]${{RC}} ${{LF}}[${{LOG_LEVEL}}]${{RC}} \033[35m(${{FILE}}:${{LINE}})${{RC}} ${{CNR}}${{STR}}${{RC}}\n"
); );
cs::requests::init(); cs::requests::init();
blt::arg_parse parser; blt::arg_parse parser;