mirror of
https://git.sr.ht/~tsileo/microblog.pub
synced 2024-12-22 13:14:28 +00:00
No more inline CSS
This commit is contained in:
parent
2fb85e138e
commit
ebdba62a06
11 changed files with 213 additions and 66 deletions
|
@ -71,6 +71,7 @@ from app.templates import is_current_user_admin
|
||||||
from app.uploads import UPLOAD_DIR
|
from app.uploads import UPLOAD_DIR
|
||||||
from app.utils import pagination
|
from app.utils import pagination
|
||||||
from app.utils.emoji import EMOJIS_BY_NAME
|
from app.utils.emoji import EMOJIS_BY_NAME
|
||||||
|
from app.utils.highlight import HIGHLIGHT_CSS_HASH
|
||||||
from app.utils.url import check_url
|
from app.utils.url import check_url
|
||||||
from app.webfinger import get_remote_follow_template
|
from app.webfinger import get_remote_follow_template
|
||||||
|
|
||||||
|
@ -133,9 +134,10 @@ class CustomMiddleware:
|
||||||
headers["x-xss-protection"] = "1; mode=block"
|
headers["x-xss-protection"] = "1; mode=block"
|
||||||
headers["x-frame-options"] = "SAMEORIGIN"
|
headers["x-frame-options"] = "SAMEORIGIN"
|
||||||
# TODO(ts): disallow inline CSS?
|
# TODO(ts): disallow inline CSS?
|
||||||
headers[
|
headers["content-security-policy"] = (
|
||||||
"content-security-policy"
|
f"default-src 'self'; "
|
||||||
] = "default-src 'self'; style-src 'self' 'unsafe-inline';"
|
f"style-src 'self' 'sha256-{HIGHLIGHT_CSS_HASH}';"
|
||||||
|
)
|
||||||
if not DEBUG:
|
if not DEBUG:
|
||||||
headers["strict-transport-security"] = "max-age=63072000;"
|
headers["strict-transport-security"] = "max-age=63072000;"
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,36 @@ $code-highlight-background: #f0f0f0;
|
||||||
color: $primary-color;
|
color: $primary-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#admin {
|
||||||
|
.admin-menu {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-top-menu {
|
||||||
|
margin: 30px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.width-95 {
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-new {
|
||||||
|
textarea {
|
||||||
|
font-size: 1.2em;
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.show-more-wrapper {
|
.show-more-wrapper {
|
||||||
.p-summary {
|
.p-summary {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -65,13 +95,6 @@ blockquote {
|
||||||
color: $muted-color;
|
color: $muted-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.poll-bar {
|
|
||||||
width:100%;height:20px;
|
|
||||||
line {
|
|
||||||
stroke: $secondary-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.light-background {
|
.light-background {
|
||||||
background: $light-background;
|
background: $light-background;
|
||||||
}
|
}
|
||||||
|
@ -240,6 +263,9 @@ footer {
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
li {
|
li {
|
||||||
display: block;
|
display: block;
|
||||||
|
span {
|
||||||
|
padding-right:10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +300,57 @@ footer {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.show-hide-sensitive-btn {
|
||||||
|
display:inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-margin-top {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.float-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.poll-items {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
li {
|
||||||
|
display: block;
|
||||||
|
p {
|
||||||
|
margin: 20px 0 10px 0;
|
||||||
|
.poll-vote {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll-bar {
|
||||||
|
width:100%;height:20px;
|
||||||
|
line {
|
||||||
|
stroke: $secondary-color;
|
||||||
|
stroke-width: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-wrapper {
|
||||||
|
.attachment-item {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
img.attachment {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
a.attachment {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
audio.attachment {
|
||||||
|
width: 480px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
form {
|
form {
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
|
@ -334,7 +411,7 @@ nav.flexbox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.activity-attachment {
|
.activity-attachment {
|
||||||
margin: 30px 0;
|
margin: 30px 0 20px 0;
|
||||||
img, audio, video {
|
img, audio, video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 740px;
|
max-width: 740px;
|
||||||
|
@ -345,6 +422,20 @@ nav.flexbox {
|
||||||
max-width: 740px;
|
max-width: 740px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.activity-og-meta {
|
||||||
|
display: flex;
|
||||||
|
column-gap: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
img {
|
||||||
|
max-width: 200px;
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
|
small {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ap-object-expanded {
|
.ap-object-expanded {
|
||||||
border: 2px dashed $secondary-color;
|
border: 2px dashed $secondary-color;
|
||||||
}
|
}
|
||||||
|
@ -367,3 +458,54 @@ nav.flexbox {
|
||||||
.emoji, .custom-emoji {
|
.emoji, .custom-emoji {
|
||||||
max-width: 25px;
|
max-width: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.indieauth-box {
|
||||||
|
display: flex;
|
||||||
|
column-gap: 20px;
|
||||||
|
|
||||||
|
.indieauth-logo {
|
||||||
|
flex: initial;
|
||||||
|
width: 100px;
|
||||||
|
img {
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.indieauth-details {
|
||||||
|
flex: 1;
|
||||||
|
div {
|
||||||
|
padding-left: 20px;
|
||||||
|
a {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-interactions {
|
||||||
|
display: flex;
|
||||||
|
column-gap: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: 20px;
|
||||||
|
.interactions-block {
|
||||||
|
flex: 0 1 30%;
|
||||||
|
max-width: 50%;
|
||||||
|
.facepile-wrapper {
|
||||||
|
display: flex;
|
||||||
|
column-gap: 20px;
|
||||||
|
row-gap: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: 20px;
|
||||||
|
a {
|
||||||
|
height: 50px;
|
||||||
|
img {
|
||||||
|
max-width: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.and-x-more {
|
||||||
|
display: inline-block;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
<form class="form" action="{{ request.url_for("admin_actions_new") }}" enctype="multipart/form-data" method="POST">
|
<form class="form" action="{{ request.url_for("admin_actions_new") }}" enctype="multipart/form-data" method="POST" class="admin-new">
|
||||||
{{ utils.embed_csrf_token() }}
|
{{ utils.embed_csrf_token() }}
|
||||||
{{ utils.embed_redirect_url() }}
|
{{ utils.embed_redirect_url() }}
|
||||||
<p>
|
<p>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
{% if request.query_params.type == "Article" %}
|
{% if request.query_params.type == "Article" %}
|
||||||
<p>
|
<p>
|
||||||
<input type="text" style="width:95%" name="name" placeholder="Title">
|
<input type="text" class="width-95" name="name" placeholder="Title">
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
<span class="ji"><img src="{{ emoji.icon.url }}" alt="{{ emoji.name }}" title="{{ emoji.name }}" class="custom-emoji"></span>
|
<span class="ji"><img src="{{ emoji.icon.url }}" alt="{{ emoji.name }}" title="{{ emoji.name }}" class="custom-emoji"></span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<textarea name="content" rows="10" cols="50" autofocus="autofocus" designMode="on" placeholder="Hey!" style="font-size:1.2em;width:95%;">{{ content }}</textarea>
|
<textarea name="content" rows="10" cols="50" autofocus="autofocus" designMode="on" placeholder="Hey!">{{ content }}</textarea>
|
||||||
|
|
||||||
{% if request.query_params.type == "Question" %}
|
{% if request.query_params.type == "Question" %}
|
||||||
<p>
|
<p>
|
||||||
|
@ -69,20 +69,20 @@
|
||||||
</p>
|
</p>
|
||||||
{% for i in ["1", "2", "3", "4"] %}
|
{% for i in ["1", "2", "3", "4"] %}
|
||||||
<p>
|
<p>
|
||||||
<input type="text" name="poll_answer_{{ i }}" style="width:95%;" placeholder="Option {{ i }}, leave empty to disable">
|
<input type="text" name="poll_answer_{{ i }}" class="width-95" placeholder="Option {{ i }}, leave empty to disable">
|
||||||
</p>
|
</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<input type="text" name="content_warning" placeholder="content warning (will mark the post as sensitive)"{% if content_warning %} value="{{ content_warning }}"{% endif %} style="width:95%;">
|
<input type="text" name="content_warning" placeholder="content warning (will mark the post as sensitive)"{% if content_warning %} value="{{ content_warning }}"{% endif %} class="width-95">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input type="checkbox" name="is_sensitive" id="is_sensitive"> <label for="is_sensitive">Mark attachment(s) as sensitive</label>
|
<input type="checkbox" name="is_sensitive" id="is_sensitive"> <label for="is_sensitive">Mark attachment(s) as sensitive</label>
|
||||||
</p>
|
</p>
|
||||||
<input type="hidden" name="in_reply_to" value="{{ request.query_params.in_reply_to }}">
|
<input type="hidden" name="in_reply_to" value="{{ request.query_params.in_reply_to }}">
|
||||||
<p>
|
<p>
|
||||||
<input id="files" name="files" type="file" multiple style="width:95%;">
|
<input id="files" name="files" type="file" class="width-95" multiple>
|
||||||
</p>
|
</p>
|
||||||
<div id="alts"></div>
|
<div id="alts"></div>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<data class="p-name" value="{{ local_actor.display_name}}'s articles"></data>
|
<data class="p-name" value="{{ local_actor.display_name}}'s articles"></data>
|
||||||
{% for outbox_object in objects %}
|
{% for outbox_object in objects %}
|
||||||
<li>
|
<li>
|
||||||
<span class="muted" style="padding-right:10px;">{{ outbox_object.ap_published_at.strftime("%b %d, %Y") }}</span> <a href="{{ outbox_object.url }}">{{ outbox_object.name }}</a>
|
<span class="muted">{{ outbox_object.ap_published_at.strftime("%b %d, %Y") }}</span> <a href="{{ outbox_object.url }}">{{ outbox_object.name }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<a href="{{ url_for }}" {% if request.url.path == url_for %}class="active"{% endif %}>{{ text }}</a>
|
<a href="{{ url_for }}" {% if request.url.path == url_for %}class="active"{% endif %}>{{ text }}</a>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
<div style="margin:30px 0 0 0;">
|
<div class="public-top-menu">
|
||||||
<nav class="flexbox">
|
<nav class="flexbox">
|
||||||
<ul>
|
<ul>
|
||||||
<li>{{ header_link("index", "Notes") }}</li>
|
<li>{{ header_link("index", "Notes") }}</li>
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div style="padding: 20px;">
|
<div class="empty-state">
|
||||||
<p>Nothing to see here yet!</p>
|
<p>Nothing to see here yet!</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div style="display:flex;column-gap: 20px;">
|
<div class"indieauth-box">
|
||||||
{% if client.logo %}
|
{% if client.logo %}
|
||||||
<div style="flex:initial;width:100px;">
|
<div class="indieauth-logo">
|
||||||
<img src="{{client.logo | media_proxy_url }}" style="max-width:100px;" alt="{{ client.name }} logo">
|
<img src="{{client.logo | media_proxy_url }}" alt="{{ client.name }} logo">
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div style="flex:1;">
|
<div class="indieauth-details">
|
||||||
<div style="padding-left: 20px;">
|
<div>
|
||||||
<a class="lcolor" style="font-size:1.2em;font-weight:600;" href="{{ client.url }}">{{ client.name }}</a>
|
<a class="lcolor" href="{{ client.url }}">{{ client.name }}</a>
|
||||||
<p>wants you to login as <strong class="lcolor">{{ me }}</strong> with the following redirect URI: <code>{{ redirect_uri }}</code>.</p>
|
<p>wants you to login as <strong class="lcolor">{{ me }}</strong> with the following redirect URI: <code>{{ redirect_uri }}</code>.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,7 @@
|
||||||
<link rel="alternate" href="{{ url_for("rss_feed") }}" type="application/rss+xml" title="{{ local_actor.display_name}}'s microblog">
|
<link rel="alternate" href="{{ url_for("rss_feed") }}" type="application/rss+xml" title="{{ local_actor.display_name}}'s microblog">
|
||||||
<link rel="alternate" href="{{ url_for("atom_feed") }}" type="application/atom+xml" title="{{ local_actor.display_name}}'s microblog">
|
<link rel="alternate" href="{{ url_for("atom_feed") }}" type="application/atom+xml" title="{{ local_actor.display_name}}'s microblog">
|
||||||
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
||||||
<style>
|
<style>{{ highlight_css }}</style>
|
||||||
{{ highlight_css }}
|
|
||||||
</style>
|
|
||||||
{% block head %}{% endblock %}
|
{% block head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -23,7 +21,7 @@
|
||||||
{% set url_for = request.app.router.url_path_for(url) %}
|
{% set url_for = request.app.router.url_path_for(url) %}
|
||||||
<a href="{{ url_for }}" {% if request.url.path == url_for %}class="active"{% endif %}>{{ text }}</a>
|
<a href="{{ url_for }}" {% if request.url.path == url_for %}class="active"{% endif %}>{{ text }}</a>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
<div style="margin-bottom:30px;padding: 0 20px;">
|
<div class="admin-menu">
|
||||||
<nav class="flexbox">
|
<nav class="flexbox">
|
||||||
<ul>
|
<ul>
|
||||||
<li>{{ admin_link("index", "Public") }}</li>
|
<li>{{ admin_link("index", "Public") }}</li>
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
{% if facepile_item %}
|
{% if facepile_item %}
|
||||||
<a href="{{ facepile_item.actor_url }}">{{ facepile_item.actor_name }}</a>
|
<a href="{{ facepile_item.actor_url }}">{{ facepile_item.actor_name }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a style="font-weight:bold;" href="{{ notif.webmention.source }}">{{ notif.webmention.source }}</a>
|
<a class="bold" href="{{ notif.webmention.source }}">{{ notif.webmention.source }}</a>
|
||||||
</div>
|
</div>
|
||||||
{{ utils.display_object(notif.outbox_object) }}
|
{{ utils.display_object(notif.outbox_object) }}
|
||||||
{% elif notif.notification_type.value == "updated_webmention" %}
|
{% elif notif.notification_type.value == "updated_webmention" %}
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
{% if facepile_item %}
|
{% if facepile_item %}
|
||||||
<a href="{{ facepile_item.actor_url }}">{{ facepile_item.actor_name }}</a>
|
<a href="{{ facepile_item.actor_url }}">{{ facepile_item.actor_name }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a style="font-weight:bold;" href="{{ notif.webmention.source }}">{{ notif.webmention.source }}</a>
|
<a class="bold" href="{{ notif.webmention.source }}">{{ notif.webmention.source }}</a>
|
||||||
</div>
|
</div>
|
||||||
{{ utils.display_object(notif.outbox_object) }}
|
{{ utils.display_object(notif.outbox_object) }}
|
||||||
{% elif notif.notification_type.value == "deleted_webmention" %}
|
{% elif notif.notification_type.value == "deleted_webmention" %}
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
{% if facepile_item %}
|
{% if facepile_item %}
|
||||||
<a href="{{ facepile_item.actor_url }}">{{ facepile_item.actor_name }}</a>
|
<a href="{{ facepile_item.actor_url }}">{{ facepile_item.actor_name }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a style="font-weight:bold;" href="{{ notif.webmention.source }}">{{ notif.webmention.source }}</a>
|
<a class="bold" href="{{ notif.webmention.source }}">{{ notif.webmention.source }}</a>
|
||||||
</div>
|
</div>
|
||||||
{{ utils.display_object(notif.outbox_object) }}
|
{{ utils.display_object(notif.outbox_object) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -206,7 +206,7 @@
|
||||||
<div class="icon-box">
|
<div class="icon-box">
|
||||||
<img src="{{ actor.resized_icon_url }}" alt="{{ actor.display_name }}'s avatar" class="actor-icon u-photo">
|
<img src="{{ actor.resized_icon_url }}" alt="{{ actor.display_name }}'s avatar" class="actor-icon u-photo">
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ actor.url }}" class="u-url" style="">
|
<a href="{{ actor.url }}" class="u-url">
|
||||||
<div><strong>{{ actor.display_name | clean_html(actor) | safe }}</strong></div>
|
<div><strong>{{ actor.display_name | clean_html(actor) | safe }}</strong></div>
|
||||||
<div class="actor-handle p-name">{{ actor.handle }}</div>
|
<div class="actor-handle p-name">{{ actor.handle }}</div>
|
||||||
</a>
|
</a>
|
||||||
|
@ -292,16 +292,16 @@
|
||||||
{% macro display_og_meta(object) %}
|
{% macro display_og_meta(object) %}
|
||||||
{% if object.og_meta %}
|
{% if object.og_meta %}
|
||||||
{% for og_meta in object.og_meta %}
|
{% for og_meta in object.og_meta %}
|
||||||
<div class="activity-og-meta" style="display:flex;column-gap: 20px;margin:20px 0;">
|
<div class="activity-og-meta">
|
||||||
{% if og_meta.image %}
|
{% if og_meta.image %}
|
||||||
<div>
|
<div>
|
||||||
<img src="{{ og_meta.image | media_proxy_url }}" style="max-width:200px;max-height:100px;">
|
<img src="{{ og_meta.image | media_proxy_url }}">
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div>
|
<div>
|
||||||
<a href="{{ og_meta.url | privacy_replace_url }}">{{ og_meta.title }}</a>
|
<a href="{{ og_meta.url | privacy_replace_url }}">{{ og_meta.title }}</a>
|
||||||
{% if og_meta.site_name %}
|
{% if og_meta.site_name %}
|
||||||
<small style="display:block;">{{ og_meta.site_name }}</small>
|
<small>{{ og_meta.site_name }}</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -314,27 +314,27 @@
|
||||||
|
|
||||||
{% for attachment in object.attachments %}
|
{% for attachment in object.attachments %}
|
||||||
{% if object.sensitive and (attachment.type == "Image" or (attachment | has_media_type("image")) or attachment.type == "Video" or (attachment | has_media_type("video"))) %}
|
{% if object.sensitive and (attachment.type == "Image" or (attachment | has_media_type("image")) or attachment.type == "Video" or (attachment | has_media_type("video"))) %}
|
||||||
<div>
|
<div class="attachment-wrapper">
|
||||||
<label for="{{attachment.proxied_url}}" class="label-btn" style="display:inline-block;">show/hide sensitive content</label>
|
<label for="{{attachment.proxied_url}}" class="label-btn show-hide-sensitive-btn">show/hide sensitive content</label>
|
||||||
<div>
|
<div>
|
||||||
<div class="sensitive-attachment">
|
<div class="sensitive-attachment">
|
||||||
<input class="sensitive-attachment-state" type="checkbox" id="{{attachment.proxied_url}}" aria-hidden="true">
|
<input class="sensitive-attachment-state" type="checkbox" id="{{attachment.proxied_url}}" aria-hidden="true">
|
||||||
<div class="sensitive-attachment-box">
|
<div class="sensitive-attachment-box">
|
||||||
<div></div>
|
<div></div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div style="margin-top:20px;">
|
<div class="attachment-item">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if attachment.type == "Image" or (attachment | has_media_type("image")) %}
|
{% if attachment.type == "Image" or (attachment | has_media_type("image")) %}
|
||||||
{% if attachment.url not in object.inlined_images %}
|
{% if attachment.url not in object.inlined_images %}
|
||||||
<img src="{{ attachment.resized_url or attachment.proxied_url }}"{% if attachment.name %} title="{{ attachment.name }}" alt="{{ attachment.name }}"{% endif %} class="attachment" style="margin:0;">
|
<img src="{{ attachment.resized_url or attachment.proxied_url }}"{% if attachment.name %} title="{{ attachment.name }}" alt="{{ attachment.name }}"{% endif %} class="attachment">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif attachment.type == "Video" or (attachment | has_media_type("video")) %}
|
{% elif attachment.type == "Video" or (attachment | has_media_type("video")) %}
|
||||||
<video controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %}></video>
|
<video controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %}></video>
|
||||||
{% elif attachment.type == "Audio" or (attachment | has_media_type("audio")) %}
|
{% elif attachment.type == "Audio" or (attachment | has_media_type("audio")) %}
|
||||||
<audio controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name%} title="{{ attachment.name }}"{% endif %} style="width:480px;" class="attachment"></audio>
|
<audio controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name%} title="{{ attachment.name }}"{% endif %} class="attachment"></audio>
|
||||||
{% elif attachment.type == "Link" %}
|
{% elif attachment.type == "Link" %}
|
||||||
<a href="{{ attachment.url }}" class="attachment" style="display:inline-block;margin-bottom: 15px;">{{ attachment.url }}</a>
|
<a href="{{ attachment.url }}" class="attachment">{{ attachment.url }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachment">{{ attachment.url }}</a>
|
<a href="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachment">{{ attachment.url }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -371,7 +371,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if object.ap_type == "Article" %}
|
{% if object.ap_type == "Article" %}
|
||||||
<h2 class="p-name" style="margin-top:0;">{{ object.name }}</h2>
|
<h2 class="p-name no-margin-top">{{ object.name }}</h2>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if is_article_mode %}
|
{% if is_article_mode %}
|
||||||
|
@ -401,11 +401,11 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if object.poll_items %}
|
{% if object.poll_items %}
|
||||||
<ul style="list-style-type: none;padding:0;">
|
<ul class="poll-items">
|
||||||
{% for item in object.poll_items %}
|
{% for item in object.poll_items %}
|
||||||
<li style="display:block;">
|
<li>
|
||||||
{% set pct = item | poll_item_pct(object.poll_voters_count) %}
|
{% set pct = item | poll_item_pct(object.poll_voters_count) %}
|
||||||
<p style="margin:20px 0 10px 0;">
|
<p>
|
||||||
{% if can_vote %}
|
{% if can_vote %}
|
||||||
<input type="{% if object.is_one_of_poll %}radio{% else %}checkbox{% endif %}" name="name" value="{{ item.name }}" id="{{object.permalink_id}}-{{item.name}}">
|
<input type="{% if object.is_one_of_poll %}radio{% else %}checkbox{% endif %}" name="name" value="{{ item.name }}" id="{{object.permalink_id}}-{{item.name}}">
|
||||||
<label for="{{object.permalink_id}}-{{item.name}}">
|
<label for="{{object.permalink_id}}-{{item.name}}">
|
||||||
|
@ -414,17 +414,17 @@
|
||||||
{{ item.name | clean_html(object) | safe }}
|
{{ item.name | clean_html(object) | safe }}
|
||||||
|
|
||||||
{% if object.voted_for_answers and item.name in object.voted_for_answers %}
|
{% if object.voted_for_answers and item.name in object.voted_for_answers %}
|
||||||
<span class="muted" style="padding-left:20px;">you voted for this answer</span>
|
<span class="muted poll-vote">you voted for this answer</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if can_vote %}
|
{% if can_vote %}
|
||||||
</label>
|
</label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<span style="float:right;">{{ pct }}% <span class="muted">({{ item.replies.totalItems }} votes)</span></span>
|
<span class="float-right">{{ pct }}% <span class="muted">({{ item.replies.totalItems }} votes)</span></span>
|
||||||
</p>
|
</p>
|
||||||
<svg class="poll-bar">
|
<svg class="poll-bar">
|
||||||
<line x1="0" y1="10px" x2="{{ pct or 1 }}%" y2="10px" style="stroke-width: 20px;"></line>
|
<line x1="0" y1="10px" x2="{{ pct or 1 }}%" y2="10px"></line>
|
||||||
</svg>
|
</svg>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -447,7 +447,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="activity-attachment" style="margin-bottom:20px;">
|
<div class="activity-attachment">
|
||||||
{{ display_attachments(object) }}
|
{{ display_attachments(object) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -575,17 +575,17 @@
|
||||||
|
|
||||||
|
|
||||||
{% if likes or shares or webmentions %}
|
{% if likes or shares or webmentions %}
|
||||||
<div style="display: flex;column-gap: 20px;flex-wrap: wrap;margin-top:20px;">
|
<div class="public-interactions">
|
||||||
{% if likes %}
|
{% if likes %}
|
||||||
<div style="flex: 0 1 30%;max-width: 50%;">Likes
|
<div class="interactions-block">Likes
|
||||||
<div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;">
|
<div class="facepile-wrapper">
|
||||||
{% for like in likes %}
|
{% for like in likes %}
|
||||||
<a href="{% if is_admin %}{{ url_for("admin_profile") }}?actor_id={{ like.actor.ap_id }}{% else %}{{ like.actor.url }}{% endif %}" title="{{ like.actor.handle }}" style="height:50px;" rel="noreferrer">
|
<a href="{% if is_admin %}{{ url_for("admin_profile") }}?actor_id={{ like.actor.ap_id }}{% else %}{{ like.actor.url }}{% endif %}" title="{{ like.actor.handle }}" rel="noreferrer">
|
||||||
<img src="{{ like.actor.resized_icon_url }}" alt="{{ like.actor.handle}}" style="max-width:50px;">
|
<img src="{{ like.actor.resized_icon_url }}" alt="{{ like.actor.handle}}">
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if object.likes_count > likes | length %}
|
{% if object.likes_count > likes | length %}
|
||||||
<div style="display:inline-block;align-self:center;">
|
<div class="and-x-more">
|
||||||
and {{ object.likes_count - likes | length }} more.
|
and {{ object.likes_count - likes | length }} more.
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -594,15 +594,15 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if shares %}
|
{% if shares %}
|
||||||
<div style="flex: 0 1 30%;max-width: 50%;">Shares
|
<div class="interactions-block">Shares
|
||||||
<div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;">
|
<div class="facepile-wrapper">
|
||||||
{% for share in shares %}
|
{% for share in shares %}
|
||||||
<a href="{% if is_admin %}{{ url_for("admin_profile") }}?actor_id={{ share.actor.ap_id }}{% else %}{{ share.actor.url }}{% endif %}" title="{{ share.actor.handle }}" style="height:50px;" rel="noreferrer">
|
<a href="{% if is_admin %}{{ url_for("admin_profile") }}?actor_id={{ share.actor.ap_id }}{% else %}{{ share.actor.url }}{% endif %}" title="{{ share.actor.handle }}" rel="noreferrer">
|
||||||
<img src="{{ share.actor.resized_icon_url }}" alt="{{ share.actor.handle}}" style="max-width:50px;">
|
<img src="{{ share.actor.resized_icon_url }}" alt="{{ share.actor.handle}}">
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if object.announces_count > shares | length %}
|
{% if object.announces_count > shares | length %}
|
||||||
<div style="display:inline-block;align-self:center;">
|
<div class="and-x-more">
|
||||||
and {{ object.announces_count - shares | length }} more.
|
and {{ object.announces_count - shares | length }} more.
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -611,13 +611,13 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if webmentions %}
|
{% if webmentions %}
|
||||||
<div style="flex: 0 1 30%;max-width: 50%;">Webmentions
|
<div class="interactions-block">Webmentions
|
||||||
<div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;">
|
<div class="facepile-wrapper">
|
||||||
{% for webmention in webmentions %}
|
{% for webmention in webmentions %}
|
||||||
{% set wm = webmention.as_facepile_item %}
|
{% set wm = webmention.as_facepile_item %}
|
||||||
{% if wm %}
|
{% if wm %}
|
||||||
<a href="{{ wm.url }}" title="{{ wm.actor_name }}" style="height:50px;" rel="noreferrer">
|
<a href="{{ wm.url }}" title="{{ wm.actor_name }}" rel="noreferrer">
|
||||||
<img src="{{ wm.actor_icon_url | media_proxy_url }}" alt="{{ wm.actor_name }}" style="max-width:50px;">
|
<img src="{{ wm.actor_icon_url | media_proxy_url }}" alt="{{ wm.actor_name }}">
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|
||||||
from bs4 import BeautifulSoup # type: ignore
|
from bs4 import BeautifulSoup # type: ignore
|
||||||
|
@ -11,6 +13,9 @@ from app.config import CODE_HIGHLIGHTING_THEME
|
||||||
_FORMATTER = HtmlFormatter(style=CODE_HIGHLIGHTING_THEME)
|
_FORMATTER = HtmlFormatter(style=CODE_HIGHLIGHTING_THEME)
|
||||||
|
|
||||||
HIGHLIGHT_CSS = _FORMATTER.get_style_defs()
|
HIGHLIGHT_CSS = _FORMATTER.get_style_defs()
|
||||||
|
HIGHLIGHT_CSS_HASH = base64.b64encode(
|
||||||
|
hashlib.sha256(HIGHLIGHT_CSS.encode()).digest()
|
||||||
|
).decode()
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(256)
|
@lru_cache(256)
|
||||||
|
|
Loading…
Reference in a new issue