close #99 add markdown

--HG--
rename : djangobb/static/forum/js/board.js => djangobb/static/forum/js/markup/bbcode/board.js
This commit is contained in:
alafin 2010-11-28 17:57:54 +02:00
parent 16c230bbc6
commit f8b072ebb2
13 changed files with 209 additions and 75 deletions

View file

@ -13,6 +13,7 @@ from djangobb_forum.models import Topic, Post, Profile, Reputation, Report, \
Forum, Attachment, TZ_CHOICES, PRIVACY_CHOICES
from djangobb_forum.markups import bbmarkup
from djangobb_forum import settings as forum_settings
from djangobb_forum.util import convert_text_to_html
@ -66,7 +67,7 @@ class AddPostForm(forms.ModelForm):
self.fields['name'].widget = forms.HiddenInput()
self.fields['name'].required = False
self.fields['body'].widget = forms.Textarea(attrs={'class':'bbcode', 'rows':'20', 'cols':'95'})
self.fields['body'].widget = forms.Textarea(attrs={'class':'markup', 'rows':'20', 'cols':'95'})
if not forum_settings.ATTACHMENT_SUPPORT:
self.fields['attachment'].widget = forms.HiddenInput()
@ -90,7 +91,7 @@ class AddPostForm(forms.ModelForm):
topic = self.topic
post = Post(topic=topic, user=self.user, user_ip=self.ip,
markup='bbcode',
markup=self.user.forum_profile.markup,
body=self.cleaned_data['body'])
post.save()
@ -123,7 +124,7 @@ class EditPostForm(forms.ModelForm):
self.topic = kwargs.pop('topic', None)
super(EditPostForm, self).__init__(*args, **kwargs)
self.fields['name'].initial = self.topic
self.fields['body'].widget = forms.Textarea(attrs={'class':'bbcode'})
self.fields['body'].widget = forms.Textarea(attrs={'class':'markup'})
def save(self, commit=True):
post = super(EditPostForm, self).save(commit=False)
@ -210,12 +211,13 @@ class PersonalityProfileForm(forms.ModelForm):
fields = ['show_avatar', 'signature']
def __init__(self, *args, **kwargs):
self.markup = kwargs.pop('markup', None)
super(PersonalityProfileForm, self).__init__(*args, **kwargs)
self.fields['signature'].widget = forms.Textarea(attrs={'class':'bbcode', 'rows':'10', 'cols':'75'})
self.fields['signature'].widget = forms.Textarea(attrs={'class':'markup', 'rows':'10', 'cols':'75'})
def save(self, commit=True):
profile = super(PersonalityProfileForm, self).save(commit=False)
profile.signature = bbmarkup.bbcode(profile.signature)
profile.signature = convert_text_to_html(profile.signature, self.markup)
if commit:
profile.save()
return profile
@ -224,7 +226,7 @@ class PersonalityProfileForm(forms.ModelForm):
class DisplayProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['theme', 'show_smilies']
fields = ['theme', 'markup', 'show_smilies']
class PrivacyProfileForm(forms.ModelForm):
@ -303,7 +305,7 @@ class ReputationForm(forms.ModelForm):
super(ReputationForm, self).__init__(*args, **kwargs)
self.fields['post'].widget = forms.HiddenInput()
self.fields['sign'].widget = forms.HiddenInput()
self.fields['reason'].widget = forms.Textarea(attrs={'class':'bbcode'})
self.fields['reason'].widget = forms.Textarea(attrs={'class':'markup'})
def clean_to_user(self):
name = self.cleaned_data['to_user']

View file

@ -1,7 +1,6 @@
from datetime import datetime
import os
import os.path
from markdown import Markdown
from django.db import models
from django.contrib.auth.models import User, Group
@ -10,9 +9,8 @@ from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils.hashcompat import sha_constructor
from djangobb_forum.markups import bbmarkup
from djangobb_forum.fields import AutoOneToOneField, ExtendedImageField, JSONField
from djangobb_forum.util import urlize, smiles
from djangobb_forum.util import smiles, convert_text_to_html
from djangobb_forum import settings as forum_settings
if 'south' in settings.INSTALLED_APPS:
@ -43,10 +41,12 @@ PRIVACY_CHOICES = (
(2, _(u'Hide your e-mail address and disallow form e-mail.')),
)
MARKUP_CHOICES = (
('bbcode', 'bbcode'),
('markdown', 'markdown'),
)
MARKUP_CHOICES = [('bbcode', 'bbcode')]
try:
import markdown
MARKUP_CHOICES.append(("markdown", "markdown"))
except ImportError:
pass
path = os.path.join(settings.MEDIA_ROOT, 'forum', 'themes')
THEME_CHOICES = [(theme, theme) for theme in os.listdir(path)
@ -192,14 +192,7 @@ class Post(models.Model):
verbose_name_plural = _('Posts')
def save(self, *args, **kwargs):
if self.markup == 'bbcode':
self.body_html = bbmarkup.bbcode(self.body)
elif self.markup == 'markdown' and MARKDOWN_AVAILABLE:
self.body_html = unicode(Markdown(self.body, safe_mode='escape'))
#self.body_html = markdown(self.body, 'safe')
else:
raise Exception('Invalid markup property: %s' % self.markup)
self.body_html = urlize(self.body_html)
self.body_html = convert_text_to_html(self.body, self.markup)
if forum_settings.SMILES_SUPPORT and self.user.forum_profile.show_smilies:
self.body_html = smiles(self.body_html)
super(Post, self).save(*args, **kwargs)

View file

@ -1,3 +1,4 @@
{% load forum_extras %}
{% load i18n %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
@ -7,13 +8,8 @@
<meta name="description" content="{{ forum_settings.FORUM_META_DESCRIPTION }} " />
<meta name="keywords" content="{{ forum_settings.FORUM_META_KEYWORDS }}" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
{% if request.user.is_authenticated %}
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}forum/themes/{{ request.user.forum_profile.theme }}/style.css" />
{% else %}
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}forum/themes/default/style.css" />
{% endif %}
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}forum/js/markitup/skins/markitup/style.css" />
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}forum/js/markitup/sets/bbcode/style.css" />
{% set_theme_style request.user %}
<link rel="alternate" type="application/atom+xml" href="{% url djangobb:forum_posts_feed %}" title="{% trans "Latest posts on forum" %}" />
<link rel="alternate" type="application/atom+xml" href="{% url djangobb:forum_topics_feed %}" title="{% trans "Latest topics on forum" %}" />
@ -23,15 +19,17 @@
var MEDIA_URL = "{{ MEDIA_URL }}";
var POST_PREVIEW_URL = "{% url djangobb:post_preview %}";
</script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="{{ MEDIA_URL }}forum/js/board.js"></script>
<script type="text/javascript" src="{{ MEDIA_URL }}forum/js/markitup/jquery.markitup.pack.js"></script>
<script type="text/javascript" src="{{ MEDIA_URL }}forum/js/markitup/sets/bbcode/set.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
{% if post %}
{% set_markup_editor request.user post.markup %}
{% else %}
{% set_markup_editor request.user %}
{% endif %}
<script type="text/javascript" >
$(document).ready(function() {
$(".bbcode").markItUp(mySettings);
});
$(".markup").markItUp(mySettings);
});
</script>
<!-- Highlightjs goodies -->

View file

@ -20,6 +20,16 @@
</div>
</fieldset>
<br/>
<fieldset>
<legend>{% trans "Markup" %}</legend>
<div class="infldset">
<div class="rbox">
{{ form.markup.errors }}
<label>{{ form.markup }}<br></label>
</div>
</div>
</fieldset>
<br/>
<fieldset>
<legend>{% trans "Post display legend" %}</legend>
<div class="infldset">

View file

@ -274,3 +274,34 @@ def gravatar(email):
return url
else:
return ''
@register.simple_tag
def set_theme_style(user):
theme_style = ''
selected_theme = ''
if user.is_authenticated():
selected_theme = user.forum_profile.theme
theme_style = '<link rel="stylesheet" type="text/css" href="%(media_url)sforum/themes/%(theme)s/style.css" />'
else:
theme_style = '<link rel="stylesheet" type="text/css" href="%(media_url)sforum/themes/default/style.css" />'
return theme_style % dict(
media_url=settings.MEDIA_URL,
theme=selected_theme
)
@register.simple_tag
def set_markup_editor(user, markup=None):
markup_style = ''
if user.is_authenticated():
markup_style = '''
<link rel="stylesheet" type="text/css" href="%(media_url)sforum/js/markitup/skins/markitup/style.css" />
<link rel="stylesheet" type="text/css" href="%(media_url)sforum/js/markitup/sets/%(markup)s/style.css" />
<script type="text/javascript" src="%(media_url)sforum/js/markitup/jquery.markitup.pack.js"></script>
<script type="text/javascript" src="%(media_url)sforum/js/markitup/sets/%(markup)s/set.js"></script>
<script type="text/javascript" src="%(media_url)sforum/js/markup/%(markup)s/board.js"></script>
''' % dict(
media_url=settings.MEDIA_URL,
markup=markup if markup else user.forum_profile.markup
)
return markup_style

View file

@ -3,6 +3,10 @@ import os.path
import random
import re
from HTMLParser import HTMLParser
try:
import markdown
except ImportError:
pass
from django.shortcuts import render_to_response
from django.template import RequestContext
@ -17,7 +21,7 @@ from django.contrib.sites.models import Site
from django.conf import settings
from djangobb_forum import settings as forum_settings
from djangobb_forum.markups import bbmarkup
#compile smiles regexp
_SMILES = [(re.compile(smile_re), path) for smile_re, path in forum_settings.SMILES]
@ -284,3 +288,12 @@ def set_language(request, language):
request.session['django_language'] = language
else:
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language)
def convert_text_to_html(text, markup):
if markup == 'bbcode':
text = bbmarkup.bbcode(text)
elif markup == 'markdown':
text = markdown.markdown(text, safe_mode='escape')
else:
raise Exception('Invalid markup property: %s' % markup)
return urlize(text)

View file

@ -1,6 +1,5 @@
import math
from datetime import datetime, timedelta
from markdown import Markdown
from datetime import datetime, timedelta
from django.shortcuts import get_object_or_404
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseForbidden
@ -24,10 +23,9 @@ from djangobb_forum.forms import AddPostForm, EditPostForm, UserSearchForm,\
PostSearchForm, ReputationForm, MailToForm, EssentialsProfileForm,\
PersonalProfileForm, MessagingProfileForm, PersonalityProfileForm,\
DisplayProfileForm, PrivacyProfileForm, ReportForm, UploadAvatarForm
from djangobb_forum.markups import bbmarkup
from djangobb_forum.templatetags import forum_extras
from djangobb_forum import settings as forum_settings
from djangobb_forum.util import urlize, smiles
from djangobb_forum.util import smiles, convert_text_to_html
from djangobb_forum.templatetags.forum_extras import forum_moderated_by
from haystack.query import SearchQuerySet, SQ
@ -391,10 +389,12 @@ def user(request, username):
if request.user.is_authenticated() and user == request.user or request.user.is_superuser:
if 'section' in request.GET:
section = request.GET['section']
profile_url = reverse('djangobb:forum_profile', args=[user.username]) + '?section=' + section
if section == 'privacy':
form = build_form(PrivacyProfileForm, request, instance=user.forum_profile)
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect(profile_url)
return {'active_menu':'privacy',
'profile': user,
'form': form,
@ -404,15 +404,17 @@ def user(request, username):
form = build_form(DisplayProfileForm, request, instance=user.forum_profile)
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect(profile_url)
return {'active_menu':'display',
'profile': user,
'form': form,
'TEMPLATE': 'forum/profile/profile_display.html'
}
elif section == 'personality':
form = build_form(PersonalityProfileForm, request, instance=user.forum_profile)
form = build_form(PersonalityProfileForm, request, markup=user.forum_profile.markup, instance=user.forum_profile)
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect(profile_url)
return {'active_menu':'personality',
'profile': user,
'form': form,
@ -422,6 +424,7 @@ def user(request, username):
form = build_form(MessagingProfileForm, request, instance=user.forum_profile)
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect(profile_url)
return {'active_menu':'messaging',
'profile': user,
'form': form,
@ -431,6 +434,7 @@ def user(request, username):
form = build_form(PersonalProfileForm, request, instance=user.forum_profile, user=user)
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect(profile_url)
return {'active_menu':'personal',
'profile': user,
'form': form,
@ -442,7 +446,7 @@ def user(request, username):
if request.method == 'POST' and form.is_valid():
profile = form.save()
set_language(request, profile.language)
return HttpResponseRedirect(reverse('djangobb:forum_profile', args=[user.username]))
return HttpResponseRedirect(profile_url)
return {'active_menu':'essentials',
'profile': user,
@ -754,17 +758,10 @@ def show_attachment(request, hash):
@render_to('forum/post_preview.html')
def post_preview(request):
'''Preview for markitup'''
markup = request.user.forum_profile.markup
data = request.POST.get('data', '')
if markup == 'bbcode':
data = bbmarkup.bbcode(data)
elif markup == 'markdown' and MARKDOWN_AVAILABLE:
data = unicode(Markdown(data, safe_mode='escape'))
else:
raise Exception('Invalid markup property: %s' % markup)
data = urlize(data)
data = convert_text_to_html(data, markup)
if forum_settings.SMILES_SUPPORT:
data = smiles(data)
return {'data': data}

View file

@ -11,31 +11,38 @@
// Feel free to add more tags
// -------------------------------------------------------------------
mySettings = {
previewParserPath: '',
previewParserPath: POST_PREVIEW_URL, // path to your Markdown parser
onShiftEnter: {keepDefault:false, openWith:'\n\n'},
markupSet: [
{name:'First Level Heading', key:'1', placeHolder:'Your title here...', closeWith:function(markItUp) { return miu.markdownTitle(markItUp, '=') } },
{name:'Second Level Heading', key:'2', placeHolder:'Your title here...', closeWith:function(markItUp) { return miu.markdownTitle(markItUp, '-') } },
{name:'Heading 3', key:'3', openWith:'### ', placeHolder:'Your title here...' },
{name:'Heading 4', key:'4', openWith:'#### ', placeHolder:'Your title here...' },
{name:'Heading 5', key:'5', openWith:'##### ', placeHolder:'Your title here...' },
{name:'Heading 6', key:'6', openWith:'###### ', placeHolder:'Your title here...' },
{separator:'---------------' },
markupSet: [
{name:'Bold', key:'B', openWith:'**', closeWith:'**'},
{name:'Italic', key:'I', openWith:'_', closeWith:'_'},
{separator:'---------------' },
{name:'Picture', key:'P', replaceWith:'![[![Alternative text]!]]([![Url:!:http://]!] "[![Title]!]")'},
{name:'Link', key:'L', openWith:'[', closeWith:']([![Url:!:http://]!] "[![Title]!]")', placeHolder:'Your text to link here...' },
{separator:'---------------' },
{name:'Bulleted List', openWith:'- ' },
{name:'Numeric List', openWith:function(markItUp) {
return markItUp.line+'. ';
}},
{separator:'---------------' },
{name:'Picture', key:'P', replaceWith:'![[![Alternative text]!]]([![Url:!:http://]!] "[![Title]!]")'},
{name:'Link', key:'L', openWith:'[', closeWith:']([![Url:!:http://]!] "[![Title]!]")', placeHolder:'Your text to link here...' },
{separator:'---------------'},
{name:'Quotes', openWith:'> '},
{name:'Code Block / Code', openWith:'(!(\t|!|`)!)', closeWith:'(!(`)!)'},
{name:'Smiles', openWith:'', closeWith:'', dropMenu:[
{name:'Smile', openWith:':)'},
{name:'Neutral', openWith:':|'},
{name:'Sad', openWith:':('},
{name:'Big smile', openWith:':D'},
{name:'Yikes', openWith:':o'},
{name:'Wink', openWith:';)'},
{name:'Hmm', openWith:':/'},
{name:'Tongue', openWith:':P'},
{name:'Lol', openWith:':lol:'},
{name:'Mad', openWith:':mad:'},
{name:'Roll', openWith:':rolleyes:'},
{name:'Cool', openWith:':cool:'},
]},
{separator:'---------------'},
{name:'Preview', call:'preview', className:"preview"}
{name:'Preview', className:"preview", call:'preview' }
]
}

View file

@ -3,38 +3,76 @@
// By Jay Salvat - http://markitup.jaysalvat.com/
// ------------------------------------------------------------------*/
.markItUp .markItUpButton1 a {
background-image:url(images/h1.png);
background-image:url(images/bold.png);
}
.markItUp .markItUpButton2 a {
background-image:url(images/h2.png);
background-image:url(images/italic.png);
}
.markItUp .markItUpButton3 a {
background-image:url(images/h3.png);
background-image:url(images/picture.png);
}
.markItUp .markItUpButton4 a {
background-image:url(images/h4.png);
background-image:url(images/link.png);
}
.markItUp .markItUpButton5 a {
background-image:url(images/h5.png);
background-image:url(images/list-bullet.png);
}
.markItUp .markItUpButton6 a {
background-image:url(images/h6.png);
background-image:url(images/list-numeric.png);
}
.markItUp .markItUpButton7 a {
background-image:url(images/bold.png);
background-image:url(images/quotes.png);
}
.markItUp .markItUpButton8 a {
background-image:url(images/italic.png);
background-image:url(images/code.png);
}
.markItUp .markItUpButton9 a {
background-image:url(images/list-bullet.png);
.markItUp .markItUpButton9 a {
background-image:url(../../../../img/smilies/smile.png);
}
.markItUp .markItUpButton9-1 a {
background-image:url(../../../../img/smilies/smile.png);
}
.markItUp .markItUpButton9-2 a {
background-image:url(../../../../img/smilies/neutral.png);
}
.markItUp .markItUpButton9-3 a {
background-image:url(../../../../img/smilies/sad.png);
}
.markItUp .markItUpButton9-4 a {
background-image:url(../../../../img/smilies/big_smile.png);
}
.markItUp .markItUpButton9-5 a {
background-image:url(../../../../img/smilies/yikes.png);
}
.markItUp .markItUpButton9-6 a {
background-image:url(../../../../img/smilies/wink.png);
}
.markItUp .markItUpButton9-7 a {
background-image:url(../../../../img/smilies/hmm.png);
}
.markItUp .markItUpButton9-8 a {
background-image:url(../../../../img/smilies/tongue.png);
}
.markItUp .markItUpButton9-9 a {
background-image:url(../../../../img/smilies/lol.png);
}
.markItUp .markItUpButton9-10 a {
background-image:url(../../../../img/smilies/mad.png);
}
.markItUp .markItUpButton9-11 a {
background-image:url(../../../../img/smilies/roll.png);
}
.markItUp .markItUpButton9-12 a {
background-image:url(../../../../img/smilies/cool.png);
}
.markItUp .markItUpButton10 a {
background-image:url(images/list-numeric.png);
background-image:url(images/preview.png);
}
.markItUp .markItUpButton11 a {
background-image:url(images/picture.png);
}

View file

@ -0,0 +1,45 @@
var txt = ''
function copyQ(nick) {
txt = ''
if (document.getSelection) {
txt = document.getSelection()
} else
if (document.selection) {
txt = document.selection.createRange().text;
}
txt = '>' + nick + ':' + txt + '\n\n'
}
function insertAtCaret (textObj, textFieldValue) {
if (document.all) {
if (textObj.createTextRange && textObj.caretPos && !window.opera) {
var caretPos = textObj.caretPos;
caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ?textFieldValue + ' ' : textFieldValue;
} else {
textObj.value += textFieldValue;
}
} else {
if (textObj.selectionStart) {
var rangeStart = textObj.selectionStart;
var rangeEnd = textObj.selectionEnd;
var tempStr1 = textObj.value.substring(0, rangeStart);
var tempStr2 = textObj.value.substring(rangeEnd, textObj.value.length);
textObj.value = tempStr1 + textFieldValue + tempStr2;
textObj.selectionStart = textObj.selectionEnd = rangeStart + textFieldValue.length;
} else {
textObj.value += textFieldValue;
}
}
}
function pasteQ() {
if (txt!='' && document.forms['post']['body'])
insertAtCaret(document.forms['post']['body'], txt);
}
function pasteN(text) {
if (text != '' && document.forms['post']['body'])
insertAtCaret(document.forms['post']['body'], "**" + text + "**\n");
}

View file

@ -1,3 +1,4 @@
Markdown==2.0
django-messages==0.4.4
whoosh
south>=0.7.2

View file

@ -1,6 +1,5 @@
Django>=1.2
PIL>=1.1.7
Markdown==2.0
django-registration==0.7
django-haystack>=1.1.0
-e hg+http://bitbucket.org/benoitc/django-authopenid#egg=django-authopenid