forked from forks/microblog.pub
Microformats support
This commit is contained in:
parent
33154b7e01
commit
9c41c68958
8 changed files with 66 additions and 12 deletions
|
@ -6,6 +6,7 @@ from typing import Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import bleach
|
import bleach
|
||||||
|
import html2text
|
||||||
import timeago # type: ignore
|
import timeago # type: ignore
|
||||||
from bs4 import BeautifulSoup # type: ignore
|
from bs4 import BeautifulSoup # type: ignore
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
|
@ -32,6 +33,11 @@ from app.utils.highlight import highlight
|
||||||
_templates = Jinja2Templates(directory="app/templates")
|
_templates = Jinja2Templates(directory="app/templates")
|
||||||
|
|
||||||
|
|
||||||
|
H2T = html2text.HTML2Text()
|
||||||
|
H2T.ignore_links = True
|
||||||
|
H2T.ignore_images = True
|
||||||
|
|
||||||
|
|
||||||
def _filter_domain(text: str) -> str:
|
def _filter_domain(text: str) -> str:
|
||||||
hostname = urlparse(text).hostname
|
hostname = urlparse(text).hostname
|
||||||
if not hostname:
|
if not hostname:
|
||||||
|
@ -219,6 +225,10 @@ def _replace_custom_emojis(content: str, note: Object) -> str:
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def _html2text(content: str) -> str:
|
||||||
|
return H2T.handle(content)
|
||||||
|
|
||||||
|
|
||||||
_templates.env.filters["domain"] = _filter_domain
|
_templates.env.filters["domain"] = _filter_domain
|
||||||
_templates.env.filters["media_proxy_url"] = _media_proxy_url
|
_templates.env.filters["media_proxy_url"] = _media_proxy_url
|
||||||
_templates.env.filters["clean_html"] = _clean_html
|
_templates.env.filters["clean_html"] = _clean_html
|
||||||
|
@ -226,3 +236,4 @@ _templates.env.filters["timeago"] = _timeago
|
||||||
_templates.env.filters["format_date"] = _format_date
|
_templates.env.filters["format_date"] = _format_date
|
||||||
_templates.env.filters["has_media_type"] = _has_media_type
|
_templates.env.filters["has_media_type"] = _has_media_type
|
||||||
_templates.env.filters["pluralize"] = _pluralize
|
_templates.env.filters["pluralize"] = _pluralize
|
||||||
|
_templates.env.filters["html2text"] = _html2text
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<data class="u-photo" value="{{ local_actor.icon_url }}"></data>
|
<data class="u-photo" value="{{ local_actor.icon_url }}"></data>
|
||||||
<a href="{{ local_actor.url }}" class="u-url u-uid no-hover title">
|
<a href="{{ local_actor.url }}" class="u-url u-uid no-hover title">
|
||||||
<span style="font-size:1.1em;">{{ local_actor.name }}</span>
|
<span style="font-size:1.1em;">{{ local_actor.name }}</span>
|
||||||
<span style="font-size:0.85em;" class="subtitle-username">{{ local_actor.handle }}</span>
|
<span style="font-size:0.85em;" class="p-name subtitle-username">{{ local_actor.handle }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="p-note summary">
|
<div class="p-note summary">
|
||||||
|
|
|
@ -1,11 +1,27 @@
|
||||||
{%- import "utils.html" as utils with context -%}
|
{%- import "utils.html" as utils with context -%}
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<link rel="alternate" href="{{ local_actor.url }}" title="ActivityPub profile" type="application/activity+json">
|
||||||
|
<meta content="profile" property="og:type" />
|
||||||
|
<meta content="{{ local_actor.url }}" property="og:url" />
|
||||||
|
<meta content="{{ local_actor.display_name }}'s microblog" property="og:site_name" />
|
||||||
|
<meta content="Homepage" property="og:title" />
|
||||||
|
<meta content="{{ local_actor.summary | html2text }}" property="og:description" />
|
||||||
|
<meta content="{{ local_actor.url }}" property="og:image" />
|
||||||
|
<meta content="summary" property="twitter:card" />
|
||||||
|
<meta content="{{ local_actor.handle }}" property="profile:username" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include "header.html" %}
|
{% include "header.html" %}
|
||||||
|
|
||||||
|
<div class="h-feed">
|
||||||
|
<data class="p-name" value="{{ local_actor.display_name}}'s notes"></data>
|
||||||
{% for outbox_object in objects %}
|
{% for outbox_object in objects %}
|
||||||
{{ utils.display_object(outbox_object) }}
|
{{ utils.display_object(outbox_object) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if has_previous_page %}
|
{% if has_previous_page %}
|
||||||
<a href="{{ url_for("index") }}?page={{ current_page - 1 }}">Previous</a>
|
<a href="{{ url_for("index") }}?page={{ current_page - 1 }}">Previous</a>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<style>
|
<style>
|
||||||
{{ highlight_css }}
|
{{ highlight_css }}
|
||||||
</style>
|
</style>
|
||||||
|
{% block head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
{%- import "utils.html" as utils with context -%}
|
{%- import "utils.html" as utils with context -%}
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<link rel="alternate" href="{{ request.url }}" type="application/activity+json">
|
||||||
|
<meta name="description" content="{{ outbox_object.content | html2text | trim | truncate(50) }}">
|
||||||
|
<meta content="article" property="og:type" />
|
||||||
|
<meta content="{{ outbox_object.url }}" property="og:url" />
|
||||||
|
<meta content="{{ local_actor.display_name }}'s microblog" property="og:site_name" />
|
||||||
|
<meta content="Note" property="og:title" />
|
||||||
|
<meta content="{{ outbox_object.content | html2text | trim | truncate(50) }}" property="og:description" />
|
||||||
|
<meta content="{{ local_actor.icon_url }}" property="og:image" />
|
||||||
|
<meta content="summary" property="twitter:card" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include "header.html" %}
|
{% include "header.html" %}
|
||||||
|
|
||||||
|
|
|
@ -111,13 +111,13 @@
|
||||||
|
|
||||||
{% macro display_actor(actor, actors_metadata) %}
|
{% macro display_actor(actor, actors_metadata) %}
|
||||||
{% set metadata = actors_metadata.get(actor.ap_id) %}
|
{% set metadata = actors_metadata.get(actor.ap_id) %}
|
||||||
<div style="display: flex;column-gap: 20px;margin:20px 0 10px 0;" class="actor-box">
|
<div style="display: flex;column-gap: 20px;margin:20px 0 10px 0;" class="actor-box h-card p-author">
|
||||||
<div style="flex: 0 0 48px;">
|
<div style="flex: 0 0 48px;">
|
||||||
<img src="{{ actor.resized_icon_url }}" style="max-width:45px;">
|
<img src="{{ actor.resized_icon_url }}" style="max-width:45px;">
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ actor.url }}" style="">
|
<a href="{{ actor.url }}" class="u-url" style="">
|
||||||
<div><strong>{{ actor.display_name | clean_html(actor) | safe }}</strong></div>
|
<div><strong>{{ actor.display_name | clean_html(actor) | safe }}</strong></div>
|
||||||
<div>{{ actor.handle }}</div>
|
<div class="p-name">{{ actor.handle }}</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% if is_admin and metadata %}
|
{% if is_admin and metadata %}
|
||||||
|
@ -145,15 +145,15 @@
|
||||||
|
|
||||||
{% macro display_object_expanded(object) %}
|
{% macro display_object_expanded(object) %}
|
||||||
|
|
||||||
<div class="activity-expanded">
|
<div class="activity-expanded h-entry">
|
||||||
|
|
||||||
{{ display_actor(object.actor, {}) }}
|
{{ display_actor(object.actor, {}) }}
|
||||||
|
|
||||||
<div>
|
<div class="e-content">
|
||||||
{{ object.content | clean_html(object) | safe }}
|
{{ object.content | clean_html(object) | safe }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="{{ object.url }}">{{ object.ap_published_at | format_date }}</a>
|
<a href="{{ object.url }}" class="u-url u-uid"><time class="dt-published" datetime="{{ object.ap_published_at }}">{{ object.ap_published_at | format_date }}</time></a>
|
||||||
{{ object.visibility.value }}
|
{{ object.visibility.value }}
|
||||||
{% if object.is_from_outbox %}
|
{% if object.is_from_outbox %}
|
||||||
{{ object.likes_count }} likes
|
{{ object.likes_count }} likes
|
||||||
|
@ -170,17 +170,17 @@
|
||||||
|
|
||||||
{% macro display_object(object) %}
|
{% macro display_object(object) %}
|
||||||
{% if object.ap_type in ["Note", "Article", "Video"] %}
|
{% if object.ap_type in ["Note", "Article", "Video"] %}
|
||||||
<div class="activity-wrap" id="{{ object.permalink_id }}">
|
<div class="activity-wrap h-entry" id="{{ object.permalink_id }}">
|
||||||
<div class="activity-content">
|
<div class="activity-content">
|
||||||
<img src="{{ object.actor.resized_icon_url }}" alt="" class="actor-icon">
|
<img src="{{ object.actor.resized_icon_url }}" alt="" class="actor-icon">
|
||||||
<div class="activity-header">
|
<div class="activity-header">
|
||||||
<strong>{{ object.actor.display_name }}</strong>
|
<strong>{{ object.actor.display_name }}</strong>
|
||||||
<span>{{ object.actor.handle }}</span>
|
<a href="{{ object.actor.url}}" class="p-author h-card">{{ object.actor.handle }}</a>
|
||||||
<span class="activity-date" title="{{ object.ap_published_at.isoformat() }}">
|
<span class="activity-date" title="{{ object.ap_published_at.isoformat() }}">
|
||||||
{{ object.visibility.value }}
|
{{ object.visibility.value }}
|
||||||
<a href="{{ object.url }}">{{ object.ap_published_at | timeago }}</a>
|
<a href="{{ object.url }}" class="u-url u-uid"><time class="dt-published" datetime="{{ object.ap_published_at }}">{{ object.ap_published_at | timeago }}</time></a>
|
||||||
</span>
|
</span>
|
||||||
<div class="activity-main">
|
<div class="activity-main e-content">
|
||||||
{{ object.content | clean_html(object) | safe }}
|
{{ object.content | clean_html(object) | safe }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
14
poetry.lock
generated
14
poetry.lock
generated
|
@ -315,6 +315,14 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "html2text"
|
||||||
|
version = "2020.1.16"
|
||||||
|
description = "Turn HTML into equivalent Markdown-structured text."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "html5lib"
|
name = "html5lib"
|
||||||
version = "1.1"
|
version = "1.1"
|
||||||
|
@ -1046,7 +1054,7 @@ dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"]
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.10"
|
python-versions = "^3.10"
|
||||||
content-hash = "2ac30190905e28cfb50e57e23142f0508522727ca7eca010904792c549501698"
|
content-hash = "ecb1ed5abd25037b2ba0154e079d813607ae59a29e9a6d544dc47c249d382af1"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
alembic = [
|
alembic = [
|
||||||
|
@ -1283,6 +1291,10 @@ h11 = [
|
||||||
{file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"},
|
{file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"},
|
||||||
{file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"},
|
{file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"},
|
||||||
]
|
]
|
||||||
|
html2text = [
|
||||||
|
{file = "html2text-2020.1.16-py3-none-any.whl", hash = "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b"},
|
||||||
|
{file = "html2text-2020.1.16.tar.gz", hash = "sha256:e296318e16b059ddb97f7a8a1d6a5c1d7af4544049a01e261731d2d5cc277bbb"},
|
||||||
|
]
|
||||||
html5lib = [
|
html5lib = [
|
||||||
{file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"},
|
{file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"},
|
||||||
{file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"},
|
{file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"},
|
||||||
|
|
|
@ -34,6 +34,7 @@ loguru = "^0.6.0"
|
||||||
mdx-linkify = "^2.1"
|
mdx-linkify = "^2.1"
|
||||||
Pillow = "^9.1.1"
|
Pillow = "^9.1.1"
|
||||||
blurhash-python = "^1.1.3"
|
blurhash-python = "^1.1.3"
|
||||||
|
html2text = "^2020.1.16"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
black = "^22.3.0"
|
black = "^22.3.0"
|
||||||
|
|
Loading…
Reference in a new issue