|
|
@ -1,8 +1,11 @@ |
|
|
|
import os |
|
|
|
import json |
|
|
|
from flask import Flask, request, render_template, redirect, url_for |
|
|
|
from flask import Flask, request, render_template, render_template_string, redirect, url_for |
|
|
|
from urllib.request import urlopen |
|
|
|
from urllib.parse import urlencode |
|
|
|
from urllib.parse import urlencode, urlparse |
|
|
|
import subprocess |
|
|
|
from jinja2 import Template |
|
|
|
import re |
|
|
|
|
|
|
|
# To sanitize Flask input fields |
|
|
|
from markupsafe import Markup, escape |
|
|
@ -23,9 +26,9 @@ def get_pad_content(pad_name, ext=""): |
|
|
|
if ext: |
|
|
|
pad_name = f'{ pad_name }{ ext }' |
|
|
|
|
|
|
|
print(pad_name) |
|
|
|
# print(pad_name) |
|
|
|
|
|
|
|
arguments = { |
|
|
|
arguments = { |
|
|
|
'padID' : pad_name, |
|
|
|
'apikey' : APP.config['PAD_API_KEY'] |
|
|
|
} |
|
|
@ -43,7 +46,7 @@ def get_pad_content(pad_name, ext=""): |
|
|
|
return content |
|
|
|
|
|
|
|
def all_pads(): |
|
|
|
arguments = { |
|
|
|
arguments = { |
|
|
|
'apikey' : APP.config['PAD_API_KEY'], |
|
|
|
} |
|
|
|
api_call = 'listAllPads' |
|
|
@ -62,10 +65,14 @@ def create_pad_on_first_run(name, ext): |
|
|
|
default_template = 'templates/default.md' |
|
|
|
elif 'css' in ext: |
|
|
|
default_template = 'templates/default.css' |
|
|
|
elif 'pandoc-template' in ext: |
|
|
|
default_template = 'templates/default.pandoc-template.html' |
|
|
|
elif 'wildcard-template' in ext: |
|
|
|
default_template = 'templates/default.wildcard-template.html' |
|
|
|
default_template = open(default_template).read() |
|
|
|
|
|
|
|
# Create pad and add the default template |
|
|
|
arguments = { |
|
|
|
arguments = { |
|
|
|
'padID' : pad, |
|
|
|
'apikey' : APP.config['PAD_API_KEY'], |
|
|
|
'text' : default_template |
|
|
@ -73,16 +80,31 @@ def create_pad_on_first_run(name, ext): |
|
|
|
api_call = 'createPad' |
|
|
|
json.load(urlopen(f"{ APP.config['PAD_API_URL'] }/{ api_call }", data=urlencode(arguments).encode())) |
|
|
|
|
|
|
|
def md_to_html(md_pad_content): |
|
|
|
# Convert Markdown to HTML |
|
|
|
# html = markdown.markdown(md_pad_content, extensions=['meta', 'attr_list']) # attr_list does not work |
|
|
|
def md_to_html(md_pad_content, name): |
|
|
|
# Convert Markdown to HTML, using the pandoc template from the NAME.template.html pad |
|
|
|
# ---------------------------------------------------------------------------------- |
|
|
|
#app_hostname = get_app_hostname() |
|
|
|
#app_root = get_app_root() |
|
|
|
#template_url = f"{ app_hostname }{ app_root }/{ name }/template.html" |
|
|
|
#template_url = "http://127.0.0.1:5555/octomode/techno/template.html" |
|
|
|
#md_url = f"{ app_hostname }{ app_root }/{ name }/pad.md" |
|
|
|
#md_url = "http://127.0.0.1:5555/octomode/techno/pad.md" |
|
|
|
#APP.logger.info("template_url", template_url) |
|
|
|
#APP.logger.info("md_url", md_url) |
|
|
|
#result = subprocess.run(["pandoc", "--from", "markdown", "--to", "html", "--template", f"{ template_url }", md_url], capture_output=True, text=True) |
|
|
|
#html = result.stdout |
|
|
|
#APP.logger.info("html", html) |
|
|
|
#APP.logger.info("result.stderr", result.stderr) |
|
|
|
|
|
|
|
# Convert Markdown to HTML, using the default pandoc template |
|
|
|
# ---------------------------------------------------------------------------------- |
|
|
|
html = pypandoc.convert_text(md_pad_content, 'html', format='md') |
|
|
|
|
|
|
|
# Sanitize the Markdown |
|
|
|
# html = bleach.clean(html) |
|
|
|
|
|
|
|
# Another built-in Flask way to sanitize |
|
|
|
# html = escape(html) |
|
|
|
# html = escape(html) |
|
|
|
html = Markup(html) |
|
|
|
|
|
|
|
return html |
|
|
@ -95,6 +117,30 @@ def get_md_metadata(md_pad_content): |
|
|
|
|
|
|
|
return metadata |
|
|
|
|
|
|
|
def get_app_root(): |
|
|
|
# we need application root to make all the URLs work..... |
|
|
|
if APP.config['APPLICATION_ROOT'] == '/': |
|
|
|
app_root = '' |
|
|
|
elif APP.config['APPLICATION_ROOT'].endswith('/'): |
|
|
|
app_root = APP.config['APPLICATION_ROOT'][:-1] |
|
|
|
else: |
|
|
|
app_root = APP.config['APPLICATION_ROOT'] |
|
|
|
|
|
|
|
return app_root |
|
|
|
|
|
|
|
def get_app_hostname(): |
|
|
|
# function to get the hostname that the application runs on |
|
|
|
# for example: localhost:5555, or https://cc.vvvvvvaria.org |
|
|
|
# TODO: not working atm, this always returns localhost:5555 ...... |
|
|
|
# -------------------------------------------- |
|
|
|
# app_protocol = urlparse(request.base_url).scheme + "://" |
|
|
|
# app_url = urlparse(request.base_url).netloc |
|
|
|
# app_hostname = app_protocol + app_url |
|
|
|
|
|
|
|
app_hostname = APP.config['APPLICATION_HOSTNAME'] |
|
|
|
|
|
|
|
return app_hostname |
|
|
|
|
|
|
|
# --- |
|
|
|
|
|
|
|
@APP.route('/', methods=['GET', 'POST']) |
|
|
@ -102,10 +148,10 @@ def index(): |
|
|
|
name = False |
|
|
|
if request.values.get('name'): |
|
|
|
name = escape(request.values.get('name')) # Returns a Markup() object, which is "None" when False |
|
|
|
if name: |
|
|
|
if name: |
|
|
|
# This is when the environment is "created" |
|
|
|
# The pads are filled with the default templates (pad, stylesheet, template) |
|
|
|
exts = ['.md', '.css'] |
|
|
|
exts = ['.md', '.css', '.pandoc-template.html', '.wildcard-template.html'] |
|
|
|
for ext in exts: |
|
|
|
create_pad_on_first_run(name, ext) |
|
|
|
return redirect(url_for("pad", name=name)) |
|
|
@ -126,47 +172,84 @@ def stylesheet(name): |
|
|
|
url = f"{ APP.config['PAD_URL'] }/{ name }.css" |
|
|
|
return render_template('iframe.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) |
|
|
|
|
|
|
|
@APP.route('/<name>/pandoc-template/') |
|
|
|
def pandoctemplate(name): |
|
|
|
url = f"{ APP.config['PAD_URL'] }/{ name }.pandoc-template.html" |
|
|
|
return render_template('iframe.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) |
|
|
|
|
|
|
|
@APP.route('/<name>/html/') |
|
|
|
def html(name): |
|
|
|
# only here we need application root to make all the URLs work..... |
|
|
|
if APP.config['APPLICATION_ROOT'] == '/': |
|
|
|
app_root = '' |
|
|
|
elif APP.config['APPLICATION_ROOT'].endswith('/'): |
|
|
|
app_root = APP.config['APPLICATION_ROOT'][:-1] |
|
|
|
else: |
|
|
|
app_root = APP.config['APPLICATION_ROOT'] |
|
|
|
app_root = get_app_root() |
|
|
|
url = f"{ app_root }/{ name }/preview.html" |
|
|
|
return render_template('iframe.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) |
|
|
|
return render_template('iframe.html', url=url, name=name.strip()) |
|
|
|
|
|
|
|
@APP.route('/<name>/pdf/') |
|
|
|
def pdf(name): |
|
|
|
# only here we need application root to make all the URLs work..... |
|
|
|
if APP.config['APPLICATION_ROOT'] == '/': |
|
|
|
app_root = '' |
|
|
|
elif APP.config['APPLICATION_ROOT'].endswith('/'): |
|
|
|
app_root = APP.config['APPLICATION_ROOT'][:-1] |
|
|
|
else: |
|
|
|
app_root = APP.config['APPLICATION_ROOT'] |
|
|
|
app_root = get_app_root() |
|
|
|
url = f"{ app_root }/{name}/pagedjs.html" |
|
|
|
return render_template('pdf.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) |
|
|
|
|
|
|
|
@APP.route('/<name>/pdfmyk/') |
|
|
|
def pdfmyk(name): |
|
|
|
app_root = get_app_root() |
|
|
|
url = f"{ app_root }/{name}/pagedjs-myk.html" |
|
|
|
return render_template('pdf.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) |
|
|
|
|
|
|
|
@APP.route('/<name>/pdfck/') |
|
|
|
def pdfck(name): |
|
|
|
app_root = get_app_root() |
|
|
|
url = f"{ app_root }/{name}/pagedjs-ck.html" |
|
|
|
return render_template('pdf.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) |
|
|
|
|
|
|
|
@APP.route('/<name>/wildcard-template/') |
|
|
|
def wildcardtemplate(name): |
|
|
|
url = f"{ APP.config['PAD_URL'] }/{ name }.wildcard-template.html" |
|
|
|
return render_template('iframe.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) |
|
|
|
|
|
|
|
@APP.route('/<name>/wildcard/') |
|
|
|
def wildcard(name): |
|
|
|
app_root = get_app_root() |
|
|
|
url = url_for("wildcardpage", name=name) |
|
|
|
return render_template('iframe.html', url=url, name=name.strip()) |
|
|
|
|
|
|
|
@APP.route('/<name>/podcast/') |
|
|
|
def podcast(name): |
|
|
|
app_root = get_app_root() |
|
|
|
url = f"{ app_root }/{ name }/podcast.rss" |
|
|
|
return render_template('iframe.html', url=url, name=name.strip()) |
|
|
|
|
|
|
|
# ////////////////// |
|
|
|
# RENDERED RESOURCES |
|
|
|
# RENDERED RESOURCES |
|
|
|
# ////////////////// |
|
|
|
# (These are not saved as a file on the server) |
|
|
|
|
|
|
|
@APP.route('/<name>/stylesheet.css') |
|
|
|
def css(name): |
|
|
|
css = get_pad_content(name, '.css') |
|
|
|
css = get_pad_content(name, ext='.css') |
|
|
|
# Insert CSS sanitizer here. |
|
|
|
|
|
|
|
return css, 200, {'Content-Type': 'text/css; charset=utf-8'} |
|
|
|
|
|
|
|
# only used for the pandoc command using the subprocess |
|
|
|
# --- |
|
|
|
#@APP.route('/<name>/pad.md') |
|
|
|
#def md(name): |
|
|
|
# # TO GENERATE THE CONTENT IN MARKDOWN |
|
|
|
# template_pad_content = get_pad_content(name, ext='.md') |
|
|
|
# |
|
|
|
# return template_pad_content, 200, {'Content-Type': 'text/plain; charset=utf-8'} |
|
|
|
|
|
|
|
@APP.route('/<name>/pandoc-template.html') |
|
|
|
def pandoctemplatehtml(name): |
|
|
|
# TO GENERATE THE TEMPLATE AS HTML FILE |
|
|
|
template_pad_content = get_pad_content(name, ext='.pandoc-template.html') |
|
|
|
|
|
|
|
return template_pad_content, 200, {'Content-Type': 'text/html; charset=utf-8'} |
|
|
|
|
|
|
|
@APP.route('/<name>/preview.html') |
|
|
|
def preview(name): |
|
|
|
# TO GENERATE THE PREVIEW WEBPAGE |
|
|
|
md_pad_content = get_pad_content(name, ext='.md') |
|
|
|
html = md_to_html(md_pad_content) |
|
|
|
html = md_to_html(md_pad_content, name) |
|
|
|
metadata = get_md_metadata(md_pad_content) |
|
|
|
if metadata: |
|
|
|
lang = metadata['language'][0] |
|
|
@ -179,15 +262,102 @@ def preview(name): |
|
|
|
|
|
|
|
@APP.route('/<name>/pagedjs.html') |
|
|
|
def pagedjs(name): |
|
|
|
# TO GENERATE THE PAGED.JS WEBPAGE |
|
|
|
# TO GENERATE THE PAGED.JS PAGE |
|
|
|
md_pad_content = get_pad_content(name, ext='.md') |
|
|
|
html = md_to_html(md_pad_content) |
|
|
|
|
|
|
|
### HACKSS START HERE |
|
|
|
md_pad_content=re.sub(r"(!.+/publication/images/)(.+)(\){.colorz})", r"\1.myk-ck/\2.jpg\3", md_pad_content) |
|
|
|
md_pad_content=re.sub(r"(!.+/publication/images/)(.+)(\){.mono})", r"\1.ck/\2-col.jpg\3", md_pad_content) |
|
|
|
md_pad_content=re.sub(r"(!.+/publication/images/)(.+)(\){.othermono})", r"\1.myk/\2-col.jpg\3", md_pad_content) |
|
|
|
### HACKSS END HERE |
|
|
|
|
|
|
|
html = md_to_html(md_pad_content, name) |
|
|
|
metadata = get_md_metadata(md_pad_content) |
|
|
|
lang = metadata['language'][0] |
|
|
|
title = metadata['title'][0] |
|
|
|
|
|
|
|
return render_template('pagedjs.html', name=name.strip(), pad_content=html, lang=lang, title=title) |
|
|
|
|
|
|
|
@APP.route('/<name>/pagedjs-myk.html') |
|
|
|
def pagedjsmyk(name): |
|
|
|
# TO GENERATE THE PAGED.JS PAGE |
|
|
|
md_pad_content = get_pad_content(name, ext='.md') |
|
|
|
|
|
|
|
### HACKSS START HERE |
|
|
|
md_pad_content=re.sub(r"(!.+/publication/images/)(.+)(\){.colorz})", r"\1.myk/\2.jpg\3", md_pad_content) |
|
|
|
md_pad_content=re.sub(r"(!.+/publication/images/)(.+)(\){.othermono})", r"\1.myk/\2.jpg\3", md_pad_content) |
|
|
|
### HACKSS END HERE |
|
|
|
|
|
|
|
html = md_to_html(md_pad_content, name) |
|
|
|
metadata = get_md_metadata(md_pad_content) |
|
|
|
lang = metadata['language'][0] |
|
|
|
title = metadata['title'][0] |
|
|
|
return render_template('pagedjs-myk.html', name=name.strip(), pad_content=html, lang=lang, title=title) |
|
|
|
|
|
|
|
@APP.route('/<name>/pagedjs-ck.html') |
|
|
|
def pagedjsck(name): |
|
|
|
# TO GENERATE THE PAGED.JS PAGE |
|
|
|
md_pad_content = get_pad_content(name, ext='.md') |
|
|
|
|
|
|
|
### HACKSS START HERE |
|
|
|
md_pad_content=re.sub(r"(!.+/publication/images/)(.+)(\){.colorz})", r"\1.ck/\2.jpg\3", md_pad_content) |
|
|
|
md_pad_content=re.sub(r"(!.+/publication/images/)(.+)(\){.mono})", r"\1.ck/\2.jpg\3", md_pad_content) |
|
|
|
### HACKSS END HERE |
|
|
|
|
|
|
|
html = md_to_html(md_pad_content, name) |
|
|
|
metadata = get_md_metadata(md_pad_content) |
|
|
|
lang = metadata['language'][0] |
|
|
|
title = metadata['title'][0] |
|
|
|
return render_template('pagedjs-ck.html', name=name.strip(), pad_content=html, lang=lang, title=title) |
|
|
|
|
|
|
|
|
|
|
|
@APP.route('/<name>/wildcard.html') |
|
|
|
def wildcardpage(name): |
|
|
|
md_pad_content = get_pad_content(name, ext='.md') |
|
|
|
wildcard_template_pad_content = get_pad_content(name, ext='.wildcard-template.html') |
|
|
|
audio = [] |
|
|
|
pdf = [] |
|
|
|
images = [] |
|
|
|
allall = [] |
|
|
|
for line in md_pad_content.splitlines(): |
|
|
|
slines=re.split("\s|\"|\(|\)|>|<",line) |
|
|
|
for sline in slines: |
|
|
|
if "http" in sline and sline not in allall: |
|
|
|
if ".mp3" in sline: |
|
|
|
audio.append(sline) |
|
|
|
allall.append(sline) |
|
|
|
elif ".ogg" in sline: |
|
|
|
audio.append(sline) |
|
|
|
allall.append(sline) |
|
|
|
elif ".pdf" in sline: |
|
|
|
pdf.append(sline) |
|
|
|
allall.append(sline) |
|
|
|
elif ".jpg" in sline: |
|
|
|
images.append(sline) |
|
|
|
allall.append(sline) |
|
|
|
|
|
|
|
return render_template_string(wildcard_template_pad_content, name=name.strip(), allall=allall, pdf=pdf, images=images, audio=audio) |
|
|
|
|
|
|
|
@APP.route('/<name>/podcast.rss') |
|
|
|
def rss(name): |
|
|
|
# parse for audio links |
|
|
|
md_pad_content = get_pad_content(name, ext='.md') |
|
|
|
audio = [] |
|
|
|
for line in md_pad_content.splitlines(): |
|
|
|
if ".mp3" in line: |
|
|
|
audio.append(line) |
|
|
|
# parse metadata |
|
|
|
metadata = get_md_metadata(md_pad_content) |
|
|
|
title = metadata['title'][0] |
|
|
|
app_url = get_app_hostname() + get_app_root() |
|
|
|
octomode_link = app_url + url_for("main", name=name) |
|
|
|
rss_link = app_url + url_for("rss", name=name) |
|
|
|
# render podcast.rss template |
|
|
|
with open("templates/podcast.rss", "r") as t: |
|
|
|
template = Template(t.read()) |
|
|
|
rss = template.render(name=name.strip(), title=title, audio=audio, octomode_link=octomode_link, rss_link=rss_link) |
|
|
|
|
|
|
|
return rss, 200, {'Content-Type': 'text/xml; charset=utf-8'} |
|
|
|
|
|
|
|
# ////////////////// |
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|