Add markdown utils
- External links open in a new tab - Clicking on image open an image modal
This commit is contained in:
parent
a75a080b9c
commit
d7cc620a0a
12 changed files with 51 additions and 16 deletions
|
@ -33,6 +33,7 @@ SITE_ID = 1
|
|||
SITE_NAME = "LQDOJ"
|
||||
SITE_LONG_NAME = "LQDOJ: Le Quy Don Online Judge"
|
||||
SITE_ADMIN_EMAIL = False
|
||||
SITE_DOMAIN = "lqdoj.edu.vn"
|
||||
|
||||
DMOJ_REQUIRE_STAFF_2FA = True
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ import bleach
|
|||
from django.utils.html import escape
|
||||
from bs4 import BeautifulSoup
|
||||
from pymdownx import superfences
|
||||
from django.conf import settings
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from judge.markdown_extensions import YouTubeExtension, EmoticonExtension
|
||||
|
||||
|
@ -96,6 +98,35 @@ ALLOWED_ATTRS = [
|
|||
]
|
||||
|
||||
|
||||
def _wrap_img_iframe_with_lazy_load(soup):
|
||||
for img in soup.findAll("img"):
|
||||
if img.get("src"):
|
||||
img["loading"] = "lazy"
|
||||
for img in soup.findAll("iframe"):
|
||||
if img.get("src"):
|
||||
img["loading"] = "lazy"
|
||||
return soup
|
||||
|
||||
|
||||
def _wrap_images_with_featherlight(soup):
|
||||
for img in soup.findAll("img"):
|
||||
if img.get("src"):
|
||||
link = soup.new_tag("a", href=img["src"], **{"data-featherlight": "image"})
|
||||
img.wrap(link)
|
||||
return soup
|
||||
|
||||
|
||||
def _open_external_links_in_new_tab(soup):
|
||||
domain = settings.SITE_DOMAIN.lower()
|
||||
for a in soup.findAll("a", href=True):
|
||||
href = a["href"]
|
||||
if href.startswith("http://") or href.startswith("https://"):
|
||||
link_domain = urlparse(href).netloc.lower()
|
||||
if link_domain != domain:
|
||||
a["target"] = "_blank"
|
||||
return soup
|
||||
|
||||
|
||||
def markdown(value, lazy_load=False):
|
||||
extensions = EXTENSIONS
|
||||
html = _markdown.markdown(
|
||||
|
@ -106,13 +137,13 @@ def markdown(value, lazy_load=False):
|
|||
|
||||
if not html:
|
||||
html = escape(value)
|
||||
if lazy_load:
|
||||
|
||||
soup = BeautifulSoup(html, features="html.parser")
|
||||
for img in soup.findAll("img"):
|
||||
if img.get("src"):
|
||||
img["loading"] = "lazy"
|
||||
for img in soup.findAll("iframe"):
|
||||
if img.get("src"):
|
||||
img["loading"] = "lazy"
|
||||
if lazy_load:
|
||||
soup = _wrap_img_iframe_with_lazy_load(soup)
|
||||
|
||||
soup = _wrap_images_with_featherlight(soup)
|
||||
soup = _open_external_links_in_new_tab(soup)
|
||||
html = str(soup)
|
||||
|
||||
return '<div class="md-typeset content-description">%s</div>' % html
|
||||
|
|
|
@ -924,3 +924,8 @@ input::placeholder{
|
|||
margin-right: 0.1em;
|
||||
}
|
||||
}
|
||||
|
||||
.featherlight-content {
|
||||
max-height: 80% !important;
|
||||
border-radius: 10px;
|
||||
}
|
|
@ -475,7 +475,11 @@ function onWindowReady() {
|
|||
|
||||
$('a').click(function() {
|
||||
var href = $(this).attr('href');
|
||||
if (!href || href === '#' || href.startsWith("javascript")) {
|
||||
var target = $(this).attr('target');
|
||||
if (!href || href === '#' || href.startsWith("javascript") ||
|
||||
$(this).attr("data-featherlight") ||
|
||||
target === "_blank"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -297,6 +297,7 @@
|
|||
{% include "extra_js.html" %}
|
||||
<script src="{{ static('common.js') }}"></script>
|
||||
<script src="{{ static('libs/clipboard/tooltip.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
|
||||
<script>
|
||||
moment.locale('{{ LANGUAGE_CODE }}');
|
||||
$(function () {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script>
|
||||
{% compress js %}
|
||||
{{ comment_form.media.js }}
|
||||
<script type="text/javascript">
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block three_col_js %}
|
||||
<script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
function changeTabParameter(newTab) {
|
||||
const url = new URL(window.location);
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
}
|
||||
|
||||
.featherlight-content {
|
||||
border-radius: 10px;
|
||||
height: 80%;
|
||||
width: 60%;
|
||||
overflow: auto;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
window.big_input = (window.valid_files.length > 100);
|
||||
</script>
|
||||
<script type="text/javascript" src="{{ static('jquery-ui.min.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ static('fine-uploader/jquery.fine-uploader.js') }}"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
});
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
{% block js_media %}
|
||||
{{ form.media.js }}
|
||||
<script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script>
|
||||
<script type="text/javascript" src="{{ static('event.js') }}"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
{% compress js %}
|
||||
<script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script>
|
||||
<script type="text/javascript" src="{{ static('libs/timezone-map/timezone-picker.js') }}"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
|
|
Loading…
Reference in a new issue