Refactor lib, add cli

This commit is contained in:
subnixr 2018-04-07 04:17:49 +02:00
parent 9b9e0f2662
commit e444d2b2f6
8 changed files with 235 additions and 83 deletions

View File

@ -0,0 +1,47 @@
import os
import markdown
import jinja2
def read_markdown(page_name, markdown_path):
md_file = os.path.join(markdown_path, page_name + '.md')
with open(md_file) as f:
md_text = f.read()
return md_text
def render_from_text(md_text, template_path):
md = markdown.Markdown(extensions=['meta'], output_format='html5')
html = md.convert(md_text)
# get markdown metadata
data = {key: md.Meta[key][0] for key in md.Meta.keys()}
data.update({
'content': html,
# 'page_name': page_name, # Needed?
})
template_name = data.get('template', 'default')
template_file = os.path.join(template_path, template_name + '.html')
with open(template_file) as f:
template = f.read()
page = jinja2.Template(template).render(**data)
return page
def render(page_name, markdown_path, template_path):
md_text = read_markdown(page_name, markdown_path)
page = render_from_text(md_text, template_path)
return page
def save(md_text, page_name, markdown_path):
md_file = os.path.join(markdown_path, page_name + '.md')
with open(md_file, 'w') as f:
f.write(md_text)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3 #!/home/subnixr/.virtualenvs/ciclostile/bin/python3
import os import os
import ciclostile import ciclostile

View File

@ -0,0 +1,64 @@
#!/home/subnixr/.virtualenvs/ciclostile/bin/python3
import os
from flask import Flask, send_from_directory, render_template, request
from flask_httpauth import HTTPDigestAuth
import ciclostile
working_dir = os.getcwd()
target_path, template_path, markdown_path = [
os.path.join(working_dir, folder_name)
for folder_name in ['target', 'templates', 'markdown']
]
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret key here'
auth = HTTPDigestAuth()
users = {
'admin': 'password',
}
@auth.get_password
def get_pw(username):
if username in users:
return users.get(username)
return None
@app.route('/assets/<path:path>')
def assets(path):
assets_path = os.path.join(target_path, 'assets')
return send_from_directory(assets_path, path)
@app.route('/<string:page_name>')
@app.route('/<string:page_name>.html')
def page(page_name):
return ciclostile.render(page_name, markdown_path, template_path)
@app.route('/<string:page_name>/edit')
@auth.login_required
def edit(page_name):
md_text = ciclostile.read_markdown(page_name, markdown_path)
return render_template('edit.html', **locals())
@app.route('/edit', methods=['POST'])
@auth.login_required
def edit_actions():
page_name = request.form['page_name']
md_text = request.form['md_text']
if request.form['action'] == 'preview':
return ciclostile.render_from_text(md_text, template_path)
if request.form['action'] == 'save':
ciclostile.save(md_text, page_name, markdown_path)
return page(page_name)
if __name__ == '__main__':
app.run()

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>INDEX</title>
</head>
<body>
<ul>
{% for page in pages %}
<li>{{page['title']}}</li>
{% endfor %}
</ul>
</body>
</html>

4
setup.py Normal file → Executable file
View File

@ -1,4 +1,4 @@
from distutils.core import setup from setuptools import setup
from os import path from os import path
here = path.abspath(path.dirname(__file__)) here = path.abspath(path.dirname(__file__))
@ -16,7 +16,7 @@ setup(
package_dir={'': 'src'}, package_dir={'': 'src'},
packages=['ciclostile'], packages=['ciclostile'],
scripts=['src/ciclostile_render', 'src/ciclostile_web'], scripts=['src/ciclostile_cli'],
install_requires=['markdown', 'jinja2', 'flask', 'flask-httpauth'] install_requires=['markdown', 'jinja2', 'flask', 'flask-httpauth']
) )

View File

@ -1,47 +1,38 @@
#!/usr/bin/env python3
import os import os
import markdown import markdown
import jinja2 import jinja2
def read_markdown(page_name, markdown_path): def parse(mdtext, parser=None):
md_file = os.path.join(markdown_path, page_name + '.md') if parser is None:
parser = markdown.Markdown(extensions=['meta'], output_format='html5')
with open(md_file) as f: html = parser.convert(mdtext)
md_text = f.read()
return md_text
def render_from_text(md_text, template_path):
md = markdown.Markdown(extensions=['meta'], output_format='html5')
html = md.convert(md_text)
# get markdown metadata # get markdown metadata
data = {key: md.Meta[key][0] for key in md.Meta.keys()} data = {key: parser.Meta[key][0] for key in parser.Meta.keys()}
data.update({ data.update({
'content': html, 'content': html,
# 'page_name': page_name, # Needed?
}) })
return data
template_name = data.get('template', 'default')
template_file = os.path.join(template_path, template_name + '.html')
with open(template_file) as f:
template = f.read()
page = jinja2.Template(template).render(**data)
return page
def render(page_name, markdown_path, template_path): def parse_file(filepath, parser=None):
md_text = read_markdown(page_name, markdown_path) with open(filepath) as fh:
page = render_from_text(md_text, template_path) return parse(fh.read(), parser=parser)
return page
def save(md_text, page_name, markdown_path): def index(folder):
md_file = os.path.join(markdown_path, page_name + '.md') data = {'pages': []}
parser = markdown.Markdown(extensions=['meta'], output_format='html5')
for dirpath, _, files in os.walk(folder):
valid_files = (os.path.join(dirpath, f)
for f in files
if f.endswith('.md'))
for fpath in valid_files:
data['pages'].append(parse_file(fpath, parser=parser))
return data
with open(md_file, 'w') as f:
f.write(md_text) def compile(template, data):
t = jinja2.Template(template)
return t.render(**data)

34
src/ciclostile_cli Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env python3
import sys
import click
import ciclostile
@click.group()
def cli():
pass
@cli.command()
@click.option('-t', '--template', type=click.File('r'))
@click.option('-o', '--output', type=click.File('w'), default=sys.stdout)
@click.argument('markdown', type=click.File('r'), default=sys.stdin)
def compile(template, output, markdown):
data = ciclostile.parse(markdown.read())
html = ciclostile.compile(template.read(), data)
output.write(html)
@cli.command()
@click.option('-t', '--template', type=click.File('r'))
@click.option('-o', '--output', type=click.File('w'), default=sys.stdout)
@click.argument('folder', type=click.Path(exists=True,
file_okay=False))
def index(template, output, folder):
data = ciclostile.index(folder)
html = ciclostile.compile(template.read(), data)
output.write(html)
if __name__ == "__main__":
cli()

View File

@ -1,64 +1,64 @@
#!/usr/bin/env python3 # #!/usr/bin/env python3
import os # import os
from flask import Flask, send_from_directory, render_template, request # from flask import Flask, send_from_directory, render_template, request
from flask_httpauth import HTTPDigestAuth # from flask_httpauth import HTTPDigestAuth
import ciclostile # import ciclostile
working_dir = os.getcwd() # working_dir = os.getcwd()
target_path, template_path, markdown_path = [ # target_path, template_path, markdown_path = [
os.path.join(working_dir, folder_name) # os.path.join(working_dir, folder_name)
for folder_name in ['target', 'templates', 'markdown'] # for folder_name in ['target', 'templates', 'markdown']
] # ]
app = Flask(__name__) # app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret key here' # app.config['SECRET_KEY'] = 'secret key here'
auth = HTTPDigestAuth() # auth = HTTPDigestAuth()
users = { # users = {
'admin': 'password', # 'admin': 'password',
} # }
@auth.get_password # @auth.get_password
def get_pw(username): # def get_pw(username):
if username in users: # if username in users:
return users.get(username) # return users.get(username)
return None # return None
@app.route('/assets/<path:path>') # @app.route('/assets/<path:path>')
def assets(path): # def assets(path):
assets_path = os.path.join(target_path, 'assets') # assets_path = os.path.join(target_path, 'assets')
return send_from_directory(assets_path, path) # return send_from_directory(assets_path, path)
@app.route('/<string:page_name>') # @app.route('/<string:page_name>')
@app.route('/<string:page_name>.html') # @app.route('/<string:page_name>.html')
def page(page_name): # def page(page_name):
return ciclostile.render(page_name, markdown_path, template_path) # return ciclostile.render(page_name, markdown_path, template_path)
@app.route('/<string:page_name>/edit') # @app.route('/<string:page_name>/edit')
@auth.login_required # @auth.login_required
def edit(page_name): # def edit(page_name):
md_text = ciclostile.read_markdown(page_name, markdown_path) # md_text = ciclostile.read_markdown(page_name, markdown_path)
return render_template('edit.html', **locals()) # return render_template('edit.html', **locals())
@app.route('/edit', methods=['POST']) # @app.route('/edit', methods=['POST'])
@auth.login_required # @auth.login_required
def edit_actions(): # def edit_actions():
page_name = request.form['page_name'] # page_name = request.form['page_name']
md_text = request.form['md_text'] # md_text = request.form['md_text']
if request.form['action'] == 'preview': # if request.form['action'] == 'preview':
return ciclostile.render_from_text(md_text, template_path) # return ciclostile.render_from_text(md_text, template_path)
if request.form['action'] == 'save': # if request.form['action'] == 'save':
ciclostile.save(md_text, page_name, markdown_path) # ciclostile.save(md_text, page_name, markdown_path)
return page(page_name) # return page(page_name)
if __name__ == '__main__': # if __name__ == '__main__':
app.run() # app.run()