adding scripts and paged.js

master
ana 2 years ago
parent baf2243432
commit 97081bf0b9

@ -0,0 +1,249 @@
# Pagedjs Flask boilerplate / recipe
The boilerplate uses the python framework [Flask](https://palletsprojects.com/p/flask/) to run the webinterface and to generate the HTML of the book. To generate the PDF it uses the javascript library [paged.js](https://pagedjs.org/) together with the chromium webbrowser in headless mode.
The
## Index
- [Installation](#installation)
- [Contents of the boilerplate](#contents-of-the-boilerplate)
- [Usage](#usage)
- [Deployment](#deployment)
- [Furter reading](#further-reading)
## Installation
> This installation guide assumes a basic understanding of the shell or terminal. If you are not familiar with it there are many [introduction tutorials](https://www.digitalocean.com/community/tutorials/an-introduction-to-the-linux-terminal) online. During the summerschool relearn this [short introduction](http://relearn.be/2013/r/cheat-sheet::git-and-the-command-line.html) was written.
### Getting the boilerplate
The easiest way to get this boilerplate is to [download](https://gitlab.constantvzw.org/anais_berck/pagedjs-flask-boilerplate/-/archive/main/pagedjs-flask-boilerplate-main.zip) a copy of it on gitlab.
You can also clone the repository using git. Make sure you execute the command in the folder where you want to place the boilerplate:
```bash
git clone git@gitlab.constantvzw.org:anais_berck/pagedjs-flask-boilerplate.git
```
### Python3
The boilerplate uses Python 3. If you know you have it installed this step can be skipped. If you are not sure it's installed on your computer, run the following command in the terminal:
```bash
python3 --version
```
It should output the version number of the copy of Python you have installed, something like:
```
3.10.7
```
If the terminal instead prints something like:
```
Command 'python3' not found...
```
It is most likely Python isn't installed. You can [download it, and find installation instructions here](https://www.python.org/downloads/).
### Flask
> It is advised to install Flask in a virtual environment, how to use and install them isn't covered here. Please find more information on virtual environments in the [Python documentation](https://docs.python.org/3/tutorial/venv.html)
Extensive installation instructions for Flask can be found [here](https://flask.palletsprojects.com/en/latest/installation/), but it is easiest to install it with the python package manager (pip), with the command:
```bash
pip3 install flask
```
### Node
Pagedjs-cli uses `node.js`, and it is installed with the node pakacge manager `npm` if you know you have installed a (recent) version of `node.js` and `npm`, you can skip this step. First check `npm` is installed using the command:
```bash
npm --version
```
It should output the version number of the copy of npm you have installed, something like:
```
8.15.1
```
If the terminal instead prints something like:
```
Command 'npm' not found...
```
It is most likely npm (and node) arent't installed. There are several ways on how to do it. The easiest is with nvm, the [node virtual manage](https://github.com/nvm-sh/nvm). You can find extensive instructions on it [here](https://github.com/nvm-sh/nvm#installing-and-updating). But it can be installed with the following command, it downloads and executes the install script:
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
```
Then, to avoid having to restart your terminal, run:
```bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
```
Then install the latest Long Term Support release of node and npm:
```bash
nvm install --lts
```
### pagedjs-cli
Finally install [pagedjs-cli](https://gitlab.coko.foundation/pagedjs/pagedjs-cli), with the command:
```bash
npm install -g pagedjs-cli
```
It is quite likely you'll get some warning messages during installation. This doesn't mean it failed though!
To verify `pagedjs-cli` was correctly installed, run:
```bash
pagedjs-cli --help
```
This should print out the usage instructions. When it produces an error it is quite likely your version of `node` and or `npm` was too old. In the [previous step](#node) you'll find instructions on how to install a more recent version of `node` using `nvm`.
### Starting the boilerplate
Now that all the pieces are in place you can start the boilerplate by running:
```bash
./run.sh
```
This command should start the Flask application. If you open a browser and load the url: <http://localhost:5000> you should see the index of the boiler plate. When you click the link 'generate' a PDF-file should be downloaded 🤞.
<!--
### in case pagedjs-cli does not show up, follow these instructions:
check the version of node (this should be: v16.17.0)
```sh
node --version
```
check if nvm is installed
```bash
nvm
```
if nvm does not show up, install nvm with the following command:
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
```
copy the following code into the terminal:
'export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion'
install the latest version of nvm:
```bash
nvm install --lts'
```
check the version of node (this should be: v16.17.0)
```bash
node --version'
```
now install paged.js:
```bash
npm install -g pagedjs-cli
```
check if it is installed:
```bash
whereis pagedjs-cli
```
add this path to settings.py
/home/ana/.nvm/versions/node/v16.17.0/bin/pagedjs-cli
Finally edit a copy of `settings.example.py` and save it as `settings.py`.
It is important to set the `PAGEDJS_BINARY_PATH`, you should be able to find it
by running: `whereis pagedjs-cli`. -->
## Contents of the boilerplate
- `app.py` the flask webapp, generating the views
- `pagedjs.py` helper functions to run pagedjs-cli from python
- `utils.py` utitilities for generative books
- `templates/index.html` jinja template for the index
- `templates/book.html` jinja template for the book itself
- `static/style.css` css style rules for the index and book (it's possible to split them up, also adjust the templates then)
- `static/pagedjs.interface.css` css style rules provided by paged.js to have a more rich preview in debug mode
## Usage
### Running the boilerplate
The boilerplate can be started with the bash script `run.sh`. This script starts the application in development mode. Which is practical during development as it reloads whenever it detects a change to the code.
### Debug mode
The boilerplate has a debug mode. In debug mode the generate function doesn't generate a PDF but instead returns an HTML preview with the help of paged.js. This should be slightly quicker, but also allows to inspect the generated HTML. Activate the debug mode by setting the `DEBUG` variable in `settings.py` to `True`:
```python
DEBUG = True
```
### Adjusting the boilerplate
The boilerplate uses a Flask app to generate the html for the index and book, the code of the application is in the file `app.py`. You can find more information on Flask [here](https://flask.palletsprojects.com/en/2.2.x/quickstart/). Summarised very shortly, Flask is a light frame work for web applications. Flask applications are written in python, these applcations consist of functions generating HTML using the [`route()` decorator](https://flask.palletsprojects.com/en/2.2.x/quickstart/#routing) these functions are linked to a url, in `app.py` the index is defined like so:
```python
@app.route('/')
def index():
return render_template('index.html')
```
On line 1 of this snippet the url is defined, and on line 3 the html is generated and returned to the browser of the visitor. Flask uses the [Jinja](https://jinja.palletsprojects.com/en/3.1.x/) templating engine. You can find extensive documentation on it [here](https://jinja.palletsprojects.com/en/3.1.x/templates/).
The application has two views, defined by similarly named functions: `index` and `generate`. The function `index` generates and shows the homepage. The function `generate` generates the HTML book. You can insert the code for your book in this function.
The application uses Jinja templates to generate the HTML of the book. It is advised to generate your data in the application and to then use this data in the template to generate the HTML. The data can be forwarded to the tempate by extending the `render_template` call in the python script using keyword arguments. Where you define the name of the argument before the equal sign, and assign the value after it:
```python
generated_data = function_call()
html = render_template('book.html', DEBUG=DEBUG, generated_data=generated_data)
```
The variable will be available in the template under the name that you set before the equal sign (=):
```jinja
<section>
{{ generated_data }}
</section>
```
It is possible to generate HTML in the python script and to forward this HTML as a variable to the template, it is important though to mark it in the template as a snippet of HTML that shouldn't be escaped. You do this with the `safe` filter:
```jinja
{{ variable_containing_html|safe }}
```
The template `templates/book.html` is used with for the book, the template `templates/index.html` is used for the index-page of the application. The styles are set in `static/style.css`.
## Deployment
To do: instructions on how to install it on a server and make it publicly accessible. It should be noted this boilerplate does not make any effort at rate-limiting.
## Further reading
- In the [documentation of paged.js](https://pagedjs.org/documentation/) a lot of information on print specific functionality in CSS can be found.
- [Jinja documentation](https://jinja.palletsprojects.com/en/3.1.x/templates/)
- [Flask documentation](https://flask.palletsprojects.com/en/2.2.x/)

Binary file not shown.

164
app.py

@ -0,0 +1,164 @@
from flask import Flask, render_template, Response, abort, url_for, request
# from weasyprint import HTML
import os
from pagedjs import make_pdf_from_url
from settings import DEBUG, HTML_TMP_DIR, SITEURL
import tempfile
from werkzeug.security import safe_join
from dreaming_trees import call_trees, open_dreams, part_of_speech, convert_token_to_text, replace_pos, highlight_word, in_between
# create list of dictionaries with Forest, ha, Tree_1, Tree_2, Tree_3, CO2 in tonnes, ratio
file = "data_trees.csv"
data = call_trees(file)
# open file with dreams
textfile = "dreams_selection_till_p47.txt"
dreaming = open_dreams(textfile)
app = Flask(__name__)
"""
GENERAL:
Everything you print here, shows up in the terminal.
If you want to have it show up in the html pages add the texts there in html.
import your script mentioning the different functions
add this for commands in script with functions
if __name__ == '__main__':
-> if you call script by its own name, it will execute the commands,
otherwise it will only activate the functions to be called elsewhere
"""
"""
Shows the index page of the application
"""
@app.route('/')
def index():
return render_template('index.html')
"""
Shows the first form or view in Flask
the app.route is the webaddress
you need to create the template in templates, and specify what variables you want to use in that template
"""
@app.route('/step1')
def step_1():
locations = []
for element in data:
locations.append(element['Forest'])
return render_template('step1.html', locations=locations)
"""
Shows the second form
You need to get the chosen variable from the first template, by using request
And again, specify the variables you will be using in the template
"""
@app.route('/step2', methods=['GET', 'POST'])
def step_2():
location = request.form['location']
trees = [data[int(location)]['Tree_0'], data[int(location)]['Tree_1'], data[int(location)]['Tree_2']]
return render_template('step2.html', location=location, trees=trees)
"""
This is where the book generation happens.
Get the different variables the reader has chosen by using the request function.
Declare all variable you want to use in the book template.
Specify these variables in html = render.template('book.html'...)
"""
@app.route('/generate', methods=['GET', 'POST'])
def generate ():
location = request.form['location']
place = data[int(location)]['Forest']
tree = request.form['tree']
name_tree = "Tree_"+tree
dream_tree = data[int(location)][name_tree]
selected_description = name_tree + "_description"
description_tree = data[int(location)][selected_description]
doc, tokens, verbs, nouns, adjectives, articles = part_of_speech(dreaming)
tokenized_text = convert_token_to_text(doc)
if float(data[int(location)]["CO2"]) < 1:
# if ration is <1
# replace articles and nouns by spaces of same length
article_text = replace_pos(tokenized_text, articles)
final_textlist = replace_pos(article_text, nouns)
final_text = " ".join(final_textlist)
elif float(data[int(location)]["CO2"]) > 110000:
verb_text = highlight_word(tokenized_text, verbs)
final_textlist = highlight_word(verb_text, nouns)
final_text = " ".join(final_textlist)
else:
final_textlist = in_between(tokenized_text, nouns)
final_text = " ".join(final_textlist)
print(final_textlist)
"""
Insert your own Python code in this function.
"""
# Rendering of the template. Forward generated data to the template
# using named arguments, for example, if a variable chapters was generated
# you can add it to the function like so:
# html = render_template('book.html', DEBUG=DEBUG, chapters=chapters)
html = render_template('book.html', DEBUG=DEBUG, tree=tree, dream_tree=dream_tree, location=location, \
description_tree=description_tree, final_text=final_text, place=place)
if (DEBUG):
return html
else:
pdf = make_pdf(html)
r = Response(pdf, mimetype='application/pdf')
r.headers.extend({
'Content-Disposition': 'attachment; filename="Title of the.pdf"'
})
return r
"""
Proxy(?) for pagedjs, it stores the provided html in a separate file.
Now pagedjs can connect to the application through HTTP.
This way static files, like fonts, images and css can be served in a regular way.
"""
def make_pdf (html):
if not os.path.exists(HTML_TMP_DIR):
os.mkdir(HTML_TMP_DIR)
with tempfile.NamedTemporaryFile(mode='w', prefix='book_', dir=HTML_TMP_DIR, delete=False) as tmpfile:
tmpfile.write(html)
tmpfile.flush()
bookname = os.path.basename(tmpfile.name)
url = SITEURL + url_for('show_book', bookname=bookname)
tmpfile.close()
# Generate the pdf with pagedjs
return make_pdf_from_url(url)
"""
View for pagedjs. It loads the generated HTML from the tmp dir and returns it.
"""
@app.route('/book/<string:bookname>')
def show_book (bookname):
bookpath = safe_join(HTML_TMP_DIR, bookname)
if os.path.exists(bookpath):
with open(bookpath, 'r') as h:
html = h.read()
return html
abort(404)

@ -1,4 +1,4 @@
Forest,ha,Tree_1,Tree_1_description,Tree_2,Tree_2_description,Tree_3,Tree_3_description,CO2,ratio Forest,ha,Tree_0,Tree_0_description,Tree_1,Tree_1_description,Tree_2,Tree_2_description,CO2,ratio
Sonian Forest,4421,Beech,"Beech (Fagus) is a genus of deciduous trees in the family Fagaceae, native to temperate Europe, Asia and North America. Recent classifications recognize 10 to 13 species in two distinct subgenera, Engleriana and Fagus. The better known Fagus subgenus beeches are high-branching with tall, stout trunks and smooth silver-grey bark. The European beech (Fagus sylvatica) is the most commonly cultivated.",Oak,"An oak is a tree or shrub in the genus Quercus of the beech family, Fagaceae. There are approximately 500 extant species of oaks. The genus Quercus is native to the Northern Hemisphere, and includes deciduous and evergreen species extending from cool temperate to tropical latitudes in the Americas, Asia, Europe, and North Africa. North America has the largest number of oak species, with approximately 160 species in Mexico of which 109 are endemic and about 90 in the United States. The second greatest area of oak diversity is China, with approximately 100 species.",Hornbeam,"In the Sonian Forest lives a very old hornbeam that became my friend. It took me a long time to establish a relationship. The hornbeam is a very trustworthy companion. The tree helps me to center my thoughts, to answer personal questions, the tree also advises me in my work.",53052,<100000 Sonian Forest,4421,Beech,"Beech (Fagus) is a genus of deciduous trees in the family Fagaceae, native to temperate Europe, Asia and North America. Recent classifications recognize 10 to 13 species in two distinct subgenera, Engleriana and Fagus. The better known Fagus subgenus beeches are high-branching with tall, stout trunks and smooth silver-grey bark. The European beech (Fagus sylvatica) is the most commonly cultivated.",Oak,"An oak is a tree or shrub in the genus Quercus of the beech family, Fagaceae. There are approximately 500 extant species of oaks. The genus Quercus is native to the Northern Hemisphere, and includes deciduous and evergreen species extending from cool temperate to tropical latitudes in the Americas, Asia, Europe, and North Africa. North America has the largest number of oak species, with approximately 160 species in Mexico of which 109 are endemic and about 90 in the United States. The second greatest area of oak diversity is China, with approximately 100 species.",Hornbeam,"In the Sonian Forest lives a very old hornbeam that became my friend. It took me a long time to establish a relationship. The hornbeam is a very trustworthy companion. The tree helps me to center my thoughts, to answer personal questions, the tree also advises me in my work.",53052,<100000
Congolian Coastal Forest,18970000,Khaya,"Khaya is a genus of five tree species in the mahogany family Meliaceae. The timber of Khaya is called African mahogany, and is valued as a substitute to American mahogany (of the genus Swietenia). The genus is native to tropical Africa and Madagascar. All species grow to around 3035m tall, rarely 45m, with a trunk over 1m diameter, often buttressed at the base.",Oil palm,"Khaya is a genus of five tree species in the mahogany family Meliaceae. The timber of Khaya is called African mahogany, and is valued as a substitute to American mahogany (of the genus Swietenia). The genus is native to tropical Africa and Madagascar. All species grow to around 3035m tall, rarely 45m, with a trunk over 1m diameter, often buttressed at the base.",Okoume,"Aucoumea klaineana (angouma, gaboon, or okoumé) is a tree in the family Burseraceae, native to equatorial west Africa in Gabon, the Republic of the Congo, and Río Muni. It is a large hardwood tree growing to 3040 m (100130 feet) tall, rarely larger, with a trunk 1.02.5 m (3.58 feet) diameter above the often large basal buttresses. The tree generally grows in small stands, with the roots of the trees intertwined with neighboring trees. In Gabon, it is the primary timber species.",227640000,>220000000 Congolian Coastal Forest,18970000,Khaya,"Khaya is a genus of five tree species in the mahogany family Meliaceae. The timber of Khaya is called African mahogany, and is valued as a substitute to American mahogany (of the genus Swietenia). The genus is native to tropical Africa and Madagascar. All species grow to around 3035m tall, rarely 45m, with a trunk over 1m diameter, often buttressed at the base.",Oil palm,"Khaya is a genus of five tree species in the mahogany family Meliaceae. The timber of Khaya is called African mahogany, and is valued as a substitute to American mahogany (of the genus Swietenia). The genus is native to tropical Africa and Madagascar. All species grow to around 3035m tall, rarely 45m, with a trunk over 1m diameter, often buttressed at the base.",Okoume,"Aucoumea klaineana (angouma, gaboon, or okoumé) is a tree in the family Burseraceae, native to equatorial west Africa in Gabon, the Republic of the Congo, and Río Muni. It is a large hardwood tree growing to 3040 m (100130 feet) tall, rarely larger, with a trunk 1.02.5 m (3.58 feet) diameter above the often large basal buttresses. The tree generally grows in small stands, with the roots of the trees intertwined with neighboring trees. In Gabon, it is the primary timber species.",227640000,>220000000
Berlin,,Maple,"In front of my window there is a beautiful maple that whistles in the wind. The tree invites me to contemplate on the weather, the different seasons, the changing colours.",Plane,"Platanus is a genus consisting of a small number of tree species native to the Northern Hemisphere. All mature members of Platanus are tall, reaching 3050 m (98164 ft) in height. The hybrid London plane (Platanus × acerifolia) has proved particularly tolerant of urban conditions, and has been widely planted in cities. They are often known in English as planes or plane trees. ",Horse chestnut,"The genus Aesculus, with species called buckeye and horse chestnut, comprises 1319 species of flowering plants in the family Sapindaceae or soaptrees. Carl Linnaeus named the genus Aesculus after the Roman name for an edible acorn. Common names for these trees include ""buckeye"" and ""horse chestnut"", though they are not in the same order as the true chestnuts, Castanea. ",0.003,<1 Berlin,,Maple,"In front of my window there is a beautiful maple that whistles in the wind. The tree invites me to contemplate on the weather, the different seasons, the changing colours.",Plane,"Platanus is a genus consisting of a small number of tree species native to the Northern Hemisphere. All mature members of Platanus are tall, reaching 3050 m (98164 ft) in height. The hybrid London plane (Platanus × acerifolia) has proved particularly tolerant of urban conditions, and has been widely planted in cities. They are often known in English as planes or plane trees. ",Horse chestnut,"The genus Aesculus, with species called buckeye and horse chestnut, comprises 1319 species of flowering plants in the family Sapindaceae or soaptrees. Carl Linnaeus named the genus Aesculus after the Roman name for an edible acorn. Common names for these trees include ""buckeye"" and ""horse chestnut"", though they are not in the same order as the true chestnuts, Castanea. ",0.003,<1

1 Forest ha Tree_0 Tree_0_description Tree_1 Tree_1_description Tree_3 Tree_2 Tree_3_description Tree_2_description CO2 ratio
2 Sonian Forest 4421 Beech Beech (Fagus) is a genus of deciduous trees in the family Fagaceae, native to temperate Europe, Asia and North America. Recent classifications recognize 10 to 13 species in two distinct subgenera, Engleriana and Fagus. The better known Fagus subgenus beeches are high-branching with tall, stout trunks and smooth silver-grey bark. The European beech (Fagus sylvatica) is the most commonly cultivated. Beech Oak Beech (Fagus) is a genus of deciduous trees in the family Fagaceae, native to temperate Europe, Asia and North America. Recent classifications recognize 10 to 13 species in two distinct subgenera, Engleriana and Fagus. The better known Fagus subgenus beeches are high-branching with tall, stout trunks and smooth silver-grey bark. The European beech (Fagus sylvatica) is the most commonly cultivated. An oak is a tree or shrub in the genus Quercus of the beech family, Fagaceae. There are approximately 500 extant species of oaks. The genus Quercus is native to the Northern Hemisphere, and includes deciduous and evergreen species extending from cool temperate to tropical latitudes in the Americas, Asia, Europe, and North Africa. North America has the largest number of oak species, with approximately 160 species in Mexico of which 109 are endemic and about 90 in the United States. The second greatest area of oak diversity is China, with approximately 100 species. Hornbeam Oak Hornbeam In the Sonian Forest lives a very old hornbeam that became my friend. It took me a long time to establish a relationship. The hornbeam is a very trustworthy companion. The tree helps me to center my thoughts, to answer personal questions, the tree also advises me in my work. An oak is a tree or shrub in the genus Quercus of the beech family, Fagaceae. There are approximately 500 extant species of oaks. The genus Quercus is native to the Northern Hemisphere, and includes deciduous and evergreen species extending from cool temperate to tropical latitudes in the Americas, Asia, Europe, and North Africa. North America has the largest number of oak species, with approximately 160 species in Mexico of which 109 are endemic and about 90 in the United States. The second greatest area of oak diversity is China, with approximately 100 species. In the Sonian Forest lives a very old hornbeam that became my friend. It took me a long time to establish a relationship. The hornbeam is a very trustworthy companion. The tree helps me to center my thoughts, to answer personal questions, the tree also advises me in my work. 53052 <100000
3 Congolian Coastal Forest 18970000 Khaya Khaya is a genus of five tree species in the mahogany family Meliaceae. The timber of Khaya is called African mahogany, and is valued as a substitute to American mahogany (of the genus Swietenia). The genus is native to tropical Africa and Madagascar. All species grow to around 30–35m tall, rarely 45m, with a trunk over 1m diameter, often buttressed at the base. Khaya Oil palm Khaya is a genus of five tree species in the mahogany family Meliaceae. The timber of Khaya is called African mahogany, and is valued as a substitute to American mahogany (of the genus Swietenia). The genus is native to tropical Africa and Madagascar. All species grow to around 30–35m tall, rarely 45m, with a trunk over 1m diameter, often buttressed at the base. Okoume Oil palm Okoume Aucoumea klaineana (angouma, gaboon, or okoumé) is a tree in the family Burseraceae, native to equatorial west Africa in Gabon, the Republic of the Congo, and Río Muni. It is a large hardwood tree growing to 30–40 m (100–130 feet) tall, rarely larger, with a trunk 1.0–2.5 m (3.5–8 feet) diameter above the often large basal buttresses. The tree generally grows in small stands, with the roots of the trees intertwined with neighboring trees. In Gabon, it is the primary timber species. Khaya is a genus of five tree species in the mahogany family Meliaceae. The timber of Khaya is called African mahogany, and is valued as a substitute to American mahogany (of the genus Swietenia). The genus is native to tropical Africa and Madagascar. All species grow to around 30–35m tall, rarely 45m, with a trunk over 1m diameter, often buttressed at the base. Aucoumea klaineana (angouma, gaboon, or okoumé) is a tree in the family Burseraceae, native to equatorial west Africa in Gabon, the Republic of the Congo, and Río Muni. It is a large hardwood tree growing to 30–40 m (100–130 feet) tall, rarely larger, with a trunk 1.0–2.5 m (3.5–8 feet) diameter above the often large basal buttresses. The tree generally grows in small stands, with the roots of the trees intertwined with neighboring trees. In Gabon, it is the primary timber species. 227640000 >220000000
4 Berlin Maple In front of my window there is a beautiful maple that whistles in the wind. The tree invites me to contemplate on the weather, the different seasons, the changing colours. Maple Plane In front of my window there is a beautiful maple that whistles in the wind. The tree invites me to contemplate on the weather, the different seasons, the changing colours. Platanus is a genus consisting of a small number of tree species native to the Northern Hemisphere. All mature members of Platanus are tall, reaching 30–50 m (98–164 ft) in height. The hybrid London plane (Platanus × acerifolia) has proved particularly tolerant of urban conditions, and has been widely planted in cities. They are often known in English as planes or plane trees. Horse chestnut Plane Horse chestnut The genus Aesculus, with species called buckeye and horse chestnut, comprises 13–19 species of flowering plants in the family Sapindaceae or soaptrees. Carl Linnaeus named the genus Aesculus after the Roman name for an edible acorn. Common names for these trees include "buckeye" and "horse chestnut", though they are not in the same order as the true chestnuts, Castanea. Platanus is a genus consisting of a small number of tree species native to the Northern Hemisphere. All mature members of Platanus are tall, reaching 30–50 m (98–164 ft) in height. The hybrid London plane (Platanus × acerifolia) has proved particularly tolerant of urban conditions, and has been widely planted in cities. They are often known in English as planes or plane trees. The genus Aesculus, with species called buckeye and horse chestnut, comprises 13–19 species of flowering plants in the family Sapindaceae or soaptrees. Carl Linnaeus named the genus Aesculus after the Roman name for an edible acorn. Common names for these trees include "buckeye" and "horse chestnut", though they are not in the same order as the true chestnuts, Castanea. 0.003 <1

@ -75,93 +75,96 @@ def in_between(text, pos_list):
# text = text.replace(letter, "!") # text = text.replace(letter, "!")
# return text # return text
# -------------- # if you call script by its own name, it will execute the commands\
# create list of dictionaries with Forest, ha, Tree_1, Tree_2, Tree_3, CO2 in tonnes, ratio # otherwise it will only activate the functions to be called elsewhere
file = "data_trees.csv" if __name__ == '__main__':
data = call_trees(file) # --------------
#print(data) # create list of dictionaries with Forest, ha, Tree_1, Tree_2, Tree_3, CO2 in tonnes, ratio
file = "data_trees.csv"
# open file with dreams data = call_trees(file)
textfile = "dreams_selection_till_p47.txt" #print(data)
dreaming = open_dreams(textfile)
#print(dreaming) # open file with dreams
textfile = "dreams_selection_till_p47.txt"
# choose location and tree dreaming = open_dreams(textfile)
print("These are locations where you can catch dreams near trees: \n") #print(dreaming)
nr = 0
for element in data: # choose location and tree
print(str(nr) + ' --- ' + element['Forest']) print("These are locations where you can catch dreams near trees: \n")
nr += 1 nr = 0
print("\n") for element in data:
location = input("Where do you want to receive your dream? Type a number: \n") print(str(nr) + ' --- ' + element['Forest'])
print("Thanks for choosing "+ data[int(location)]['Forest']+".\n") nr += 1
print("There are 3 trees that offer dream services: \n") print("\n")
print("1" + ' --- ' + data[int(location)]['Tree_1']) location = input("Where do you want to receive your dream? Type a number: \n")
print("2" + ' --- ' + data[int(location)]['Tree_2']) print("Thanks for choosing "+ data[int(location)]['Forest']+".\n")
print("3" + ' --- ' + data[int(location)]['Tree_3']) print("There are 3 trees that offer dream services: \n")
print("\n") print("1" + ' --- ' + data[int(location)]['Tree_1'])
tree_number = input("Which tree do you prefer to dream with? Type a number: \n") print("2" + ' --- ' + data[int(location)]['Tree_2'])
selected_tree = "Tree_"+tree_number print("3" + ' --- ' + data[int(location)]['Tree_3'])
dream_tree = data[int(location)][selected_tree] print("\n")
tree_number = input("Which tree do you prefer to dream with? Type a number: \n")
print("\n_________________________________\n") selected_tree = "Tree_"+tree_number
dream_tree = data[int(location)][selected_tree]
# Printing text
title = "Dreaming with "+ dream_tree +" in "+ data[int(location)]['Forest']
print(title)
print("_________________________________\n")
selected_description = selected_tree + "_description"
description_tree = data[int(location)][selected_description]
print(description_tree)
print("\n_________________________________\n")
template_text = "Trees absorb CO2 from the air and generate oxygen. \
In forests and parks, the concentration of trees is high and CO2 emissions are often low,\
because traffic is inexistant. The air quality for humans is therefore generally better.\
The hypothesis exists that the high concentration of trees allows for more lucid dreaming.\
It is said as well that a personal relationship to a tree can enhance lucid dreaming as well,\
even if the tree is living in an urban area."
print(template_text)
print("\n_________________________________\n")
doc, tokens, verbs, nouns, adjectives, articles = part_of_speech(dreaming)
# print("Verbs:", verbs)
# print("Nouns:", nouns)
# print("Adjectives:", adjectives)
# print("Articles:", articles)
# convert spacy token objects to strings in list
tokenized_text = convert_token_to_text(doc)
if float(data[int(location)]["CO2"]) < 1:
# if ration is <1
# replace verbs by spaces of same length
article_text = replace_pos(tokenized_text, articles)
final_text = replace_pos(article_text, nouns)
print("ENJOY YOUR DREAMS ! \n")
print("\n_________________________________\n")
print(" ".join(final_text))
print("\n_________________________________\n")
elif float(data[int(location)]["CO2"]) > 110000:
verb_text = highlight_word(tokenized_text, verbs)
final_text = highlight_word(verb_text, nouns)
print("ENJOY YOUR DREAMS ! \n")
print("\n_________________________________\n")
print(" ".join(final_text))
print("\n_________________________________\n")
else:
final_text = in_between(tokenized_text, nouns)
print("ENJOY YOUR DREAMS ! \n")
print("\n_________________________________\n") print("\n_________________________________\n")
print(" ".join(final_text))
# Printing text
title = "Dreaming with "+ dream_tree +" in "+ data[int(location)]['Forest']
print(title)
print("_________________________________\n")
selected_description = selected_tree + "_description"
description_tree = data[int(location)][selected_description]
print(description_tree)
print("\n_________________________________\n") print("\n_________________________________\n")
template_text = "Trees absorb CO2 from the air and generate oxygen. \
In forests and parks, the concentration of trees is high and CO2 emissions are often low,\
because traffic is inexistant. The air quality for humans is therefore generally better.\
The hypothesis exists that the high concentration of trees allows for more lucid dreaming.\
It is said as well that a personal relationship to a tree can enhance lucid dreaming as well,\
even if the tree is living in an urban area."
print(template_text)
print("\n_________________________________\n")
# create 3 dream convertors depending on where the trees are located doc, tokens, verbs, nouns, adjectives, articles = part_of_speech(dreaming)
# if ratio is < 1, , > 500000 # print("Verbs:", verbs)
# print("Nouns:", nouns)
# print("Adjectives:", adjectives)
# print("Articles:", articles)
# convert spacy token objects to strings in list
tokenized_text = convert_token_to_text(doc)
if float(data[int(location)]["CO2"]) < 1:
# if ration is <1
# replace verbs by spaces of same length
article_text = replace_pos(tokenized_text, articles)
final_text = replace_pos(article_text, nouns)
print("ENJOY YOUR DREAMS ! \n")
print("\n_________________________________\n")
print(" ".join(final_text))
print("\n_________________________________\n")
elif float(data[int(location)]["CO2"]) > 110000:
verb_text = highlight_word(tokenized_text, verbs)
final_text = highlight_word(verb_text, nouns)
print("ENJOY YOUR DREAMS ! \n")
print("\n_________________________________\n")
print(" ".join(final_text))
print("\n_________________________________\n")
else:
final_text = in_between(tokenized_text, nouns)
print("ENJOY YOUR DREAMS ! \n")
print("\n_________________________________\n")
print(" ".join(final_text))
print("\n_________________________________\n")
# create 3 dream convertors depending on where the trees are located
# if ratio is < 1, , > 500000

@ -0,0 +1,110 @@
import subprocess
import tempfile
import os.path
from settings import PAGEDJS_BINARY_PATH
basepath = os.path.abspath(os.path.dirname(__file__))
"""
Calls the pagedjs binary.
path_html path to the html sources to be read by pagedjs
path_pdf output path of the generated pdf
cwd path to be used as current working directory for the subprocess
extra_scripts array of paths to additional javascript
"""
def run_pagedjs (path_html, path_pdf, cwd=None, extra_scripts=[]):
args = [
PAGEDJS_BINARY_PATH
]
for script in extra_scripts:
args.extend([
'--additional-script',
script
])
args.extend([
'-o', path_pdf,
path_html
])
try:
return subprocess.check_output(args, cwd=cwd, stderr=subprocess.STDOUT).decode()
except subprocess.CalledProcessError as e:
return 'Error:\n{}'.format(e.output.decode())
"""
Generates a PDF based on provided HTML using pagedjs and returns the generated PDF.
If optional path_out is provided the PDF is written there and the function returns the path.
Optional extra_scripts is a list of strings with javascript.
Scripts are sent in the same order to paged.js
"""
def make_pdf_from_string (html, path_out=None, extra_scripts=[]):
with tempfile.TemporaryDirectory(prefix='algoliterary_publishing_house_') as tempdir:
with tempfile.NamedTemporaryFile(dir=tempdir, mode='w', suffix='.html', delete=False) as temphtml:
# Store html in a temporary file
temphtml.write(html)
temphtml.close()
name_in = temphtml.name
extra_scripts_tmp = []
for script in extra_scripts:
with tempfile.NamedTemporaryFile(dir=tempdir, mode='w', suffix='.js', delete=False) as tempjs:
tempjs.write(script)
tempjs.close()
extra_scripts_tmp.append(tempjs.name)
# Make a temporary file for the generated PDF
with tempfile.NamedTemporaryFile(dir=tempdir, mode='w', suffix='.pdf', delete=False) as temppdf:
temppdf.close()
name_out = temppdf.name
# Make the pdf
run_pagedjs(name_in, name_out, cwd=basepath, extra_scripts=extra_scripts_tmp)
if path_out:
import shutil
shutil.copy(name_out, path_out)
return path_out
else:
with open(name_out, 'rb') as generated_pdf:
return generated_pdf.read()
"""
Generates a PDF based on provided HTML using pagedjs and returns the generated PDF.
If optional path_out is provided the PDF is written there and the function returns the path.
Optional extra_scripts is a list of strings with javascript.
Scripts are sent in the same order to paged.js
"""
def make_pdf_from_url (url, path_out=None, extra_scripts=[]):
with tempfile.TemporaryDirectory(prefix='algoliterary_publishing_house_') as tempdir:
extra_scripts_tmp = []
for script in extra_scripts:
with tempfile.NamedTemporaryFile(dir=tempdir, mode='w', suffix='.js', delete=False) as tempjs:
tempjs.write(script)
tempjs.close()
extra_scripts_tmp.append(tempjs.name)
# Make a temporary file for the generated PDF
with tempfile.NamedTemporaryFile(dir=tempdir, mode='w', suffix='.pdf', delete=False) as temppdf:
temppdf.close()
name_out = temppdf.name
# Make the pdf
run_pagedjs(url, name_out, cwd=basepath, extra_scripts=extra_scripts_tmp)
if path_out:
import shutil
shutil.copy(name_out, path_out)
return path_out
else:
with open(name_out, 'rb') as generated_pdf:
return generated_pdf.read()

@ -0,0 +1,4 @@
#!/bin/bash
export FLASK_APP=app.py
export FLASK_ENV=development # Disable line on deployment
flask run

@ -0,0 +1,11 @@
PAGEDJS_BINARY_PATH = 'pagedjs-cli' # os.path.join(os.path.dirname(__file__), 'node_modules/pagedjs-cli/bin/paged')
# Path to the pagedjs-cli executable
# Find it on linux with `whereis pagedjs-cli`
# Let's try the simple way first :-)
DEBUG = False
# When set to true, the application doesn't generate a PDF,
# but uses the pagedjs-polyfill to show a preview of the document
SITEURL = 'http://localhost:5000'
# Baseurl on the server. For now only in devployment
HTML_TMP_DIR = '/tmp/publishing_house/'
# Location where the temporary html files are stored

File diff suppressed because it is too large Load Diff

@ -0,0 +1,180 @@
/* CSS for Paged.js interface v0.3 */
/* Change the look */
:root {
--color-background: whitesmoke;
--color-pageSheet: #cfcfcf;
--color-pageBox: violet;
--color-paper: white;
--color-marginBox: transparent;
--pagedjs-crop-color: black;
--pagedjs-crop-shadow: white;
--pagedjs-crop-stroke: 1px;
}
/* To define how the book look on the screen: */
@media screen, pagedjs-ignore {
body {
background-color: var(--color-background);
}
.pagedjs_pages {
display: flex;
width: calc(var(--pagedjs-width) * 2);
flex: 0;
flex-wrap: wrap;
margin: 0 auto;
}
.pagedjs_page {
background-color: var(--color-paper);
box-shadow: 0 0 0 1px var(--color-pageSheet);
margin: 0;
flex-shrink: 0;
flex-grow: 0;
margin-top: 10mm;
}
.pagedjs_first_page {
margin-left: var(--pagedjs-width);
}
.pagedjs_page:last-of-type {
margin-bottom: 10mm;
}
.pagedjs_pagebox{
box-shadow: 0 0 0 1px var(--color-pageBox);
}
.pagedjs_left_page{
z-index: 20;
width: calc(var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width))!important;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop {
border-color: transparent;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-middle{
width: 0;
}
.pagedjs_right_page{
z-index: 10;
position: relative;
left: calc(var(--pagedjs-bleed-left)*-1);
}
/* show the margin-box */
.pagedjs_margin-top-left-corner-holder,
.pagedjs_margin-top,
.pagedjs_margin-top-left,
.pagedjs_margin-top-center,
.pagedjs_margin-top-right,
.pagedjs_margin-top-right-corner-holder,
.pagedjs_margin-bottom-left-corner-holder,
.pagedjs_margin-bottom,
.pagedjs_margin-bottom-left,
.pagedjs_margin-bottom-center,
.pagedjs_margin-bottom-right,
.pagedjs_margin-bottom-right-corner-holder,
.pagedjs_margin-right,
.pagedjs_margin-right-top,
.pagedjs_margin-right-middle,
.pagedjs_margin-right-bottom,
.pagedjs_margin-left,
.pagedjs_margin-left-top,
.pagedjs_margin-left-middle,
.pagedjs_margin-left-bottom {
box-shadow: 0 0 0 1px inset var(--color-marginBox);
}
/* uncomment this part for recto/verso book : ------------------------------------ */
/*
.pagedjs_pages {
flex-direction: column;
width: 100%;
}
.pagedjs_first_page {
margin-left: 0;
}
.pagedjs_page {
margin: 0 auto;
margin-top: 10mm;
}
.pagedjs_left_page{
width: calc(var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width) + var(--pagedjs-bleed-left))!important;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop{
border-color: var(--pagedjs-crop-color);
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-middle{
width: var(--pagedjs-cross-size)!important;
}
.pagedjs_right_page{
left: 0;
}
*/
/*--------------------------------------------------------------------------------------*/
/* uncomment this par to see the baseline : -------------------------------------------*/
/* .pagedjs_pagebox {
--pagedjs-baseline: 22px;
--pagedjs-baseline-position: 5px;
--pagedjs-baseline-color: cyan;
background: linear-gradient(transparent 0%, transparent calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) var(--pagedjs-baseline)), transparent;
background-size: 100% var(--pagedjs-baseline);
background-repeat: repeat-y;
background-position-y: var(--pagedjs-baseline-position);
} */
/*--------------------------------------------------------------------------------------*/
}
/* Marks (to delete when merge in paged.js) */
.pagedjs_marks-crop{
z-index: 999999999999;
}
.pagedjs_bleed-top .pagedjs_marks-crop,
.pagedjs_bleed-bottom .pagedjs_marks-crop{
box-shadow: 1px 0px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-top .pagedjs_marks-crop:last-child,
.pagedjs_bleed-bottom .pagedjs_marks-crop:last-child{
box-shadow: -1px 0px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-left .pagedjs_marks-crop,
.pagedjs_bleed-right .pagedjs_marks-crop{
box-shadow: 0px 1px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-left .pagedjs_marks-crop:last-child,
.pagedjs_bleed-right .pagedjs_marks-crop:last-child{
box-shadow: 0px -1px 0px 0px var(--pagedjs-crop-shadow);
}

@ -0,0 +1,19 @@
h1 {
text-decoration: underline;
break-after: always;
}
/**
@page {
size: 210mm 297mm;
margin: 10mm 5mm;
}
*/
/**
@media print {
h1 {
}
}
*/

@ -0,0 +1,32 @@
<!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">
<link href="{{ url_for('static', filename='style.css') }}" rel="stylesheet">
{% if DEBUG %}
<link href="{{ url_for('static', filename='pagedjs.interface.css') }}" rel="stylesheet">
<script src="{{ url_for('static', filename='js/paged.polyfill.js') }}"></script>
<!-- <script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script> -->
{% endif %}
<title>Generated book</title>
</head>
<body>
<h1>Dreaming with {{ dream_tree }} in {{ place }}</h1>
<p>{{description_tree}}</p>
<p>Trees absorb CO2 from the air and generate oxygen. \
In forests and parks, the concentration of trees is high and CO2 emissions are often low,\
because traffic is inexistant. The air quality for humans is therefore generally better.\
The hypothesis exists that the high concentration of trees allows for more lucid dreaming.\
It is said as well that a personal relationship to a tree can enhance lucid dreaming as well,\
even if the tree is living in an urban area</p>
<h2>ENJOY YOUR DREAMS!</h2>
<p>{{final_text}}</p>
<h2>Credits</h2>
<p>This work was developed by Ipek Burçak and An Mertens during the Anaïs Berck residency at Meyboom, Brussels in Sept-Oct 2022.</p>
<p>The dreams are a selection of <a href = "https://archivedream.wordpress.com/">Pandemic Dreams Archive</a>, a project by Erick Felinto, Fabiane M. Borges, Lívia Diniz, Rafael Frazão and Tiago F. Pimentel.</p>
</body>
</html>

@ -0,0 +1,23 @@
<!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">
<link href="{{ url_for('static', filename='style.css') }}" rel="stylesheet">
<title>Generative book</title>
</head>
<body>
<h1>Pagedjs, Flask Boilerplate.</h1>
<p>
The boilerplate seems to be running fine.
</p>
<p>
<a href="{{ url_for('generate') }}">Generate</a> a PDF.
</p>
<!-- Or to generate the book with a post request, uncomment the block below. -->
<!-- <form method="post" action="{{ url_for('generate') }}">
<button>Generate</button>
</form> -->
</body>
</html>

@ -0,0 +1,13 @@
<h1>Dreaming with trees</h1>
<p>These are locations where you can catch dreams near trees.</p>
<p>Please choose one:</p>
<form method="POST" action="/step2">
<ul>
{% for location in locations %}
<li><input type="radio" name="location" value="{{ loop.index0 }}">{{ location }}</li>
{% endfor %}
</ul>
<input type ="submit" value ="Choose"/>
</form>

@ -0,0 +1,14 @@
<p>There are 3 trees that offer dream services.</p>
<p>Which tree do you prefer to dream with?</p>
<p>Please choose one:</p>
<form method="POST" action="/generate">
<input type="hidden" name="location" value="{{ location }}" />
<ul>
{% for tree in trees %}
<li><input type="radio" name="tree" value="{{ loop.index0 }}"> {{ tree }}</li>
{% endfor %}
</ul>
<input type="submit" value="Generate dreams"/>
</form>

@ -0,0 +1,27 @@
import os
from fcntl import lockf, LOCK_EX, LOCK_UN
def get_edition_count(counter_path):
# Try to open a file descriptor to the given path
fd = os.open(counter_path, os.O_RDWR|os.O_CREAT)
# Lock the file so it can't be read in other processes
lockf(fd, LOCK_EX)
# Open the file and read
fo = os.fdopen(fd, 'r+', encoding='utf-8')
content = fo.read()
if not content:
edition_count = 0
else:
edition_count = int(content.strip())
edition_count += 1
# Clear file, write incremented value, unlock file and close
fo.seek(0)
fo.truncate()
fo.write(str(edition_count))
fo.flush()
lockf(fd, LOCK_UN)
os.close(fd)
return edition_count
Loading…
Cancel
Save