def test_markdownify_error(self, ): # This tests that real errors don't raise VersionNotCompatible # errors, which could be misleading. try: markdownify(None) except Exception as e: self.assertNotIsInstance(e, VersionNotCompatible) else: self.fail("no assertion raised")
def html(self): """ Return the html version of the markdown. Wraps it as a SafeString so it will display without being escaped. This should probably be done and cached somewhere and let this method do a lookup for the cached version. An alternative would be to double the storage in the DB but that could mean having to update the whole DB if we fix something about martor. Storing this in a memcached instance would probably be better """ # TODO: Store the results in memcached for speed return SafeString(markdownify(self.text))
def get_markdown(self): """ return a cleaned html. in case there is a markdown we use markdown package to convert them to html. Returns: str: string of safe html """ content = self.content markdown_content = markdownify(content) return mark_safe(markdown_content)
def safe_markdown(field_name): """ Safe the markdown text as html ouput. Usage: {% load martortags %} {{ field_name|safe_markdown }} Example: {{ post.description|safe_markdown }} """ return mark_safe(insert_ui_elems(markdownify(field_name)))
def get_img_count(self): """ count img tags in html. using BeautifulSoup4 search through html. Returns: int: length of the images after filtering through using BeautifulSoup4 """ content = self.content markdown_content = markdownify(content) img_tags = BeautifulSoup(markdown_content, features="html.parser").find_all("img") return len(img_tags)
def save(self, *args, **kwargs): # Parse markdown and cache it. self.formatted_image_credit = markdownify(self.image_credit) self.formatted_content = markdownify(self.content) self.unformatted_content = strip_tags(self.formatted_content) # Must save before attempting to access a ManyToManyField (tags) super().save(*args, **kwargs) # Only set the related articles if they haven't already been specified. if not self.related_1 or not self.related_2: # Check if the smallest tag has at least two other articles. tags = [] for tag in self.tags.all(): articles = tag.articles.exclude(pk=self.pk).exclude( published=False) if articles.count() >= 2: tags.append((articles, articles.count())) tags.sort(key=operator.itemgetter(1)) if tags: # Find two articles in this tag that are older, or just the oldest. articles = tags[0][0] older_articles = articles.order_by('-date').exclude( date__gt=self.date) if older_articles.count() < 2: related_articles = articles.order_by('date') else: related_articles = older_articles else: related_articles = Article.objects.exclude(pk=self.pk).exclude( published=False) if not self.related_1: self.related_1 = related_articles[0] if not self.related_2: self.related_2 = related_articles[1] super().save(*args, **kwargs)
def save(self, *args, **kwargs): ''' On save, update timestamps ''' if not self.id: self.created_at = timezone.now() self.last_modified = timezone.now() # These are in separate fields intentionally. # `content` is the raw content of the post and what is used in the admin's preview. # `html_content` is what is used on the frontend. This keeps the frontend and backend Markdown flavors in sync. # This is great since the django-markdown-editor supports lots of markdown plugins and react-markdown does not. self.html_content = markdownify(self.content) return super(Tweet, self).save(*args, **kwargs)
def get_text_count(self): """ count strings in html. using BeautifulSoup4 to sanitize html tags. Returns: int: length of the string after sanitized by BeautifulSoup4 """ content = self.content markdown_content = markdownify(content) souped = BeautifulSoup(markdown_content, features="html.parser").findAll(text=True) stripted_text = "".join(souped).replace(" ", "") return len(stripted_text)
def bio_html(self): """ Return the markdownified biography of this author """ return SafeString(markdownify(self.bio_text))
def save_idea(request, form, template_name, new=False): if request.method == "POST": if form.is_valid(): idea = form.save(commit=False) if GOOGLE_RECAPTCHA_URL: ''' Begin reCAPTCHA validation ''' recaptcha_response = request.POST.get('g-recaptcha-response') url = GOOGLE_RECAPTCHA_URL values = { 'secret': GOOGLE_RECAPTCHA_SECRET_KEY, 'response': recaptcha_response } data = urllib.parse.urlencode(values).encode() req = urllib.request.Request(url, data=data) response = urllib.request.urlopen(req) result = json.loads(response.read().decode()) ''' End reCAPTCHA validation ''' if not result['success']: messages.error(request, _('Invalid reCAPTCHA. Please try again.')) return render(request, template_name, {'form': form}) if new: idea_autor = UserProfile.objects.get(user=request.user) idea.author = idea_autor idea.creation_date = timezone.now() idea.phase = Phase.GROW.id if (idea.challenge): idea.category = idea.challenge.category category_image = Category_Image.get_random_image( idea.challenge.category) else: category_image = Category_Image.get_random_image( idea.category) if category_image: idea.category_image = category_image.image.url idea.save() idea.authors.add(idea.author) phase_history = Phase_History(current_phase=Phase.GROW.id, previous_phase=0, date_change=timezone.now(), idea=idea, author=idea.author, current=True) phase_history.save() else: idea.save() idea.authors.clear() idea.authors.add( UserProfile.objects.get(user__email=request.user.email)) if form.cleaned_data['authors']: for author in form.cleaned_data['authors']: idea.authors.add(author) notify.send( request.user, icon_class="fas fa-plus", recipient=author.user, description=_("You're a co-author of a new idea!"), target=idea, verb='author') messages.success(request, _('Idea saved successfully!')) audit(request.user.username, get_client_ip(request), 'SAVE_IDEA_OPERATION', Idea.__name__, str(idea.id)) mark = markdownify(idea.summary + idea.target + idea.oportunity + idea.solution) string = BeautifulSoup(mark, 'html.parser') usernames = list( set(username.text[1::] for username in string.findAll( 'a', {'class': 'direct-mention-link'}))) for username in usernames: user = UserProfile.objects.get(user__username=username) notify.send( request.user, icon_class="fas fa-at", recipient=user.user, description=_("You have been mentioned in an idea!"), target=idea, verb='mention') return redirect('idea_list') return render(request, template_name, {'form': form})
def save(self, *args, **kwargs): # Parse markdown and cache it. self.formatted_image_credit = markdownify(self.image_credit) self.formatted_content = markdownify(self.content) super().save(*args, **kwargs)
def save(self, *args, **kwargs): # Parse markdown and cache it. self.formatted_bio = markdownify(self.bio) super().save(*args, **kwargs)
def save(self, *args, **kwargs): # Parse markdown and cache it. self.formatted_content = markdownify(self.content) self.unformatted_content = strip_tags(self.formatted_content) super().save(*args, **kwargs)
def test_markdownify_xss_handled(self): xss_payload = "[aaaa](javascript:alert(1))" response = markdownify(xss_payload) self.assertEqual(response, '<p><a href="alert(1)">aaaa</a></p>')