Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ content/
.eggs
*.egg-info
dist/
.idea
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
build: off
build: false

environment:
matrix:
Expand Down
5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@
author='Alexander Jung-Loddenkemper',
author_email='[email protected]',
url='https://github.com/alexanderjulo/wiki',
packages=find_packages(),
packages=find_packages(exclude=['tests']),
include_package_data=True,
python_requires='>3.7',
install_requires=[
'Flask>=0.9',
'Click>=6,<7',
'Click>=6',
'Flask-Login>=0.4',
'Flask-WTF>=0.8',
'Markdown>=2.2.0',
'Pygments>=1.5',
'WTForms>=1.0.2',
'Werkzeug>=0.8.3',
'python-markdown-math'
Expand Down
4 changes: 1 addition & 3 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import shutil
from tempfile import mkdtemp
from tempfile import mkstemp
# from tempfile import mkstemp
from unittest import TestCase

from wiki.core import Wiki
Expand All @@ -18,7 +18,6 @@


class WikiBaseTestCase(TestCase):

#: The contents of the ``config.py`` file.
config_content = CONFIGURATION

Expand Down Expand Up @@ -69,7 +68,6 @@ def create_file(self, name, content=u'', folder=None):

return path


def tearDown(self):
"""
Will remove the root directory and all contents if one
Expand Down
6 changes: 1 addition & 5 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

from . import WikiBaseTestCase


PAGE_CONTENT = u"""\
title: Test
tags: one, two, 3, jö
Expand All @@ -28,12 +27,10 @@
Hello, how are you guys?
"""


CONTENT_HTML = u"""\
<p>Hello, how are you guys?</p>
<p><strong>Is it not <em>magnificent</em></strong>?</p>"""


WIKILINK_PAGE_CONTENT = u"""\
title: link

Expand Down Expand Up @@ -100,7 +97,7 @@ def test_handle_spaces(self):
other spaces correctly substituted.
"""
assert (clean_url(' /hello you/wonderful/person ')
== '/hello_you/wonderful/person')
== '/hello_you/wonderful/person')

def test_handle_uppercase(self):
"""
Expand Down Expand Up @@ -228,7 +225,6 @@ def setUp(self):

self.page_path = self.create_file('test.md', self.page_content)


def test_page_loading_fails(self):
"""
Assert that content is loaded correctly from disk.
Expand Down
1 change: 1 addition & 0 deletions wiki/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from wiki.core import Wiki

__all__ = ['Wiki']
4 changes: 4 additions & 0 deletions wiki/cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
CLI
~~~
Expand All @@ -7,6 +8,7 @@
import click
from wiki.web import create_app


@click.group()
@click.option('--directory', type=click.Path(exists=True), default=None)
@click.pass_context
Expand All @@ -15,6 +17,7 @@ def main(ctx, directory):
Base setup for all the following commands.

\b
:param ctx: context?
:param str directory: the directory to run wiki in, optional.
If no directory is provided the current directory will be
used.
Expand All @@ -34,6 +37,7 @@ def web(ctx, debug, host, port):
Run the web app.

\b
:param ctx: context?
:param bool debug: whether or not to run the web app in debug
mode.
:param str host: Set the host to 0.0.0.0 to connect from outside.
Expand Down
24 changes: 14 additions & 10 deletions wiki/core.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Wiki core
~~~~~~~~~
Expand Down Expand Up @@ -97,7 +98,7 @@ def __init__(self, text):
'fenced_code',
'meta',
'tables',
'mdx_math' # mathjax support
'mdx_math' # mathjax support
])
self.input = text
self.markdown = None
Expand All @@ -123,7 +124,6 @@ def process_markdown(self):
"""
self.html = self.md.convert(self.pre)


def split_raw(self):
"""
Split text into raw meta and content.
Expand All @@ -141,12 +141,13 @@ def process_meta(self):
# entries, so we have to loop over the meta values a second
# time to put them into a dictionary in the correct order
self.meta = OrderedDict()
for line in self.meta_raw.split('\n'):
key = line.split(':', 1)[0]
# markdown metadata always returns a list of lines, we will
# reverse that here
self.meta[key.lower()] = \
'\n'.join(self.md.Meta[key.lower()])
if self.md.Meta: # skip meta-less
for line in self.meta_raw.split('\n'):
key = line.split(':', 1)[0]
# markdown metadata always returns a list of lines, we will
# reverse that here
self.meta[key.lower()] = \
'\n'.join(self.md.Meta[key.lower()])

def process_post(self):
"""
Expand Down Expand Up @@ -174,6 +175,9 @@ def process(self):

class Page(object):
def __init__(self, path, url, new=False):
self.content = None
self._html = None
self.body = None
self.path = path
self.url = url
self._meta = OrderedDict()
Expand Down Expand Up @@ -321,7 +325,7 @@ def index(self):
root = os.path.abspath(self.root)
for cur_dir, _, files in os.walk(root):
# get the url of the current directory
cur_dir_url = cur_dir[len(root)+1:]
cur_dir_url = cur_dir[len(root) + 1:]
for cur_file in files:
path = os.path.join(cur_dir, cur_file)
if cur_file.endswith('.md'):
Expand Down Expand Up @@ -382,7 +386,7 @@ def index_by_tag(self, tag):
tagged.append(page)
return sorted(tagged, key=lambda x: x.title.lower())

def search(self, term, ignore_case=True, attrs=['title', 'tags', 'body']):
def search(self, term, ignore_case=True, attrs=('title', 'tags', 'body')):
pages = self.index()
regex = re.compile(term, re.IGNORECASE if ignore_case else 0)
matched = []
Expand Down
7 changes: 7 additions & 0 deletions wiki/web/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import os

from flask import current_app
Expand All @@ -9,23 +10,28 @@
from wiki.core import Wiki
from wiki.web.user import UserManager


class WikiError(Exception):
pass


def get_wiki():
wiki = getattr(g, '_wiki', None)
if wiki is None:
wiki = g._wiki = Wiki(current_app.config['CONTENT_DIR'])
return wiki


current_wiki = LocalProxy(get_wiki)


def get_users():
users = getattr(g, '_users', None)
if users is None:
users = g._users = UserManager(current_app.config['CONTENT_DIR'])
return users


current_users = LocalProxy(get_users)


Expand All @@ -52,6 +58,7 @@ def create_app(directory):
loginmanager = LoginManager()
loginmanager.login_view = 'wiki.user_login'


@loginmanager.user_loader
def load_user(name):
return current_users.get_user(name)
14 changes: 14 additions & 0 deletions wiki/web/forms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Forms
~~~~~
Expand All @@ -12,6 +13,7 @@
from wtforms import PasswordField
from wtforms.validators import InputRequired
from wtforms.validators import ValidationError
from wtforms.validators import EqualTo

from wiki.core import clean_url
from wiki.web import current_wiki
Expand Down Expand Up @@ -58,3 +60,15 @@ def validate_password(form, field):
return
if not user.check_password(field.data):
raise ValidationError('Username and password do not match.')


class RegistrationForm(FlaskForm):
name = StringField('Username', [InputRequired()])
password = PasswordField('Password', [InputRequired()])
password_confirm = PasswordField('Confirm Password',
validators=[InputRequired(), EqualTo('password')])

def validate_name(form, field):
user = current_users.get_user(form.name.data)
if user:
raise ValidationError('This username already exist.')
26 changes: 24 additions & 2 deletions wiki/web/routes.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Routes
~~~~~~
Expand All @@ -8,6 +9,7 @@
from flask import render_template
from flask import request
from flask import url_for
from flask import current_app
from flask_login import current_user
from flask_login import login_required
from flask_login import login_user
Expand All @@ -18,9 +20,11 @@
from wiki.web.forms import LoginForm
from wiki.web.forms import SearchForm
from wiki.web.forms import URLForm
from wiki.web.forms import RegistrationForm
from wiki.web import current_wiki
from wiki.web import current_users
from wiki.web.user import protect
from wiki.web.user import UserManager


bp = Blueprint('wiki', __name__)
Expand All @@ -38,6 +42,11 @@ def home():
@bp.route('/index/')
@protect
def index():
import locale
current_app.logger.info("defaultlocale: {}".format(locale.getdefaultlocale()))
current_app.logger.info("locale: {}".format(locale.getlocale()))
current_app.logger.info("preferredencoding: {}".format(locale.getpreferredencoding()))
locale.setlocale(locale.LC_ALL, 'ru_RU')
pages = current_wiki.index()
return render_template('index.html', pages=pages)

Expand All @@ -50,6 +59,7 @@ def display(url):


@bp.route('/create/', methods=['GET', 'POST'])
@login_required
@protect
def create():
form = URLForm()
Expand All @@ -60,6 +70,7 @@ def create():


@bp.route('/edit/<path:url>/', methods=['GET', 'POST'])
@login_required
@protect
def edit(url):
page = current_wiki.get(url)
Expand All @@ -84,6 +95,7 @@ def preview():


@bp.route('/move/<path:url>/', methods=['GET', 'POST'])
@login_required
@protect
def move(url):
page = current_wiki.get_or_404(url)
Expand All @@ -96,6 +108,7 @@ def move(url):


@bp.route('/delete/<path:url>/')
@login_required
@protect
def delete(url):
page = current_wiki.get_or_404(url)
Expand Down Expand Up @@ -155,9 +168,17 @@ def user_index():
pass


@bp.route('/user/create/')
@bp.route('/user/create/', methods=['GET', 'POST'])
def user_create():
pass
form = RegistrationForm()
if form.validate_on_submit():
user = form.name.data
password = form.password.data
UserManager(current_app.config['CONTENT_DIR']).add_user(name=user, password=password)
# user.set('authenticated', True)
flash('Registration successful.', 'success')
return redirect(request.args.get("next") or url_for('wiki.index'))
return render_template('register.html', form=form)


@bp.route('/user/<int:user_id>/')
Expand All @@ -166,6 +187,7 @@ def user_admin(user_id):


@bp.route('/user/delete/<int:user_id>/')
@login_required
def user_delete(user_id):
pass

Expand Down
13 changes: 9 additions & 4 deletions wiki/web/templates/base.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{% from "helpers.html" import input %}
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> {{ config.TITLE }} </title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='bootstrap.css') }}">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='responsive.css') }}">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='pygments.css') }}">
Expand Down Expand Up @@ -39,10 +41,13 @@
</ul>

<ul class="nav pull-right">
{% if current_user.is_anonymous %}
<li><a href="{{ url_for('wiki.user_login') }}">Login</a></li>
{% else %}
{% if current_user.is_authenticated %}
<li><a href="{{ url_for('wiki.user_logout') }}">Logout</a></li>
{% else %}
<ul class="nav">
<li><a href="{{ url_for('wiki.user_login') }}">Login</a></li>
<li><a href="{{ url_for('wiki.user_create') }}">Register</a></li>
</ul>
{% endif %}
</ul>
</div>
Expand Down
Loading