mirror of
https://github.com/DarrenOfficial/dpaste.git
synced 2024-11-15 08:02:54 +11:00
Right-To-Left Support
This commit is contained in:
parent
3bfb153b74
commit
0f5fbd28f4
10 changed files with 99 additions and 17 deletions
|
@ -46,6 +46,26 @@ if (wordwrapCheckbox && snippetDiv) {
|
||||||
wordwrapCheckbox.onchange = toggleWordwrap;
|
wordwrapCheckbox.onchange = toggleWordwrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Right-To-Left
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const rtlCheckbox = document.getElementById('id_rtl');
|
||||||
|
const snippetArea = document.getElementById('id_content');
|
||||||
|
|
||||||
|
function toggleRTL() {
|
||||||
|
if (rtlCheckbox.checked) {
|
||||||
|
snippetArea.dir = 'rtl';
|
||||||
|
} else {
|
||||||
|
snippetArea.dir = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rtlCheckbox && snippetArea) {
|
||||||
|
toggleRTL();
|
||||||
|
rtlCheckbox.onchange = toggleRTL;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Line Highlighting
|
// Line Highlighting
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -8,7 +8,14 @@
|
||||||
.snippet-form {
|
.snippet-form {
|
||||||
background-color: $bgColor;
|
background-color: $bgColor;
|
||||||
|
|
||||||
label { display: none; }
|
label {
|
||||||
|
display: none;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options-rtl label {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
|
|
|
@ -20,24 +20,37 @@ def get_expire_values(expires):
|
||||||
else:
|
else:
|
||||||
expire_type = Snippet.EXPIRE_TIME
|
expire_type = Snippet.EXPIRE_TIME
|
||||||
expires = expires and expires or config.EXPIRE_DEFAULT
|
expires = expires and expires or config.EXPIRE_DEFAULT
|
||||||
expires = datetime.datetime.now() + datetime.timedelta(seconds=int(expires))
|
expires = datetime.datetime.now() + datetime.timedelta(
|
||||||
|
seconds=int(expires)
|
||||||
|
)
|
||||||
return expires, expire_type
|
return expires, expire_type
|
||||||
|
|
||||||
|
|
||||||
class SnippetForm(forms.ModelForm):
|
class SnippetForm(forms.ModelForm):
|
||||||
content = forms.CharField(
|
content = forms.CharField(
|
||||||
label=_('Content'),
|
label=_('Content'),
|
||||||
widget=forms.Textarea(attrs={'placeholder': _('Awesome code goes here...')}),
|
widget=forms.Textarea(
|
||||||
|
attrs={'placeholder': _('Awesome code goes here...')}
|
||||||
|
),
|
||||||
max_length=config.MAX_CONTENT_LENGTH,
|
max_length=config.MAX_CONTENT_LENGTH,
|
||||||
strip=False,
|
strip=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
lexer = forms.ChoiceField(
|
lexer = forms.ChoiceField(
|
||||||
label=_('Lexer'), initial=LEXER_DEFAULT, choices=LEXER_CHOICES
|
label=_('Lexer'),
|
||||||
|
initial=LEXER_DEFAULT,
|
||||||
|
choices=LEXER_CHOICES
|
||||||
)
|
)
|
||||||
|
|
||||||
expires = forms.ChoiceField(
|
expires = forms.ChoiceField(
|
||||||
label=_('Expires'), choices=config.EXPIRE_CHOICES, initial=config.EXPIRE_DEFAULT
|
label=_('Expires'),
|
||||||
|
choices=config.EXPIRE_CHOICES,
|
||||||
|
initial=config.EXPIRE_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
rtl = forms.BooleanField(
|
||||||
|
label=_('Right to Left'),
|
||||||
|
required=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Honeypot field
|
# Honeypot field
|
||||||
|
@ -49,7 +62,7 @@ class SnippetForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Snippet
|
model = Snippet
|
||||||
fields = ('content', 'lexer')
|
fields = ('content', 'lexer', 'rtl')
|
||||||
|
|
||||||
def __init__(self, request, *args, **kwargs):
|
def __init__(self, request, *args, **kwargs):
|
||||||
super(SnippetForm, self).__init__(*args, **kwargs)
|
super(SnippetForm, self).__init__(*args, **kwargs)
|
||||||
|
|
|
@ -34,13 +34,14 @@ class Highlighter(object):
|
||||||
return l[1]
|
return l[1]
|
||||||
return fallback
|
return fallback
|
||||||
|
|
||||||
def render(self, code_string, lexer_name, **kwargs):
|
def render(self, code_string, lexer_name, direction=None, **kwargs):
|
||||||
highlighted_string = self.highlight(code_string, lexer_name=lexer_name)
|
highlighted_string = self.highlight(code_string, lexer_name=lexer_name)
|
||||||
context = {
|
context = {
|
||||||
'highlighted': highlighted_string,
|
'highlighted': highlighted_string,
|
||||||
'highlighted_splitted': highlighted_string.splitlines(),
|
'highlighted_splitted': highlighted_string.splitlines(),
|
||||||
'lexer_name': lexer_name,
|
'lexer_name': lexer_name,
|
||||||
'lexer_display_name': self.get_lexer_display_name(lexer_name),
|
'lexer_display_name': self.get_lexer_display_name(lexer_name),
|
||||||
|
'direction': direction,
|
||||||
}
|
}
|
||||||
context.update(kwargs)
|
context.update(kwargs)
|
||||||
return render_to_string(self.template_name, context)
|
return render_to_string(self.template_name, context)
|
||||||
|
@ -76,7 +77,9 @@ class MarkdownHighlighter(PlainTextHighlighter):
|
||||||
|
|
||||||
return mark_safe(
|
return mark_safe(
|
||||||
misaka.html(
|
misaka.html(
|
||||||
code_string, extensions=self.extensions, render_flags=self.render_flags
|
code_string,
|
||||||
|
extensions=self.extensions,
|
||||||
|
render_flags=self.render_flags
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
18
dpaste/migrations/0007_snippet_rtl.py
Normal file
18
dpaste/migrations/0007_snippet_rtl.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 2.1.1 on 2018-12-19 13:39
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('dpaste', '0006_auto_20180622_1051'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='snippet',
|
||||||
|
name='rtl',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='Right-to-left'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -22,7 +22,10 @@ def generate_secret_id(length):
|
||||||
)
|
)
|
||||||
|
|
||||||
secret_id = ''.join(
|
secret_id = ''.join(
|
||||||
[R.choice(config.SLUG_CHOICES) for i in range(length or config.SLUG_LENGTH)]
|
[
|
||||||
|
R.choice(config.SLUG_CHOICES)
|
||||||
|
for i in range(length or config.SLUG_LENGTH)
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if this slug already exists, if not, return this new slug
|
# Check if this slug already exists, if not, return this new slug
|
||||||
|
@ -51,13 +54,16 @@ class Snippet(models.Model):
|
||||||
_('Secret ID'), max_length=255, blank=True, null=True, unique=True
|
_('Secret ID'), max_length=255, blank=True, null=True, unique=True
|
||||||
)
|
)
|
||||||
content = models.TextField(_('Content'))
|
content = models.TextField(_('Content'))
|
||||||
lexer = models.CharField(_('Lexer'), max_length=30, default=highlight.LEXER_DEFAULT)
|
lexer = models.CharField(
|
||||||
|
_('Lexer'), max_length=30, default=highlight.LEXER_DEFAULT
|
||||||
|
)
|
||||||
published = models.DateTimeField(_('Published'), auto_now_add=True)
|
published = models.DateTimeField(_('Published'), auto_now_add=True)
|
||||||
expire_type = models.PositiveSmallIntegerField(
|
expire_type = models.PositiveSmallIntegerField(
|
||||||
_('Expire Type'), choices=EXPIRE_CHOICES, default=EXPIRE_CHOICES[0][0]
|
_('Expire Type'), choices=EXPIRE_CHOICES, default=EXPIRE_CHOICES[0][0]
|
||||||
)
|
)
|
||||||
expires = models.DateTimeField(_('Expires'), blank=True, null=True)
|
expires = models.DateTimeField(_('Expires'), blank=True, null=True)
|
||||||
view_count = models.PositiveIntegerField(_('View count'), default=0)
|
view_count = models.PositiveIntegerField(_('View count'), default=0)
|
||||||
|
rtl = models.BooleanField(_('Right-to-left'), default=False)
|
||||||
parent = models.ForeignKey(
|
parent = models.ForeignKey(
|
||||||
'self',
|
'self',
|
||||||
null=True,
|
null=True,
|
||||||
|
@ -80,11 +86,17 @@ class Snippet(models.Model):
|
||||||
super(Snippet, self).save(*args, **kwargs)
|
super(Snippet, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('snippet_details', kwargs={'snippet_id': self.secret_id})
|
return reverse(
|
||||||
|
'snippet_details', kwargs={'snippet_id': self.secret_id}
|
||||||
|
)
|
||||||
|
|
||||||
def highlight(self):
|
def highlight(self):
|
||||||
HighlighterClass = highlight.get_highlighter_class(self.lexer)
|
HighlighterClass = highlight.get_highlighter_class(self.lexer)
|
||||||
return HighlighterClass().render(self.content, self.lexer)
|
return HighlighterClass().render(
|
||||||
|
code_string=self.content,
|
||||||
|
lexer_name=self.lexer,
|
||||||
|
direction='rtl' if self.rtl else 'ltr',
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lexer_name(self):
|
def lexer_name(self):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="snippet-text">
|
<div class="snippet-text">
|
||||||
<article>
|
<article dir="{{ direction }}">
|
||||||
<div>{{ highlighted }}</div>
|
<div>{{ highlighted }}</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
|
@ -18,6 +18,14 @@
|
||||||
{{ form.expires }}
|
{{ form.expires }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p class="options-rtl">
|
||||||
|
{{ form.rtl }}
|
||||||
|
<label for="{{ form.rtl.auto_id }}">
|
||||||
|
{% trans "Right-to-Left" %}
|
||||||
|
<small>[beta]</small>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p class="action">
|
<p class="action">
|
||||||
<button class="btn" type="submit">
|
<button class="btn" type="submit">
|
||||||
{% trans "Paste Snippet" %}
|
{% trans "Paste Snippet" %}
|
||||||
|
|
|
@ -39,7 +39,6 @@ class SnippetView(FormView):
|
||||||
"""
|
"""
|
||||||
Create a new snippet.
|
Create a new snippet.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
form_class = SnippetForm
|
form_class = SnippetForm
|
||||||
template_name = 'dpaste/new.html'
|
template_name = 'dpaste/new.html'
|
||||||
|
|
||||||
|
@ -100,7 +99,11 @@ class SnippetDetailView(SnippetView, DetailView):
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
snippet = self.get_object()
|
snippet = self.get_object()
|
||||||
return {'content': snippet.content, 'lexer': snippet.lexer}
|
return {
|
||||||
|
'content': snippet.content,
|
||||||
|
'lexer': snippet.lexer,
|
||||||
|
'rtl': snippet.rtl,
|
||||||
|
}
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
snippet = form.save(parent=self.get_object())
|
snippet = form.save(parent=self.get_object())
|
||||||
|
|
|
@ -7,11 +7,9 @@
|
||||||
"postinstall": "npm run build",
|
"postinstall": "npm run build",
|
||||||
"start": "npm run build && pipenv run ./manage.py runserver",
|
"start": "npm run build && pipenv run ./manage.py runserver",
|
||||||
"docs": "pipenv run sphinx-build -c docs docs docs/_build/html",
|
"docs": "pipenv run sphinx-build -c docs docs docs/_build/html",
|
||||||
|
|
||||||
"build-css": "node-sass --output-style compressed -o build client/scss/dpaste.scss ",
|
"build-css": "node-sass --output-style compressed -o build client/scss/dpaste.scss ",
|
||||||
"build-js": "uglifyjs --compress=\"drop_console=true,ecma=6\" --mangle=\"toplevel\" --output=build/dpaste.js client/js/dpaste.js",
|
"build-js": "uglifyjs --compress=\"drop_console=true,ecma=6\" --mangle=\"toplevel\" --output=build/dpaste.js client/js/dpaste.js",
|
||||||
"build": "npm run build-css && npm run build-js",
|
"build": "npm run build-css && npm run build-js",
|
||||||
|
|
||||||
"watch-css": "npm run build && node-sass --source-map true -o build/ --watch client/scss/dpaste.scss",
|
"watch-css": "npm run build && node-sass --source-map true -o build/ --watch client/scss/dpaste.scss",
|
||||||
"watch-docs": "pipenv run sphinx-autobuild -c docs docs docs/_build/html"
|
"watch-docs": "pipenv run sphinx-autobuild -c docs docs docs/_build/html"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue