Before implementing router

This commit is contained in:
sorenpeter 2023-10-08 18:16:33 +02:00
parent e60ca7f0d3
commit 17f4cb6086
15 changed files with 2349 additions and 39 deletions

BIN
avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

1902
error_log Normal file

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@ if ($config['debug_mode']) {
$txt_file_path = $config['txt_file_path'];
require_once('base.php');
require_once('partials/base.php');
/*
if (!has_valid_session()) {

View file

@ -17,6 +17,7 @@ require_once("partials/base.php");
<!-- PHP: GET HEADER --><?php include 'partials/header.php';?>
<main>
<!-- PHP: GET PROFILE CARD -->
<?php
if (!empty($_GET['twts'])) { // Show twts for some user
@ -34,7 +35,6 @@ if (!empty($_GET['twts'])) { // Show twts for some user
}
} ?>
<main class="timeline">
<!-- PHP: GET TIMELIE --><?php include 'partials/timeline.php'?>

155
libs/Slimdown.php Normal file
View file

@ -0,0 +1,155 @@
<?php
/**
* Slimdown - A simple regex-based Markdown parser in PHP. Supports the
* following elements (and can be extended via `Slimdown::add_rule()`):
*
* - Headers
* - Links
* - Bold
* - Emphasis
* - Deletions
* - Quotes
* - Code blocks
* - Inline code
* - Blockquotes
* - Ordered/unordered lists
* - Horizontal rules
* - Images
*
* Author: Johnny Broadway <johnny@johnnybroadway.com>
* Website: https://github.com/jbroadway/slimdown
* License: MIT
*/
class Slimdown {
public static $rules = array (
'/```(.*?)```/s' => self::class .'::code_parse', // code blocks
//'/\n(#+)(.*)/' => self::class .'::header', // headers
'/\n(#\s+)(.*)/' => self::class .'::header', // headers - only with a space between # and text, to avoid matching with `#hashtags`
//'/\!\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::img', // images
'/\!\[(.*?)\]\(([^\)]+)\)/' => self::class .'::img', // images 2
'/\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::link', // links
'/(\*\*|__)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<strong>\2</strong>', // bold
'/(\*|_)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<em>\2</em>', // emphasis
'/(\~\~)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<del>\2</del>', // del
'/\:\"(.*?)\"\:/' => '<q>\1</q>', // quote
'/`(.*?)`/' => '<code>\1</code>', // inline code
'/\n\*(.*)/' => self::class .'::ul_list', // ul lists
'/\n[0-9]+\.(.*)/' => self::class .'::ol_list', // ol lists
'/\n(&gt;|\>)(.*)/' => self::class .'::blockquote', // blockquotes
'/\n-{5,}/' => "\n<hr />", // horizontal rule
'/\n([^\n]+)\n/' => self::class .'::para', // add paragraphs
'/<\/ul>\s?<ul>/' => '', // fix extra ul
'/<\/ol>\s?<ol>/' => '', // fix extra ol
'/<\/blockquote><blockquote>/' => "\n", // fix extra blockquote
'/<a href=\'(.*?)\'>/' => self::class .'::fix_link', // fix links
'/<img src=\'(.*?)\'/' => self::class .'::fix_img', // fix images
'/<p>{{{([0-9]+)}}}<\/p>/s' => self::class .'::reinsert_code_blocks' // re-insert code blocks
);
private static $code_blocks = [];
private static function code_parse ($regs) {
$item = $regs[1];
$item = htmlentities ($item, ENT_COMPAT);
$item = str_replace ("\n\n", '<br>', $item);
$item = str_replace ("\n", '<br>', $item);
while (mb_substr ($item, 0, 4) === '<br>') {
$item = mb_substr ($item, 4);
}
while (mb_substr ($item, -4) === '<br>') {
$item = mb_substr ($item, 0, -4);
}
// Store code blocks with placeholders to avoid other regexes affecting them
self::$code_blocks[] = sprintf ("<pre><code>%s</code></pre>", trim ($item));
return sprintf ("{{{%d}}}", count (self::$code_blocks) - 1);
}
private static function reinsert_code_blocks ($regs) {
// Reinsert the stored code blocks at the end
$index = $regs[1];
return self::$code_blocks[$index];
}
private static function para ($regs) {
$line = $regs[1];
$trimmed = trim ($line);
if (preg_match ('/^<\/?(ul|ol|li|h|p|bl|table|tr|th|td|code)/', $trimmed)) {
return "\n" . $line . "\n";
}
if (! empty ($trimmed)) {
//return sprintf ("\n<p>%s</p>\n", $trimmed);
}
return $trimmed;
}
private static function ul_list ($regs) {
$item = $regs[1];
return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim ($item));
}
private static function ol_list ($regs) {
$item = $regs[1];
return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim ($item));
}
private static function blockquote ($regs) {
$item = $regs[2];
return sprintf ("\n<blockquote>%s</blockquote>", trim ($item));
}
private static function header ($regs) {
list ($tmp, $chars, $header) = $regs;
$level = strlen ($chars);
return sprintf ('<h%d>%s</h%d>', $level, trim ($header), $level);
}
private static function link ($regs) {
list ($tmp, $text, $link) = $regs;
// Substitute _ and * in links so they don't break the URLs
$link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link);
return sprintf ('<a href=\'%s\'>%s</a>', $link, $text);
}
private static function img ($regs) {
list ($tmp, $text, $link) = $regs;
// Substitute _ and * in links so they don't break the URLs
$link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link);
return sprintf ('<img src=\'%s\' alt=\'%s\' />', $link, $text);
}
private static function fix_link ($regs) {
// Replace substitutions so links are preserved
$fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]);
return sprintf ('<a href=\'%s\'>', $fixed_link);
}
private static function fix_img ($regs) {
// Replace substitutions so links are preserved
$fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]);
return sprintf ('<img src=\'%s\'', $fixed_link);
}
/**
* Add a rule.
*/
public static function add_rule ($regex, $replacement) {
self::$rules[$regex] = $replacement;
}
/**
* Render some Markdown into HTML.
*/
public static function render ($text) {
self::$code_blocks = [];
$text = "\n" . $text . "\n";
foreach (self::$rules as $regex => $replacement) {
if (is_callable ( $replacement)) {
$text = preg_replace_callback ($regex, $replacement, $text);
} else {
$text = preg_replace ($regex, $replacement, $text);
}
}
return trim ($text);
}
}

156
libs/_Slimdown.php Normal file
View file

@ -0,0 +1,156 @@
<?php
/**
* Slimdown - A simple regex-based Markdown parser in PHP. Supports the
* following elements (and can be extended via `Slimdown::add_rule()`):
*
* - Headers
* - Links
* - Bold
* - Emphasis
* - Deletions
* - Quotes
* - Code blocks
* - Inline code
* - Blockquotes
* - Ordered/unordered lists
* - Horizontal rules
* - Images
*
* Author: Johnny Broadway <johnny@johnnybroadway.com>
* Website: https://github.com/jbroadway/slimdown
* License: MIT
*/
class Slimdown {
public static $rules = array (
'/```(.*?)```/s' => self::class .'::code_parse', // code blocks
//'/\n(#+)(.*)/' => self::class .'::header', // headers
'/\n(#\s+)(.*)/' => self::class .'::header', // headers - only with a space between # and text, to avoid matching with `#hashtags`
//'/\!\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::img', // images
'/\!\[(.*?)\]\(([^\)]+)\)/' => self::class .'::img', // images 2
'/\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::link', // links
'/(\*\*|__)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<strong>\2</strong>', // bold
'/(\*|_)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<em>\2</em>', // emphasis
'/(\~\~)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<del>\2</del>', // del
'/\:\"(.*?)\"\:/' => '<q>\1</q>', // quote
'/`(.*?)`/' => '<code>\1</code>', // inline code
'/\n\*(.*)/' => self::class .'::ul_list', // ul lists
'/\n[0-9]+\.(.*)/' => self::class .'::ol_list', // ol lists
'/\n(&gt;|\>)(.*)/' => self::class .'::blockquote', // blockquotes
'/\n-{5,}/' => "\n<hr />", // horizontal rule
'/\n([^\n]+)\n/' => self::class .'::para', // add paragraphs
'/<\/ul>\s?<ul>/' => '', // fix extra ul
'/<\/ol>\s?<ol>/' => '', // fix extra ol
'/<\/blockquote><blockquote>/' => "\n", // fix extra blockquote
'/<a href=\'(.*?)\'>/' => self::class .'::fix_link', // fix links
'/<img src=\'(.*?)\'/' => self::class .'::fix_img', // fix images
'/<p>{{{([0-9]+)}}}<\/p>/s' => self::class .'::reinsert_code_blocks' // re-insert code blocks
);
private static $code_blocks = [];
private static function code_parse ($regs) {
$item = $regs[1];
$item = htmlentities ($item, ENT_COMPAT);
$item = str_replace ("\n\n", '<br>', $item);
$item = str_replace ("\n", '<br>', $item);
while (mb_substr ($item, 0, 4) === '<br>') {
$item = mb_substr ($item, 4);
}
while (mb_substr ($item, -4) === '<br>') {
$item = mb_substr ($item, 0, -4);
}
// Store code blocks with placeholders to avoid other regexes affecting them
self::$code_blocks[] = sprintf ("<pre><code>%s</code></pre>", trim ($item));
return sprintf ("{{{%d}}}", count (self::$code_blocks) - 1);
}
private static function reinsert_code_blocks ($regs) {
// Reinsert the stored code blocks at the end
$index = $regs[1];
return self::$code_blocks[$index];
}
private static function para ($regs) {
$line = $regs[1];
$trimmed = trim ($line);
if (preg_match ('/^<\/?(ul|ol|li|h|p|bl|table|tr|th|td|code)/', $trimmed)) {
return "\n" . $line . "\n";
}
if (! empty ($trimmed)) {
//return sprintf ("\n<p>%s</p>\n", $trimmed);
return sprintf ("\n%s\n", $trimmed); // avoind addin <p>-tags and extra vetical margins
}
return $trimmed;
}
private static function ul_list ($regs) {
$item = $regs[1];
return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim ($item));
}
private static function ol_list ($regs) {
$item = $regs[1];
return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim ($item));
}
private static function blockquote ($regs) {
$item = $regs[2];
return sprintf ("\n<blockquote>%s</blockquote>", trim ($item));
}
private static function header ($regs) {
list ($tmp, $chars, $header) = $regs;
$level = strlen ($chars);
return sprintf ('<h%d>%s</h%d>', $level, trim ($header), $level);
}
private static function link ($regs) {
list ($tmp, $text, $link) = $regs;
// Substitute _ and * in links so they don't break the URLs
$link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link);
return sprintf ('<a href=\'%s\'>%s</a>', $link, $text);
}
private static function img ($regs) {
list ($tmp, $text, $link) = $regs;
// Substitute _ and * in links so they don't break the URLs
$link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link);
return sprintf ('<img src=\'%s\' alt=\'%s\' />', $link, $text);
}
private static function fix_link ($regs) {
// Replace substitutions so links are preserved
$fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]);
return sprintf ('<a href=\'%s\'>', $fixed_link);
}
private static function fix_img ($regs) {
// Replace substitutions so links are preserved
$fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]);
return sprintf ('<img src=\'%s\'', $fixed_link);
}
/**
* Add a rule.
*/
public static function add_rule ($regex, $replacement) {
self::$rules[$regex] = $replacement;
}
/**
* Render some Markdown into HTML.
*/
public static function render ($text) {
self::$code_blocks = [];
$text = "\n" . $text . "\n";
foreach (self::$rules as $regex => $replacement) {
if (is_callable ( $replacement)) {
$text = preg_replace_callback ($regex, $replacement, $text);
} else {
$text = preg_replace ($regex, $replacement, $text);
}
}
return trim ($text);
}
}

View file

@ -123,15 +123,17 @@ function replaceMentionsFromTwt(string $twtString): string {
// Example input: 'Hello @<eapl.mx https://eapl.mx/twtxt.txt>, how are you? @<nick https://server.com/something/twtxt.txt>';
// Example output: Hello <a href="?url=https://eapl.mx/twtxt.txt">@eapl.mx@eapl.mx/twtxt.txt</a>, how are you? <a href="?url=https://server.com/something/twtxt.txt">@nick@server.com/something/twtxt.txt</a>
#$pattern = '/@<([^ ]+)\s([^>]+)>/';
#$replacement = '<a href="?url=$2">@$1</a>';
$pattern = '/@<([^ ]+)\s([^>]+)>/';
$replacement = '<a href="?url=$2">@$1</a>';
#$twtString = '@<nick https://eapl.mx/twtxt.txt>';
$pattern = '/@<([^ ]+) ([^>]+)>/';
$replacement = '@$1';
#$pattern = '/@<([^ ]+) ([^>]+)>/';
#$replacement = '@$1';
$result = preg_replace($pattern, $replacement, $twtString);
return $result;
// from https://github.com/hxii/picoblog/blob/master/picoblog.php
//$pattern = '/\@<([a-zA-Z0-9\.]+)\W+(https?:\/\/[^>]+)>/';
//return preg_replace($pattern,'<a href="$2">@$1</a>',$twtString);
}
function replaceLinksFromTwt(string $twtString) {
@ -156,12 +158,23 @@ function replaceMarkdownLinksFromTwt(string $twtString) {
function replaceImagesFromTwt(string $twtString) {
$pattern = '/!\[(.*?)\]\((.*?)\)/';
$replacement = '<img src="$2" alt="$1">';
//$replacement = '<img src="$2" alt="$1">';
$replacement = '<a href="$2"><img src="$2" alt="$1"></a>';
$result = preg_replace($pattern, $replacement, $twtString);
return $result;
}
function replaceTagsFromTwt(string $twtString) {
$pattern = '/#(\w+)?/';
$replacement = '<a href="#">#\1</a>'; // Dummy link
//$replacement = '<a href="?tag=$1" class="tag">#${1}</a>';
$result = preg_replace($pattern, $replacement, $twtString);
return $result;
}
function getTimeElapsedString($timestamp, $full = false) {
$now = new DateTime;
$ago = new DateTime;
@ -320,7 +333,7 @@ function getTwtsFromTwtxtString($url) {
$twtContent = replaceMentionsFromTwt($twtContent);
// Convert HTML problematic characters
$twtContent = htmlentities($twtContent);
//$twtContent = htmlentities($twtContent); // TODO: Messing up rendering of @mentions #BUG
// Replace the Line separator character (U+2028)
// \u2028 is \xE2 \x80 \xA8 in UTF-8
@ -331,8 +344,9 @@ function getTwtsFromTwtxtString($url) {
// that's why I leave the UTF-8 representation for future reference
$twtContent = str_replace("\u{2028}", "\n<br>\n", $twtContent);
$twtContent = replaceLinksFromTwt($twtContent);
$twtContent = replaceImagesFromTwt($twtContent);
$twtContent = replaceMarkdownLinksFromTwt($twtContent);
//$twtContent = replaceMarkdownLinksFromTwt($twtContent);
//$twtContent = replaceImagesFromTwt($twtContent);
$twtContent = Slimdown::render($twtContent);
// Get and remote the hash
$hash = getReplyHashFromTwt($twtContent);
@ -340,10 +354,12 @@ function getTwtsFromTwtxtString($url) {
$twtContent = str_replace("(#$hash)", '', $twtContent);
}
// TODO: Make ?tag= filtering feature
$twtContent = replaceTagsFromTwt($twtContent);
// TODO: Get mentions
$mentions = getMentionsFromTwt($twtContent);
// Get Lang metadata
if (($timestamp = strtotime($dateStr)) === false) {
@ -370,7 +386,7 @@ function getTwtsFromTwtxtString($url) {
$twt->mainURL = $twtxtData->mainURL;
$twtxtData->twts[$timestamp] = $twt;
// TODO: Interpret the content as markdown
// TODO: Interpret the content as markdown -- @DONE using Slimdown.php above
}
}
}

View file

@ -20,6 +20,7 @@ declare(strict_types=1);
require_once("libs/session.php"); // TODO: Move all to base.php
require_once('libs/twtxt.php');
require_once('libs/hash.php');
require_once('libs/Slimdown.php');
const TWTS_PER_PAGE = 50;

View file

@ -1,13 +1,18 @@
<header>
<nav>
<ul>
<li><a href=".">🧶 Timeline</a></li>
<li>🧶 <a href=".">Timeline</a> for
<a href="http://localhost:8000/?twts=http://darch.dk/twtxt.txt">sorenpeter</a>@darch.dk</li> <!-- TODO: make automatic via PHP and show avatar as well -->
<li><?php include 'partials/listSelect.php'; ?></li>
</ul>
<ul class="secondary">
<li><a href="load_twt_files.php?url=<?= $url ?>">Refresh</a></li>
<?php //if ($validSession) { // TODO: Make login seqcure ?>
<?php if( isset($_SESSION['password'])) {
if($_SESSION['password']=="$password") { // Hacky login ?>
<li><a href="new_twt.php">New post</a></li>
<li><a href="follow.php">Add feed</a></li>
<li><a href="/admin">Settings</a></li>
<li><form method="post" action="" id="logout_form">
<input type="submit" name="page_logout" value="Log out" class="link-btn">
</form>
@ -15,7 +20,7 @@
<?php } } else { ?>
<li><a href="login.php">Log in</a></li>
<?php } ?>
<li><?php include 'partials/listSelect.php'; ?></li>
<li><a href="following.php">Following <?php echo count($twtFollowingList); ?> feeds</a></li>
</ul>
</nav>
</header>

View file

@ -5,6 +5,8 @@
<option value="twtxt.txt" selected>twtxt.txt (Main)</option>
<?php
// TODO: fix it so if List -> Selected for both public and private lists
if( isset($_SESSION['password'])) {
if($_SESSION['password']=="$password") { // Hacky login
@ -25,11 +27,11 @@
}
}
foreach (glob("lists/twtxt-*.txt") as $filename) {
foreach (glob("twtxt-*.txt") as $filename) {
if($filename == $_GET['lists']) $attr="selected";
else $attr = "";
$listName = $filename;
$listName = str_replace("lists/twtxt-", "", $listName);
$listName = str_replace("twtxt-", "", $listName);
$listName = str_replace("_", " ", $listName);
$listName = str_replace(".txt", "", $listName);
echo "<option value='{$filename}' {$attr}>$listName</option>";

View file

@ -21,15 +21,6 @@ $profile = getTwtsFromTwtxtString($url);
<blockquote><?= $profile->description ?></blockquote>
<nav>
<ul>
<li><a href="">Posts</a></li>
<li><a href="">Replies</a></li>
<li><a href="">Gallery</a></li>
<li><a target="_blank" href="<?= $profile->mainURL ?>"></i>twtxt.txt</a></li>
</ul>
</nav>
</section>
<!-- <aside>
@ -39,3 +30,12 @@ $profile = getTwtsFromTwtxtString($url);
</aside> -->
</div>
<nav class="profile">
<ul>
<li><a href="">Posts</a></li>
<li><a href="">Replies</a></li>
<li><a href="">Gallery</a></li>
<li><a target="_blank" href="<?= $profile->mainURL ?>"></i>twtxt.txt</a></li>
</ul>
</nav>

View file

@ -7,28 +7,32 @@
</center> -->
<?php foreach ($twts as $twt) { ?>
<article class="post-entry">
<a href="?twts=<?= $twt->mainURL ?>">
<img src='<?= $twt->avatar ?>' class="avatar" onerror="this.onerror=null;this.src='imgs/image_not_found.png';">
</a>
<div class="">
<div>
<a href="?twts=<?= $twt->mainURL ?>" class="author">
<strong><?= $twt->nick ?></strong>@<?= parse_url($twt->mainURL, PHP_URL_HOST); ?>
</a>
<div class="twt-msg">
<?= $twt->content ?>
<!-- Not sure what this does...
<?php foreach ($twt->mentions as $mention) { ?>
<br><?= $mention['nick'] ?>(<?= $mention['url'] ?>)
<?php } ?>
-->
</div>
<small>
<?php if($twt->replyToHash) { ?>
<a href="?hash=<?= $twt->replyToHash?>">Conversation</a> |
<?php } ?>
<!-- TODO make depending on session or nor -->
<a href="new_twt.php?hash=<?= $twt->hash ?>">Reply</a>
(<a href="new_twt.php?hash=<?= $twt->hash ?>">via email</a>)
<a href='?hash=<?= $twt->hash ?>' class="right"><span title="<?= $twt->fullDate ?> "><?= $twt->displayDate ?></span></a>
</small>
</div>

View file

@ -40,4 +40,4 @@ totp_secret = "LZM25BDJPRVTNFZQBDOPQKFSKUAAS6BI"
secure_cookies = true
; Simple password for unnamed user
password = ""
password = "brandbil"

View file

@ -25,13 +25,23 @@
body {
background-color: var(--code-bg);
font-family: sans-serif;
/* max-width: 700px;
margin: 1rem auto; */
line-height: 1.25;
}
main {
max-width: 700px;
margin: 1rem auto;
line-height: 1.25;
}
a, button, body, h1, h2, h3, h4, h5, h6 {
color: var(--primary);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* == Forms (from https://adi.tilde.institute/default.css/) ==================== */
@ -111,14 +121,19 @@ fieldset {
hr {
background: var(--border-color);
background: var(--border);
border: 0;
height: 1px;
width: 100%;
}
header {
margin-bottom: 2rem;
border-bottom: thin solid var(--tertiary);
}
nav {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
@ -132,8 +147,22 @@ nav ul {
display: flex;
justify-content: space-between;
padding-left: 0.5rem;
margin: 0.25rem 0rem;
}
nav ul.secondary {
padding: 0 0.75rem;
font-size: small;
}
/*
nav ul.secondary a {
text-decoration: underline;
font-weight: normal;
}
*/
nav ul li {
display: inline-block;
list-style: none;
@ -155,9 +184,11 @@ nav .link-btn {
cursor: pointer;
margin: 0;
padding: 0;
width: 100%;
color: var(--primary);
font-weight: bold;
/*text-decoration: underline;*/
border-radius: 0;
}
img {
@ -203,11 +234,29 @@ a.author {
color: var(--secondary);
}
.profile nav a {
/*.profile nav a {
font-size: small;
text-decoration: underline;
}*/
nav.profile {
padding: 0;
/* display: flex;*/
/* justify-content: space-around;*/
}
nav.profile a {
/* font-size: small;*/
/* text-decoration: underline;*/
/* border: thin solid var(--border);
border-radius: var(--radius);
background-color: var(--entry);
padding: 0.5rem 1rem;*/
margin: 0 0.5rem;
}
article {
background-color: var(--entry);
color: var(--secondary);
@ -227,6 +276,18 @@ article .twt-msg {
padding: 0.5rem 0;
}
article .twt-msg a{
text-decoration: underline;
}
article .twt-msg > blockquote {
margin: 0;
border-left: thick solid var(--border);
padding: 0.25rem 0.5rem;
display: inline-block;
font-style: italic;
}
article .twt-msg img {
margin: 0.25rem -0.25rem;
border: thin solid var(--border);
@ -241,11 +302,19 @@ article .twt-msg > img:last-child {
}
article small {
padding-left: 0.15rem ;
/* padding-left: 0.15rem;*/
}
article small .right{
/*
article small a {
text-decoration: none;
font-weight: bold;
}
*/
article small a.right {
padding-right: 0.25rem;
font-weight: normal;
}
nav.pagnation {