Skip to content

Commit d61fe66

Browse files
committed
Merge branch 'release/6.1.0'
2 parents ae71661 + 892ec67 commit d61fe66

File tree

7 files changed

+74
-22
lines changed

7 files changed

+74
-22
lines changed

HISTORY.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@ History
44
-------
55

66

7+
6.1.0 (2015-06-25)
8+
++++++++++++++++++
9+
10+
* Upgrade to Bootstrap 3.3.5
11+
* Properly quote help text (@joshkel)
12+
13+
14+
6.0.0 (2015-04-21)
15+
++++++++++++++++++
16+
17+
* No more media="screen" in CSS tags, complying to Bootstraps examples
18+
19+
720
5.4.0 (2015-04-21)
821
++++++++++++++++++
922

bootstrap3/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# -*- coding: utf-8 -*-
22

3-
__version__ = '5.4.0'
3+
__version__ = '6.1.0'

bootstrap3/bootstrap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# Default settings
1212
BOOTSTRAP3_DEFAULTS = {
1313
'jquery_url': '//code.jquery.com/jquery.min.js',
14-
'base_url': '//netdna.bootstrapcdn.com/bootstrap/3.3.4/',
14+
'base_url': '//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/',
1515
'css_url': None,
1616
'theme_url': None,
1717
'javascript_url': None,

bootstrap3/renderers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from django.forms.extras import SelectDateWidget
1010
from django.forms.forms import BaseForm, BoundField
1111
from django.forms.formsets import BaseFormSet
12-
from django.utils.html import conditional_escape, strip_tags
12+
from django.utils.html import conditional_escape, escape, strip_tags
1313
from django.template import Context
1414
from django.template.loader import get_template
1515
from django.utils.safestring import mark_safe
@@ -273,7 +273,7 @@ def add_placeholder_attrs(self):
273273
def add_help_attrs(self):
274274
if not isinstance(self.widget, CheckboxInput):
275275
self.widget.attrs['title'] = self.widget.attrs.get(
276-
'title', strip_tags(self.field_help))
276+
'title', escape(strip_tags(self.field_help)))
277277

278278
def add_required_attrs(self):
279279
if self.set_required and is_widget_required_attribute(self.widget):
@@ -306,7 +306,7 @@ def put_inside_label(self, html):
306306
content = '{field} {label}'.format(field=html, label=self.field.label)
307307
return render_label(
308308
content=content, label_for=self.field.id_for_label,
309-
label_title=strip_tags(self.field_help))
309+
label_title=escape(strip_tags(self.field_help)))
310310

311311
def fix_date_select_input(self, html):
312312
div1 = '<div class="col-xs-4">'

bootstrap3/tests.py

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
from .exceptions import BootstrapError
1414
from .utils import add_css_class
1515

16+
try:
17+
from html.parser import HTMLParser
18+
except ImportError:
19+
from HTMLParser import HTMLParser
20+
1621

1722
RADIO_CHOICES = (
1823
('1', 'Radio 1'),
@@ -47,10 +52,15 @@ class TestForm(forms.Form):
4752
)
4853
password = forms.CharField(widget=forms.PasswordInput)
4954
message = forms.CharField(required=False, help_text='<i>my_help_text</i>')
50-
sender = forms.EmailField(label='Sender © unicode')
55+
sender = forms.EmailField(
56+
label='Sender © unicode',
57+
help_text='E.g., "[email protected]"')
5158
secret = forms.CharField(initial=42, widget=forms.HiddenInput)
5259
cc_myself = forms.BooleanField(
53-
required=False, help_text='You will get a copy in your mailbox.')
60+
required=False,
61+
help_text='cc stands for "carbon copy." '
62+
'You will get a copy in your mailbox.'
63+
)
5464
select1 = forms.ChoiceField(choices=RADIO_CHOICES)
5565
select2 = forms.MultipleChoiceField(
5666
choices=RADIO_CHOICES,
@@ -136,21 +146,40 @@ def render_field(field, **context_args):
136146
return render_template('{% bootstrap_field field %}', **context_args)
137147

138148

149+
def get_title_from_html(html):
150+
class GetTitleParser(HTMLParser):
151+
def __init__(self):
152+
HTMLParser.__init__(self)
153+
self.title = None
154+
155+
def handle_starttag(self, tag, attrs):
156+
for attr, value in attrs:
157+
if attr == 'title':
158+
self.title = value
159+
160+
parser = GetTitleParser()
161+
parser.feed(html)
162+
163+
return parser.title
164+
165+
139166
class SettingsTest(TestCase):
140167
def test_settings(self):
141168
from .bootstrap import BOOTSTRAP3
142169
self.assertTrue(BOOTSTRAP3)
143170

171+
def test_bootstrap_javascript_tag(self):
172+
res = render_template('{% bootstrap_javascript %}')
173+
self.assertEqual(res.strip(), '<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>')
174+
175+
def test_bootstrap_css_tag(self):
176+
res = render_template('{% bootstrap_css %}')
177+
self.assertEqual(res.strip(), '<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">')
178+
144179
def test_settings_filter(self):
145-
res = render_template(
146-
'{% load bootstrap3 %}' +
147-
'{{ "required_css_class"|bootstrap_setting }}')
180+
res = render_template('{{ "required_css_class"|bootstrap_setting }}')
148181
self.assertEqual(res.strip(), 'bootstrap3-req')
149-
res = render_template(
150-
'{% load bootstrap3 %}' +
151-
'{% if "javascript_in_head"|bootstrap_setting %}' +
152-
'head{% else %}body{% endif %}'
153-
)
182+
res = render_template('{% if "javascript_in_head"|bootstrap_setting %}head{% else %}body{% endif %}')
154183
self.assertEqual(res.strip(), 'head')
155184

156185
def test_required_class(self):
@@ -263,6 +292,14 @@ def test_show_help(self):
263292
res = render_template('{% bootstrap_field form.subject show_help=0 %}')
264293
self.assertNotIn('my_help_text', res)
265294

295+
def test_help_with_quotes(self):
296+
# Checkboxes get special handling, so test a checkbox and something else
297+
res = render_form_field('sender')
298+
self.assertEqual(get_title_from_html(res), TestForm.base_fields['sender'].help_text)
299+
300+
res = render_form_field('cc_myself')
301+
self.assertEqual(get_title_from_html(res), TestForm.base_fields['cc_myself'].help_text)
302+
266303
def test_subject(self):
267304
res = render_form_field('subject')
268305
self.assertIn('type="text"', res)

bootstrap3/utils.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from django.template import Variable, VariableDoesNotExist
88
from django.template.base import FilterExpression, kwarg_re, TemplateSyntaxError
99

10-
1110
from .text import text_value
1211

1312

@@ -97,14 +96,17 @@ def remove_css_class(css_classes, css_class):
9796
return ' '.join(classes_list)
9897

9998

100-
def render_link_tag(url, rel='stylesheet', media='all'):
99+
def render_link_tag(url, rel='stylesheet', media=None):
101100
"""
102101
Build a link tag
103102
"""
104-
return render_tag(
105-
'link',
106-
attrs={'href': url, 'rel': rel, 'media': media},
107-
close=False)
103+
attrs = {
104+
'href': url,
105+
'rel': rel,
106+
}
107+
if media:
108+
attrs['media'] = media
109+
return render_tag('link', attrs=attrs, close=False)
108110

109111

110112
def render_tag(tag, attrs=None, content=None, close=True):

docs/settings.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ The ``BOOTSTRAP3`` dict variable contains these settings and defaults:
1818
'jquery_url': '//code.jquery.com/jquery.min.js',
1919
2020
# The Bootstrap base URL
21-
'base_url': '//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/',
21+
'base_url': '//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/',
2222
2323
# The complete URL to the Bootstrap CSS file (None means derive it from base_url)
2424
'css_url': None,

0 commit comments

Comments
 (0)