First version of Grafting a Tree book generator.
parent
30bd684622
commit
628b681940
Binary file not shown.
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env/ python
|
||||
from sys import stdout
|
||||
from flask import Flask, Response, render_template, request
|
||||
from pagedjs import make_pdf
|
||||
from graft_a_tree import graft_a_tree
|
||||
from io import StringIO
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
BASEURL = ''
|
||||
MIN_GROW_YEARS = 0
|
||||
MAX_GROW_YEARS = 25
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
def wrap (text, width):
|
||||
return'\n'.join([(' \\\n').join(textwrap.wrap(line, width=width - 2)) for line in text.splitlines()])
|
||||
|
||||
with open('graft_a_tree.py', 'r') as script:
|
||||
source_code = script.read()
|
||||
|
||||
@app.route('{}/'.format(BASEURL))
|
||||
def index():
|
||||
return render_template('index.html', BASEURL=BASEURL)
|
||||
|
||||
@app.route('{}/graft'.format(BASEURL), methods=['POST'])
|
||||
def graft():
|
||||
years = max(MIN_GROW_YEARS, min(MAX_GROW_YEARS, int(request.form['years'])))
|
||||
|
||||
with StringIO() as script_stdout:
|
||||
default_stdout = sys.stdout
|
||||
sys.stdout = script_stdout
|
||||
graft_a_tree(years)
|
||||
content = script_stdout.getvalue()
|
||||
sys.stdout = default_stdout
|
||||
|
||||
html = render_template('book.html', content=content, source_code=wrap(source_code, 100).replace(' ', ' ').replace('\n', '<br />'))
|
||||
# print(html)
|
||||
print('html rendered')
|
||||
pdf = make_pdf(html)
|
||||
print('made pdf')
|
||||
r = Response(pdf, mimetype='application/pdf')
|
||||
|
||||
r.headers.extend({
|
||||
'Content-Disposition': 'attachment; filename="grafted-tree.pdf"'
|
||||
})
|
||||
|
||||
return r
|
@ -0,0 +1,3 @@
|
||||
nltk
|
||||
wikipedia
|
||||
flask
|
@ -0,0 +1,3 @@
|
||||
export FLASK_APP=app.py
|
||||
export FLASK_ENV=development
|
||||
flask run
|
@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
body, html {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
page-break-after: right;
|
||||
}
|
||||
|
||||
.tree{
|
||||
page-break-before: always;
|
||||
page: tree;
|
||||
}
|
||||
|
||||
code {
|
||||
page-break-before: right;
|
||||
font-size: 57.5%;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tree.first {
|
||||
page-break-before: right;
|
||||
page: initial;
|
||||
}
|
||||
|
||||
|
||||
.tree[data-year] {
|
||||
string-set: year attr(data-year);
|
||||
}
|
||||
|
||||
@page {
|
||||
size: a5 portrait;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Grafted tree</h1>
|
||||
|
||||
{% autoescape false %}
|
||||
{{ content }}
|
||||
|
||||
<code>{{ source_code }}</code>
|
||||
{% endautoescape %}
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
[data-message] {
|
||||
display: none;
|
||||
font-size: var(--font-size-smaller);
|
||||
line-height: var(--line-height--smaller);
|
||||
font-style: italic;
|
||||
margin: var(--line-height--smaller) 0;
|
||||
}
|
||||
|
||||
[data-message][data-active] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Grafting a tree</h1>
|
||||
<p>
|
||||
<form action="{{ BASEURL }}/graft" method="POST">
|
||||
Graft a tree for <input type="number" name="years" value="3" max="25" min="0" size="4" /> years.
|
||||
<button type="submit">Graft</button>
|
||||
</form>
|
||||
</p>
|
||||
<p data-message="working">
|
||||
Grafting your tree. This might take a while.
|
||||
</p>
|
||||
<p data-message="error">
|
||||
Something went wrong.
|
||||
</p>
|
||||
<script>
|
||||
function getFilename (headers, fallback) {
|
||||
if (headers.has('Content-Disposition')) {
|
||||
header = headers.get('Content-Disposition')
|
||||
matches = header.match(/filename="(.+)"/)
|
||||
|
||||
if (matches.length == 2) {
|
||||
return matches[1]
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
(function () {
|
||||
if (fetch) {
|
||||
var form = document.querySelector('form'),
|
||||
button = form.querySelector('button'),
|
||||
messageWorking = document.querySelector('[data-message="working"]'),
|
||||
messageError = document.querySelector('[data-message="error"]');
|
||||
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
button.disabled = true;
|
||||
delete messageError.dataset.active;
|
||||
messageWorking.dataset.active = true;
|
||||
const data = new FormData(form);
|
||||
|
||||
fetch(form.action, {
|
||||
method: "POST",
|
||||
body: data
|
||||
}).then(function (r) {
|
||||
console.log(r);
|
||||
r.blob().then(function (blob) {
|
||||
var filename = getFilename(r.headers, 'Grafted-tree.pdf');
|
||||
const a = document.createElement('a');
|
||||
a.setAttribute('href', URL.createObjectURL(blob));
|
||||
a.setAttribute('download', filename);
|
||||
|
||||
if (document.createEvent) {
|
||||
const event = document.createEvent('MouseEvents');
|
||||
event.initEvent('click', true, true);
|
||||
a.dispatchEvent(event);
|
||||
}
|
||||
else {
|
||||
a.click();
|
||||
}
|
||||
delete messageWorking.dataset.active;
|
||||
button.disabled = false;
|
||||
});
|
||||
}).catch(function() {
|
||||
delete messageWorking.dataset.active;
|
||||
messageError.dataset.active = true;
|
||||
button.disabled = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue