Code highlighting

This commit is contained in:
Thomas Sileo 2019-08-25 00:16:39 +02:00
parent 14e5e6b7e7
commit 562aae86f3
6 changed files with 42 additions and 2 deletions

2
app.py
View file

@ -72,6 +72,7 @@ from core.shared import noindex
from core.shared import paginated_query from core.shared import paginated_query
from utils.blacklist import is_blacklisted from utils.blacklist import is_blacklisted
from utils.emojis import EMOJIS from utils.emojis import EMOJIS
from utils.highlight import HIGHLIGHT_CSS
from utils.key import get_secret_key from utils.key import get_secret_key
from utils.template_filters import filters from utils.template_filters import filters
@ -153,6 +154,7 @@ def inject_config():
else 0, else 0,
me=ME, me=ME,
base_url=config.BASE_URL, base_url=config.BASE_URL,
highlight_css=HIGHLIGHT_CSS,
) )

View file

@ -24,3 +24,4 @@ pyyaml
pillow pillow
emoji-unicode emoji-unicode
html5lib html5lib
Pygments

View file

@ -21,6 +21,7 @@
width: 25px; width: 25px;
height: 25px; height: 25px;
} }
{{ highlight_css }}
</style> </style>
{% block headers %}{% endblock %} {% block headers %}{% endblock %}
</head> </head>

View file

@ -77,7 +77,7 @@
{% if obj | has_type(['Article', 'Page']) %} {% if obj | has_type(['Article', 'Page']) %}
{{ obj.name }} <a href="{{ obj | url_or_id | get_url }}">{{ obj | url_or_id | get_url }}</a> {{ obj.name }} <a href="{{ obj | url_or_id | get_url }}">{{ obj | url_or_id | get_url }}</a>
{% elif obj | has_type('Question') %} {% elif obj | has_type('Question') %}
{{ obj.content | clean | replace_custom_emojis(obj) | safe }} {{ obj.content | clean | replace_custom_emojis(obj) | code_highlight | safe }}
<ul style="list-style:none;padding:0;"> <ul style="list-style:none;padding:0;">
@ -146,7 +146,7 @@
{% else %} {% else %}
{{ obj.content | clean | replace_custom_emojis(obj) | safe }} {{ obj.content | clean | replace_custom_emojis(obj) | code_highlight | safe }}
{% endif %} {% endif %}
</div> </div>

30
utils/highlight.py Normal file
View file

@ -0,0 +1,30 @@
from functools import lru_cache
from bs4 import BeautifulSoup
from pygments import highlight as phighlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import guess_lexer
from config import THEME_STYLE
from config import ThemeStyle
_FORMATTER = HtmlFormatter(
style="default" if THEME_STYLE == ThemeStyle.LIGHT else "vim"
)
HIGHLIGHT_CSS = _FORMATTER.get_style_defs()
@lru_cache(512)
def highlight(html: str) -> str:
soup = BeautifulSoup(html, "html5lib")
for code in soup.find_all("code"):
if not code.parent.name == "pre":
continue
lexer = guess_lexer(code.text)
tag = BeautifulSoup(phighlight(code.text, lexer, _FORMATTER)).body.next
pre = code.parent
pre.replaceWith(tag)
out = soup.body
out.name = "div"
return str(out)

View file

@ -21,6 +21,7 @@ from config import ID
from config import MEDIA_CACHE from config import MEDIA_CACHE
from core.activitypub import _answer_key from core.activitypub import _answer_key
from utils import parse_datetime from utils import parse_datetime
from utils.highlight import highlight
from utils.media import Kind from utils.media import Kind
from utils.media import _is_img from utils.media import _is_img
@ -47,6 +48,11 @@ def visibility_is_public(v: str) -> bool:
return v in [ap.Visibility.PUBLIC.name, ap.Visibility.UNLISTED.name] return v in [ap.Visibility.PUBLIC.name, ap.Visibility.UNLISTED.name]
@filters.app_template_filter()
def code_highlight(content):
return highlight(content)
@filters.app_template_filter() @filters.app_template_filter()
def emojify(text): def emojify(text):
return emoji_unicode.replace( return emoji_unicode.replace(