244 lines
6.1 KiB
Python
244 lines
6.1 KiB
Python
# WikiNote3
|
|
# Copyright © 2020 Lee Yingtong Li (RunasSudo)
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
from .markup import WNMarkdown
|
|
|
|
import flask
|
|
|
|
import os
|
|
import pickle
|
|
|
|
app = flask.Flask(__name__, template_folder='jinja2')
|
|
|
|
if os.path.exists('index.pickle'):
|
|
try:
|
|
with open('index.pickle', 'rb') as f:
|
|
index = pickle.load(f)
|
|
except:
|
|
print('Error loading index.pickle')
|
|
import traceback; traceback.print_exc()
|
|
|
|
@app.route('/')
|
|
def index_page():
|
|
children = []
|
|
for child in os.listdir('./data/pages'):
|
|
if child.endswith('.md'):
|
|
children.append(child[:-3])
|
|
else:
|
|
children.append(child)
|
|
children.sort()
|
|
|
|
if not os.path.exists('./data/pages/Home.md'):
|
|
return flask.render_template('page_404.html', page={
|
|
'path': '',
|
|
'title': 'Home',
|
|
'children': children
|
|
})
|
|
|
|
with(open(fname, 'r')) as f:
|
|
page_source = f.read()
|
|
|
|
md = WNMarkdown()
|
|
page_content = md.convert(page_source)
|
|
|
|
return flask.render_template('page_rendered.html', page={
|
|
'path': '',
|
|
'title': 'Home',
|
|
'content': page_content,
|
|
'toc': md.toc_tokens,
|
|
'meta': md.meta,
|
|
'children': children
|
|
})
|
|
|
|
@app.route('/page/<path:path>')
|
|
def page_view(path):
|
|
fname = flask.safe_join('./data/pages', path) + '.md'
|
|
|
|
children = []
|
|
if os.path.isdir(flask.safe_join('./data/pages', path)):
|
|
for child in os.listdir(flask.safe_join('./data/pages', path)):
|
|
if child.startswith('_'):
|
|
continue
|
|
if child.endswith('.md'):
|
|
children.append(child[:-3])
|
|
else:
|
|
children.append(child)
|
|
children.sort()
|
|
|
|
if not os.path.exists(fname):
|
|
return flask.render_template('page_404.html', page={
|
|
'path': path,
|
|
'title': path.split('/')[-1],
|
|
'children': children
|
|
})
|
|
|
|
with(open(fname, 'r')) as f:
|
|
page_source = f.read()
|
|
|
|
md = WNMarkdown()
|
|
page_content = md.convert(page_source)
|
|
|
|
return flask.render_template('page_rendered.html', page={
|
|
'path': path,
|
|
'title': path.split('/')[-1],
|
|
'content': page_content,
|
|
'toc': md.toc_tokens,
|
|
'meta': md.meta,
|
|
'children': children
|
|
})
|
|
|
|
@app.route('/toc/<path:path>')
|
|
def page_toc(path):
|
|
fname = flask.safe_join('./data/pages', path) + '.md'
|
|
|
|
if not os.path.exists(fname):
|
|
return flask.render_template('page_404.html', page={
|
|
'path': path,
|
|
'title': path.split('/')[-1],
|
|
'children': []
|
|
})
|
|
|
|
with(open(fname, 'r')) as f:
|
|
page_source = f.read()
|
|
|
|
md = WNMarkdown()
|
|
_ = md.convert(page_source)
|
|
|
|
return flask.render_template('page_toc.html', page={
|
|
'path': path,
|
|
'title': path.split('/')[-1],
|
|
'toc': md.toc_tokens
|
|
})
|
|
|
|
@app.route('/preview/<path:path>')
|
|
def page_preview(path):
|
|
fname = flask.safe_join('./data/pages', path) + '.md'
|
|
|
|
if not os.path.exists(fname):
|
|
return ''
|
|
|
|
with(open(fname, 'r')) as f:
|
|
page_source = f.read()
|
|
|
|
md = WNMarkdown()
|
|
page_root = md.parse(page_source)
|
|
|
|
# Delete all but first section
|
|
for section in list(page_root[1:]):
|
|
page_root.remove(section)
|
|
|
|
# Delete all but introductory text
|
|
for elem in list(page_root[0][1:]):
|
|
page_root[0].remove(elem)
|
|
|
|
# Delete footnotes
|
|
def walk_tree(elem):
|
|
last_child = None
|
|
for child in list(elem):
|
|
if child.get('class') == 'footnote-ref':
|
|
if child.tail:
|
|
# Combine tail text
|
|
if last_child is not None:
|
|
last_child.tail += child.tail
|
|
else:
|
|
elem.text += child.tail
|
|
elem.remove(child)
|
|
walk_tree(child)
|
|
last_child = child
|
|
walk_tree(page_root[0])
|
|
|
|
page_content = md.serialise(page_root)
|
|
return page_content
|
|
|
|
@app.route('/image/<name>')
|
|
def image_view(name):
|
|
fname = flask.safe_join(os.getcwd(), './data/images', name[0].upper(), name)
|
|
return flask.send_file(fname)
|
|
|
|
@app.route('/image/<name>/about')
|
|
def image_about(name):
|
|
fname = flask.safe_join(os.getcwd(), './data/images', name[0].upper(), os.path.splitext(name)[0] + '.md')
|
|
|
|
with(open(fname, 'r')) as f:
|
|
page_source = f.read()
|
|
|
|
md = WNMarkdown()
|
|
page_content = md.convert(page_source)
|
|
|
|
return flask.render_template('image_about.html', page={
|
|
'path': name,
|
|
'title': name,
|
|
'content': page_content,
|
|
'meta': md.meta
|
|
})
|
|
|
|
@app.route('/tag/')
|
|
def tags_list():
|
|
return flask.render_template('tags_list.html', tags=sorted(index['tags'].keys()))
|
|
|
|
@app.route('/tag/<name>')
|
|
def tag_view(name):
|
|
pages = index['tags'][name]
|
|
pages.sort(key=lambda p: p['kind'])
|
|
pages.sort(key=lambda p: p['path'])
|
|
return flask.render_template('tag_view.html', name=name, pages=pages)
|
|
|
|
@app.cli.command('index')
|
|
def cli_index():
|
|
app.config['SERVER_NAME'] = 'localhost'
|
|
|
|
with app.app_context():
|
|
tags = {}
|
|
|
|
base_path = './data/pages'
|
|
for dirpath, dirnames, filenames in os.walk(base_path):
|
|
for fname in filenames:
|
|
if fname.endswith('.md'):
|
|
page_path = dirpath[len(base_path)+1:] + '/' + fname[:-3]
|
|
|
|
with(open(flask.safe_join(dirpath, fname), 'r')) as f:
|
|
page_source = f.read()
|
|
md = WNMarkdown()
|
|
md.convert(page_source)
|
|
|
|
for tag in md.meta.get('tags', []):
|
|
if tag not in tags:
|
|
tags[tag] = []
|
|
tags[tag].append({'kind': 'page', 'path': page_path})
|
|
|
|
base_path = './data/images'
|
|
for dirpath, dirnames, filenames in os.walk(base_path):
|
|
for fname in filenames:
|
|
if fname.endswith('.md'):
|
|
continue
|
|
|
|
md_path = flask.safe_join(dirpath, os.path.splitext(fname)[0] + '.md')
|
|
if os.path.exists(md_path):
|
|
with(open(md_path, 'r')) as f:
|
|
page_source = f.read()
|
|
md = WNMarkdown()
|
|
md.convert(page_source)
|
|
|
|
for tag in md.meta.get('tags', []):
|
|
if tag not in tags:
|
|
tags[tag] = []
|
|
tags[tag].append({'kind': 'image', 'path': fname})
|
|
|
|
with open('index.pickle', 'wb') as f:
|
|
pickle.dump({
|
|
'tags': tags
|
|
}, f)
|