Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/icewind1991/files_markdown.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Appelman <icewind@owncloud.com>2013-05-04 22:45:05 +0400
committerRobin Appelman <icewind@owncloud.com>2013-05-04 22:45:05 +0400
commit4b31f5cd0fe7277f0cb756026f6816e601a587da (patch)
tree29d2f7e3dfcc1c2890a622eb2526a97412c8969d
parent9d5d8283be0140595a0c52cd04b1128c7cb1cb90 (diff)
Allow using wkhtmltopdf to download markdown files as pdfwkhtmltopdf
-rw-r--r--ajax/checkconvert.php18
-rw-r--r--ajax/download.php55
-rw-r--r--bin/.gitignore1
-rw-r--r--bin/README2
-rw-r--r--css/render.css386
-rw-r--r--js/editor.js40
-rw-r--r--lib/wkhtmltopdf.php25
-rw-r--r--templates/render.php14
8 files changed, 540 insertions, 1 deletions
diff --git a/ajax/checkconvert.php b/ajax/checkconvert.php
new file mode 100644
index 0000000..03aa197
--- /dev/null
+++ b/ajax/checkconvert.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+\OCP\JSON::checkLoggedIn();
+\OCP\JSON::callCheck();
+\OCP\JSON::setContentTypeHeader();
+
+try {
+ $converter = new \OCA\Files_Markdown\WKHTMLtoPDF();
+ echo 'true';
+} catch (Exception $e) {
+ echo 'false';
+}
diff --git a/ajax/download.php b/ajax/download.php
new file mode 100644
index 0000000..878d5f4
--- /dev/null
+++ b/ajax/download.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+\OCP\JSON::checkLoggedIn();
+\OCP\JSON::callCheck();
+
+try {
+ $converter = new \OCA\Files_Markdown\WKHTMLtoPDF();
+} catch (Exception $e) {
+ \OC_JSON::error(array('error' => 'binary not found'));
+ exit();
+}
+
+$sourceName = \OC\Files\Filesystem::getLocalFile($_POST['name']);
+$sourceName = basename($sourceName);
+$sourceName = substr($sourceName, 0, strrpos($sourceName, '.'));
+$targetName = $sourceName . '.pdf';
+
+// we can't use /tmp on all system since systemd's PriveTmp prevents apache's tmp files from being accessed by wkpdftohtml
+$basedir = \OC_User::getHome(\OC_User::getUser()) . '/files_markdown';
+if (!is_dir($basedir)) {
+ mkdir($basedir);
+}
+
+$targetFile = $basedir . '/' . $targetName;
+$sourceFile = $basedir . '/' . $sourceName . '.html';
+$source = $_POST['html'];
+
+$css = realpath(__DIR__ . '/../css/render.css');
+$template = new \OC_Template('files_markdown', 'render');
+$template->assign('css', file_get_contents($css));
+$template->assign('mathjaxcss', $_POST['mathjaxcss']);
+$template->assign('html', $source);
+$html = $template->fetchPage();
+file_put_contents($sourceFile, $html);
+
+$converter->renderHTMLFile($sourceFile, $targetFile);
+
+if (preg_match("/MSIE/", $_SERVER["HTTP_USER_AGENT"])) {
+ header('Content-Disposition: attachment; filename="' . rawurlencode($targetName) . '"');
+} else {
+ header('Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode($targetName)
+ . '; filename="' . rawurlencode($targetName) . '"');
+}
+header('Content-Transfer-Encoding: binary');
+header('Content-Type: application/pdf');
+header('Content-Length: ' . filesize($targetFile));
+readfile($targetFile);
+unlink($targetFile);
+unlink($sourceFile);
diff --git a/bin/.gitignore b/bin/.gitignore
new file mode 100644
index 0000000..d01a0cc
--- /dev/null
+++ b/bin/.gitignore
@@ -0,0 +1 @@
+wkhtmltopdf
diff --git a/bin/README b/bin/README
new file mode 100644
index 0000000..2d2f392
--- /dev/null
+++ b/bin/README
@@ -0,0 +1,2 @@
+download the latest version of wkhtmltopdf from https://code.google.com/p/wkhtmltopdf/downloads/list
+, place it in this folder with the name "whtmltopdf" and make it executable.
diff --git a/css/render.css b/css/render.css
new file mode 100644
index 0000000..8b74a7c
--- /dev/null
+++ b/css/render.css
@@ -0,0 +1,386 @@
+#preview {
+ font-family: Helvetica, arial, sans-serif;
+ font-size: 14px;
+ line-height: 1.6;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ padding-left: 20px;
+ padding-right: 20px;
+ background-color: white;
+ margin-left: 10px;
+}
+
+#preview > *:first-child {
+ margin-top: 0 !important;
+}
+
+#preview > *:last-child {
+ margin-bottom: 0 !important;
+}
+
+#preview a {
+ color: #4183C4;
+}
+
+#preview a.absent {
+ color: #cc0000;
+}
+
+#preview a.anchor {
+ display: block;
+ padding-left: 30px;
+ margin-left: -30px;
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+}
+
+#preview h1, #preview h2, #preview h3, #preview h4, #preview h5, #preview h6 {
+ margin: 20px 0 10px;
+ padding: 0;
+ font-weight: bold;
+ -webkit-font-smoothing: antialiased;
+ cursor: text;
+ position: relative;
+}
+
+#preview h1:hover a.anchor, #preview h2:hover a.anchor,
+#preview h3:hover a.anchor, #preview h4:hover a.anchor,
+#preview h5:hover a.anchor, #preview h6:hover a.anchor {
+ background: url("../../images/modules/styleguide/para.png") no-repeat 10px center;
+ text-decoration: none;
+}
+
+#preview h1 tt, #preview h1 code {
+ font-size: inherit;
+}
+
+#preview h2 tt, #preview h2 code {
+ font-size: inherit;
+}
+
+#preview h3 tt, #preview h3 code {
+ font-size: inherit;
+}
+
+#preview h4 tt, #preview h4 code {
+ font-size: inherit;
+}
+
+#preview h5 tt, #preview h5 code {
+ font-size: inherit;
+}
+
+#preview h6 tt, #preview h6 code {
+ font-size: inherit;
+}
+
+#preview h1 {
+ font-size: 28px;
+ color: black;
+}
+
+#preview h2 {
+ font-size: 24px;
+ border-bottom: 1px solid #cccccc;
+ color: black;
+}
+
+#preview h3 {
+ font-size: 18px;
+}
+
+#preview h4 {
+ font-size: 16px;
+}
+
+#preview h5 {
+ font-size: 14px;
+}
+
+#preview h6 {
+ color: #777777;
+ font-size: 14px;
+}
+
+#preview p, #preview blockquote, #preview ul, #preview ol, #preview dl, #preview li, #preview table, #preview pre {
+ margin: 15px 0;
+}
+
+#preview hr {
+ background: transparent url("../../images/modules/pulls/dirty-shade.png") repeat-x 0 0;
+ border: 0 none;
+ color: #cccccc;
+ height: 4px;
+ padding: 0;
+}
+
+#preview > h2:first-child {
+ margin-top: 0;
+ padding-top: 0;
+}
+
+#preview > h1:first-child {
+ margin-top: 0;
+ padding-top: 0;
+}
+
+#preview > h1:first-child + h2 {
+ margin-top: 0;
+ padding-top: 0;
+}
+
+#preview > h3:first-child, #preview > h4:first-child, #preview > h5:first-child, #preview > h6:first-child {
+ margin-top: 0;
+ padding-top: 0;
+}
+
+#preview a:first-child h1, #preview a:first-child h2, #preview a:first-child h3, #preview a:first-child h4, #preview a:first-child h5, #preview a:first-child h6 {
+ margin-top: 0;
+ padding-top: 0;
+}
+
+#preview h1 p, #preview h2 p, #preview h3 p, #preview h4 p, #preview h5 p, #preview h6 p {
+ margin-top: 0;
+}
+
+#preview li p.first {
+ display: inline-block;
+}
+
+#preview ul, #preview ol {
+ padding-left: 30px;
+}
+
+#preview ul :first-child, #preview ol :first-child {
+ margin-top: 0;
+}
+
+#preview ul :last-child, #preview ol :last-child {
+ margin-bottom: 0;
+}
+
+#preview dl {
+ padding: 0;
+}
+
+#preview dl dt {
+ font-size: 14px;
+ font-weight: bold;
+ font-style: italic;
+ padding: 0;
+ margin: 15px 0 5px;
+}
+
+#preview dl dt:first-child {
+ padding: 0;
+}
+
+#preview dl dt > :first-child {
+ margin-top: 0;
+}
+
+#preview dl dt > :last-child {
+ margin-bottom: 0;
+}
+
+#preview dl dd {
+ margin: 0 0 15px;
+ padding: 0 15px;
+}
+
+#preview dl dd > :first-child {
+ margin-top: 0;
+}
+
+#preview dl dd > :last-child {
+ margin-bottom: 0;
+}
+
+#preview blockquote {
+ border-left: 4px solid #dddddd;
+ padding: 0 15px;
+ color: #777777;
+}
+
+#preview blockquote > :first-child {
+ margin-top: 0;
+}
+
+#preview blockquote > :last-child {
+ margin-bottom: 0;
+}
+
+#preview table {
+ padding: 0;
+}
+
+#preview table tr {
+ border-top: 1px solid #cccccc;
+ background-color: white;
+ margin: 0;
+ padding: 0;
+}
+
+#preview table tr:nth-child(2n) {
+ background-color: #f8f8f8;
+}
+
+#preview table tr th {
+ font-weight: bold;
+ border: 1px solid #cccccc;
+ text-align: left;
+ margin: 0;
+ padding: 6px 13px;
+}
+
+#preview table tr td {
+ border: 1px solid #cccccc;
+ text-align: left;
+ margin: 0;
+ padding: 6px 13px;
+}
+
+#preview table tr th :first-child, #preview table tr td :first-child {
+ margin-top: 0;
+}
+
+#preview table tr th :last-child, #preview table tr td :last-child {
+ margin-bottom: 0;
+}
+
+#preview img {
+ max-width: 100%;
+}
+
+#preview span.frame {
+ display: block;
+ overflow: hidden;
+}
+
+#preview span.frame > span {
+ border: 1px solid #dddddd;
+ display: block;
+ float: left;
+ overflow: hidden;
+ margin: 13px 0 0;
+ padding: 7px;
+ width: auto;
+}
+
+#preview span.frame span img {
+ display: block;
+ float: left;
+}
+
+#preview span.frame span span {
+ clear: both;
+ color: #333333;
+ display: block;
+ padding: 5px 0 0;
+}
+
+#preview span.align-center {
+ display: block;
+ overflow: hidden;
+ clear: both;
+}
+
+#preview span.align-center > span {
+ display: block;
+ overflow: hidden;
+ margin: 13px auto 0;
+ text-align: center;
+}
+
+#preview span.align-center span img {
+ margin: 0 auto;
+ text-align: center;
+}
+
+#preview span.align-right {
+ display: block;
+ overflow: hidden;
+ clear: both;
+}
+
+#preview span.align-right > span {
+ display: block;
+ overflow: hidden;
+ margin: 13px 0 0;
+ text-align: right;
+}
+
+#preview span.align-right span img {
+ margin: 0;
+ text-align: right;
+}
+
+#preview span.float-left {
+ display: block;
+ margin-right: 13px;
+ overflow: hidden;
+ float: left;
+}
+
+#preview span.float-left span {
+ margin: 13px 0 0;
+}
+
+#preview span.float-right {
+ display: block;
+ margin-left: 13px;
+ overflow: hidden;
+ float: right;
+}
+
+#preview span.float-right > span {
+ display: block;
+ overflow: hidden;
+ margin: 13px auto 0;
+ text-align: right;
+}
+
+#preview code, #preview tt {
+ margin: 0 2px;
+ padding: 0 5px;
+ white-space: nowrap;
+ border: 1px solid #eaeaea;
+ background-color: #f8f8f8;
+ border-radius: 3px;
+}
+
+#preview pre code {
+ margin: 0;
+ padding: 0;
+ white-space: pre;
+ border: none;
+ background: transparent;
+}
+
+#preview .highlight pre {
+ background-color: #f8f8f8;
+ border: 1px solid #cccccc;
+ font-size: 13px;
+ line-height: 19px;
+ overflow: auto;
+ padding: 6px 10px;
+ border-radius: 3px;
+}
+
+#preview pre {
+ background-color: #f8f8f8;
+ border: 1px solid #cccccc;
+ font-size: 13px;
+ line-height: 19px;
+ overflow: auto;
+ padding: 6px 10px;
+ border-radius: 3px;
+}
+
+#preview pre code, #preview pre tt {
+ background-color: transparent;
+ border: none;
+}
diff --git a/js/editor.js b/js/editor.js
index 48e3c38..2a4e4e1 100644
--- a/js/editor.js
+++ b/js/editor.js
@@ -45,7 +45,15 @@ $(document).ready(function () {
editor.width(halfWidth - 10);
preview.height(editor.height());
});
- })
+ });
+ $.get(OC.filePath('files_markdown', 'ajax', 'checkconvert.php')).then(function (result) {
+ if (result) {
+ var downloadButton = $('<button/>');
+ downloadButton.click(downloadPDF);
+ downloadButton.text(t('files_markdown', 'Download PDF'));
+ $('#editorcontrols').append(downloadButton);
+ }
+ });
});
});
FileActions.setDefault('text/markdown', 'Edit');
@@ -72,4 +80,34 @@ $(document).ready(function () {
}
});
+function downloadPDF() {
+ var html = $('#preview').html(),
+ form = $('<form/>'),
+ textfield = $('<textarea/>'),
+ input = $('<input/>');
+
+ form.attr('action', OC.filePath('files_markdown', 'ajax', 'download.php')).attr('method', 'post');
+ input.attr('name', 'name');
+ input.val($('div.crumb.last').text())
+ form.append(input);
+
+ textfield.attr('name', 'html');
+ textfield.val(html);
+ form.append(textfield);
+
+ input = $('<input/>')
+ input.attr('name', 'requesttoken');
+ input.val(oc_requesttoken);
+ form.append(input);
+
+ input = $('<input/>')
+ input.attr('name', 'mathjaxcss');//we need the css mathjax inserts for fonts and such
+ input.val($('head style').last().text());
+ form.append(input);
+
+ form.hide();
+ $('body').append(form);
+ form.submit();
+}
+
var mathJaxLoaded = false;
diff --git a/lib/wkhtmltopdf.php b/lib/wkhtmltopdf.php
new file mode 100644
index 0000000..2a74ed7
--- /dev/null
+++ b/lib/wkhtmltopdf.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\Files_Markdown;
+
+class WKHTMLtoPDF {
+ private $bin;
+
+ public function __construct() {
+ $this->bin = realpath(__DIR__ . '/../bin/wkhtmltopdf');
+ if (!file_exists($this->bin)) {
+ throw new \Exception('binary not found');
+ }
+ }
+
+ public function renderHTMLFile($source, $target) {
+ $cmd = $this->bin . ' --output-format pdf ' . escapeshellarg($source) . ' ' . escapeshellarg($target);
+ exec($cmd);
+ }
+}
diff --git a/templates/render.php b/templates/render.php
new file mode 100644
index 0000000..5c38736
--- /dev/null
+++ b/templates/render.php
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <style>
+ <?php echo $_['mathjaxcss'];?>
+ </style>
+ <style>
+ <?php echo $_['css'];?>
+ </style>
+ </head>
+ <body id='preview'>
+ <?php echo $_['html']; ?>
+ </body>
+</html>