manetta
3 years ago
17 changed files with 428 additions and 271 deletions
@ -0,0 +1,9 @@ |
|||||
|
default: run |
||||
|
|
||||
|
setup: |
||||
|
@python3 -m venv .venv |
||||
|
@.venv/bin/pip install -r requirements.txt |
||||
|
|
||||
|
run: |
||||
|
@.venv/bin/python octomode.py |
||||
|
|
@ -0,0 +1,213 @@ |
|||||
|
import flask |
||||
|
from flask import request |
||||
|
from urllib.request import urlopen |
||||
|
from urllib.parse import urlencode |
||||
|
import json |
||||
|
import os |
||||
|
import pypandoc |
||||
|
from jinja2 import Template |
||||
|
|
||||
|
APP = flask.Flask(__name__) |
||||
|
APP.config.from_object("config.Config") |
||||
|
|
||||
|
# --- |
||||
|
|
||||
|
def get_pad_content(pad): |
||||
|
arguments = { |
||||
|
'padID' : pad, |
||||
|
'apikey' : APP.config['PAD_API_KEY'] |
||||
|
} |
||||
|
api_call = 'getText' |
||||
|
response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode())) |
||||
|
|
||||
|
# create pad in case it does not yet exist |
||||
|
if response['code'] == 1 and 'padID does not exist' == response['message']: |
||||
|
api_call = 'createPad' |
||||
|
urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode()) |
||||
|
api_call = 'getText' |
||||
|
response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode())) |
||||
|
|
||||
|
# print(response) |
||||
|
content = response['data']['text'] |
||||
|
return content |
||||
|
|
||||
|
def all_pads(): |
||||
|
arguments = { |
||||
|
'apikey' : APP.config['PAD_API_KEY'], |
||||
|
} |
||||
|
api_call = 'listAllPads' |
||||
|
response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode())) |
||||
|
|
||||
|
return response |
||||
|
|
||||
|
def create_pad_on_first_run(name, ext): |
||||
|
pads = all_pads() |
||||
|
pad = name+ext |
||||
|
|
||||
|
if 'md' in ext: |
||||
|
default_template = 'templates/default.md' |
||||
|
elif 'css' in ext: |
||||
|
default_template = 'templates/default.css' |
||||
|
elif 'template' in ext: |
||||
|
default_template = 'templates/default-pandoc-template.html' |
||||
|
|
||||
|
if 'template' in ext: |
||||
|
default_template = open(default_template).read() |
||||
|
jinja_template = Template(default_template) |
||||
|
default_template = jinja_template.render(name=name.strip()) |
||||
|
else: |
||||
|
default_template = open(default_template).read() |
||||
|
|
||||
|
if pad not in pads['data']['padIDs']: |
||||
|
arguments = { |
||||
|
'padID' : pad, |
||||
|
'apikey' : APP.config['PAD_API_KEY'], |
||||
|
'text' : default_template |
||||
|
} |
||||
|
api_call = 'createPad' |
||||
|
response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode())) |
||||
|
|
||||
|
def update_pad_contents(name): |
||||
|
# download the md pad + stylesheet + template pad |
||||
|
md_pad = f'{ name }.md' |
||||
|
css_pad = f'{ name }.css' |
||||
|
template_pad = f'{ name }.template' |
||||
|
md = get_pad_content(md_pad) |
||||
|
css = get_pad_content(css_pad) |
||||
|
template = get_pad_content(template_pad) |
||||
|
# !!! this breaks the whole idea that this application can be shared by multiple projects at the same time |
||||
|
# !!! but py_pandoc needs to run with files........ hmmm |
||||
|
with open('templates/pandoc-template.html', 'w') as f: |
||||
|
f.write(template) |
||||
|
|
||||
|
return md, css, template |
||||
|
|
||||
|
# --- |
||||
|
|
||||
|
@APP.route('/', methods=['GET', 'POST']) |
||||
|
def index(): |
||||
|
name = request.values.get('name') |
||||
|
if name: |
||||
|
# This is when the environment is "created" |
||||
|
# The pads are filled with the default templates (pad, stylesheet, template) |
||||
|
exts = ['.md', '.css', '.template'] |
||||
|
for ext in exts: |
||||
|
create_pad_on_first_run(name, ext) |
||||
|
return flask.redirect(f'/{ name }/') |
||||
|
else: |
||||
|
return flask.render_template('start.html') |
||||
|
|
||||
|
@APP.route('/<name>/', methods=['GET']) |
||||
|
def main(name): |
||||
|
# !!! Add a if/else here to check if the environment is "created" already |
||||
|
ext = '.md' |
||||
|
create_pad_on_first_run(name, ext) |
||||
|
return flask.render_template('pad.html', name=name.strip(), ext=ext) |
||||
|
|
||||
|
@APP.route('/<name>/pad/') |
||||
|
def pad(name): |
||||
|
ext = '.md' |
||||
|
create_pad_on_first_run(name, ext) |
||||
|
return flask.render_template('pad.html', name=name.strip(), ext=ext) |
||||
|
|
||||
|
@APP.route('/<name>/stylesheet/', methods=['GET']) |
||||
|
def stylesheet(name): |
||||
|
ext = '.css' |
||||
|
create_pad_on_first_run(name, ext) |
||||
|
return flask.render_template('pad.html', name=name.strip(), ext=ext) |
||||
|
|
||||
|
@APP.route('/<name>/template/', methods=['GET']) |
||||
|
def template(name): |
||||
|
ext = '.template' |
||||
|
create_pad_on_first_run(name, ext) |
||||
|
return flask.render_template('pad.html', name=name.strip(), ext=ext) |
||||
|
|
||||
|
# @APP.route('/<name>/html/') |
||||
|
# def html(name): |
||||
|
# # update pad contents |
||||
|
# md, css, template = update_pad_contents(name) |
||||
|
# # generate html page |
||||
|
# pandoc_args = [ |
||||
|
# # '--css=static/print.css', |
||||
|
# '--toc', |
||||
|
# '--toc-depth=1', |
||||
|
# '--template=templates/pandoc-template.html', |
||||
|
# '--standalone' |
||||
|
# ] |
||||
|
# html = pypandoc.convert_text(md, 'html', format='md', extra_args=pandoc_args) |
||||
|
|
||||
|
# return flask.render_template('html.html', html=html, name=name.strip()) |
||||
|
|
||||
|
@APP.route('/<name>/pdf/') |
||||
|
def pdf(name): |
||||
|
# In case the URL is edited directly with a new name |
||||
|
exts = ['.md', '.css', '.template'] |
||||
|
for ext in exts: |
||||
|
create_pad_on_first_run(name, ext) |
||||
|
return flask.render_template('pdf.html', name=name.strip()) |
||||
|
|
||||
|
# ////////////// |
||||
|
# rendered resources (not saved as a file on the server) |
||||
|
|
||||
|
@APP.route('/<name>/print.css') |
||||
|
def css(name): |
||||
|
x, css, x = update_pad_contents(name) |
||||
|
|
||||
|
return css, 200, {'Content-Type': 'text/css; charset=utf-8'} |
||||
|
|
||||
|
@APP.route('/<name>/pandoc-template.html') |
||||
|
def pandoc_template(name): |
||||
|
x, x, template = update_pad_contents(name) |
||||
|
|
||||
|
return template, 200, {'Content-Type': 'text/html; charset=utf-8'} |
||||
|
|
||||
|
@APP.route('/<name>/pagedjs.html') |
||||
|
def pagedjs(name): |
||||
|
# update pad contents |
||||
|
md, css, template = update_pad_contents(name) |
||||
|
# generate html page with the pandoc template (with paged.js inserted in the header) |
||||
|
pandoc_args = [ |
||||
|
'--toc', |
||||
|
'--toc-depth=1', |
||||
|
'--template=templates/pandoc-template.html', |
||||
|
'--standalone' |
||||
|
] |
||||
|
html = pypandoc.convert_text(md, 'html', format='md', extra_args=pandoc_args) |
||||
|
|
||||
|
return html, 200, {'Content-Type': 'text/html; charset=utf-8'} |
||||
|
|
||||
|
# ////////////// |
||||
|
|
||||
|
def flask_logger(): |
||||
|
# creates logging information |
||||
|
# https://www.vantage-ai.com/en/blog/adding-on-screen-logging-in-a-few-steps-using-a-flask-application |
||||
|
|
||||
|
from io import StringIO |
||||
|
import logging |
||||
|
from time import sleep |
||||
|
|
||||
|
log_stream = StringIO() |
||||
|
handler = logging.StreamHandler(log_stream) |
||||
|
log = logging.getLogger('werkzeug') |
||||
|
log.setLevel(logging.DEBUG) |
||||
|
log.addHandler(handler) |
||||
|
|
||||
|
while True: |
||||
|
yield log_stream.getvalue() |
||||
|
# "flush" the stream, move the seek/truncate points to 0 |
||||
|
log_stream.seek(0) |
||||
|
log_stream.truncate(0) |
||||
|
|
||||
|
sleep(0.1) |
||||
|
|
||||
|
@APP.route('/log/', methods=['GET']) |
||||
|
def log(): |
||||
|
# returns logging information |
||||
|
return flask.Response(flask_logger(), mimetype="text/plain", content_type="text/event-stream") |
||||
|
|
||||
|
# ///////////// |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
APP.debug=True |
||||
|
APP.run(host="0.0.0.0", port=f'{ APP.config["PORTNUMBER"] }', threaded=True) |
@ -1,3 +1,6 @@ |
|||||
flask |
flask |
||||
etherpump |
|
||||
markdown |
markdown |
||||
|
urllib3 |
||||
|
pandoc |
||||
|
pypandoc |
||||
|
jinja |
@ -1,58 +0,0 @@ |
|||||
import flask |
|
||||
from flask import request |
|
||||
import urllib, json |
|
||||
import os |
|
||||
|
|
||||
# Create the application. |
|
||||
APP = flask.Flask(__name__) |
|
||||
|
|
||||
# --- |
|
||||
|
|
||||
#The following three lines are the variables that need to be changed when making a new project. |
|
||||
|
|
||||
PROJECTNAME = 'dsn' |
|
||||
DIR_PATH = '/home/systers/dsn-documentation' |
|
||||
PORTNUMBER = 5123 |
|
||||
|
|
||||
# --- |
|
||||
|
|
||||
|
|
||||
pads = [ |
|
||||
f'{ PROJECTNAME }.md', |
|
||||
f'{ PROJECTNAME }.css' |
|
||||
] |
|
||||
|
|
||||
def download(pads): |
|
||||
# using etherpump |
|
||||
for pad in pads: |
|
||||
os.system(f'{ DIR_PATH }/venv/bin/etherpump gettext { pad } > { DIR_PATH }/static/{ pad }') |
|
||||
|
|
||||
@APP.route('/', methods=['GET']) |
|
||||
def pad(): |
|
||||
return flask.render_template('pad.html') |
|
||||
|
|
||||
@APP.route('/pagedjs/', methods=['GET', 'POST']) |
|
||||
def pagedjs(): |
|
||||
# download the main post-script pad + stylesheet pad |
|
||||
download(pads) |
|
||||
# generate html page with the pandoc template (with paged.js inserted in the header) |
|
||||
os.system(f'pandoc -f markdown -t html -c { PROJECTNAME }.css --toc --toc-depth=1 --template { DIR_PATH }/templates/pandoc-template-pagedjs.html --standalone { DIR_PATH }/static/{ PROJECTNAME }.md -o { DIR_PATH }/static/{ PROJECTNAME }.pagedjs.html') |
|
||||
|
|
||||
return flask.render_template('pagedjs.html') |
|
||||
|
|
||||
@APP.route('/html/', methods=['GET', 'POST']) |
|
||||
def html(): |
|
||||
# download the main post-script pad + stylesheet pad |
|
||||
download(pads) |
|
||||
# generate html page |
|
||||
os.system(f'pandoc -f markdown -t html -c { PROJECTNAME }.css --toc --toc-depth=1 --standalone { DIR_PATH }/static/{ PROJECTNAME }.md -o { DIR_PATH }/static/{ PROJECTNAME }.html') |
|
||||
|
|
||||
return flask.render_template('html.html') |
|
||||
|
|
||||
@APP.route('/stylesheet/', methods=['GET']) |
|
||||
def stylesheet(): |
|
||||
return flask.render_template('stylesheet.html') |
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
APP.debug=True |
|
||||
APP.run(port=f'{ PORTNUMBER }') |
|
@ -1,180 +0,0 @@ |
|||||
/* CSS for Paged.js interface – v0.2 */ |
|
||||
|
|
||||
/* 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 { |
|
||||
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); |
|
||||
} |
|
@ -1,16 +1,80 @@ |
|||||
body{ |
body{ |
||||
background-color: #eaa0f9; |
min-width: 900px; |
||||
margin: 1vh 5vw 2vh 5vw; |
|
||||
} |
} |
||||
|
|
||||
|
/* GENERAL RULES */ |
||||
|
|
||||
|
/* main title element that says "in octomode" */ |
||||
|
h1 em.octomode{ |
||||
|
color: darkorchid; |
||||
|
} |
||||
|
|
||||
|
/* navigation */ |
||||
div#nav{ |
div#nav{ |
||||
|
position: fixed; |
||||
|
width: calc(100% - 1em); |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
margin: 0; |
||||
|
padding: 0 0.5em; |
||||
|
} |
||||
|
div#nav h1{ |
||||
position: absolute; |
position: absolute; |
||||
top:1em; |
width: auto; |
||||
right: 1em; |
line-height: 0; |
||||
|
margin: 0.75em 15px; |
||||
|
float: left; |
||||
} |
} |
||||
iframe{ |
div#nav div#buttons{ |
||||
width: 90vw; |
margin: 0.5em 15px; |
||||
height: 88vh; |
float: right; |
||||
} |
} |
||||
input{ |
div#nav input{ |
||||
min-width: 300px; |
min-width: 300px; |
||||
} |
} |
||||
|
/* iframe rules */ |
||||
|
iframe{ |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
border: none; |
||||
|
} |
||||
|
/* main content area */ |
||||
|
div#wrapper{ |
||||
|
position: fixed; |
||||
|
top: 50px; |
||||
|
left: 25px; |
||||
|
width: calc(100vw - 25px - 25px); |
||||
|
height: calc(100vh - 50px - 25px); |
||||
|
} |
||||
|
|
||||
|
/*div#logger-wrapper{ |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
z-index: -1; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
overflow-y: auto; |
||||
|
padding: 0 1em; |
||||
|
background-color: lightyellow; |
||||
|
display: flex; |
||||
|
flex-direction: column-reverse; |
||||
|
white-space: pre; |
||||
|
}*/ |
||||
|
|
||||
|
/* start page */ |
||||
|
body.start-page *{ |
||||
|
font-family: serif; |
||||
|
font-size: 115%; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
/* Z-INDEX */ |
||||
|
|
||||
|
div#wrapper, |
||||
|
div.pagedjs_pages{ |
||||
|
z-index: 1; |
||||
|
} |
||||
|
div#nav{ |
||||
|
z-index: 11; |
||||
|
} |
@ -0,0 +1,32 @@ |
|||||
|
<!doctype html> |
||||
|
<html lang="$language$"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
<script src="/static/paged.js" type="text/javascript"></script> |
||||
|
<script src="/static/paged.polyfill.js" type="text/javascript"></script> |
||||
|
<link href="/static/pagedjs.css" rel="stylesheet" type="text/css" media="screen"> |
||||
|
<link href="/{{ name }}/print.css" rel="stylesheet" type="text/css" media="print"> |
||||
|
<title>$title$</title> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
|
||||
|
<section id="cover"> |
||||
|
<h1>$title$</h1> |
||||
|
</section> |
||||
|
|
||||
|
$if(toc)$ |
||||
|
<section id="TOC" role="doc-toc"> |
||||
|
$if(toc-title)$ |
||||
|
<h2 id="$idprefix$toc-title">$toc-title$</h2> |
||||
|
$endif$ |
||||
|
$table-of-contents$ |
||||
|
</section> |
||||
|
$endif$ |
||||
|
|
||||
|
$body$ |
||||
|
|
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,10 @@ |
|||||
|
@page{ |
||||
|
size: A5; |
||||
|
} |
||||
|
@page:first{ |
||||
|
background-color: pink; |
||||
|
} |
||||
|
section#cover, |
||||
|
section#TOC{ |
||||
|
page-break-after: always; |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
--- |
||||
|
title: hello! |
||||
|
language: en |
||||
|
--- |
||||
|
|
||||
|
# Hello? |
@ -1,5 +1,5 @@ |
|||||
{% extends "base.html" %} |
{% extends "base.html" %} |
||||
|
|
||||
{% block content %} |
{% block content %} |
||||
<iframe src="{{ url_for('static', filename='dsn.html')}}"></iframe> |
{{ html | safe }} |
||||
{% endblock %} |
{% endblock %} |
||||
|
@ -1,6 +1,4 @@ |
|||||
{% extends "base.html" %} |
{% extends "base.html" %} |
||||
|
|
||||
{% block content %} |
{% block content %} |
||||
<iframe src="https://pad.vvvvvvaria.org/dsn.css"></iframe> |
|
||||
{% endblock %} |
{% endblock %} |
||||
|
|
@ -1,5 +1,5 @@ |
|||||
{% extends "base.html" %} |
{% extends "base.html" %} |
||||
|
|
||||
{% block content %} |
{% block content %} |
||||
<iframe src="https://pad.vvvvvvaria.org/dsn.md"></iframe> |
<iframe src="https://pad.vvvvvvaria.org/{{ name }}{{ ext }}"></iframe> |
||||
{% endblock %} |
{% endblock %} |
||||
|
@ -1,5 +0,0 @@ |
|||||
{% extends "base.html" %} |
|
||||
|
|
||||
{% block content %} |
|
||||
<iframe src="{{ url_for('static', filename='dsn.pagedjs.html')}}"></iframe> |
|
||||
{% endblock %} |
|
@ -0,0 +1,30 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
|
||||
|
{% block content %} |
||||
|
<iframe id="pdf" name="pdf" src="/{{ name }}/pagedjs.html"></iframe> |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block footer %} |
||||
|
<script> |
||||
|
function printPage(){ |
||||
|
window.frames["pdf"].focus(); |
||||
|
window.frames["pdf"].print(); |
||||
|
} |
||||
|
|
||||
|
window.addEventListener('load', function () { |
||||
|
|
||||
|
// Load the main.css again, to load the stylesheet for the nav |
||||
|
var cssLink = document.createElement('link'); |
||||
|
cssLink.rel = 'stylesheet'; |
||||
|
cssLink.href = '/static/main.css'; |
||||
|
var head = document.getElementsByTagName('head')[0]; |
||||
|
head.insertBefore(cssLink, head.firstChild); |
||||
|
|
||||
|
// Insert the SAVE button |
||||
|
const nav = document.getElementById('buttons'); |
||||
|
const save = '<a href="#"><button id="save" onClick="printPage()">save</button></a>'; |
||||
|
nav.innerHTML = nav.innerHTML + save; |
||||
|
|
||||
|
}) |
||||
|
</script> |
||||
|
{% endblock %} |
@ -0,0 +1,13 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang='en'> |
||||
|
<head> |
||||
|
<meta charset="utf-8" /> |
||||
|
<title>octomode</title> |
||||
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}"> |
||||
|
</head> |
||||
|
<body class="start-page"> |
||||
|
<form action="/" method="POST"> |
||||
|
<h1><input type="submit" value="open"> <input type="text" name="name"> <em class="octomode">in octomode</em></h1> |
||||
|
</form> |
||||
|
</body> |
||||
|
</html> |
Loading…
Reference in new issue