summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--debian/changelog5
-rw-r--r--debian/control2
-rw-r--r--html/index.html1
-rw-r--r--html/whiteboard.css14
-rw-r--r--html/whiteboard.js15
-rw-r--r--whiteboard.cpp13
6 files changed, 47 insertions, 3 deletions
diff --git a/debian/changelog b/debian/changelog
index ab688ed..d773faf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,10 @@
-whiteboard (1.7) UNRELEASED; urgency=medium
+whiteboard (1.7) unstable; urgency=medium
* Fix crash on stats.html page reload/close
* Focus on reconnect button
+ * Added Markdown to PDF download via pandoc
- -- Roland Reichwein <mail@reichwein.it> Wed, 08 Feb 2023 18:22:26 +0100
+ -- Roland Reichwein <mail@reichwein.it> Fri, 10 Feb 2023 18:01:37 +0100
whiteboard (1.6) unstable; urgency=medium
diff --git a/debian/control b/debian/control
index e6499aa..7641847 100644
--- a/debian/control
+++ b/debian/control
@@ -8,7 +8,7 @@ Homepage: http://www.reichwein.it/whiteboard/
Package: whiteboard
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libxml2-utils
+Depends: ${shlibs:Depends}, ${misc:Depends}, libxml2-utils, pandoc
Recommends: webserver
Homepage: http://www.reichwein.it/whiteboard/
Description: Web application for an collaborative editor
diff --git a/html/index.html b/html/index.html
index decc540..b72e23b 100644
--- a/html/index.html
+++ b/html/index.html
@@ -23,6 +23,7 @@
<button class="button" onclick="on_qrcode_click();">QR code</button>
<span id="status">Starting up...</span>
<button class="buttonred" id="reconnect" onclick="on_reconnect_click();" hidden>Reconnect</button>
+ <span class="helper"></span><img class="center-img clickable" onclick="on_pdf_click();" src="pdf-icon-30.png" height="37" width="30"/></span>
<br/>
<br/>
Reichwein.IT Whiteboard <span id="version"></span> by <a href="https://www.reichwein.it">https://www.reichwein.it</a><br/>
diff --git a/html/whiteboard.css b/html/whiteboard.css
index 4de9b46..2d222d5 100644
--- a/html/whiteboard.css
+++ b/html/whiteboard.css
@@ -20,6 +20,20 @@ div.status {
color: #FF0000;
}
+span.helper {
+ display: inline-block;
+ height: 100%;
+ vertical-align: middle;
+}
+
+img.center-img {
+ vertical-align: middle;
+}
+
+.clickable {
+ cursor: pointer;
+}
+
textarea {
/*
height: 30vh;
diff --git a/html/whiteboard.js b/html/whiteboard.js
index 38f972f..379c757 100644
--- a/html/whiteboard.js
+++ b/html/whiteboard.js
@@ -94,6 +94,14 @@ function on_version(version)
document.getElementById("version").textContent = version;
}
+function on_pdf(pdf)
+{
+ var a = document.getElementById("download-a");
+ a.href = "data:application/pdf;base64," + pdf;
+ a.download = get_id() + ".pdf"
+ a.click();
+}
+
function on_modify_ack(rev)
{
if (rev != revision + 1)
@@ -128,6 +136,8 @@ function on_message(e) {
on_qrcode(xmlDocument.getElementsByTagName("png")[0].textContent);
} else if (type == "version") {
on_version(xmlDocument.getElementsByTagName("version")[0].textContent);
+ } else if (type == "pdf") {
+ on_pdf(xmlDocument.getElementsByTagName("pdf")[0].textContent);
} else if (type == "error") {
alert(xmlDocument.getElementsByTagName("message")[0].textContent);
} else {
@@ -334,3 +344,8 @@ function on_qrcode_click()
websocket.send(new XMLSerializer().serializeToString(xmlDocument));
}
+function on_pdf_click()
+{
+ websocket.send("<request><command>pdf</command><id>" + get_id() + "</id></request>");
+}
+
diff --git a/whiteboard.cpp b/whiteboard.cpp
index 88f4f3b..220d85e 100644
--- a/whiteboard.cpp
+++ b/whiteboard.cpp
@@ -34,11 +34,13 @@
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio/strand.hpp>
+#include <boost/process.hpp>
#include <fmt/core.h>
#include "libreichwein/base64.h"
#include "libreichwein/file.h"
+#include "libreichwein/tempfile.h"
#include "libreichwein/xml.h"
#include "config.h"
@@ -50,6 +52,7 @@ namespace pt = boost::property_tree;
using namespace std::string_literals;
using namespace std::placeholders;
namespace fs = std::filesystem;
+namespace bp = boost::process;
namespace {
@@ -389,6 +392,16 @@ public:
} else if (command == "getstats") {
setup_stats_timer();
return stats_xml();
+ } else if (command == "pdf") {
+ std::string id {xml.get<std::string>("request.id")};
+ Reichwein::Tempfile mdFilePath{".md"};
+ Reichwein::File::setFile(mdFilePath.getPath(), m_storage.getDocument(id));
+ Reichwein::Tempfile pdfFilePath{".pdf"};
+ int system_result{bp::system("/usr/bin/pandoc", mdFilePath.getPath().generic_string(), "-o", pdfFilePath.getPath().generic_string())};
+ if (system_result)
+ throw std::runtime_error("pandoc returned: "s + std::to_string(system_result));
+ std::string pdfdata{Reichwein::File::getFile(pdfFilePath.getPath())};
+ return make_xml({{"type", "pdf"}, {"pdf", Reichwein::Base64::encode64(pdfdata)}});
} else {
throw std::runtime_error("Bad command: "s + command);
}