CSS : Modifications consequent to XHTML modifications;

Python : Modifications consequent to XHTML modifications;
TOML   : Various of modifications;
XHTML  : Uniform templates.
This commit is contained in:
Schimon Jehudah, Adv. 2024-11-05 10:51:28 +02:00
parent 82fb55ca1c
commit cbcf3b58d0
8 changed files with 512 additions and 289 deletions

View file

@ -448,20 +448,14 @@ resources = [
] ]
[leechcraft] [leechcraft]
title = "LeechCraft" title = "Leech Craft"
about = """ about = """
LeechCraft is a free open source cross-platform modular live environment. LeechCraft is a free open source cross-platform modular live environment and \
internet-client.
It has modules for everything, which include an HTML browser; a multiprotocol \ LeechCraft allows to chat, browse the internet, read Atom/RSS feeds, download \
modular IM client with support for encryption and audio calls; a \ files via BitTorrent, FTP, HTTP and DC, automatically download, play or stream \
collection-oriented media player with social features like recommended artists \ podcasts (and other media files) and much more.
and nearby events; a BitTorrent client; a document viewer (ePUB, DjVu, PDF, \
MOBI, etc.); an RSS feed reader with extensive support for Broadcatching and \
podcasts ; a package manager with its own repository of plugins, themes, icons \
and much more.
The Summary tab that displays all your downloads, updates and statuses (like \
new articles in news feeds).
LeechCraft is a modular system, and by installing different modules you can \ LeechCraft is a modular system, and by installing different modules you can \
customize the feature set, keeping off the things you do not need and have a \ customize the feature set, keeping off the things you do not need and have a \

View file

@ -12,7 +12,7 @@ div, h1, h2, h3, h4, h5 {
font-family: system-ui; font-family: system-ui;
} }
h1, h2, h3 { h1, h2 {
text-align: center; text-align: center;
margin: 0; margin: 0;
padding: 1em; padding: 1em;
@ -58,12 +58,64 @@ div:has(#bar) {
} }
*/ */
#subject { #conference,
#pubsub {
text-align: initial;
}
#subject pre {
margin: auto; margin: auto;
max-height: 30vh; max-height: 30vh;
overflow: auto; overflow: auto;
padding: 1em; padding: 1em;
width: 90vw; }
#entries,
#messages,
#subject {
padding: 0 2em 0 2em;
}
.entry,
.message,
#subject {
margin-bottom: 1em;
}
.entry > .link a,
.entry > a,
.message > a {
text-decoration: none;
}
.entry .summary {
padding: 1em 0 0 1em;
}
#subject pre,
#vcard-note,
#vcard-note-full {
color: #505050;
margin-left: 5em;
margin-right: 5em;
/* overflow: hidden; */
padding: 0 2em 2em 2em;
text-align: center;
/* text-overflow: ellipsis;
white-space: nowrap; */
}
#subject pre {
font-size: 120%;
text-align: initial;
margin: unset;
}
#subject pre,
.message .content {
overflow-wrap: break-word;
padding: 1em 0 0 1em;
white-space: pre-wrap;
} }
#bar, #bar,
@ -156,14 +208,21 @@ label,
#input, #input,
.vcard-link, .vcard-link,
.system-menu { .system-menu {
border-radius: 2em;
font-size: 1.34em; font-size: 1.34em;
}
#download,
#input,
.vcard-link {
border-radius: 2em;
padding: 0.5em; padding: 0.5em;
} }
/*
#system-title > * { #system-title > * {
width: 18%; width: 18%;
} }
*/
#profile-top, #profile-top,
#system-title { #system-title {
@ -271,17 +330,20 @@ h1 {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
/*
#count { #count {
margin: 1em; margin: 1em;
/* min-height: 1.5em; */
}
/*
#count > a:before {
content: ' • ';
} }
*/ */
#count > a:after {
content: ' • ';
}
#count > a:last-child:after {
content: '';
}
#graphics, #graphics,
#photo { #photo {
border-radius: 50px; border-radius: 50px;
@ -317,12 +379,26 @@ h1 {
display: grid; display: grid;
} }
#vcard-links-extra > a {
border: 1px solid #434a53;
border-radius: 1em;
margin: 1em auto;
padding: 1em;
text-decoration: none;
width: 50%;
}
#vcard-links > a:hover,
#vcard-links-extra > a:hover {
background: #ebebeb;
}
#vcard-links { #vcard-links {
padding-bottom: 1em; padding-bottom: 1em;
} }
.vcard-link { .vcard-link {
filter: drop-shadow(0 0 0 black); /* filter: drop-shadow(0 0 0 black); */
margin: 1em; margin: 1em;
outline: solid; outline: solid;
outline-color: #cfcfcf; outline-color: #cfcfcf;
@ -468,25 +544,6 @@ h1 {
display: block; /* Show details upon checked checkbox */ display: block; /* Show details upon checked checkbox */
} }
#vcard-note-full {
color: #505050;
margin-left: 5em;
margin-right: 5em;
padding: 0 2em 2em 2em;
text-align: center;
}
#vcard-note {
color: #505050;
margin-left: 5em;
margin-right: 5em;
/* overflow: hidden; */
padding: 2em;
text-align: center;
/* text-overflow: ellipsis;
white-space: nowrap; */
}
#vcard-note:hover { #vcard-note:hover {
overflow: unset; overflow: unset;
white-space: unset; white-space: unset;
@ -517,7 +574,7 @@ h1 {
padding: 1em; padding: 1em;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
width: 12.2%; /* width: 12.2%; */
} }
#software-menu img { #software-menu img {
@ -653,11 +710,6 @@ h1 {
width: 80%; width: 80%;
} }
#entries {
/* padding: 2em; */
text-align: left;
}
/* /*
.entry > * { .entry > * {
margin-bottom: 1em; margin-bottom: 1em;
@ -679,6 +731,7 @@ h1 {
text-decoration: none; text-decoration: none;
} }
.entry > .link a,
#count > a, #count > a,
#preview { #preview {
color: #5c5656; color: #5c5656;
@ -688,6 +741,9 @@ h1 {
#count > a:hover, #count > a:hover,
#preview:hover { #preview:hover {
color: #000; color: #000;
}
#preview:hover {
text-decoration: underline; text-decoration: underline;
} }
@ -890,10 +946,16 @@ h1 {
} }
#action > #add, #action > #add,
#action-bar > #add { #action-bar > #add,
#system-title > h1 {
display: none; display: none;
} }
#system-title {
padding-bottom: 2em;
padding-top: 2em;
}
body { body {
background: #f5f5f5; background: #f5f5f5;
} }
@ -916,6 +978,7 @@ h1 {
padding-bottom: unset; padding-bottom: unset;
} }
#container-of-selection,
#profile { #profile {
border-radius: unset; border-radius: unset;
filter: unset; filter: unset;
@ -995,3 +1058,11 @@ h1 {
} }
} }
@media (max-width: 480px) {
#security-notices > .notice {
width: 300px;
}
}

73
fasi.py
View file

@ -109,7 +109,6 @@ class HttpInstance:
exception = jid_vcard = messages_10 = note = node_title = \ exception = jid_vcard = messages_10 = note = node_title = \
node_note = number_of_pages = page_number = previous = \ node_note = number_of_pages = page_number = previous = \
selection = services_sorted = subject = None selection = services_sorted = subject = None
node_name = 'urn:xmpp:microblog:0'
link_href = 'xmpp:{}?join'.format(jid_bare) link_href = 'xmpp:{}?join'.format(jid_bare)
link_text = 'Join' link_text = 'Join'
xmpp_uri = '{}'.format(jid_bare) xmpp_uri = '{}'.format(jid_bare)
@ -119,7 +118,7 @@ class HttpInstance:
jid_details = Data.open_file_toml(filename) jid_details = Data.open_file_toml(filename)
else: else:
jid_details = await FileUtilities.cache_jid_data( jid_details = await FileUtilities.cache_jid_data(
jabber_id, password, jid_bare, node_name, alias=alias) jabber_id, password, jid_bare, alias=alias)
count = jid_details['count'] count = jid_details['count']
items = jid_details['items'] items = jid_details['items']
@ -157,7 +156,7 @@ class HttpInstance:
if jid_kind: if jid_kind:
# Action and instance type # Action and instance type
action, instance = XmppUtilities.set_action_instance_type(jid_kind, node_name) action, instance = XmppUtilities.set_action_instance_type(jid_kind)
else: # jid_info['error'] else: # jid_info['error']
action = 'Contact' action = 'Contact'
instance = view_href = '' instance = view_href = ''
@ -166,10 +165,10 @@ class HttpInstance:
# Query URI links # Query URI links
print('Query URI links') print('Query URI links')
links = XmppUtilities.get_query_uri_links(jid_bare, jid_kind, node_name) links = XmppUtilities.get_query_uri_links(jid_bare, jid_kind)
link_href = XmppUtilities.get_link_href(jid_bare, jid_kind, node_name) link_href = XmppUtilities.get_link_href(jid_bare, jid_kind)
view_href = XmppUtilities.get_view_href(jid_bare, jid_kind, node_name) view_href = XmppUtilities.get_view_href(jid_bare, jid_kind)
xmpp_uri = XmppUtilities.get_xmpp_uri(jid_bare, jid_kind, node_name) xmpp_uri = XmppUtilities.get_xmpp_uri(jid_bare, jid_kind)
# Graphic files # Graphic files
filename, filepath, filetype, selection = FileUtilities.handle_photo(jid_bare, jid_vcard, link_href) filename, filepath, filetype, selection = FileUtilities.handle_photo(jid_bare, jid_vcard, link_href)
@ -202,7 +201,6 @@ class HttpInstance:
'messages' : messages_10, 'messages' : messages_10,
'node_title' : node_title, 'node_title' : node_title,
'node_note' : node_note, 'node_note' : node_note,
'node_name' : node_name,
'number_of_pages' : number_of_pages, 'number_of_pages' : number_of_pages,
'page_number' : page_number, 'page_number' : page_number,
'previous' : previous, 'previous' : previous,
@ -241,7 +239,7 @@ class HttpInstance:
directory = 'xep_0060/{}/{}/'.format(jid_bare, node_name_vcard4) directory = 'xep_0060/{}/{}/'.format(jid_bare, node_name_vcard4)
filename = directory + item_id_vcard4 + '.xml' filename = directory + item_id_vcard4 + '.xml'
if os.path.exists(filename) and os.path.getsize(filename) > 0: if os.path.exists(filename) and os.path.getsize(filename) > 0:
jid_details = Data.open_file_xml(filename) xml_data = Data.open_file_xml(filename)
else: else:
await FileUtilities.cache_vcard_data( await FileUtilities.cache_vcard_data(
jabber_id, password, jid_bare, node_name_vcard4, item_id_vcard4) jabber_id, password, jid_bare, node_name_vcard4, item_id_vcard4)
@ -255,13 +253,30 @@ class HttpInstance:
# Action and instance type # Action and instance type
action = 'Profile' action = 'Profile'
filename = 'details/{}.toml'.format(jid_bare)
if os.path.exists(filename) and os.path.getsize(filename) > 0:
jid_details = Data.open_file_toml(filename)
else:
jid_details = await FileUtilities.cache_jid_data(
jabber_id, password, jid_bare, alias=alias)
# Set node name to 'urn:xmpp:microblog:0'
jid_kind = jid_details['kind']
nodes = jid_details['nodes']
if (jid_kind not in ('conference', 'mix', 'muc') and
'@' in jid_bare and
'urn:xmpp:microblog:0' in nodes):
node_name = 'urn:xmpp:microblog:0'
# Query URI links # Query URI links
print('Query URI links') print('Query URI links')
jid_kind = 'account' jid_kind = 'account'
link_href = XmppUtilities.get_link_href(jid_bare, jid_kind)
xmpp_uri = XmppUtilities.get_xmpp_uri(jid_bare, jid_kind, node_name_vcard4) xmpp_uri = XmppUtilities.get_xmpp_uri(jid_bare, jid_kind, node_name_vcard4)
links = XmppUtilities.get_query_uri_links(jid_bare, jid_kind, node_name)
# Graphic files # Graphic files
#filename, filepath, filetype, selection = FileUtilities.handle_photo(jid_bare, jid_vcard, link_href) filename, filepath, filetype, selection = FileUtilities.handle_photo(jid_bare, jid_vcard, link_href)
#except Exception as e: #except Exception as e:
else: else:
@ -297,11 +312,12 @@ class HttpInstance:
'chat_client' : chat_client, 'chat_client' : chat_client,
'entries' : entries, 'entries' : entries,
'exception' : exception, 'exception' : exception,
#'filename' : filename, 'filename' : filename,
'jid_bare' : jid, 'jid_bare' : jid,
'jid_note' : note, 'jid_note' : note,
#'jid_title' : title, #'jid_title' : title,
#'node_title' : node_title, #'node_title' : node_title,
'links' : links,
'node_name' : node_name_vcard4, 'node_name' : node_name_vcard4,
'number_of_pages' : number_of_pages, 'number_of_pages' : number_of_pages,
'page_number' : page_number, 'page_number' : page_number,
@ -658,7 +674,7 @@ class HttpInstance:
'type' : jid_details['image_type']} 'type' : jid_details['image_type']}
messages = jid_details['messages'] messages = jid_details['messages']
#note = nodes[node_name]['title'] if node_name in nodes else jid_details['note'] #note = nodes[node_name]['title'] if node_name in nodes else jid_details['note']
note = jid_details['note'] #note = jid_details['note']
# vCard4 # vCard4
node_name_vcard4 = 'urn:xmpp:vcard4' node_name_vcard4 = 'urn:xmpp:vcard4'
@ -673,7 +689,7 @@ class HttpInstance:
vcard_info = Syndication.extract_vcard4_items(child_element) vcard_info = Syndication.extract_vcard4_items(child_element)
title = vcard_info['fn'] title = vcard_info['fn']
alias = vcard_info['alias'] alias = vcard_info['alias']
note = vcard_info['note'] #note = vcard_info['note']
else: else:
await FileUtilities.cache_vcard_data( await FileUtilities.cache_vcard_data(
jabber_id, password, jid_bare, node_name_vcard4, item_id_vcard4) jabber_id, password, jid_bare, node_name_vcard4, item_id_vcard4)
@ -690,8 +706,10 @@ class HttpInstance:
await FileUtilities.cache_node_data( await FileUtilities.cache_node_data(
jabber_id, password, jid_bare, node_name) jabber_id, password, jid_bare, node_name)
# Node items # JID or node items
entries = [] if jid_kind in ('mix', 'muc', 'conference', 'server'):
count_item = jid_details['count']
elif jid_kind in ('account', 'pubsub'):
node_items = os.listdir(directory) node_items = os.listdir(directory)
if 'urn:xmpp:avatar:metadata.xml' in node_items: if 'urn:xmpp:avatar:metadata.xml' in node_items:
node_items.remove('urn:xmpp:avatar:metadata.xml') node_items.remove('urn:xmpp:avatar:metadata.xml')
@ -747,8 +765,8 @@ class HttpInstance:
jid_vcard = jid_kind = links = message = selection = url = \ jid_vcard = jid_kind = links = message = selection = url = \
vcard4 = None vcard4 = None
note_500 = note[:500] #note_500 = note[:500]
note = note_500 + '' if note_500 < note else note_500 #note = note_500 + ' …' if note_500 < note else note_500
# NOTE Handling of variables "title" and "note" in case of '/j/{jid}/{node_name}' is confusing. # NOTE Handling of variables "title" and "note" in case of '/j/{jid}/{node_name}' is confusing.
# TODO Add new keys that are of 'node' and be utilized for nodes, instead of reusing a variable for several roles. # TODO Add new keys that are of 'node' and be utilized for nodes, instead of reusing a variable for several roles.
@ -1555,24 +1573,17 @@ class Syndication:
else: else:
url = '' url = ''
extra_resources = { vcard['extras'] = {}
'code' : [], for element in xml_data.findall(namespace + "group"):
'gallery' : [], category = '?'
'journal' : [],
'movim' : [],
'peertube' : [],
}
for res in extra_resources:
#for element in xml_data.findall(namespace + 'group[contains(@name, "{}")]'.format(res)):
#for element in xml_data.findall(namespace + 'group[strats-with(@name, "{}")]'.format(res)):
matching_elements = [group for group in xml_data.findall(namespace + "group") if res in group.get('name', '')]
for element in matching_elements:
for i in element.find(namespace + 'x-ablabel'): for i in element.find(namespace + 'x-ablabel'):
txt = i.text txt = i.text
for i in element.find(namespace + 'url'): for i in element.find(namespace + 'url'):
uri = i.text uri = i.text
extra_resources[res].append({'label' : txt, 'uri' : uri}) for i in element.find(namespace + 'url/' + namespace + 'parameters/' + namespace + 'type'):
vcard[res] = extra_resources[res] category = i.text
if not category in vcard['extras']: vcard['extras'][category] = []
vcard['extras'][category].append({'label' : txt, 'uri' : uri})
vcard['alias'] = alias vcard['alias'] = alias
vcard['email'] = email vcard['email'] = email

View file

@ -6,20 +6,55 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" /> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<title>{{brand_name}}: {{action}} {% if title %}{{title}}{% else %}{{jid_bare}}{% endif %}</title> <title>{{brand_name}}: {{action}} {% if alias %}{{alias}}{% else %}{{title}}{% endif %}</title>
<meta name="description" content="{{action}} {{title}}" /> <meta name="description" content="{{action}} {% if alias %}{{alias}}{% else %}{{title}}{% endif %}" />
<meta name="generator" content="Fast And Sleek Invite" /> <meta name="generator" content="Fast And Sleek Invite" />
<meta name="uri" content="{{xmpp_uri}}" /> <meta name="uri" content="{{xmpp_uri}}" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta property="og:description" content="{{action}} {{title}}" /> <meta property="og:description" content="{{action}} {% if alias %}{{alias}}{% else %}{{title}}{% endif %}" />
<meta property="og:image" content="/photo/{{filename}}" /> <meta property="og:image" content="/photo/{{filename}}" />
<meta property="og:site_name" content="{{brand_name}}" /> <meta property="og:site_name" content="{{brand_name}}" />
<meta property="og:title" content="{{title}}" /> <meta property="og:title" content="{% if alias %}{{alias}}{% else %}{{title}}{% endif %}" />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content="{{url}}" /> <meta property="og:url" content="{{url}}" />
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" /> <link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
<link rel="icon" href="/img/favicon.svg" type="image/svg+xml" /> <link rel="icon" href="/img/favicon.svg" type="image/svg+xml" />
<link rel="stylesheet" href="/css/stylesheet.css" media="screen" type="text/css" /> <link rel="stylesheet" href="/css/stylesheet.css" media="screen" type="text/css" />
{% if selection %}
<style>
body {
/* background-repeat: no-repeat; */
background:
url(/img/background.svg),
linear-gradient(
to right,
rgba({{selection[0][2]}}, {{selection[0][1]}}, {{selection[0][0]}}, 0.7),
rgba({{selection[1][2]}}, {{selection[1][1]}}, {{selection[1][0]}}, 0.7)
);
}
@media (prefers-color-scheme: dark) {
body {
background:
url(/img/background.svg),
linear-gradient(
to right,
rgba({{selection[0][2]-50}}, {{selection[0][1]-50}}, {{selection[0][0]-50}}, 0.7),
rgba({{selection[1][2]-50}}, {{selection[1][1]-50}}, {{selection[1][0]-50}}, 0.7)
);
}
}
@media (max-width: 725px) and (prefers-color-scheme: dark) {
body {
background: #2b2a33;
}
}
@media (max-width: 725px) {
body {
background: #f5f5f5;
}
}
</style>
{% endif %}
</head> </head>
<body> <body>
<div id="overlay"> <div id="overlay">
@ -32,9 +67,29 @@
</a> </a>
</div> </div>
<div id="container"> <div id="container">
<div id="content"> <div id="profile">
<h1>{{title}}</h1>
{% if filename %}
<div id="graphics">
<!-- a href="xmpp:{{jid_bare}}" -->
<img id="photo" src="/photo/{{filename}}" />
<img id="qrcode" src="/qr/{{jid_bare}}.png" />
<!-- /a -->
</div>
{% endif %}
<div id="vcard-note">
{% if note %}{{note}}{% endif %}
</div>
<!-- div>
<pre id="xmpp-uri">{{xmpp_uri}}</pre>
</div -->
{% if exception %}
<div>
<code>{{exception}}</code>
</div>
{% endif %}
{% if links %} {% if links %}
<div id="action-bar"> <div id="action">
{% for link in links %} {% for link in links %}
<a href="{{link['href']}}" id="{{link['iden']}}"> <a href="{{link['href']}}" id="{{link['iden']}}">
{{link['name']}} {{link['name']}}
@ -42,31 +97,22 @@
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
<div id="profile-top"> <div id="conference">
{% if filename %}
<img id="photo" src="/photo/{{filename}}" />
{% endif %}
<span id="titles">
<h1>{% if jid_title %}{{jid_title}}{% else %}Group Chat{% endif %}</h1>
<a href="/j/{{jid_bare}}">
<h2>{% if jid_note %}{{jid_note}}{% else %}{{jid_bare}}{% endif %}</h2>
</a>
</span>
<img id="qrcode" src="/qr/{{jid_bare}}.png" />
</div>
<div>
{% if subject %} {% if subject %}
<pre id="subject">{{subject}}</pre> <div id="subject">
{% endif %} <strong>🗣️ Subject</strong>
<pre>{{subject}}</pre>
</div> </div>
{% endif %}
{% if messages %} {% if messages %}
<div id="entries"> <div id="messages">
{% for message in messages %} {% for message in messages %}
<div class="entry" <div class="message"
id="{{message['id']}}"> id="{{message['id']}}">
<a href="#{{message['id']}}" title="{{message['timestamp']}}">💬️</a>
<strong>{{message['alias']}}</strong> <strong>{{message['alias']}}</strong>
<div class="summary">{{message['body']}}</div> <div class="content">{{message['body']}}</div>
<div class="date">{{message['timestamp']}}</div> <!-- div class="date">{{message['timestamp']}}</div -->
<!-- <!--
% if reactions % % if reactions %
<div class="reactions"> <div class="reactions">
@ -80,12 +126,6 @@
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
{% if exception %}
<div>
<code id="exception">{{exception}}</code>
</div>
{% endif %}
</div>
</div> </div>
{% if number_of_pages %} {% if number_of_pages %}
<div id="number-of-pages"> <div id="number-of-pages">
@ -117,6 +157,25 @@
<a href="./">Previous</a> <a href="./">Previous</a>
</div> </div>
{% endif %} {% endif %}
</div>
<div id="notice">
If you already have <strong>{% if news_client and jid_kind == 'pubsub' %}{{news_client}}{% elif chat_client %}{{chat_client}}{% else %}an XMPP Client{% endif %}</strong> you can
<br/>
{% if jid_kind in ('conference', 'mix', 'muc') %}
join to
{% elif jid_kind == 'pubsub' %}
subscribe to
{% elif jid_kind == 'bot' %}
try
{% elif jid_kind == 'server' %}
explore
{% else %}
talk with
{% endif %}
<strong>{{title}}</strong>
right now.
</div>
</div>
{% if message %} {% if message %}
<div id="xmpp-message">{{message}}</div> <div id="xmpp-message">{{message}}</div>
{% endif %} {% endif %}

View file

@ -36,7 +36,7 @@
<a class="system-menu" href="/selection">&lt; Systems</a> <a class="system-menu" href="/selection">&lt; Systems</a>
<h1>{{title}}</h1> <h1>{{title}}</h1>
{% if skipped %} {% if skipped %}
<a class="system-menu" href="/download/{{software}}/all">All clients &gt;</a> <a class="system-menu" href="/download/{{software}}/all">Clients &gt;</a>
{% elif not featured %} {% elif not featured %}
<a class="system-menu" href="/download/{{software}}">Featured &gt;</a> <a class="system-menu" href="/download/{{software}}">Featured &gt;</a>
{% else %} {% else %}
@ -72,12 +72,12 @@
<img src="/img/fdroid.svg" /> <img src="/img/fdroid.svg" />
</a> </a>
<span> <span>
<strong>Recommended:</strong>
We advise installing an XMPP client with the We advise installing an XMPP client with the
<a href="https://f-droid.org">F-Droid</a> repository, to <a href="https://f-droid.org">F-Droid</a> repository, to
ensure that you are always using the most updated and secure ensure that you are always using the most updated and secure
version of your XMPP chat client of choice, with the latest version of your XMPP chat client of choice, with the latest
and best that XMPP has to offer. and best that XMPP has to offer.
<strong>(recommended)</strong>
</span> </span>
</span> </span>
<span class="notice"> <span class="notice">
@ -85,13 +85,13 @@
<img src="/img/plant.svg" /> <img src="/img/plant.svg" />
</a> </a>
<span> <span>
<strong>Optional:</strong>
We further suggest using an updated Android system. If your We further suggest using an updated Android system. If your
smartphone manufacturer has ceased to provide updates, smartphone manufacturer has ceased to provide updates,
then you can install <a href="https://divestos.org">DivestOS then you can install <a href="https://divestos.org">DivestOS
Mobile</a>, <a href="https://grapheneos.org/">GrapheneOS</a> Mobile</a>, <a href="https://grapheneos.org/">GrapheneOS</a>
or find another custom ROM for your device at or find another custom ROM for your device at
<a href="https://customrombay.org">CustomRomBay</a>. <a href="https://customrombay.org">CustomRomBay</a>.
<strong>(optional)</strong>
</span> </span>
</span> </span>
</div> </div>
@ -175,6 +175,7 @@
<dt> <dt>
<a href="{{client['href']}}" id="{{client['iden']}}"> <a href="{{client['href']}}" id="{{client['iden']}}">
<img class="narrow" src="/img/{{client['iden']}}.svg"/> <img class="narrow" src="/img/{{client['iden']}}.svg"/>
<!-- img class="narrow" src="/img/{{client['iden']}}-small.svg"/ -->
<strong>{{client['name']}}</strong> <strong>{{client['name']}}</strong>
</a> </a>
</dt> </dt>

View file

@ -103,12 +103,27 @@
</a> </a>
</div --> </div -->
<div id="count"> <div id="count">
{% if count_item or count_message %} {% if jid_kind in ('conference', 'mix', 'muc') %}
<a href="{{view_href}}">{% if count_item %}{{count_item}} {{instance}}{% elif count_message %}Preview{% endif %}</a> {% if count_message %}
<span></span> <a href="{{view_href}}">
{% if count_item %}
{{count_item}} {{instance}}
{% else %}
Preview
{% endif %}
</a>
{% else %}
<span>
{{count_item}} {{instance}}
</span>
{% endif %}
{% elif count_item %}
<a href="{{view_href}}">
{{instance}}
</a>
{% endif %} {% endif %}
{% if vcard4 %} {% if vcard4 %}
<a href="/c/{{jid_bare}}">my profile</a> <a href="/c/{{jid_bare}}">interests</a>
{% endif %} {% endif %}
</div> </div>
</div> </div>

View file

@ -6,20 +6,55 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" /> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<title>{{brand_name}}: {{action}} {% if title %}{{title}}{% else %}{{jid_bare}}{% endif %}</title> <title>{{brand_name}}: {{action}} {% if alias %}{{alias}}{% else %}{{title}}{% endif %}</title>
<meta name="description" content="{{action}} {{title}}" /> <meta name="description" content="{{action}} {% if alias %}{{alias}}{% else %}{{title}}{% endif %}" />
<meta name="generator" content="Fast And Sleek Invite" /> <meta name="generator" content="Fast And Sleek Invite" />
<meta name="uri" content="{{xmpp_uri}}" /> <meta name="uri" content="{{xmpp_uri}}" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta property="og:description" content="{{action}} {{title}}" /> <meta property="og:description" content="{{action}} {% if alias %}{{alias}}{% else %}{{title}}{% endif %}" />
<meta property="og:image" content="/photo/{{filename}}" /> <meta property="og:image" content="/photo/{{filename}}" />
<meta property="og:site_name" content="{{brand_name}}" /> <meta property="og:site_name" content="{{brand_name}}" />
<meta property="og:title" content="{{title}}" /> <meta property="og:title" content="{% if alias %}{{alias}}{% else %}{{title}}{% endif %}" />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content="{{url}}" /> <meta property="og:url" content="{{url}}" />
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" /> <link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
<link rel="icon" href="/img/favicon.svg" type="image/svg+xml" /> <link rel="icon" href="/img/favicon.svg" type="image/svg+xml" />
<link rel="stylesheet" href="/css/stylesheet.css" media="screen" type="text/css" /> <link rel="stylesheet" href="/css/stylesheet.css" media="screen" type="text/css" />
{% if selection %}
<style>
body {
/* background-repeat: no-repeat; */
background:
url(/img/background.svg),
linear-gradient(
to right,
rgba({{selection[0][2]}}, {{selection[0][1]}}, {{selection[0][0]}}, 0.7),
rgba({{selection[1][2]}}, {{selection[1][1]}}, {{selection[1][0]}}, 0.7)
);
}
@media (prefers-color-scheme: dark) {
body {
background:
url(/img/background.svg),
linear-gradient(
to right,
rgba({{selection[0][2]-50}}, {{selection[0][1]-50}}, {{selection[0][0]-50}}, 0.7),
rgba({{selection[1][2]-50}}, {{selection[1][1]-50}}, {{selection[1][0]-50}}, 0.7)
);
}
}
@media (max-width: 725px) and (prefers-color-scheme: dark) {
body {
background: #2b2a33;
}
}
@media (max-width: 725px) {
body {
background: #f5f5f5;
}
}
</style>
{% endif %}
</head> </head>
<body> <body>
<div id="overlay"> <div id="overlay">
@ -32,9 +67,29 @@
</a> </a>
</div> </div>
<div id="container"> <div id="container">
<div id="content"> <div id="profile">
<h1>{{title}}</h1>
{% if filename %}
<div id="graphics">
<!-- a href="xmpp:{{jid_bare}}" -->
<img id="photo" src="/photo/{{filename}}" />
<img id="qrcode" src="/qr/{{jid_bare}}.png" />
<!-- /a -->
</div>
{% endif %}
<div id="vcard-note">
{% if note %}{{note}}{% endif %}
</div>
<!-- div>
<pre id="xmpp-uri">{{xmpp_uri}}</pre>
</div -->
{% if exception %}
<div>
<code>{{exception}}</code>
</div>
{% endif %}
{% if links %} {% if links %}
<div id="action-bar"> <div id="action">
{% for link in links %} {% for link in links %}
<a href="{{link['href']}}" id="{{link['iden']}}"> <a href="{{link['href']}}" id="{{link['iden']}}">
{{link['name']}} {{link['name']}}
@ -42,31 +97,18 @@
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
<div id="profile-top"> <div id="pubsub">
{% if filename %}
<img id="photo" src="/photo/{{filename}}" />
{% endif %}
<span id="titles">
<h1>{{node_title}}</h1>
<a href="/j/{{jid_bare}}/{{node_name}}">
<h2>{{jid_title}}</h2>
</a>
{% if node_note %}
<h3>
{{node_note}}
</h3>
{% endif %}
</span>
<img id="qrcode" src="/qr/{{jid_bare}}.png" />
</div>
{% if entries %} {% if entries %}
<div id="entries"> <div id="entries">
{% for entry in entries %} {% for entry in entries %}
<div class="entry" <div class="entry"
id="{{entry['id']}}"> id="{{entry['id']}}">
<h3>
<a href="#{{entry['id']}}" title="{{entry['updated'] or entry['published']}}">📜️</a>
<strong>{{entry['title']}}</strong> <strong>{{entry['title']}}</strong>
</h3>
<div class="summary">{{entry['content'] or entry['summary']}}</div> <div class="summary">{{entry['content'] or entry['summary']}}</div>
<div class="date">{{entry['updated'] or entry['published']}}</div> <!-- div class="date">{{entry['updated'] or entry['published']}}</div -->
{% if entry['tags'] %} {% if entry['tags'] %}
<div class="tags"> <div class="tags">
<span>Tags:</span> <span>Tags:</span>
@ -76,20 +118,17 @@
</div> </div>
{% endif %} {% endif %}
<div class="link"> <div class="link">
<a href="{{entry['href']}}">Source</a>
<a href="/d/{{jid_bare}}/{{node_name}}/{{entry['id']}}" <a href="/d/{{jid_bare}}/{{node_name}}/{{entry['id']}}"
title="Permalink (i.e. permanent link)" title="Permalink (i.e. permanent link)."
class="permalink">Permalink</a> class="permalink">Permalink</a>
(<a href="{{entry['href']}}"
title="Source might require an XMPP client.">Source</a>)
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
{% if exception %}
<div>
<code id="exception">{{exception}}</code>
</div> </div>
{% endif %}
{% if number_of_pages %} {% if number_of_pages %}
<div id="number-of-pages"> <div id="number-of-pages">
{% if number_of_pages > 3 %} {% if number_of_pages > 3 %}
@ -117,23 +156,26 @@
{% endif %} {% endif %}
{% if previous %} {% if previous %}
<div id="number-of-pages"> <div id="number-of-pages">
<!-- a href="./">Return to {{node_title}}</a --> <a href="./">Previous</a>
<a href="./">Return</a>
</div> </div>
{% endif %} {% endif %}
<!-- div> </div>
<a id="preview" href="/view/{{jid_bare}}"> <div id="notice">
Preview journal OR Preview group chat If you already have <strong>{% if news_client and jid_kind == 'pubsub' %}{{news_client}}{% elif chat_client %}{{chat_client}}{% else %}an XMPP Client{% endif %}</strong> you can
</a> <br/>
</div --> {% if jid_kind in ('conference', 'mix', 'muc') %}
<!-- div> join to
<a href="{{brand_site}}"> {% elif jid_kind == 'pubsub' %}
<img id="logo-bottom" src="/img/logo-wordmark-vertical.svg" /> subscribe to
</a> {% elif jid_kind == 'bot' %}
</div --> try
<!-- div id="note"> {% elif jid_kind == 'server' %}
The Universal Messaging Standard explore
</div --> {% else %}
talk with
{% endif %}
<strong>{{title}}</strong>
right now.
</div> </div>
</div> </div>
{% if message %} {% if message %}

View file

@ -20,6 +20,41 @@
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" /> <link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
<link rel="icon" href="/img/favicon.svg" type="image/svg+xml" /> <link rel="icon" href="/img/favicon.svg" type="image/svg+xml" />
<link rel="stylesheet" href="/css/stylesheet.css" media="screen" type="text/css" /> <link rel="stylesheet" href="/css/stylesheet.css" media="screen" type="text/css" />
{% if selection %}
<style>
body {
/* background-repeat: no-repeat; */
background:
url(/img/background.svg),
linear-gradient(
to right,
rgba({{selection[0][2]}}, {{selection[0][1]}}, {{selection[0][0]}}, 0.7),
rgba({{selection[1][2]}}, {{selection[1][1]}}, {{selection[1][0]}}, 0.7)
);
}
@media (prefers-color-scheme: dark) {
body {
background:
url(/img/background.svg),
linear-gradient(
to right,
rgba({{selection[0][2]-50}}, {{selection[0][1]-50}}, {{selection[0][0]-50}}, 0.7),
rgba({{selection[1][2]-50}}, {{selection[1][1]-50}}, {{selection[1][0]-50}}, 0.7)
);
}
}
@media (max-width: 725px) and (prefers-color-scheme: dark) {
body {
background: #2b2a33;
}
}
@media (max-width: 725px) {
body {
background: #f5f5f5;
}
}
</style>
{% endif %}
</head> </head>
<body> <body>
<div id="overlay"> <div id="overlay">
@ -36,10 +71,41 @@
<h1> <h1>
{% if 'fn' in vcard_info and vcard_info['fn'] %} {% if 'fn' in vcard_info and vcard_info['fn'] %}
{{vcard_info['fn']}} {{vcard_info['fn']}}
{% elif title %}
{{title}}
{% else %} {% else %}
{{jid_bare}} {{jid_bare}}
{% endif %} {% endif %}
</h1> </h1>
{% if filename %}
<div id="graphics">
<!-- a href="xmpp:{{jid_bare}}" -->
<img id="photo" src="/photo/{{filename}}" />
<img id="qrcode" src="/qr/{{jid_bare}}.png" />
<!-- /a -->
</div>
{% endif %}
<div id="vcard-note">
{% if note %}{{note}}{% endif %}
</div>
<!-- div>
<pre id="xmpp-uri">{{xmpp_uri}}</pre>
</div -->
{% if exception %}
<div>
<code>{{exception}}</code>
</div>
{% endif %}
{% if links %}
<div id="action">
{% for link in links %}
<a href="{{link['href']}}" id="{{link['iden']}}">
{{link['name']}}
</a>
{% endfor %}
</div>
{% endif %}
<div id="vcard">
{% if 'org' in vcard_info and vcard_info['org'] %} {% if 'org' in vcard_info and vcard_info['org'] %}
<h2>{{vcard_info['org']}}</h2> <h2>{{vcard_info['org']}}</h2>
{% endif %} {% endif %}
@ -59,72 +125,36 @@
{% endif %} {% endif %}
</div> </div>
<div id="vcard-links-extra"> <div id="vcard-links-extra">
{% if 'movim' in vcard_info and vcard_info['movim'] %} {% for category in vcard_info['extras'] %}
<h3>Movim</h3> <h3>{{category.title()}}</h3>
{% for i in vcard_info['movim'] %} {% for i in vcard_info['extras'][category] %}
<a href="{{i['uri']}}">{{i['label']}}</a> <a href="{{i['uri']}}">{{i['label']}}</a>
{% endfor %} {% endfor %}
{% endif %}
{% if 'journal' in vcard_info and vcard_info['journal'] %}
<h3>Journal</h3>
{% for i in vcard_info['journal'] %}
<a href="{{i['uri']}}">{{i['label']}}</a>
{% endfor %}
{% endif %}
{% if 'gallery' in vcard_info and vcard_info['gallery'] %}
<h3>Gallery</h3>
{% for i in vcard_info['gallery'] %}
<a href="{{i['uri']}}">{{i['label']}}</a>
{% endfor %}
{% endif %}
{% if 'peertube' in vcard_info and vcard_info['peertube'] %}
<h3>PeerTube</h3>
{% for i in vcard_info['peertube'] %}
<a href="{{i['uri']}}">{{i['label']}}</a>
{% endfor %}
{% endif %}
{% if 'code' in vcard_info and vcard_info['code'] %}
<h3>Code</h3>
{% for i in vcard_info['code'] %}
<a href="{{i['uri']}}">{{i['label']}}</a>
{% endfor %}
{% endif %}
</div>
<div>
{% for i in vcard_info %}
<!-- a href="{{vcard_info[i]}}">{{i}}</a -->
{% endfor %} {% endfor %}
</div> </div>
{% if exception %} </div>
<div> {% if previous %}
<code>{{exception}}</code> <div id="number-of-pages">
<a href="./">Previous</a>
</div> </div>
{% endif %} {% endif %}
{% if links %}
<div id="action">
{% for link in links %}
<a href="{{link['href']}}" id="{{link['iden']}}">
{{link['name']}}
</a>
{% endfor %}
</div>
{% endif %}
<!-- div>
<a id="preview" href="/view/{{jid_bare}}">
Preview journal OR Preview group chat
</a>
</div -->
{% if count or jid_kind in ('conference', 'mix', 'muc') %}
<div id="count">
<a href="{{view_href}}">
{% if count %}
{{count}} {{instance}}
{% elif jid_kind in ('conference', 'mix', 'muc') %}
Preview
{% endif %}
</a>
</div> </div>
<div id="notice">
If you already have <strong>{% if news_client and jid_kind == 'pubsub' %}{{news_client}}{% elif chat_client %}{{chat_client}}{% else %}an XMPP Client{% endif %}</strong> you can
<br/>
{% if jid_kind in ('conference', 'mix', 'muc') %}
join to
{% elif jid_kind == 'pubsub' %}
subscribe to
{% elif jid_kind == 'bot' %}
try
{% elif jid_kind == 'server' %}
explore
{% else %}
talk with
{% endif %} {% endif %}
<strong>{{title}}</strong>
right now.
</div> </div>
</div> </div>
{% if message %} {% if message %}