diff --git a/.gitignore b/.gitignore index fa4c045..be13b13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ -*.pyc +build +docs/_build dpaste/settings/local.py dpaste.egg-info -docs/_build dpaste.db +node_modules diff --git a/dpaste/forms.py b/dpaste/forms.py index c64c520..8585002 100644 --- a/dpaste/forms.py +++ b/dpaste/forms.py @@ -106,7 +106,7 @@ class SnippetForm(forms.ModelForm): return self.cleaned_data def save(self, parent=None, *args, **kwargs): - MAX_SNIPPETS_PER_USER = getattr(settings, 'DPASTE_MAX_SNIPPETS_PER_USER', 10) + MAX_SNIPPETS_PER_USER = getattr(settings, 'DPASTE_MAX_SNIPPETS_PER_USER', 100) # Set parent snippet self.instance.parent = parent diff --git a/dpaste/highlight.py b/dpaste/highlight.py index ef55953..59ba8f8 100644 --- a/dpaste/highlight.py +++ b/dpaste/highlight.py @@ -33,15 +33,15 @@ from pygments.util import ClassNotFound logger = getLogger(__file__) -PLAIN_TEXT = '_text_plain' # lexer name whats rendered as text (paragraphs) +PLAIN_TEXT = '_text' # lexer name whats rendered as text (paragraphs) PLAIN_CODE = '_code' # lexer name of code with no hihglighting LEXER_LIST = getattr(settings, 'DPASTE_LEXER_LIST', ( (_('Text'), ( - ('text', 'Plain Text'), - # ('_text_markdown', 'Markdown'), - # ('_text_rst', 'reStructuredText'), - # ('_text_textile', 'Textile'), + (PLAIN_TEXT, 'Plain Text'), + # ('_markdown', 'Markdown'), + # ('_rst', 'reStructuredText'), + # ('_textile', 'Textile'), )), (_('Code'), ( (PLAIN_CODE, 'Plain Code'), @@ -129,7 +129,7 @@ LEXER_DEFAULT = getattr(settings, 'DPASTE_LEXER_DEFAULT', 'python') # Lexers which have wordwrap enabled by default LEXER_WORDWRAP = getattr(settings, 'DPASTE_LEXER_WORDWRAP', - ('text', 'rst') + ('_text', 'rst') ) @@ -150,7 +150,7 @@ def pygmentize(code_string, lexer_name=LEXER_DEFAULT): # Plain code is not highlighted, but we wrap with with regular # Pygments syntax to keep the frontend aligned. if lexer_name == PLAIN_CODE: - return '\n'.join(['{}'.format(escape(l)) + return '\n'.join(['{}'.format(escape(l)) for l in code_string.splitlines()]) # Everything else is handled by Pygments. diff --git a/dpaste/migrations/0005_remove_snippet_highlighted.py b/dpaste/migrations/0005_remove_snippet_highlighted.py new file mode 100644 index 0000000..901819f --- /dev/null +++ b/dpaste/migrations/0005_remove_snippet_highlighted.py @@ -0,0 +1,17 @@ +# Generated by Django 2.0.3 on 2018-03-14 11:03 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('dpaste', '0004_auto_20180107_1603'), + ] + + operations = [ + migrations.RemoveField( + model_name='snippet', + name='highlighted', + ), + ] diff --git a/dpaste/models.py b/dpaste/models.py index 4a54151..0f01bd0 100644 --- a/dpaste/models.py +++ b/dpaste/models.py @@ -3,13 +3,13 @@ from __future__ import unicode_literals from random import SystemRandom from django.conf import settings -from django.urls import reverse from django.db import models -from django.utils.functional import cached_property +from django.urls import reverse from django.utils.translation import ugettext_lazy as _ +from pygments import highlight from six import python_2_unicode_compatible -from .highlight import LEXER_DEFAULT +from dpaste import highlight R = SystemRandom() ONETIME_LIMIT = getattr(settings, 'DPASTE_ONETIME_LIMIT', 2) @@ -43,18 +43,22 @@ class Snippet(models.Model): (EXPIRE_ONETIME, _(u'One-Time snippet')), ) - secret_id = models.CharField(_(u'Secret ID'), max_length=255, blank=True, null=True, - unique=True) + secret_id = models.CharField( + _(u'Secret ID'), max_length=255, blank=True, null=True, unique=True) content = models.TextField(_(u'Content')) - highlighted = models.TextField(_(u'Highlighted Content')) - lexer = models.CharField(_(u'Lexer'), max_length=30, default=LEXER_DEFAULT) - published = models.DateTimeField(_(u'Published'), auto_now_add=True) - expire_type = models.PositiveSmallIntegerField(_(u'Expire Type'), - choices=EXPIRE_CHOICES, default=EXPIRE_CHOICES[0][0]) - expires = models.DateTimeField(_(u'Expires'), blank=True, null=True) - view_count = models.PositiveIntegerField(_('View count'), default=0) - parent = models.ForeignKey('self', null=True, blank=True, - related_name='children', on_delete=models.CASCADE) + lexer = models.CharField( + _(u'Lexer'), max_length=30, default=highlight.LEXER_DEFAULT) + published = models.DateTimeField( + _(u'Published'), auto_now_add=True) + expire_type = models.PositiveSmallIntegerField( + _(u'Expire Type'), choices=EXPIRE_CHOICES, default=EXPIRE_CHOICES[0][0]) + expires = models.DateTimeField( + _(u'Expires'), blank=True, null=True) + view_count = models.PositiveIntegerField( + _('View count'), default=0) + parent = models.ForeignKey( + 'self', null=True, blank=True, verbose_name=_('Parent Snippet'), + related_name='children', on_delete=models.CASCADE) class Meta: ordering = ('-published',) @@ -62,7 +66,6 @@ class Snippet(models.Model): def __str__(self): return self.secret_id - return None def save(self, *args, **kwargs): if not self.secret_id: @@ -72,12 +75,25 @@ class Snippet(models.Model): def get_absolute_url(self): return reverse('snippet_details', kwargs={'snippet_id': self.secret_id}) + def highlight(self): + return highlight.pygmentize(self.content, self.lexer) + + def highlight_lines(self): + return self.highlight().splitlines() + + @property + def lexer_name(self): + """Display name for this lexer.""" + try: + return dict( + highlight.LEXER_LIST[0][1] + + highlight.LEXER_LIST[1][1] + )[self.lexer] + except KeyError: + return _('(Deprecated Lexer)') + @property def remaining_views(self): if self.expire_type == self.EXPIRE_ONETIME: remaining = ONETIME_LIMIT - self.view_count return remaining > 0 and remaining or 0 - - @cached_property - def excerpt(self): - return self.content.replace('\n', '')[:200] diff --git a/dpaste/settings/base.py b/dpaste/settings/base.py index d68157f..c6082b9 100644 --- a/dpaste/settings/base.py +++ b/dpaste/settings/base.py @@ -52,10 +52,10 @@ USE_L10N = False LANGUAGE_CODE = 'en' LANGUAGES = ( ('en', 'English'), - ('de', 'German'), - ('es', 'Spanish'), - ('pt-br', 'Portugese (Brasil)'), - ('fr', 'French'), + # ('de', 'German'), + # ('es', 'Spanish'), + # ('pt-br', 'Portugese (Brasil)'), + # ('fr', 'French'), ) LOCALE_PATHS = ( @@ -66,6 +66,17 @@ LOCALE_PATHS = ( # Project URLS and media settings #============================================================================== +STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage' + +STATICFILES_DIRS = ( + os.path.join(PROJECT_DIR, 'build'), +) + +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +) + STATIC_ROOT = os.path.join(VAR_ROOT, 'static') STATIC_URL = '/static/' @@ -77,8 +88,6 @@ LOGIN_URL = '/accounts/login/' LOGOUT_URL = '/accounts/logout/' LOGIN_REDIRECT_URL = '/' -STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage' - #============================================================================== # Templates #==============================================================================