Commit 646fc0b1 by Piotr Mitros

simplewiki

parent c4f484c4
......@@ -92,13 +92,14 @@ INSTALLED_APPS = (
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
# 'django.contrib.admin',
'courseware',
'auth',
'django.contrib.humanize',
'static_template_view',
'textbook',
'staticbook',
'simplewiki',
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
......
import sys, os
# allow mdx_* parsers to be just dropped in the simplewiki folder
module_path = os.path.abspath(os.path.dirname(__file__))
if module_path not in sys.path:
sys.path.append(module_path)
from django.contrib import admin
from django import forms
from django.utils.translation import ugettext as _
from models import Article, Revision, Permission, ArticleAttachment
class RevisionInline(admin.TabularInline):
model = Revision
extra = 1
class RevisionAdmin(admin.ModelAdmin):
list_display = ('article', '__unicode__', 'revision_date', 'revision_user', 'revision_text')
search_fields = ('article', 'counter')
class AttachmentAdmin(admin.ModelAdmin):
list_display = ('article', '__unicode__', 'uploaded_on', 'uploaded_by')
class ArticleAdminForm(forms.ModelForm):
def clean(self):
cleaned_data = self.cleaned_data
if cleaned_data.get("slug").startswith('_'):
raise forms.ValidationError(_('Slug cannot start with _ character.'
'Reserved for internal use.'))
if not self.instance.pk:
parent = cleaned_data.get("parent")
slug = cleaned_data.get("slug")
if Article.objects.filter(slug__exact=slug, parent__exact=parent):
raise forms.ValidationError(_('Article slug and parent must be '
'unique together.'))
return cleaned_data
class Meta:
model = Article
class ArticleAdmin(admin.ModelAdmin):
list_display = ('created_by', 'slug', 'modified_on', 'parent')
search_fields = ('slug',)
prepopulated_fields = {'slug': ('title',) }
inlines = [RevisionInline]
form = ArticleAdminForm
save_on_top = True
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'current_revision':
# Try to determine the id of the article being edited
id = request.path.split('/')
import re
if len(id) > 0 and re.match(r"\d+", id[-2]):
kwargs["queryset"] = Revision.objects.filter(article=id[-2])
return db_field.formfield(**kwargs)
else:
db_field.editable = False
return db_field.formfield(**kwargs)
return super(ArticleAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
class PermissionAdmin(admin.ModelAdmin):
search_fields = ('article', 'counter')
admin.site.register(Article, ArticleAdmin)
admin.site.register(Revision, RevisionAdmin)
admin.site.register(Permission, PermissionAdmin)
admin.site.register(ArticleAttachment, AttachmentAdmin)
\ No newline at end of file
#!/usr/bin/env python
'''
WikiLink Extention for Python-Markdown
======================================
Converts CamelCase words to relative links. Requires Python-Markdown 1.6+
Basic usage:
>>> import markdown
>>> text = "Some text with a WikiLink."
>>> md = markdown.markdown(text, ['wikilink'])
>>> md
'\\n<p>Some text with a <a href="/WikiLink/" class="wikilink">WikiLink</a>.\\n</p>\\n\\n\\n'
To define custom settings the simple way:
>>> md = markdown.markdown(text,
... ['wikilink(base_url=/wiki/,end_url=.html,html_class=foo)']
... )
>>> md
'\\n<p>Some text with a <a href="/wiki/WikiLink.html" class="foo">WikiLink</a>.\\n</p>\\n\\n\\n'
Custom settings the complex way:
>>> md = markdown.Markdown(text,
... extensions = ['wikilink'],
... extension_configs = {'wikilink': [
... ('base_url', 'http://example.com/'),
... ('end_url', '.html'),
... ('html_class', '') ]},
... encoding='utf8',
... safe_mode = True)
>>> str(md)
'\\n<p>Some text with a <a href="http://example.com/WikiLink.html">WikiLink</a>.\\n</p>\\n\\n\\n'
Use MetaData with mdx_meta.py (Note the blank html_class in MetaData):
>>> text = """wiki_base_url: http://example.com/
... wiki_end_url: .html
... wiki_html_class:
...
... Some text with a WikiLink."""
>>> md = markdown.Markdown(text, ['meta', 'wikilink'])
>>> str(md)
'\\n<p>Some text with a <a href="http://example.com/WikiLink.html">WikiLink</a>.\\n</p>\\n\\n\\n'
From the command line:
python markdown.py -x wikilink(base_url=http://example.com/,end_url=.html,html_class=foo) src.txt
By [Waylan Limberg](http://achinghead.com/).
Project website: http://achinghead.com/markdown-wikilinks/
Contact: waylan [at] gmail [dot] com
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
Version: 0.4 (Oct 14, 2006)
Dependencies:
* [Python 2.3+](http://python.org)
* [Markdown 1.6+](http://www.freewisdom.org/projects/python-markdown/)
* For older dependencies use [WikiLink Version 0.3]
(http://code.limberg.name/svn/projects/py-markdown-ext/wikilinks/tags/release-0.3/)
'''
import markdown
class CamelCaseExtension(markdown.Extension):
def __init__(self, configs):
# set extension defaults
self.config = {
'base_url' : ['/', 'String to append to beginning or URL.'],
'end_url' : ['/', 'String to append to end of URL.'],
'html_class' : ['wikilink', 'CSS hook. Leave blank for none.']
}
# Override defaults with user settings
for key, value in configs :
# self.config[key][0] = value
self.setConfig(key, value)
def add_inline(self, md, name, klass, re):
pattern = klass(re)
pattern.md = md
pattern.ext = self
md.inlinePatterns.add(name, pattern, "<reference")
def extendMarkdown(self, md, md_globals):
self.add_inline(md, 'camel', CamelCaseLinks,
r'''(?P<escape>\\|\b)(?P<camelcase>([A-Z]+[a-z-_]+){2,})(?:"")?\b''')
class CamelCaseLinks(markdown.inlinepatterns.Pattern):
def handleMatch(self, m) :
if m.group('escape') == '\\':
a = markdown.etree.Element('a')#doc.createTextNode(m.group('camelcase'))
else :
url = m.group('camelcase')
#'%s%s%s'% (self.md.wiki_config['base_url'][0], \
#m.group('camelcase'), \
#self.md.wiki_config['end_url'][0])
label = m.group('camelcase').replace('_', ' ')
a = markdown.etree.Element('a')
a.set('href', url)
a.text = label
a.set('class', 'wikilink')
return a
class CamelCasePreprocessor(markdown.preprocessors.Preprocessor) :
def run(self, lines) :
'''
Updates WikiLink Extension configs with Meta Data.
Passes "lines" through unchanged.
Run as a preprocessor because must run after the
MetaPreprocessor runs and only needs to run once.
'''
if hasattr(self.md, 'Meta'):
if self.md.Meta.has_key('wiki_base_url'):
self.md.wiki_config['base_url'][0] = self.md.Meta['wiki_base_url'][0]
if self.md.Meta.has_key('wiki_end_url'):
self.md.wiki_config['end_url'][0] = self.md.Meta['wiki_end_url'][0]
if self.md.Meta.has_key('wiki_html_class'):
self.md.wiki_config['html_class'][0] = self.md.Meta['wiki_html_class'][0]
return lines
def makeExtension(configs=None) :
return CamelCaseExtension(configs=configs)
if __name__ == "__main__":
import doctest
doctest.testmod()
#!/usr/bin/env python
'''
Image Embedding Extension for Python-Markdown
======================================
Converts lone links to embedded images, provided the file extension is allowed.
Ex:
http://www.ericfehse.net/media/img/ef/blog/django-pony.jpg
becomes
<img src="http://www.ericfehse.net/media/img/ef/blog/django-pony.jpg">
mypic.jpg becomes <img src="/MEDIA_PATH/mypic.jpg">
Requires Python-Markdown 1.6+
'''
import simplewiki.settings as settings
import markdown
class ImageExtension(markdown.Extension):
def __init__(self, configs):
for key, value in configs :
self.setConfig(key, value)
def add_inline(self, md, name, klass, re):
pattern = klass(re)
pattern.md = md
pattern.ext = self
md.inlinePatterns.add(name, pattern, "<reference")
def extendMarkdown(self, md, md_globals):
self.add_inline(md, 'image', ImageLink,
r'^(?P<proto>([^:/?#])+://)?(?P<domain>([^/?#]*)/)?(?P<path>[^?#]*\.(?P<ext>[^?#]{3,4}))(?:\?([^#]*))?(?:#(.*))?$')
class ImageLink(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
img = markdown.etree.Element('img')
proto = m.group('proto') or "http://"
domain = m.group('domain')
path = m.group('path')
ext = m.group('ext')
# A fixer upper
if ext.lower() in settings.WIKI_IMAGE_EXTENSIONS:
if domain:
src = proto+domain+path
elif path:
# We need a nice way to source local attachments...
src = "/wiki/media/" + path + ".upload"
else:
src = ''
img.set('src', src)
return img
def makeExtension(configs=None) :
return ImageExtension(configs=configs)
if __name__ == "__main__":
import doctest
doctest.testmod()
\ No newline at end of file
# Source: https://github.com/mayoff/python-markdown-mathjax
import markdown
class MathJaxPattern(markdown.inlinepatterns.Pattern):
def __init__(self):
markdown.inlinepatterns.Pattern.__init__(self, r'(?<!\\)(\$\$?)(.+?)\2')
def handleMatch(self, m):
return markdown.AtomicString(m.group(2) + m.group(3) + m.group(2))
class MathJaxExtension(markdown.Extension):
def extendMarkdown(self, md, md_globals):
# Needs to come before escape matching because \ is pretty important in LaTeX
md.inlinePatterns.add('mathjax', MathJaxPattern(), '<escape')
def makeExtension(configs=None):
return MathJaxExtension(configs)
/*
================================================
autosuggest, inquisitor style
================================================
*/
body
{
position: relative;
}
div.autosuggest
{
position: absolute;
background-image: url(img_inquisitor/as_pointer.gif);
background-position: top;
background-repeat: no-repeat;
padding: 10px 0 0 0;
}
div.autosuggest div.as_header,
div.autosuggest div.as_footer
{
position: relative;
height: 6px;
padding: 0 6px;
background-image: url(img_inquisitor/ul_corner_tr.gif);
background-position: top right;
background-repeat: no-repeat;
overflow: hidden;
}
div.autosuggest div.as_footer
{
background-image: url(img_inquisitor/ul_corner_br.gif);
}
div.autosuggest div.as_header div.as_corner,
div.autosuggest div.as_footer div.as_corner
{
position: absolute;
top: 0;
left: 0;
height: 6px;
width: 6px;
background-image: url(img_inquisitor/ul_corner_tl.gif);
background-position: top left;
background-repeat: no-repeat;
}
div.autosuggest div.as_footer div.as_corner
{
background-image: url(img_inquisitor/ul_corner_bl.gif);
}
div.autosuggest div.as_header div.as_bar,
div.autosuggest div.as_footer div.as_bar
{
height: 6px;
overflow: hidden;
background-color: #333;
}
div.autosuggest ul
{
list-style: none;
margin: 0 0 -4px 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
div.autosuggest ul li
{
color: #ccc;
padding: 0;
margin: 0 4px 4px;
text-align: left;
}
div.autosuggest ul li a
{
color: #ccc;
display: block;
text-decoration: none;
background-color: transparent;
text-shadow: #000 0px 0px 5px;
position: relative;
padding: 0;
width: 100%;
}
div.autosuggest ul li a:hover
{
background-color: #444;
}
div.autosuggest ul li.as_highlight a:hover
{
background-color: #1B5CCD;
}
div.autosuggest ul li a span
{
display: block;
padding: 3px 6px;
font-weight: bold;
}
div.autosuggest ul li a span small
{
font-weight: normal;
color: #999;
}
div.autosuggest ul li.as_highlight a span small
{
color: #ccc;
}
div.autosuggest ul li.as_highlight a
{
color: #fff;
background-color: #1B5CCD;
background-image: url(img_inquisitor/hl_corner_br.gif);
background-position: bottom right;
background-repeat: no-repeat;
}
div.autosuggest ul li.as_highlight a span
{
background-image: url(img_inquisitor/hl_corner_bl.gif);
background-position: bottom left;
background-repeat: no-repeat;
}
div.autosuggest ul li a .tl,
div.autosuggest ul li a .tr
{
background-image: transparent;
background-repeat: no-repeat;
width: 6px;
height: 6px;
position: absolute;
top: 0;
padding: 0;
margin: 0;
}
div.autosuggest ul li a .tr
{
right: 0;
}
div.autosuggest ul li.as_highlight a .tl
{
left: 0;
background-image: url(img_inquisitor/hl_corner_tl.gif);
background-position: bottom left;
}
div.autosuggest ul li.as_highlight a .tr
{
right: 0;
background-image: url(img_inquisitor/hl_corner_tr.gif);
background-position: bottom right;
}
div.autosuggest ul li.as_warning
{
font-weight: bold;
text-align: center;
}
div.autosuggest ul em
{
font-style: normal;
color: #6EADE7;
}
\ No newline at end of file
body
{
font-family: 'Lucida Sans', 'Sans';
}
a img
{
border: 0;
}
div#wiki_article a {
color: #06d;
text-decoration: none;
}
div#wiki_article a:hover {
color: #f82;
text-decoration: underline;
}
hr
{
background-color: #def;
height: 2px;
border: 0;
}
div#wiki_article .toc a
{
color: #025
}
div#wiki_article p
{
/* font-size: 90%; looks funny when combined with lists/tables */
line-height: 140%;
}
div#wiki_article h1
{
font-size: 200%;
font-weight: normal;
color: #048;
}
div#wiki_article h2
{
font-size: 150%;
font-weight: normal;
color: #025;
}
div#wiki_article h3
{
font-size: 120%;
font-weight: bold;
color: #000;
}
table
{
border: 1px solid black;
border-collapse: collapse;
margin: 12px;
}
table tr.dark
{
background-color: #F3F3F3;
}
table thead tr
{
background-color: #def;
border-bottom: 2px solid black;
}
table td, th
{
padding: 6px 10px 6px 10px;
border: 1px solid black;
}
table thead th
{
padding-bottom: 8px;
padding-top: 8px;
}
div#wiki_panel
{
float: right;
}
div.wiki_box
{
width: 230px;
padding: 10px;
color: #fff;
font-size: 80%;
}
div.wiki_box div.wiki_box_contents
{ background-color: #222;
padding: 5px 10px;}
div.wiki_box div.wiki_box_header,
div.wiki_box div.wiki_box_footer
{
position: relative;
height: 6px;
padding: 0 6px;
background-image: url(../img/box_corner_tr.gif);
background-position: top right;
background-repeat: no-repeat;
overflow: hidden;
}
div.wiki_box div.wiki_box_footer
{
background-image: url(../img/box_corner_br.gif);
}
div.wiki_box div.wiki_box_header div.wiki_box_corner,
div.wiki_box div.wiki_box_footer div.wiki_box_corner
{
position: absolute;
top: 0;
left: 0;
height: 6px;
width: 6px;
background-image: url(../img/box_corner_tl.gif);
background-position: top left;
background-repeat: no-repeat;
}
div.wiki_box div.wiki_box_footer div.wiki_box_corner
{
background-image: url(../img/box_corner_bl.gif);
}
div.wiki_box div.wiki_box_header div.wiki_box_bar,
div.wiki_box div.wiki_box_footer div.wiki_box_bar
{
height: 6px;
overflow: hidden;
background-color: #222;
}
div.wiki_box a
{
color: #acf;
}
div.wiki_box p
{
margin: 5px 0;
}
div.wiki_box ul
{
padding-left: 20px;
margin-left: 0;
}
div.wiki_box div.wiki_box_title
{
margin-bottom: 5px;
font-size: 140%;
}
form#wiki_revision #id_contents
{
width:500px;
height: 400px;
font-family: monospace;
}
form#wiki_revision #id_title
{
width: 500px;
}
form#wiki_revision #id_revision_text
{
width: 500px;
}
table#wiki_revision_table
{
border: none;
border-collapse: collapse;
padding-right: 250px;
}
table#wiki_revision_table th
{
border: none;
text-align: left;
vertical-align: top;
}
table#wiki_revision_table td
{
border: none;
}
table#wiki_history_table
{
border-collapse: collapse;
border-spacing: 0;
padding-right: 250px;
}
table#wiki_history_table th#modified
{
width: 220px;
}
table#wiki_history_table td
{
border: none;
}
table#wiki_history_table tbody tr
{
border-bottom: 1px solid black;
}
table#wiki_history_table tbody td
{
vertical-align: top;
padding: 5px;
}
table#wiki_history_table tfoot td
{
border: none;
}
table#wiki_history_table tbody td.diff
{
font-family: monospace;
overflow: hidden;
border-left: 1px dotted black;
border-right: 1px dotted black;
}
table#wiki_history_table th
{
text-align: left;
}
div#wiki_attach_progress_container
{
background-color: #333;
width: 100%;
height: 20px;
display: none;
}
div#wiki_attach_progress
{
width: 25%;
background-color: #999;
}
blockquote {
margin-top: 15px;
margin-bottom: 15px;
margin-left: 50px;
padding-left: 15px;
border-left: 3px solid #666;
color: #999;
max-width: 400px ;
}
blockquote p {
margin-top: 8px;
margin-bottom: 8px;
}
div#wiki_panel
{
display:none;
}
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
# Default settings.. overwrite in your own settings.py
# Planned feature.
WIKI_USE_MARKUP_WIDGET = True
####################
# LOGIN PROTECTION #
####################
# Before setting the below parameters, please note that permissions can
# be set in the django permission system on individual articles and their
# child articles. In this way you can add a user group and give them
# special permissions, be it on the root article or some other. Permissions
# are inherited on lower levels.
# Adds standard django login protection for viewing
WIKI_REQUIRE_LOGIN_VIEW = getattr(settings, 'SIMPLE_WIKI_REQUIRE_LOGIN_VIEW',
False)
# Adds standard django login protection for editing
WIKI_REQUIRE_LOGIN_EDIT = getattr(settings, 'SIMPLE_WIKI_REQUIRE_LOGIN_EDIT',
True)
####################
# ATTACHMENTS #
####################
# This should be a directory that's writable for the web server.
# It's relative to the MEDIA_ROOT.
WIKI_ATTACHMENTS = getattr(settings, 'SIMPLE_WIKI_ATTACHMENTS',
'simplewiki/attachments/')
# If false, attachments will completely disappear
WIKI_ALLOW_ATTACHMENTS = getattr(settings, 'SIMPLE_WIKI_ALLOW_ATTACHMENTS',
True)
# If WIKI_REQUIRE_LOGIN_EDIT is False, then attachments can still be disallowed
WIKI_ALLOW_ANON_ATTACHMENTS = getattr(settings, 'SIMPLE_WIKI_ALLOW_ANON_ATTACHMENTS', False)
# Attachments are automatically stored with a dummy extension and delivered
# back to the user with their original extension.
# This setting does not add server security, but might add user security
# if set -- or force users to use standard formats, which might also
# be a good idea.
# Example: ('pdf', 'doc', 'gif', 'jpeg', 'jpg', 'png')
WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS = getattr(settings, 'SIMPLE_WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS',
None)
# At the moment this variable should not be modified, because
# it breaks compatibility with the normal Django FileField and uploading
# from the admin interface.
WIKI_ATTACHMENTS_ROOT = settings.MEDIA_ROOT
# Bytes! Default: 1 MB.
WIKI_ATTACHMENTS_MAX = getattr(settings, 'SIMPLE_WIKI_ATTACHMENTS_MAX',
1 * 1024 * 1024)
# Allow users to edit titles of pages
# (warning! titles are not maintained in the revision system.)
WIKI_ALLOW_TITLE_EDIT = getattr(settings, 'SIMPLE_WIKI_ALLOW_TITLE_EDIT', False)
# Global context processors
# These are appended to TEMPLATE_CONTEXT_PROCESSORS in your Django settings
# whenever the wiki is in use. It can be used as a simple, but effective
# way of extending simplewiki without touching original code (and thus keeping
# everything easily maintainable)
WIKI_CONTEXT_PREPROCESSORS = getattr(settings, 'SIMPLE_WIKI_CONTEXT_PREPROCESSORS',
())
####################
# AESTHETICS #
####################
# List of extensions to be used by Markdown. Custom extensions (i.e., with file
# names of mdx_*.py) can be dropped into the simplewiki (or project) directory
# and then added to this list to be utilized. Wikilinks is always enabled.
#
# For more information, see
# http://www.freewisdom.org/projects/python-markdown/Available_Extensions
WIKI_MARKDOWN_EXTENSIONS = getattr(settings, 'SIMPLE_WIKI_MARKDOWN_EXTENSIONS',
['footnotes',
'tables',
'headerid',
'fenced_code',
'def_list',
'codehilite',
'abbr',
'toc',
'camelcase', # CamelCase-style wikilinks
'video', # In-line embedding for YouTube, etc.
#'image' # In-line embedding for images - too many bugs. It has a failed REG EXP.
])
WIKI_IMAGE_EXTENSIONS = getattr(settings,
'SIMPLE_WIKI_IMAGE_EXTENSIONS',
('jpg','jpeg','gif','png','tiff','bmp'))
# Planned features
WIKI_PAGE_WIDTH = getattr(settings,
'SIMPLE_WIKI_PAGE_WIDTH', "100%")
WIKI_PAGE_ALIGN = getattr(settings,
'SIMPLE_WIKI_PAGE_ALIGN', "center")
WIKI_IMAGE_THUMB_SIZE = getattr(settings,
'SIMPLE_WIKI_IMAGE_THUMB_SIZE', (200,150))
WIKI_IMAGE_THUMB_SIZE_SMALL = getattr(settings,
'SIMPLE_WIKI_IMAGE_THUMB_SIZE_SMALL', (100,100))
{% load i18n simplewiki_utils %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="{{ LANGUAGE_CODE }}">
<head>
<title>{{ wiki_title }}</title>
<link rel="stylesheet" media="screen,print" href="/static/simplewiki/css/base.css" />
<link rel="stylesheet" media="print" href="/static/simplewiki/css/base_print.css" />
<link rel="stylesheet" href="/static/simplewiki/css/autosuggest_inquisitor.css" />
<script type="text/javascript" src="/static/simplewiki/js/bsn.AutoSuggest_c_2.0.js"></script>
<script type="text/javascript">
function set_related_article_id(s) {
document.getElementById('wiki_related_input_id').value = s.id;
document.getElementById('wiki_related_input_submit').disabled=false;
}
var x = window.onload;
window.onload = function(){
var options = {
script: "{% url search_related wiki_article.get_url %}/?self={{wiki_article.pk }}&",
json: true,
varname: "query",
maxresults: 35,
callback: set_related_article_id,
noresults: "{% trans "Nothing found!" %}"
};
var as = new AutoSuggest('wiki_related_input', options);
if (typeof x == 'function')
x();
}
</script>
{% block wiki_head %}
{% endblock %}
</head>
<body>
<h1>{% block wiki_page_title %}{% endblock %}</h1>
<hr />
{% block wiki_panel %}
<div id="wiki_panel">
<div class="wiki_box">
<div class="wiki_box_header">
<div class="wiki_box_corner"></div>
<div class="wiki_box_bar"></div>
</div>
<div class="wiki_box_contents">
<div class="wiki_box_title">{% trans "Search" %}</div>
<form method="POST" action='{% url wiki_search_articles wiki_article.get_url %}'>{% csrf_token %}
<input type="text" name="value" id="wiki_search_input" style="width: 72%" value="{{wiki_search_query|escape}}"/>
<input type="submit" id="wiki_search_input_submit" value={% trans "Go!" %} style="width: 20%" />
</form>
</div>
<div class="wiki_box_footer">
<div class="wiki_box_corner"></div>
<div class="wiki_box_bar"></div>
</div>
</div>
<div class="wiki_box">
<div class="wiki_box_header">
<div class="wiki_box_corner"></div>
<div class="wiki_box_bar"></div>
</div>
<div class="wiki_box_contents" style="position: relative;">
<div style="border: 2px outset #CCC; width: 250px; padding: 10px; background-color: #FFF; position: absolute; right: 100px; top: -80px; display: none; color: #000;" id="wiki_create_form">
{% with "this.wiki_article_name.value.replace(/([^a-zA-Z0-9\-])/g, '')+'/_create/'" as theaction %}
<form method="GET" onsubmit="this.action='{% url wiki_view "" %}{{ wiki_article.get_url }}/' + {{ theaction }};">
{% endwith %}
<h2>{% trans "Create article" %}</h2>
<p>
<label for="id_wiki_article_name">{% trans "Title of article" %}</label>
<input type="text" name="wiki_article_name" id="id_wiki_article_name" /><br/>
<label for="id_wiki_article_is_child">{% trans "Create as a child of current article"%}</label>
<input type="checkbox" name="wiki_article_is_child" id="id_wiki_artcile_is_child" disabled="true" checked={%if wiki_article%}"yes"{%else%}"no"{%endif%}>
</p>
<p>
<input type="button" class="button" value="{% trans "Cancel" %}" style="display: inline-block; margin-right: 2px;" onclick="document.getElementById('wiki_create_form').style.display='none';" />
<input type="submit" class="button" value="{% trans "Next" %} &gt;" style="display: inline-block; margin-right: 2px; font-weight: bold;" />
</p>
</form>
</div>
<p>
{% if wiki_article %}
<input type="button" onclick="javascript:location.href='{% url wiki_view wiki_article.get_url %}'" value="View" style="width: 100%;" /><br />
<input type="button" onclick="javascript:location.href='{% url wiki_edit wiki_article.get_url %}'" value="Edit" style="width: 100%;"{% if not wiki_write %} disabled="true"{%endif%} /><br />
<input type="button" onclick="javascript:location.href='{% url wiki_history wiki_article.get_url 1 %}'" value="History" style="width: 100%;" />
{% endif %}
<input type="button" onclick="document.getElementById('wiki_create_form').style.display='block';" value="{% trans "Create article" %}" style="width: 100%; margin-bottom: 2px;" class="button" />
<input type="button" onclick="javascript:location.href='{% url wiki_random wiki_article.get_url %}'" value="{% trans "Random article" %}" style="width: 100%; margin-bottom: 2px;" class="button" />
</p>
{% if wiki_article %}
{% if wiki_article.locked %}
<p><strong>{% trans "This article has been locked" %}</strong></p>
{% endif %}
<p>
<i>{% trans "Last modified" %}: {{ wiki_article.modified_on|date }}, {{ wiki_article.modified_on|time }}</i>
</p>
{% endif %}
</div>
<div class="wiki_box_footer">
<div class="wiki_box_corner"></div>
<div class="wiki_box_bar"></div>
</div>
</div>
{% if wiki_article %}
<div class="wiki_box">
<div class="wiki_box_header">
<div class="wiki_box_corner"></div>
<div class="wiki_box_bar"></div>
</div>
<div class="wiki_box_contents">
<div class="wiki_box_title">{% trans "Related articles" %}</div>
{% if wiki_article.related.all %}
<p>
{% for rel in wiki_article.related.all %}
<span class="related">
{% if wiki_write %}
<a href="javascript:if(confirm('{% trans "Are you sure, you want to delete this relation?" %}')) { location.href='{% url wiki_remove_relation wiki_article.get_url rel.id%}'; }">
<img src="{{ "simplewiki/img/delete.gif"|prepend_media_url }}" alt="{% trans "remove relation" %}" />
</a>
{% endif %}
<a href="{% url wiki_view rel.get_url %}">{{rel.title}}</a>
</span>
{% endfor %}
</p>
{% else %}
<p><i>({% trans "none" %})</i></p>
{% endif %}
{% if wiki_write %}
<form method="POST" action="{% url add_related wiki_article.get_url %}">{% csrf_token %}
<input type="text" name="value" id="wiki_related_input" style="width: 72%" />
<input type="submit" id="wiki_related_input_submit" disabled="true" value="Add" style="width: 20%" />
<input type="hidden" name="id" value="" id="wiki_related_input_id" />
</form>
{% endif %}
</div>
<div class="wiki_box_footer">
<div class="wiki_box_corner"></div>
<div class="wiki_box_bar"></div>
</div>
</div>
<div class="wiki_box">
<div class="wiki_box_header">
<div class="wiki_box_corner"></div>
<div class="wiki_box_bar"></div>
</div>
<div class="wiki_box_contents">
<div class="wiki_box_title">{% trans "Attachments" %}</div>
{% if wiki_article.attachments %}
<ul>
{% for a in wiki_article.attachments %}
<li><a href="{{a.download_url}}">{{a.filename|slice:":13"|slice:":-3" }}{% if a.filename|slice:"10:" %}...{{ a.filename|slice:"-3:" }}{% endif %}</a> ({{a.get_size|filesizeformat}})</li>
{% endfor %}
</ul>
{% else %}
<p><i>({% trans "none" %})</i></p>
{% endif %}
{% if wiki_attachments_write %}
<form method="POST" action="{% url add_attachment wiki_article.get_url %}" enctype="multipart/form-data" target="wiki_attach_frame">{% csrf_token %}
<input type="file" class="fileinput" name="attachment" size="10" /><br />
<input type="checkbox" name="overwrite" id="wiki_attach_overwrite" value="1" /> Overwrite same filename
<p><input type="submit" value="Attach" /></p>
<div id="wiki_attach_progress_container">
<div id="wiki_attach_progress"><br /></div>
</div>
</form>
<iframe name="wiki_attach_frame" style="display:none"></iframe>
{% endif %}
</div>
<div class="wiki_box_footer">
<div class="wiki_box_corner"></div>
<div class="wiki_box_bar"></div>
</div>
</div>
{% endif %}
</div>
{% endblock %}
{% block wiki_body %}
{% endblock %}
</body>
</html>
{% extends "simplewiki_base.html" %}
{% load i18n simplewiki_utils %}
{% block wiki_page_title %}
Create article
{% endblock %}
{% block wiki_body %}
<form method="POST" id="wiki_revision">{% csrf_token %}
<table id="wiki_revision_table">
{{ wiki_form }}
<tr>
<td colspan="2" align="right">
<input type="submit" value="{% trans "Create article" %}" /></td>
</tr>
</table>
</form>
{% endblock %}
{% extends "simplewiki_base.html" %}
{% load i18n simplewiki_utils %}
{% block wiki_page_title %}
{{wiki_article.title}}
{% endblock %}
{% block wiki_body %}
<form method="POST" id="wiki_revision">{% csrf_token %}
<table id="wiki_revision_table">
{{ wiki_form }}
<tr>
<td colspan="2" align="right">
<input type="submit" value="{% trans "Edit article" %}" /></td>
</tr>
</table>
</form>
{% endblock %}
{% extends "simplewiki_base.html" %}
{% load i18n simplewiki_utils %}
{% block wiki_page_title %}
Oops...
{% endblock %}
{% block wiki_body %}
<div class="wiki_error">
{{ wiki_error|safe }}
{% if wiki_err_notfound %}
{% if wiki_url %}
<p>
The page you requested could not be found.
Click <a href="{% url wiki_create wiki_url %}">here</a> to create it.
</p>
{% else %}
<p>
Or maybe rather: Congratulations! It seems that there's no root
article, which is probably because you just installed simple-wiki
and your installation is working. Now you can create the root article.
Click <a href="{% url wiki_create "" %}">here</a> to create it.
</p>
{% endif %}
{% else %}
{% if wiki_err_noparent %}
<p>
You cannot create this page, because its parent
does not exist. Click <a href="{% url wiki_create wiki_url_parent %}">here</a>
to create it.
</p>
{% else %}
{% if wiki_err_keyword %}
<p>
The page you're trying to create <b>{{wiki_url}}</b> starts with <b>_</b>, which is reserved for internal use.
</p>
{% else %}
{% if wiki_err_locked %}
<p>
The article you are trying to modify is locked.
</p>
{% else %}
{% if wiki_err_noread %}
<p>
You do not have access to read this article.
</p>
{% else %}
{% if wiki_err_nowrite %}
<p>
You do not have access to edit this article.
</p>
{% else %}
{% if wiki_err_noanon %}
<p>
Anonymous attachments are not allowed. Try logging in.
</p>
{% else %}
{% if wiki_err_create %}
<p>
You do not have access to create this article.
</p>
{% else %}
{% if wiki_err_encode %}
<p>
The url you requested could not be handled by the wiki.
Probably you used a bad character in the URL.
Only use digits, English letters, underscore and dash. For instance
/wiki/An_Article-1
</p>
{% else %}
<p>
An error has occured.
</p>
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
</div>
{% endblock %}
{% extends "simplewiki_base.html" %}
{% load i18n simplewiki_utils %}
{% block wiki_page_title %}
{{ wiki_article.title }}
{% endblock %}
{% block wiki_body %}
<form method="POST">{% csrf_token %}
<table id="wiki_history_table">
<thead>
<tr>
<th id="revision">Revision</th>
<th id="comment">Comment</th>
<th id="diff">Diff</th>
<th id="modified">Modified</th>
</tr>
</thead>
<tbody>
{% for revision in wiki_history %}
<tr style="border-top: 1px" {%cycle '' 'class="dark"'%}>
<td width="15px">
<input type="radio" name="revision" id="{{ revision.id }}" value="{{ revision.id }}"{%ifequal wiki_article.current_revision.id revision.id%} checked{%endifequal%} />
<label for="{{ revision.id }}">
{{ revision }}
{% if revision.previous_revision %}
{% ifnotequal revision.counter revision.previous_revision.counter|add:1 %}
<br/>(based on {{ revision.previous_revision }})
{% endifnotequal %}
{% endif %}
</label>
</td>
<td>{% if revision.revision_text %}{{ revision.revision_text}}{% else %}<i>None</i>{% endif %}</td>
<td class="diff">{% for x in revision.get_diff %}{{x|escape}}<br />{% endfor %}</td>
<td>{{ revision.get_user}}
<br/>
{{ revision.revision_date|date}} {{ revision.revision_date|time}}
</td>
</tr>
{% endfor %}
</tbody>
{% if wiki_prev_page or wiki_next_page %}
<tfoot>
<tr>
<td colspan="4">
{% if wiki_prev_page %}
<a href="{% url wiki_history wiki_article.get_url wiki_prev_page %}">{% trans "Previous page" %}</a>
{% endif %}
{% if wiki_next_page %}
<a href="{% url wiki_history wiki_article.get_url wiki_next_page %}">{% trans "Next page" %}</a>
{% endif %}
</td>
</tr>
</tfoot>
{% endif %}
</table>
<input type="submit" value="Change revision"{% if not wiki_write %} disabled="true"{% endif %} />
</form>
{% endblock %}
{% extends "simplewiki_base.html" %}
{% load i18n simplewiki_utils %}
{% block wiki_page_title %}
{% if wiki_search_query %}
{% trans "Search results for" %} '{{ wiki_search_query|escape }}'
{% else %}
{% trans "Displaying all articles" %}
{% endif %}
{% endblock %}
{% block wiki_body %}
{% for article in wiki_search_results %}
{% if article.get_url %}
<a href="{% url wiki_view article.get_url %}">{{ article.get_url }}</a><br/>
{% else %}
<a href="{% url wiki_view '' %}">/</a><br/>
{% endif %}
{% empty %}
{% trans "No articles were found!" %}
{% endfor %}
{% endblock %}
{% load i18n simplewiki_utils %}
{% if started %}
<script type="text/javascript">
parent.document.getElementById("wiki_attach_progress_container").style.display='block';
</script>
{% else %}
{% if finished %}
<script type="text/javascript">
parent.document.getElementById("wiki_attach_progress_container").style.display='none';
parent.location.reload();
</script>
{% else %}
{% if overwrite_warning %}
<script type="text/javascript">
if (confirm('{% trans "Warning: The filename already exists? Really overwrite" %} {{ filename }}?'))
parent.document.getElementById("wiki_attach_overwrite").checked=true;
parent.document.getElementById("wiki_attach_overwrite").form.submit();
</script>
{% else %}
{% if too_big %}
<script type="text/javascript">
alert('File is too big. Maximum: {{max_size|filesizeformat}}\nYour file was: {{file.size|filesizeformat}}');
</script>
{% else %}
<script type="text/javascript">
parent.document.getElementById("wiki_attach_progress").style.width='{{progress_width}}%';
</script>
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% extends "simplewiki_base.html" %}
{% load i18n simplewiki_utils %}
{% block wiki_page_title %}
{{ wiki_article.title }}
{% endblock %}
{% block wiki_body %}
<div id="wiki_article">
{{ wiki_article.current_revision.contents_parsed|safe }}
</div>
{% endblock %}
from django import template
from django.template.defaultfilters import stringfilter
from simplewiki.settings import *
from django.conf import settings
from django.utils.http import urlquote as django_urlquote
register = template.Library()
@register.filter()
def prepend_media_url(value):
"""Prepend user defined media root to url"""
return settings.MEDIA_URL + value
@register.filter()
def urlquote(value):
"""Prepend user defined media root to url"""
return django_urlquote(value)
\ No newline at end of file
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
from django.conf.urls.defaults import *
urlpatterns = patterns('',
url(r'^$', 'simplewiki.views.root_redirect', name='wiki_root'),
url(r'^/?([a-zA-Z\d/_-]*)/_edit/$', 'simplewiki.views.edit', name='wiki_edit'),
url(r'^/?([a-zA-Z\d/_-]*)/_create/$', 'simplewiki.views.create', name='wiki_create'),
url(r'^/?([a-zA-Z\d/_-]*)/_history/([0-9]*)/$', 'simplewiki.views.history', name='wiki_history'),
url(r'^/?([a-zA-Z\d/_-]*)/_random/$', 'simplewiki.views.random_article', name='wiki_random'),
url(r'^/?([a-zA-Z\d/_-]*)/_search/articles/$', 'simplewiki.views.search_articles', name='wiki_search_articles'),
url(r'^/?([a-zA-Z\d/_-]*)/_search/related/$', 'simplewiki.views.search_add_related', name='search_related'),
url(r'^/?([a-zA-Z\d/_-]*)/_related/add/$', 'simplewiki.views.add_related', name='add_related'),
url(r'^/?([a-zA-Z\d/_-]*)/_related/remove/(\d+)$', 'simplewiki.views.remove_related', name='wiki_remove_relation'),
url(r'^/?([a-zA-Z\d/_-]*)/_add_attachment/$', 'simplewiki.views_attachments.add_attachment', name='add_attachment'),
url(r'^/?([a-zA-Z\d/_-]*)/_view_attachment/(.+)?$', 'simplewiki.views_attachments.view_attachment', name='wiki_view_attachment'),
# url(r'^/?([a-zA-Z\d/_-]*)/_view_attachment/?$', 'simplewiki.views_attachments.list_attachments', name='wiki_list_attachments'),
url(r'^/?([a-zA-Z\d/_-]*)$', 'simplewiki.views.view', name='wiki_view'),
url(r'^(.*)$', 'simplewiki.views.encode_err', name='wiki_encode_err')
)
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404
from django.template import loader, Context
from django.db.models.fields.files import FieldFile
from django.core.servers.basehttp import FileWrapper
from django.contrib.auth.decorators import login_required
from settings import *
from models import Article, ArticleAttachment, get_attachment_filepath
from views import not_found, check_permissions, get_url_path, fetch_from_url
import os
from simplewiki.settings import WIKI_ALLOW_ANON_ATTACHMENTS
def add_attachment(request, wiki_url):
(article, path, err) = fetch_from_url(request, wiki_url)
if err:
return err
perm_err = check_permissions(request, article, check_write=True, check_locked=True)
if perm_err:
return perm_err
if not WIKI_ALLOW_ATTACHMENTS or (not WIKI_ALLOW_ANON_ATTACHMENTS and request.user.is_anonymous()):
return HttpResponseForbidden()
if request.method == 'POST':
if request.FILES.__contains__('attachment'):
attachment = ArticleAttachment()
if not request.user.is_anonymous():
attachment.uploaded_by = request.user
attachment.article = article
file = request.FILES['attachment']
file_rel_path = get_attachment_filepath(attachment, file.name)
chunk_size = request.upload_handlers[0].chunk_size
filefield = FieldFile(attachment, attachment.file, file_rel_path)
attachment.file = filefield
file_path = WIKI_ATTACHMENTS_ROOT + attachment.file.name
if not request.POST.__contains__('overwrite') and os.path.exists(file_path):
c = Context({'overwrite_warning' : True,
'wiki_article': article,
'filename': file.name})
t = loader.get_template('simplewiki_updateprogressbar.html')
return HttpResponse(t.render(c))
if file.size > WIKI_ATTACHMENTS_MAX:
c = Context({'too_big' : True,
'max_size': WIKI_ATTACHMENTS_MAX,
'wiki_article': article,
'file': file})
t = loader.get_template('simplewiki_updateprogressbar.html')
return HttpResponse(t.render(c))
def get_extension(fname):
return attachment.file.name.split('.')[-2]
if WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS and not \
get_extension(attachment.file.name) in WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS:
c = Context({'extension_err' : True,
'extensions': WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS,
'wiki_article': article,
'file': file})
t = loader.get_template('simplewiki_updateprogressbar.html')
return HttpResponse(t.render(c))
# Remove existing attachments
# TODO: Move this until AFTER having removed file.
# Current problem is that Django's FileField delete() method
# automatically deletes files
for a in article.attachments():
if file_rel_path == a.file.name:
a.delete()
def receive_file():
destination = open(file_path, 'wb+')
size = file.size
cnt = 0
c = Context({'started' : True,})
t = loader.get_template('simplewiki_updateprogressbar.html')
yield t.render(c)
for chunk in file.chunks():
cnt += 1
destination.write(chunk)
c = Context({'progress_width' : (cnt*chunk_size) / size,
'wiki_article': article,})
t = loader.get_template('simplewiki_updateprogressbar.html')
yield t.render(c)
c = Context({'finished' : True,
'wiki_article': article,})
t = loader.get_template('simplewiki_updateprogressbar.html')
destination.close()
attachment.save()
yield t.render(c)
return HttpResponse(receive_file())
return HttpResponse('')
# Taken from http://www.djangosnippets.org/snippets/365/
def send_file(request, filepath):
"""
Send a file through Django without loading the whole file into
memory at once. The FileWrapper will turn the file object into an
iterator for chunks of 8KB.
"""
filename = filepath
wrapper = FileWrapper(file(filename))
response = HttpResponse(wrapper, content_type='text/plain')
response['Content-Length'] = os.path.getsize(filename)
return response
def view_attachment(request, wiki_url, file_name):
(article, path, err) = fetch_from_url(request, wiki_url)
if err:
return err
perm_err = check_permissions(request, article, check_read=True)
if perm_err:
return perm_err
attachment = None
for a in article.attachments():
if get_attachment_filepath(a, file_name) == a.file.name:
attachment = a
if attachment:
filepath = WIKI_ATTACHMENTS_ROOT + attachment.file.name
if os.path.exists(filepath):
return send_file(request, filepath)
raise Http404()
####################
# LOGIN PROTECTION #
####################
if WIKI_REQUIRE_LOGIN_VIEW:
view_attachment = login_required(view_attachment)
if WIKI_REQUIRE_LOGIN_EDIT or not WIKI_ALLOW_ANON_ATTACHMENTS:
add_attachment = login_required(add_attachment)
......@@ -6,6 +6,7 @@ import django.contrib.auth.views
# admin.autodiscover()
urlpatterns = patterns('',
(r'^wiki/', include('simplewiki.urls')),
url(r'^courseware/(?P<course>[^/]*)/(?P<chapter>[^/]*)/(?P<section>[^/]*)/$', 'courseware.views.index'),
url(r'^courseware/(?P<course>[^/]*)/(?P<chapter>[^/]*)/$', 'courseware.views.index'),
url(r'^courseware/(?P<course>[^/]*)/$', 'courseware.views.index'),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment