2022-11-25 21:34:46 +01:00
< ? php
/*
2022-11-29 22:17:34 +01:00
Plugin Name : Include Mastodon Feed
2022-12-03 22:19:54 +01:00
Plugin URI : https :// wolfgang . lol / code / include - mastodon - feed - wordpress - plugin
2022-11-29 22:17:34 +01:00
Description : Plugin providing [ include - mastodon - feed ] shortcode
2025-05-16 12:24:18 +02:00
Version : 1.13 . 1
2022-11-25 21:34:46 +01:00
Author : wolfgang . lol
2022-12-03 22:19:54 +01:00
Author URI : https :// wolfgang . lol
2024-11-23 22:40:25 +01:00
License : MIT
License URI : https :// directory . fsf . org / wiki / License : Expat
2022-11-25 21:34:46 +01:00
*/
2023-05-02 15:26:03 +02:00
namespace IncludeMastodonFeedPlugin ;
2023-05-02 15:05:48 +02:00
2022-11-25 23:25:21 +01:00
// set defaults
$constants = [
[
2022-12-09 15:18:39 +01:00
'key' => 'INCLUDE_MASTODON_FEED_DEBUG' ,
'value' => false ,
2022-11-25 23:25:21 +01:00
],
[
2022-11-29 22:17:34 +01:00
'key' => 'INCLUDE_MASTODON_FEED_DEFAULT_INSTANCE' ,
'value' => false ,
2022-11-25 23:25:21 +01:00
],
2022-12-09 15:36:17 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_LIMIT' ,
'value' => 20 ,
],
2022-12-07 22:47:42 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_EXCLUDE_BOOSTS' ,
'value' => false ,
],
[
'key' => 'INCLUDE_MASTODON_FEED_EXCLUDE_REPLIES' ,
'value' => false ,
],
2023-06-23 20:22:24 +02:00
[
'key' => 'INCLUDE_MASTODON_FEED_EXCLUDE_CONVERSATIONSTARTERS' ,
'value' => false ,
],
2022-12-07 22:47:42 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_ONLY_PINNED' ,
'value' => false ,
],
[
'key' => 'INCLUDE_MASTODON_FEED_ONLY_MEDIA' ,
'value' => false ,
],
2024-06-20 16:56:27 +02:00
[
'key' => 'INCLUDE_MASTODON_FEED_PRESERVE_IMAGE_ASPECT_RATIO' ,
'value' => false ,
],
2024-11-16 01:03:41 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_IMAGE_SIZE' ,
'value' => 'preview' ,
],
2024-11-16 02:10:14 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_IMAGE_LINK' ,
'value' => 'status' ,
],
2022-12-09 14:55:36 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_TAGGED' ,
'value' => false ,
],
2022-12-09 15:18:39 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_LINKTARGET' ,
'value' => '_self' ,
],
2023-05-02 15:23:24 +02:00
[
'key' => 'INCLUDE_MASTODON_FEED_SHOW_PREVIEWCARDS' ,
'value' => true ,
],
2022-12-03 23:24:07 +01:00
// set styles
2022-11-25 23:25:21 +01:00
[
2022-12-07 22:47:42 +01:00
'key' => 'INCLUDE_MASTODON_FEED_DARKMODE' ,
'value' => false ,
],
[
'key' => 'INCLUDE_MASTODON_FEED_STYLE_BG_LIGHT_COLOR' ,
'value' => 'rgba(100, 100, 100, 0.15)' ,
2022-11-25 23:25:21 +01:00
],
[
2022-12-07 22:47:42 +01:00
'key' => 'INCLUDE_MASTODON_FEED_STYLE_BG_DARK_COLOR' ,
'value' => 'rgba(155, 155, 155, 0.15)' ,
2022-11-25 23:25:21 +01:00
],
[
2022-12-07 22:47:42 +01:00
'key' => 'INCLUDE_MASTODON_FEED_STYLE_ACCENT_COLOR' ,
2025-05-15 14:26:37 +02:00
'value' => 'rgb(86, 58, 204)' ,
2022-11-25 23:25:21 +01:00
],
[
2022-12-07 22:47:42 +01:00
'key' => 'INCLUDE_MASTODON_FEED_STYLE_ACCENT_FONT_COLOR' ,
'value' => 'rgb(255, 255, 255)' ,
2022-11-25 23:25:21 +01:00
],
[
2022-12-07 22:47:42 +01:00
'key' => 'INCLUDE_MASTODON_FEED_STYLE_BORDER_RADIUS' ,
'value' => '0.25rem' ,
2022-11-25 23:25:21 +01:00
],
2024-06-20 16:56:27 +02:00
[
'key' => 'INCLUDE_MASTODON_FEED_HIDE_STATUS_META' ,
'value' => false ,
],
[
'key' => 'INCLUDE_MASTODON_FEED_HIDE_DATETIME' ,
'value' => false ,
],
2022-12-08 02:28:04 +01:00
// set texts and localization
2022-12-03 23:24:07 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_TEXT_LOADING' ,
'value' => 'Loading Mastodon feed...' ,
],
2023-06-23 21:36:00 +02:00
[
'key' => 'INCLUDE_MASTODON_FEED_TEXT_NO_STATUSES' ,
2025-04-16 19:50:58 +02:00
'value' => 'No statuses available' ,
2023-06-23 21:36:00 +02:00
],
2022-12-03 23:24:07 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_TEXT_BOOSTED' ,
'value' => 'boosted 🚀' ,
],
[
'key' => 'INCLUDE_MASTODON_FEED_TEXT_VIEW_ON_INSTANCE' ,
'value' => 'view on instance' ,
],
2022-12-07 17:01:50 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_TEXT_SHOW_CONTENT' ,
'value' => 'Show content' ,
],
2023-04-09 14:02:31 +02:00
[
'key' => 'INCLUDE_MASTODON_FEED_TEXT_PERMALINK_PRE' ,
'value' => 'on' ,
],
[
'key' => 'INCLUDE_MASTODON_FEED_TEXT_PERMALINK_POST' ,
'value' => '' ,
],
[
'key' => 'INCLUDE_MASTODON_FEED_TEXT_EDITED' ,
'value' => '(edited)' ,
],
2022-12-08 02:28:04 +01:00
[
'key' => 'INCLUDE_MASTODON_FEED_DATE_LOCALE' ,
'value' => 'en-US' ,
],
[
'key' => 'INCLUDE_MASTODON_FEED_DATE_OPTIONS' ,
'value' => " { } " ,
],
2022-11-25 23:25:21 +01:00
];
foreach ( $constants as $constant ) {
if ( ! defined ( $constant [ 'key' ])) {
define ( $constant [ 'key' ], $constant [ 'value' ]);
}
}
unset ( $constants );
2022-11-25 21:34:46 +01:00
2023-05-02 15:05:48 +02:00
function error ( $msg ) {
2022-11-29 22:17:34 +01:00
return '[include-mastodon-feed] ' . $msg ;
2022-11-25 21:34:46 +01:00
}
2023-05-02 15:05:48 +02:00
function init_styles () {
2022-11-25 21:34:46 +01:00
?>
< style >
: root {
2022-12-08 02:28:04 +01:00
-- include - mastodon - feed - bg - light : < ? php echo filter_var ( INCLUDE_MASTODON_FEED_STYLE_BG_LIGHT_COLOR , FILTER_UNSAFE_RAW ); ?> ;
-- include - mastodon - feed - bg - dark : < ? php echo filter_var ( INCLUDE_MASTODON_FEED_STYLE_BG_DARK_COLOR , FILTER_UNSAFE_RAW ); ?> ;
-- include - mastodon - feed - accent - color : < ? php echo filter_var ( INCLUDE_MASTODON_FEED_STYLE_ACCENT_COLOR , FILTER_UNSAFE_RAW ); ?> ;
-- include - mastodon - feed - accent - font - color : < ? php echo filter_var ( INCLUDE_MASTODON_FEED_STYLE_ACCENT_FONT_COLOR , FILTER_UNSAFE_RAW ); ?> ;
-- include - mastodon - feed - border - radius : < ? php echo filter_var ( INCLUDE_MASTODON_FEED_STYLE_BORDER_RADIUS , FILTER_UNSAFE_RAW ); ?> ;
2022-11-25 21:34:46 +01:00
}
2025-05-15 14:26:37 +02:00
. include - mastodon - feed - wrapper . include - mastodon - feed {
list - style : none ;
padding - left : 0 ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . status {
2025-05-15 14:26:37 +02:00
display : block ;
2022-11-25 21:34:46 +01:00
margin : 0.5 rem 0 1.5 rem ;
2022-11-29 22:17:34 +01:00
border - radius : var ( -- include - mastodon - feed - border - radius );
2022-11-25 21:34:46 +01:00
padding : 0.5 rem ;
2022-11-29 22:17:34 +01:00
background : var ( -- include - mastodon - feed - bg - light );
2022-11-25 21:34:46 +01:00
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . status a {
color : var ( -- include - mastodon - feed - accent - color );
2022-11-25 21:34:46 +01:00
text - decoration : none ;
2023-06-23 19:22:17 +02:00
word - wrap : break - word ;
2022-11-25 21:34:46 +01:00
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . status a : hover {
2022-11-25 21:34:46 +01:00
text - decoration : underline ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . avatar {
2025-05-15 14:26:37 +02:00
display : inline - block ;
2022-11-25 21:34:46 +01:00
height : 1.25 rem ;
2022-11-29 22:17:34 +01:00
border - radius : var ( -- include - mastodon - feed - border - radius );
2022-11-25 21:34:46 +01:00
vertical - align : top ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . account {
2022-11-25 21:34:46 +01:00
font - size : 0.8 rem ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . account a {
2022-11-25 21:34:46 +01:00
display : inline - block ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . account . booster {
2022-11-25 21:34:46 +01:00
float : right ;
font - style : italic ;
}
2022-12-08 02:40:59 +01:00
. include - mastodon - feed . boosted . account > a : first - child ,
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . contentWarning a {
border - radius : var ( -- include - mastodon - feed - border - radius );
2022-11-25 21:34:46 +01:00
padding : 0.15 rem 0.5 rem ;
2022-11-29 22:17:34 +01:00
background : var ( -- include - mastodon - feed - accent - color );
color : var ( -- include - mastodon - feed - accent - font - color );
2022-11-25 21:34:46 +01:00
}
2022-12-08 02:40:59 +01:00
. include - mastodon - feed . boosted . account > a : first - child : hover ,
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . contentWarning a : hover {
border - radius : var ( -- include - mastodon - feed - border - radius );
2022-11-25 21:34:46 +01:00
padding : 0.15 rem 0.5 rem ;
2022-11-29 22:17:34 +01:00
background : var ( -- include - mastodon - feed - accent - font - color );
color : var ( -- include - mastodon - feed - accent - color );
2022-11-25 21:34:46 +01:00
text - decoration : none ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . contentWrapper . boosted {
2022-11-25 21:34:46 +01:00
margin : 0.5 rem 0 ;
padding : 0.5 rem ;
2022-11-29 22:17:34 +01:00
background : var ( -- include - mastodon - feed - bg - light );
2022-11-25 21:34:46 +01:00
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . contentWarning {
2022-11-25 21:34:46 +01:00
text - align : center ;
margin : 1 rem ;
padding : 1 rem ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . contentWarning . title {
2022-11-25 21:34:46 +01:00
font - weight : bold ;
}
2022-12-08 10:09:01 +01:00
. include - mastodon - feed img . emoji {
2022-11-26 20:13:26 +01:00
height : 1 rem ;
}
2022-12-08 02:28:04 +01:00
. include - mastodon - feed . content . invisible {
display : none ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . media {
2022-11-25 21:34:46 +01:00
display : flex ;
2025-05-15 14:26:37 +02:00
list - style : none ;
padding : 0 ;
2022-11-25 21:34:46 +01:00
justify - content : space - around ;
align - items : center ;
flex - wrap : wrap ;
gap : 0.5 rem ;
margin : 1 rem ;
}
2025-05-15 14:26:37 +02:00
. include - mastodon - feed . media > * {
display : block ;
2023-07-05 13:31:14 +02:00
flex - basis : calc ( 50 % - 0.5 rem );
flex - grow : 1 ;
}
. include - mastodon - feed . media > . image {
2022-11-25 21:34:46 +01:00
font - size : 0.8 rem ;
font - weight : bold ;
text - align : center ;
}
2023-07-05 13:31:14 +02:00
. include - mastodon - feed . media > . image a {
2022-11-29 22:17:34 +01:00
border - radius : var ( -- include - mastodon - feed - border - radius );
2023-06-23 19:22:17 +02:00
display : block ;
aspect - ratio : 1.618 ;
background - size : cover ;
background - position : center ;
2024-06-20 16:56:27 +02:00
}
. include - mastodon - feed . media > . image a : hover {
2023-06-23 19:22:17 +02:00
filter : contrast ( 110 % ) brightness ( 130 % ) saturate ( 130 % );
2022-11-25 21:34:46 +01:00
}
2024-06-20 16:56:27 +02:00
. include - mastodon - feed . media > . image a img {
width : 100 % ;
}
2023-07-05 13:31:14 +02:00
. include - mastodon - feed . media > . gifv video {
max - width : 100 % ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . card {
border - radius : var ( -- include - mastodon - feed - border - radius );
2022-11-25 21:34:46 +01:00
margin : 1 rem 0.5 rem ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . card iframe {
border - radius : var ( -- include - mastodon - feed - border - radius );
2022-11-25 21:34:46 +01:00
width : 100 % ;
height : 100 % ;
aspect - ratio : 2 / 1.25 ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . card a {
border - radius : var ( -- include - mastodon - feed - border - radius );
2022-11-25 21:34:46 +01:00
display : block ;
text - decoration : none ;
color : #000;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . dark . card a {
2022-11-25 23:10:55 +01:00
color : #fff;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . card a : hover {
2022-11-25 21:34:46 +01:00
text - decoration : none ;
2022-11-29 22:17:34 +01:00
background : var ( -- include - mastodon - feed - accent - color );
color : var ( -- include - mastodon - feed - accent - font - color );
2022-11-25 21:34:46 +01:00
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . card . meta {
background : var ( -- include - mastodon - feed - bg - light );
2022-11-25 21:34:46 +01:00
font - size : 0.8 rem ;
padding : 1 rem ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . card . image {
2022-11-25 21:34:46 +01:00
margin - bottom : 0.5 rem ;
text - align : center ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . card . image img {
2022-11-25 21:34:46 +01:00
max - width : 75 % ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . card . title {
2022-11-25 21:34:46 +01:00
font - weight : bold ;
}
2022-11-29 22:17:34 +01:00
. include - mastodon - feed . dark . status ,
. include - mastodon - feed . dark . contentWrapper . boosted ,
. include - mastodon - feed . dark . card {
background : var ( -- include - mastodon - feed - bg - dark );
2022-11-25 21:34:46 +01:00
}
</ style >
< ? php
}
2023-05-02 15:05:48 +02:00
add_action ( 'wp_head' , __NAMESPACE__ . '\init_styles' , 7 );
2022-11-25 21:34:46 +01:00
2023-05-02 15:05:48 +02:00
function init_scripts () {
2022-11-25 21:34:46 +01:00
?>
< script >
const mastodonFeedCreateElement = function ( type , className = null ) {
let element = document . createElement ( type );
if ( null !== className ) {
element . className = className ;
}
return element ;
}
2022-11-26 19:48:46 +01:00
const mastodonFeedCreateElementAccountLink = function ( account ) {
2022-11-25 21:34:46 +01:00
let accountLinkElem = mastodonFeedCreateElement ( 'a' );
accountLinkElem . href = account . url ;
2025-05-15 14:26:37 +02:00
accountLinkElem . setAttribute ( 'aria-label' , 'Link to Mastodon account of ' + account . display_name );
2022-11-25 21:34:46 +01:00
let accountImageElem = mastodonFeedCreateElement ( 'img' , 'avatar' );
2022-12-03 22:19:54 +01:00
accountImageElem . src = account . avatar_static ;
2025-05-07 16:19:53 +02:00
accountImageElem . loading = 'lazy' ;
2025-05-15 14:26:37 +02:00
accountImageElem . alt = 'Mastodon avatar image of ' + account . display_name ;
2022-12-03 22:19:54 +01:00
accountLinkElem . addEventListener ( 'mouseover' , ( event ) => {
accountLinkElem . querySelector ( '.avatar' ) . src = account . avatar ;
});
accountLinkElem . addEventListener ( 'mouseout' , ( event ) => {
accountLinkElem . querySelector ( '.avatar' ) . src = account . avatar_static ;
});
2022-11-25 21:34:46 +01:00
accountLinkElem . appendChild ( accountImageElem );
2022-11-26 20:13:26 +01:00
// inject emojis
let displayName = account . display_name ;
if ( account . emojis . length > 0 ) {
account . emojis . forEach ( function ( emoji ) {
displayName = mastodonFeedInjectEmoji ( displayName , emoji );
});
}
2022-11-26 20:15:24 +01:00
accountLinkElem . innerHTML += ' ' + displayName ;
2022-11-25 21:34:46 +01:00
return accountLinkElem ;
}
2025-05-15 14:26:37 +02:00
const mastodonFeedCreateElementPermalink = function ( status , label , ariaLabel ) {
2022-11-26 19:48:46 +01:00
let linkElem = mastodonFeedCreateElement ( 'a' );
linkElem . href = status . url ;
2022-12-03 23:24:07 +01:00
linkElem . appendChild ( document . createTextNode ( label ));
2025-05-15 14:26:37 +02:00
linkElem . setAttribute ( 'aria-label' , ariaLabel );
2022-11-26 19:48:46 +01:00
return linkElem ;
}
2022-12-07 16:42:26 +01:00
const mastodonFeedCreateElementMediaAttachments = function ( status , options ) {
let attachments = status . media_attachments ;
2025-05-15 14:26:37 +02:00
let mediaWrapperElem = mastodonFeedCreateElement ( 'ol' , 'media' );
2022-11-26 19:48:46 +01:00
for ( let mediaIndex = 0 ; mediaIndex < attachments . length ; mediaIndex ++ ) {
let media = attachments [ mediaIndex ];
2025-05-15 14:26:37 +02:00
let mediaElem = mastodonFeedCreateElement ( 'li' , media . type );
2022-11-26 19:48:46 +01:00
if ( 'image' == media . type ) {
2023-02-22 13:58:55 +01:00
let mediaElemImgLink = mastodonFeedCreateElement ( 'a' );
2024-11-16 01:03:41 +01:00
let imageUrl = media . url ;
2025-05-08 11:57:40 +02:00
if ( 'full' !== options . images . size && null !== media . preview_url ) {
2024-11-16 01:03:41 +01:00
imageUrl = media . preview_url ;
2022-11-26 19:48:46 +01:00
}
2024-11-16 01:03:41 +01:00
mediaElemImgLink . href = status . url ;
2024-11-16 02:10:14 +01:00
if ( 'image' === options . images . link ) {
mediaElemImgLink . href = media . remote_url ? ? media . url ;
}
2025-05-15 14:26:37 +02:00
let mediaElemImgImage = mastodonFeedCreateElement ( 'img' );
mediaElemImgImage . src = imageUrl ;
mediaElemImgImage . loading = 'lazy' ;
if ( null === media . description ) {
mediaElemImgImage . alt = 'Image attachment of Mastodon post' ;
2024-06-20 16:56:27 +02:00
}
2025-05-07 16:19:53 +02:00
else {
2025-05-15 14:26:37 +02:00
mediaElemImgImage . alt = media . description ;
}
if ( ! options . images . preserveImageAspectRatio ) {
2025-05-07 16:19:53 +02:00
mediaElemImgLink . style . backgroundImage = 'url("' + imageUrl + '")' ;
2025-05-15 14:26:37 +02:00
mediaElemImgImage . style . width = '100%' ;
mediaElemImgImage . style . height = '100%' ;
mediaElemImgImage . style . opacity = 0 ;
2025-05-07 16:19:53 +02:00
}
2025-05-15 14:26:37 +02:00
mediaElemImgLink . appendChild ( mediaElemImgImage );
2023-02-22 13:58:55 +01:00
mediaElem . appendChild ( mediaElemImgLink );
2022-11-26 19:48:46 +01:00
}
2022-12-07 16:42:26 +01:00
else if ( 'gifv' == media . type ) {
2023-02-22 13:58:55 +01:00
let mediaElemGifvLink = mastodonFeedCreateElement ( 'a' );
mediaElemGifvLink . href = status . url ;
2022-12-08 02:28:04 +01:00
let mediaElemGifv = mastodonFeedCreateElement ( 'video' , 'requiresInteraction' );
2022-12-07 16:42:26 +01:00
if ( null === media . remote_url ) {
2022-12-08 02:28:04 +01:00
mediaElemGifv . src = media . url ;
2022-12-07 16:42:26 +01:00
}
else {
mediaElemGifv . src = media . remote_url ;
}
2022-12-08 02:28:04 +01:00
mediaElemGifv . loop = true ;
2023-07-05 13:31:14 +02:00
mediaElemGifv . muted = 'muted' ;
2025-05-15 14:26:37 +02:00
if ( null === media . description ) {
mediaElemGifv . alt = 'Video attachment of Mastodon post' ;
}
else {
2025-05-09 11:38:39 +02:00
mediaElemGifv . alt = media . description ;
2022-12-07 16:42:26 +01:00
}
2023-02-22 13:58:55 +01:00
mediaElemGifvLink . appendChild ( mediaElemGifv );
mediaElem . appendChild ( mediaElemGifvLink );
2022-12-08 02:28:04 +01:00
2023-07-05 13:31:14 +02:00
mediaElemGifv . addEventListener ( 'mouseover' , ( event ) => {
mediaElemGifv . play ();
2022-12-08 02:28:04 +01:00
});
mediaElemGifv . addEventListener ( 'mouseout' , ( event ) => {
mediaElemGifv . pause ();
mediaElemGifv . currentTime = 0 ;
});
2022-12-07 16:42:26 +01:00
}
2022-11-26 19:48:46 +01:00
else {
// TODO implement support for other media types
2022-12-07 22:47:42 +01:00
// currently only image and gifv support implemented
2022-11-26 19:48:46 +01:00
mediaElem . innerHTML = 'Stripped ' + media . type + ' - only available on instance<br />' ;
2022-12-07 16:42:26 +01:00
let permalinkElem = mastodonFeedCreateElement ( 'span' , 'permalink' );
2025-05-15 14:26:37 +02:00
permalinkElem . appendChild ( mastodonFeedCreateElementPermalink ( status , options . text . viewOnInstance , 'Link to Mastodon post' ));
2022-11-26 19:48:46 +01:00
mediaElem . appendChild ( permalinkElem );
}
mediaWrapperElem . appendChild ( mediaElem );
}
return mediaWrapperElem ;
}
const mastodonFeedCreateElementPreviewCard = function ( card ) {
let cardElem = mastodonFeedCreateElement ( 'div' , 'card' );
if ( null === card . html || card . html . length < 1 ) {
let cardElemMeta = mastodonFeedCreateElement ( 'div' , 'meta' );
if ( null !== card . image ) {
let cardElemImageWrapper = mastodonFeedCreateElement ( 'div' , 'image' );
let cardElemImage = mastodonFeedCreateElement ( 'img' );
2025-05-15 14:26:37 +02:00
if ( null === card . image_description ) {
cardElemImage . alt = 'Preview image content card' ;
}
else {
cardElemImage . alt = card . image_description ;
}
2022-11-26 19:48:46 +01:00
cardElemImage . src = card . image ;
2025-05-07 16:19:53 +02:00
cardElemImage . loading = 'lazy' ;
2022-11-26 19:48:46 +01:00
cardElemImageWrapper . appendChild ( cardElemImage );
cardElemMeta . appendChild ( cardElemImageWrapper );
}
let cardElemTitle = mastodonFeedCreateElement ( 'div' , 'title' );
cardElemTitle . innerHTML = card . title ;
cardElemMeta . appendChild ( cardElemTitle );
let cardElemDescription = mastodonFeedCreateElement ( 'div' , 'description' );
cardElemDescription . innerHTML = card . description ;
cardElemMeta . appendChild ( cardElemDescription );
if ( card . url === null ) {
cardElem . appendChild ( cardElemMeta );
}
else {
let cardElemLink = mastodonFeedCreateElement ( 'a' );
cardElemLink . href = card . url ;
2025-05-15 14:26:37 +02:00
cardElemLink . setAttribute ( 'aria-label' , 'Link embedded in Mastodon post' );
2022-11-26 19:48:46 +01:00
cardElemLink . appendChild ( cardElemMeta );
cardElem . appendChild ( cardElemLink );
}
}
else {
cardElem . innerHTML = card . html ;
}
return cardElem ;
}
2022-12-08 02:28:04 +01:00
const mastodonFeedCreateElementTimeinfo = function ( status , options , url = false ) {
let createdInfo = mastodonFeedCreateElement ( 'span' , 'permalink' );
2023-04-09 14:02:31 +02:00
createdInfo . innerHTML = ' ' + options . text . permalinkPre + ' ' ;
2022-12-08 02:28:04 +01:00
if ( false === url ) {
createdInfo . innerHTML += new Date ( status . created_at ) . toLocaleString ( options . localization . date . locale , options . localization . date . options );
}
else {
2025-05-15 14:26:37 +02:00
createdInfo . appendChild ( mastodonFeedCreateElementPermalink ( status , new Date ( status . created_at ) . toLocaleString ( options . localization . date . locale , options . localization . date . options ), 'Link to Mastodon post' ));
2022-12-08 02:28:04 +01:00
}
2024-06-20 16:56:27 +02:00
createdInfo . innerHTML += ' ' + options . text . permalinkPost ;
2022-11-25 21:34:46 +01:00
return createdInfo ;
}
2022-11-26 20:13:26 +01:00
const mastodonFeedInjectEmoji = function ( string , emoji ) {
2024-06-20 16:56:27 +02:00
return string . replaceAll ( ':' + emoji . shortcode + ':' , '<img class="emoji" src="' + emoji . url + '" title="' + emoji . shortcode + '" />' );
2022-11-26 20:13:26 +01:00
}
2022-12-03 23:24:07 +01:00
const mastodonFeedRenderStatuses = function ( statuses , rootElem , options ) {
2023-06-23 21:36:00 +02:00
if ( statuses . length < 1 ) {
rootElem . innerHTML = options . text . noStatuses ;
}
else {
for ( let i = 0 ; i < statuses . length ; i ++ ) {
let status = statuses [ i ];
let isEdited = ( null === status . edited_at ? true : false );
let isReblog = ( null === status . reblog ? false : true );
2022-11-25 21:34:46 +01:00
2025-05-15 14:26:37 +02:00
let statusElem = mastodonFeedCreateElement ( 'li' , 'status' );
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
// add account meta info
2024-06-20 16:56:27 +02:00
if ( ! options . content . hideStatusMeta ) {
let accountElem = mastodonFeedCreateElement ( 'div' , 'account' );
if ( isReblog ) {
let boosterElem = mastodonFeedCreateElement ( 'span' , 'booster' );
boosterElem . appendChild ( document . createTextNode ( options . text . boosted ));
accountElem . appendChild ( boosterElem );
}
accountElem . appendChild ( mastodonFeedCreateElementAccountLink ( status . account ));
if ( ! options . content . hideDateTime ) {
accountElem . appendChild ( mastodonFeedCreateElementTimeinfo ( status , options , ( isReblog ? false : status . url )));
}
if ( null !== status . edited_at ) {
accountElem . innerHTML += ' ' + options . text . edited ;
}
statusElem . appendChild ( accountElem );
2023-06-23 21:36:00 +02:00
}
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
// prepare content rendering
let showStatus = status ;
if ( isReblog ) {
showStatus = status . reblog ;
}
let contentWrapperElem = mastodonFeedCreateElement ( 'div' , 'contentWrapper' + ( isReblog ? ' boosted' : '' ));
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
// add boosted post meta info
if ( isReblog ) {
let boostElem = mastodonFeedCreateElement ( 'div' , 'account' );
let boostAccountLink = mastodonFeedCreateElementAccountLink ( showStatus . account );
boostElem . appendChild ( boostAccountLink );
boostElem . appendChild ( mastodonFeedCreateElementTimeinfo ( showStatus , options , showStatus . url ));
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
contentWrapperElem . appendChild ( boostElem );
}
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
let contentElem = mastodonFeedCreateElement ( 'div' , 'content' );
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
// handle content warnings
if ( showStatus . sensitive || showStatus . spoiler_text . length > 0 ) {
let cwElem = mastodonFeedCreateElement ( 'div' , 'contentWarning' );
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
if ( showStatus . spoiler_text . length > 0 ) {
let cwTitleElem = mastodonFeedCreateElement ( 'div' , 'title' );
cwTitleElem . innerHTML = showStatus . spoiler_text ;
cwElem . appendChild ( cwTitleElem );
}
let cwLinkElem = mastodonFeedCreateElement ( 'a' );
cwLinkElem . href = '#' ;
2025-05-15 14:26:37 +02:00
cwLinkElem . setAttribute ( 'aria-label' , 'Show content despite warning' );
2023-06-23 21:36:00 +02:00
cwLinkElem . onclick = function () {
this . parentElement . style = 'display: none;' ;
this . parentElement . nextSibling . style = 'display: block;' ;
return false ;
}
cwLinkElem . innerHTML = options . text . showContent ;
cwElem . appendChild ( cwLinkElem );
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
contentWrapperElem . appendChild ( cwElem );
contentElem . style = 'display: none;' ;
2022-11-25 21:34:46 +01:00
}
2023-06-23 21:36:00 +02:00
// add regular content
let renderContent = showStatus . content ;
// inject emojis
if ( showStatus . emojis . length > 0 ) {
showStatus . emojis . forEach ( function ( emoji ) {
renderContent = mastodonFeedInjectEmoji ( renderContent , emoji );
});
}
contentElem . innerHTML += renderContent ;
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
// handle media attachments
if ( showStatus . media_attachments . length > 0 ) {
let mediaAttachmentsElem = mastodonFeedCreateElementMediaAttachments ( showStatus , options );
contentElem . appendChild ( mediaAttachmentsElem );
}
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
// handle preview card
if ( options . showPreviewCards && showStatus . card != null ) {
let cardElem = mastodonFeedCreateElementPreviewCard ( showStatus . card );
contentElem . appendChild ( cardElem );
}
2022-11-25 21:34:46 +01:00
2023-06-23 21:36:00 +02:00
contentWrapperElem . appendChild ( contentElem );
statusElem . appendChild ( contentWrapperElem );
rootElem . appendChild ( statusElem );
2022-11-25 21:34:46 +01:00
}
}
2025-05-15 14:26:37 +02:00
rootElem . querySelectorAll ( 'a' ) . forEach ( function ( e ) {
if ( '_self' != options . linkTarget ) {
2022-12-09 15:18:39 +01:00
e . target = options . linkTarget ;
2025-05-15 14:26:37 +02:00
}
});
2022-11-25 21:34:46 +01:00
}
2022-12-03 23:24:07 +01:00
const mastodonFeedLoad = function ( url , elementId , options ) {
2022-11-25 21:34:46 +01:00
const xhr = new XMLHttpRequest ();
xhr . open ( 'GET' , url , true );
xhr . responseType = 'json' ;
xhr . onload = function () {
const statuses = xhr . response ;
const rootElem = document . getElementById ( elementId );
rootElem . innerHTML = '' ;
2022-12-07 22:47:42 +01:00
< ? php if ( true === INCLUDE_MASTODON_FEED_DEBUG ) : ?>
2024-11-16 01:03:41 +01:00
console . log ( " <?php echo __NAMESPACE__; ?> " , 'url' , url );
console . log ( " <?php echo __NAMESPACE__; ?> " , 'elementId' , elementId );
console . log ( " <?php echo __NAMESPACE__; ?> " , 'options' , options );
2022-12-07 22:47:42 +01:00
< ? php endif ; ?>
2022-11-25 21:34:46 +01:00
if ( xhr . status === 200 ) {
2022-11-29 22:17:34 +01:00
< ? php if ( true === INCLUDE_MASTODON_FEED_DEBUG ) : ?>
2024-11-16 01:03:41 +01:00
console . log ( " <?php echo __NAMESPACE__; ?> " , 'response' , xhr . response );
2022-11-25 21:34:46 +01:00
< ? php endif ; ?>
2023-06-23 20:22:24 +02:00
if ( options . excludeConversationStarters && statuses . length > 0 ) {
const filteredStatuses = [];
for ( let i = 0 ; i < statuses . length ; i ++ ) {
2023-06-23 21:36:00 +02:00
let includeStatus = true ;
2023-06-23 20:22:24 +02:00
if ( statuses [ i ] . mentions . length > 0 ) {
const statusContent = document . createElement ( 'div' );
statusContent . innerHTML = statuses [ i ] . content ;
2023-10-13 13:13:41 +02:00
const mentionUsername = statuses [ i ] . mentions [ 0 ] . acct . split ( '@' )[ 0 ];
2023-06-23 20:22:24 +02:00
const plainTextContent = statusContent . textContent || statusContent . innerText ;
2023-10-13 13:13:41 +02:00
if ( plainTextContent . substring ( 1 , ( '@' + mentionUsername ) . length ) == mentionUsername ) {
2023-06-23 21:36:00 +02:00
includeStatus = false ;
2023-06-23 20:22:24 +02:00
}
}
2023-06-23 21:36:00 +02:00
if ( includeStatus ) {
filteredStatuses . push ( statuses [ i ]);
}
2023-06-23 20:22:24 +02:00
}
mastodonFeedRenderStatuses ( filteredStatuses , rootElem , options );
}
else {
mastodonFeedRenderStatuses ( statuses , rootElem , options );
}
2022-11-25 21:34:46 +01:00
}
else {
2022-11-29 22:17:34 +01:00
< ? php if ( true === INCLUDE_MASTODON_FEED_DEBUG ) : ?>
2024-11-16 01:03:41 +01:00
console . log ( " <?php echo __NAMESPACE__; ?> " , 'response error' , xhr );
2022-11-25 21:34:46 +01:00
< ? php endif ; ?>
rootElem . appendChild ( document . createTextNode ( xhr . response . error ));
}
};
xhr . send ();
}
</ script >
< ? php
}
2023-05-02 15:05:48 +02:00
add_action ( 'wp_footer' , __NAMESPACE__ . '\init_scripts' );
2022-11-25 21:34:46 +01:00
2023-05-02 15:05:48 +02:00
function display_feed ( $atts ) {
2022-11-25 21:34:46 +01:00
$atts = shortcode_atts (
array (
2022-12-08 02:28:04 +01:00
'instance' => ( INCLUDE_MASTODON_FEED_DEFAULT_INSTANCE === false ? false : filter_var ( INCLUDE_MASTODON_FEED_DEFAULT_INSTANCE , FILTER_UNSAFE_RAW ) ),
2022-11-25 21:34:46 +01:00
'account' => false ,
2024-06-20 16:56:27 +02:00
'tag' => false ,
2022-12-09 15:36:17 +01:00
'limit' => INCLUDE_MASTODON_FEED_LIMIT ,
'excludeboosts' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_EXCLUDE_BOOSTS ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
'excludereplies' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_EXCLUDE_REPLIES ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
2023-06-23 20:22:24 +02:00
'excludeconversationstarters' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_EXCLUDE_CONVERSATIONSTARTERS ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
2022-12-09 15:36:17 +01:00
'onlypinned' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_ONLY_PINNED ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
'onlymedia' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_ONLY_MEDIA ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
2024-06-20 16:56:27 +02:00
'preserveimageaspectratio' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_PRESERVE_IMAGE_ASPECT_RATIO ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
2024-11-16 01:03:41 +01:00
'imagesize' => INCLUDE_MASTODON_FEED_IMAGE_SIZE ,
2024-11-16 02:10:14 +01:00
'imagelink' => INCLUDE_MASTODON_FEED_IMAGE_LINK ,
2022-12-09 15:36:17 +01:00
'tagged' => INCLUDE_MASTODON_FEED_TAGGED ,
'linktarget' => INCLUDE_MASTODON_FEED_LINKTARGET ,
2023-05-02 15:23:24 +02:00
'showpreviewcards' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_SHOW_PREVIEWCARDS ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
2024-06-20 16:56:27 +02:00
'hidestatusmeta' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_HIDE_STATUS_META ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
'hidedatetime' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_HIDE_DATETIME ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
2022-12-08 02:28:04 +01:00
'text-loading' => INCLUDE_MASTODON_FEED_TEXT_LOADING ,
2023-06-23 21:36:00 +02:00
'text-nostatuses' => INCLUDE_MASTODON_FEED_TEXT_NO_STATUSES ,
2022-12-08 02:28:04 +01:00
'text-boosted' => INCLUDE_MASTODON_FEED_TEXT_BOOSTED ,
'text-viewoninstance' => INCLUDE_MASTODON_FEED_TEXT_VIEW_ON_INSTANCE ,
'text-showcontent' => INCLUDE_MASTODON_FEED_TEXT_SHOW_CONTENT ,
2023-04-09 14:02:31 +02:00
'text-permalinkpre' => INCLUDE_MASTODON_FEED_TEXT_PERMALINK_PRE ,
'text-permalinkpost' => INCLUDE_MASTODON_FEED_TEXT_PERMALINK_POST ,
'text-edited' => INCLUDE_MASTODON_FEED_TEXT_EDITED ,
2022-12-08 02:28:04 +01:00
'date-locale' => INCLUDE_MASTODON_FEED_DATE_LOCALE ,
2022-12-07 22:47:42 +01:00
'darkmode' => filter_var ( esc_html ( INCLUDE_MASTODON_FEED_DARKMODE ), FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ),
2023-06-23 19:22:17 +02:00
), array_change_key_case ( $atts , CASE_LOWER )
2022-11-25 21:34:46 +01:00
);
2023-05-02 15:23:24 +02:00
2023-06-23 19:22:17 +02:00
if ( false === filter_var ( $atts [ 'instance' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
2023-05-02 15:05:48 +02:00
return error ( 'missing configuration: instance' );
2022-11-29 22:17:34 +01:00
}
2024-06-20 16:56:27 +02:00
if ( false === filter_var ( $atts [ 'account' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ) && false === filter_var ( $atts [ 'tag' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
return error ( 'missing configuration: account id or tag' );
}
if ( false !== filter_var ( $atts [ 'account' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
$apiUrl = 'https://' . urlencode ( $atts [ 'instance' ]) . '/api/v1/accounts/' . $atts [ 'account' ] . '/statuses' ;
}
if ( false !== filter_var ( $atts [ 'tag' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
$apiUrl = 'https://' . urlencode ( $atts [ 'instance' ]) . '/api/v1/timelines/tag/' . urlencode ( $atts [ 'tag' ]);
2022-11-25 21:34:46 +01:00
}
2022-12-07 22:47:42 +01:00
$getParams = [];
2022-12-09 15:36:17 +01:00
if ( $atts [ 'limit' ] != 20 && $atts [ 'limit' ] > 0 ) {
$getParams [] = 'limit=' . filter_var ( $atts [ 'limit' ], FILTER_SANITIZE_NUMBER_INT );
}
2023-06-23 19:22:17 +02:00
if ( false !== filter_var ( $atts [ 'excludeboosts' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
2022-12-07 22:47:42 +01:00
$getParams [] = 'exclude_reblogs=true' ;
}
2023-06-23 19:22:17 +02:00
if ( false !== filter_var ( $atts [ 'excludereplies' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
2022-12-07 22:47:42 +01:00
$getParams [] = 'exclude_replies=true' ;
}
2023-06-23 19:22:17 +02:00
if ( true === filter_var ( $atts [ 'onlypinned' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
2022-12-07 22:47:42 +01:00
$getParams [] = 'pinned=true' ;
}
2023-06-23 19:22:17 +02:00
if ( true === filter_var ( $atts [ 'onlymedia' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
2022-12-07 22:47:42 +01:00
$getParams [] = 'only_media=true' ;
}
2023-06-23 19:22:17 +02:00
if ( false !== filter_var ( $atts [ 'tagged' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE )) {
2022-12-09 14:55:36 +01:00
$getParams [] = 'tagged=' . filter_var ( $atts [ 'tagged' ], FILTER_UNSAFE_RAW );
}
2022-12-07 22:47:42 +01:00
if ( sizeof ( $getParams ) > 0 ) {
$apiUrl .= '?' . implode ( '&' , $getParams );
2022-12-07 17:12:35 +01:00
}
2022-11-29 22:17:34 +01:00
$elemId = uniqid ( 'include-mastodon-feed-' );
2022-11-25 21:34:46 +01:00
ob_start ();
?>
< script >
window . addEventListener ( " load " , () => {
2022-12-03 23:24:07 +01:00
mastodonFeedLoad (
2024-11-24 17:50:04 +01:00
" <?php echo esc_url( $apiUrl , ['https'], 'apicall' ); ?> " ,
2022-12-08 02:28:04 +01:00
" <?php echo filter_var( $elemId , FILTER_UNSAFE_RAW ); ?> " ,
2022-12-03 23:24:07 +01:00
{
2025-01-24 12:24:42 +01:00
linkTarget : " <?php echo esc_js(filter_var( $atts['linktarget'] , FILTER_UNSAFE_RAW )); ?> " ,
2023-05-02 15:23:24 +02:00
showPreviewCards : < ? php echo ( filter_var ( $atts [ 'showpreviewcards' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ) ? " true " : " false " ); ?> ,
2023-06-23 20:22:24 +02:00
excludeConversationStarters : < ? php echo ( filter_var ( $atts [ 'excludeconversationstarters' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ) ? " true " : " false " ); ?> ,
2024-06-20 16:56:27 +02:00
content : {
hideStatusMeta : < ? php echo ( filter_var ( $atts [ 'hidestatusmeta' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ) ? " true " : " false " ); ?> ,
hideDateTime : < ? php echo ( filter_var ( $atts [ 'hidedatetime' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ) ? " true " : " false " ); ?>
},
2024-11-16 02:10:14 +01:00
images : {
preserveImageAspectRatio : < ? php echo ( filter_var ( $atts [ 'preserveimageaspectratio' ], FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE ) ? " true " : " false " ); ?> ,
size : " <?php echo ( " full " === $atts['imagesize'] ? " full " : " preview " ); ?> " ,
link : " <?php echo ( " image " === $atts['imagelink'] ? " image " : " status " ); ?> " ,
},
2022-12-03 23:24:07 +01:00
text : {
2024-11-23 22:40:25 +01:00
boosted : " <?php echo esc_html( $atts['text-boosted'] ); ?> " ,
2023-06-23 21:36:00 +02:00
noStatuses : " <?php echo esc_html( $atts['text-nostatuses'] ); ?> " ,
2022-12-08 02:28:04 +01:00
viewOnInstance : " <?php echo esc_js( $atts['text-viewoninstance'] ); ?> " ,
2024-11-23 22:40:25 +01:00
showContent : " <?php echo esc_html( $atts['text-showcontent'] ); ?> " ,
permalinkPre : " <?php echo esc_html( $atts['text-permalinkpre'] ); ?> " ,
permalinkPost : " <?php echo esc_html( $atts['text-permalinkpost'] ); ?> " ,
edited : " <?php echo esc_html( $atts['text-edited'] ); ?> " ,
2022-12-08 02:28:04 +01:00
},
localization : {
date : {
2025-01-24 12:24:42 +01:00
locale : " <?php echo esc_js( filter_var( $atts['date-locale'] , FILTER_UNSAFE_RAW ) ); ?> " ,
options : < ? php echo filter_var ( INCLUDE_MASTODON_FEED_DATE_OPTIONS , FILTER_UNSAFE_RAW ); ?> ,
2022-12-08 02:28:04 +01:00
}
2022-12-03 23:24:07 +01:00
}
}
);
2022-11-25 21:34:46 +01:00
});
</ script >
2025-05-15 14:26:37 +02:00
< div class = " include-mastodon-feed-wrapper " >< ol class = " include-mastodon-feed<?php echo (true == $atts['darkmode'] ? ' dark' : ''); ?> " id = " <?php echo esc_attr( $elemId ); ?> " >< li >< ? php echo esc_html ( $atts [ 'text-loading' ] ); ?> </li></ol></div>
2022-11-25 21:34:46 +01:00
< ? php
return ob_get_clean ();
}
2023-05-02 15:05:48 +02:00
add_shortcode ( 'include-mastodon-feed' , __NAMESPACE__ . '\display_feed' );