|
|
|
@ -16,6 +16,7 @@
@@ -16,6 +16,7 @@
|
|
|
|
|
#include <stack> |
|
|
|
|
#include <map> |
|
|
|
|
#include <thread> |
|
|
|
|
#include <queue> |
|
|
|
|
|
|
|
|
|
#include <json.hpp> |
|
|
|
|
#include <date.h> |
|
|
|
@ -27,9 +28,9 @@
@@ -27,9 +28,9 @@
|
|
|
|
|
#include <csignal> |
|
|
|
|
|
|
|
|
|
#include "default-templates.h" |
|
|
|
|
#include "templater.hpp" |
|
|
|
|
#include "util.h" |
|
|
|
|
#include "markdown.h" |
|
|
|
|
#include "templater.hpp" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const std::string SITE_CONFIG_FNAME = "stgen.json"; |
|
|
|
@ -101,6 +102,58 @@ class duktape {
@@ -101,6 +102,58 @@ class duktape {
|
|
|
|
|
duk_pop(ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void eval_file(std::string file) { |
|
|
|
|
compile_file(file); |
|
|
|
|
duk_call(ctx, 0); |
|
|
|
|
duk_pop(ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void testkatex()
|
|
|
|
|
{ |
|
|
|
|
eval_file("katex.min.js"); |
|
|
|
|
eval_file("auto-render.min.js"); |
|
|
|
|
|
|
|
|
|
std::string line = "const parser = new DOMParser();"; |
|
|
|
|
duk_push_lstring(ctx, line.c_str(), line.length()); |
|
|
|
|
if (duk_peval(ctx) != 0) { |
|
|
|
|
std::cout << "Error (test):" << duk_safe_to_string(ctx, -1); |
|
|
|
|
} else { |
|
|
|
|
std::cout << "Result :" << duk_safe_to_string(ctx, -1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// renderMathInElement(document.body);
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void prepare_katex() { |
|
|
|
|
eval_file("katex.min.js"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string eval_katex(std::string math_text) { |
|
|
|
|
|
|
|
|
|
spdlog::info("fuicking help math_text {}", math_text); |
|
|
|
|
|
|
|
|
|
math_text = math_text.substr(2, math_text.length() - 4); |
|
|
|
|
|
|
|
|
|
spdlog::info("fuicking help math_text {}", math_text); |
|
|
|
|
|
|
|
|
|
const char *matht = math_text.c_str(); |
|
|
|
|
|
|
|
|
|
std::string line = "katex.renderToString('"; |
|
|
|
|
line += matht; |
|
|
|
|
line += "', {throwOnError: false });"; |
|
|
|
|
|
|
|
|
|
spdlog::info("fuicking help me {}", line); |
|
|
|
|
|
|
|
|
|
duk_push_lstring(ctx, line.c_str(), line.length()); |
|
|
|
|
if (duk_peval(ctx) != 0) { |
|
|
|
|
spdlog::error("Generate katex: {}", duk_safe_to_string(ctx, -1)); |
|
|
|
|
} else { |
|
|
|
|
return std::string{duk_safe_to_string(ctx, -1)}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ""; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void test() { |
|
|
|
|
compile_file("katex.min.js"); |
|
|
|
@ -124,6 +177,7 @@ class duktape {
@@ -124,6 +177,7 @@ class duktape {
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Fork and exec a command given in args taking input from in and sending
|
|
|
|
|
* output to out. The arguments array must end in a NULL.
|
|
|
|
|
* |
|
|
|
@ -166,6 +220,8 @@ class builder {
@@ -166,6 +220,8 @@ class builder {
|
|
|
|
|
|
|
|
|
|
std::map<fs::path, time_t> last_build; |
|
|
|
|
|
|
|
|
|
duk::duktape dukengine {}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const std::set<std::string> apply_templates_exts {"md","html", "txt", "markdown", "xml", "atom", "rss"}; |
|
|
|
|
|
|
|
|
@ -181,6 +237,194 @@ class builder {
@@ -181,6 +237,194 @@ class builder {
|
|
|
|
|
//return false;
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string postprocess_js(const std::string &html) { |
|
|
|
|
using namespace tinyxml2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct mwparent { |
|
|
|
|
XMLElement *me; |
|
|
|
|
XMLElement *parent; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XMLDocument doc {}; |
|
|
|
|
auto err = doc.Parse(html.c_str(), html.length()); |
|
|
|
|
|
|
|
|
|
if (err != XML_SUCCESS) { |
|
|
|
|
spdlog::error("(1)Unable to parse xml document\n\n {}", doc.ErrorStr()); |
|
|
|
|
return html; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
XMLElement *item {doc.RootElement()}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (item == nullptr) { |
|
|
|
|
spdlog::error("Unable to parse xml document\n"); |
|
|
|
|
return html; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::queue<struct mwparent> to_visit {}; |
|
|
|
|
to_visit.push({item, nullptr}); |
|
|
|
|
|
|
|
|
|
while (!to_visit.empty()) { |
|
|
|
|
auto m = to_visit.front(); |
|
|
|
|
XMLElement *me = m.me; |
|
|
|
|
XMLElement *parent = m.parent; |
|
|
|
|
|
|
|
|
|
to_visit.pop(); |
|
|
|
|
|
|
|
|
|
std::string name {me->Name()}; |
|
|
|
|
if (name == "span") { |
|
|
|
|
const char *attrib = me->Attribute("class"); |
|
|
|
|
if (std::string{attrib} == "math") { |
|
|
|
|
std::string math_content {me->GetText()};
|
|
|
|
|
spdlog::info("help '{}'", math_content); |
|
|
|
|
std::string math_html = dukengine.eval_katex(math_content); |
|
|
|
|
|
|
|
|
|
XMLDocument math {}; |
|
|
|
|
auto err = math.Parse(math_html.c_str()); |
|
|
|
|
|
|
|
|
|
if (err != XML_SUCCESS || !math.RootElement()) { |
|
|
|
|
spdlog::error("(1)Unable to parse xml document\n\n {}", doc.ErrorStr()); |
|
|
|
|
return html; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ne->SetText(math_html.c_str());
|
|
|
|
|
|
|
|
|
|
auto nc = parent->InsertNewChildElement("span"); |
|
|
|
|
nc->SetValue(math_html.c_str()); |
|
|
|
|
|
|
|
|
|
// doc.InsertAfterChild(parent, math.RootElement());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
doc.DeleteNode(me); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XMLElement *child= me->FirstChildElement(); |
|
|
|
|
|
|
|
|
|
while (child != nullptr) { |
|
|
|
|
to_visit.push({child, me}); |
|
|
|
|
child = child->NextSiblingElement(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
XMLPrinter p {}; |
|
|
|
|
doc.Print(&p); |
|
|
|
|
|
|
|
|
|
return std::string {p.CStr()}; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** BRoken and ridiculous and wont work why did i write this. */ |
|
|
|
|
std::string replace_math(const std::string &text) { |
|
|
|
|
|
|
|
|
|
auto math_is = "$"; |
|
|
|
|
auto math_bs = "$$"; |
|
|
|
|
|
|
|
|
|
auto math_bl = "\\["; |
|
|
|
|
auto math_br = "\\]"; |
|
|
|
|
|
|
|
|
|
auto math_il = "\\("; |
|
|
|
|
auto math_ir = "\\)"; |
|
|
|
|
|
|
|
|
|
auto l_tokens = {math_is, math_bs, math_bl, math_il}; |
|
|
|
|
auto r_tokens = {math_is, math_bs, math_br, math_ir}; |
|
|
|
|
|
|
|
|
|
std::string looking_for = ""; |
|
|
|
|
bool looking = false; |
|
|
|
|
|
|
|
|
|
std::string ret_text; |
|
|
|
|
|
|
|
|
|
size_t s = 0; |
|
|
|
|
const auto end = text.length(); |
|
|
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
|
|
|
|
|
std::string::size_type min = end; |
|
|
|
|
std::string token = ""; |
|
|
|
|
|
|
|
|
|
for (auto t: l_tokens) { |
|
|
|
|
auto found = text.find(t, s); |
|
|
|
|
if (found < min){ |
|
|
|
|
min = found; |
|
|
|
|
token = t; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (min >= end || min == std::string::npos) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// differentiate $ and $$
|
|
|
|
|
if (token == math_is) { |
|
|
|
|
if (end > min + 2) { |
|
|
|
|
if (text[min + 2] == '$') |
|
|
|
|
token = math_bs; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// look for matching token
|
|
|
|
|
std::string look_for; |
|
|
|
|
|
|
|
|
|
if (token == math_bs || token == math_is) |
|
|
|
|
look_for = token;
|
|
|
|
|
|
|
|
|
|
if (token == math_bl) |
|
|
|
|
look_for = math_br; |
|
|
|
|
|
|
|
|
|
if (token == math_il) |
|
|
|
|
look_for = math_ir; |
|
|
|
|
|
|
|
|
|
s = min + token.length(); |
|
|
|
|
auto nline = text.find("\n", s); |
|
|
|
|
min = end; |
|
|
|
|
|
|
|
|
|
for (auto t: r_tokens) { |
|
|
|
|
auto found = text.find(t, s); |
|
|
|
|
if (found < min){ |
|
|
|
|
min = found; |
|
|
|
|
token = t; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (min == std::string::npos || min >= nline) { |
|
|
|
|
s = nline; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (token != look_for) { |
|
|
|
|
// continue
|
|
|
|
|
spdlog::warn("math syntax bad"); |
|
|
|
|
s = min; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// found a math block
|
|
|
|
|
std::string math_block = text.substr(s, min - s); |
|
|
|
|
spdlog::info("MATH BLOCK {}", math_block); |
|
|
|
|
|
|
|
|
|
min += look_for.length(); |
|
|
|
|
if (min >= end) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret_text; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*** Build Function ****************
|
|
|
|
|
* |
|
|
|
|
* Plugin types: |
|
|
|
@ -404,11 +648,16 @@ class builder {
@@ -404,11 +648,16 @@ class builder {
|
|
|
|
|
std::string ntext = parser.cut_frontmatter(text); |
|
|
|
|
|
|
|
|
|
// article_properties["body"] = parser.cut_frontmatter(text);
|
|
|
|
|
auto job_t = job_type::TEMPLATE; |
|
|
|
|
|
|
|
|
|
if (ext == "md" || ext == "markdown") { |
|
|
|
|
replace_math(text); |
|
|
|
|
text = parser.parse_to_html(text);
|
|
|
|
|
// text = postprocess_js(text);
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
article_properties["original"] = text; |
|
|
|
@ -422,7 +671,8 @@ class builder {
@@ -422,7 +671,8 @@ class builder {
|
|
|
|
|
article_properties["body"] = new_page; |
|
|
|
|
|
|
|
|
|
notify_file_write(target); |
|
|
|
|
compile_jobs[target] = {job_type::TEMPLATE, entry, std::map<std::string, std::string>(article_properties), article_last_update}; |
|
|
|
|
|
|
|
|
|
compile_jobs[target] = {job_t, entry, std::map<std::string, std::string>(article_properties), article_last_update}; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -532,9 +782,11 @@ class builder {
@@ -532,9 +782,11 @@ class builder {
|
|
|
|
|
s2_templr = new templater({}, {new rss_feed_plugin{}, new microblog_plugin{}}); |
|
|
|
|
|
|
|
|
|
add_default_templates(); |
|
|
|
|
|
|
|
|
|
dukengine.prepare_katex(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
~builder() {delete templr; delete textsub_templr;} |
|
|
|
|
~builder() {delete templr; delete textsub_templr; delete s2_templr;} |
|
|
|
|
|
|
|
|
|
bool get_confirmation(std::string message) { |
|
|
|
|
if (settings.no_interactive) { |
|
|
|
@ -596,6 +848,14 @@ class builder {
@@ -596,6 +848,14 @@ class builder {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (auto &e: compile_jobs) { |
|
|
|
|
if ((job_type::POSTPROCESS_HTML) & e.second.type) { |
|
|
|
|
// run js postprocessing plugins
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (auto &e: compile_jobs) { |
|
|
|
|
if ((job_type::MARKDOWN | job_type::TEMPLATE | job_type::WRITE_ARTICLE) & e.second.type) { |
|
|
|
|
write_file(e.first.string(), e.second.properties.at("body")); |
|
|
|
@ -922,12 +1182,6 @@ int main(int argc, char **argv) {
@@ -922,12 +1182,6 @@ int main(int argc, char **argv) {
|
|
|
|
|
|
|
|
|
|
auto cmd_options = parse_options(argc, argv); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
duk::duktape d {}; |
|
|
|
|
d.test(); |
|
|
|
|
|
|
|
|
|
exit(0); |
|
|
|
|
|
|
|
|
|
stgen::builder b (cmd_options); |
|
|
|
|
b.build(); |
|
|
|
|
|
|
|
|
|