- PHP 89.2%
- CSS 10.8%
|
All checks were successful
Auto Release on version bump / release (push) Successful in 6s
|
||
|---|---|---|
| .forgejo/workflows | ||
| assets | ||
| languages | ||
| social-icons | ||
| .gitattributes | ||
| .gitignore | ||
| CHANGELOG.md | ||
| changelog.txt | ||
| eg-social-timeline.css | ||
| eg-social-timeline.php | ||
| LICENSE.IT.md | ||
| LICENSE.md | ||
| README.it-IT.md | ||
| README.md | ||
| readme.txt | ||
EG Social Timeline
WordPress plugin to display a unified chronological timeline of your social activity from Mastodon (also Pleroma and Akkoma), GoToSocial, Friendica, Lemmy, Pixelfed, PeerTube, Forgejo/Gitea, Bluesky, ListenBrainz and any RSS or Atom feed.
Features
- Unified Timeline: aggregates posts from multiple platforms in chronological order
- Supported platforms:
- Mastodon, plus the Mastodon-compatible Pleroma and Akkoma
- GoToSocial (public RSS feed of the profile, to be turned on in the account settings)
- Friendica (public Atom feed of the profile)
- Lemmy, any instance, with full statistics
- ListenBrainz (public API, no token: your recent listens)
- Any RSS 2.0 or Atom feed: blog, newsletter, podcast
- Forgejo/Gitea (repository commits)
- Bluesky (public ATP API, no authentication required)
- Pixelfed (public Atom feed: photos and captions, no counts)
- PeerTube (public REST API, videos from an account or a channel)
- Per-platform limits: prevents a single platform from monopolizing the timeline
- Interactive filters: pure-CSS filter system to show/hide platforms
- Modular icon system: SVG icons loaded from files, easy to customize
- Smart cache: reduces API requests with a configurable cache
- Interaction stats: shows likes, boosts and comments for each post
- List or grid: vertical list by default, grid in the settings or page by page with
layout="grid" - Filter bar: visible, collapsible or hidden (
filters="collapsed",filters="hidden"), with its own background - Responsive: design optimized for desktop, tablet and mobile
- Configurable backgrounds: timeline background independent from the card background, one color each
- Derived contrast: text, borders and icons follow the WCAG contrast of the background you pick, no color scheme to keep in sync
- Privacy-friendly: public data only, no tracking
Screenshot
Installation
From the WordPress plugin directory (recommended)
- Go to Plugins → Add New
- Search for EG Social Timeline
- Click Install Now and then Activate
From a release ZIP
- Download the latest release from Forgejo
- Go to Plugins → Add New → Upload Plugin
- Select the downloaded ZIP file
- Click Install and then Activate
Manual (FTP/SSH)
cd wp-content/plugins
git clone https://git.emanuelegori.uno/emanuelegori/eg-social-timeline.git
Configuration
-
Go to Settings → EG Social Timeline
-
Configure at least one profile:
- Mastodon / Pleroma / Akkoma: instance URL + username (e.g.
https://mastodon.uno+emanuelegori) - GoToSocial: instance URL + username; turn on the RSS feed in your account settings first
- Friendica: instance URL + nickname (the name in
/profile/nickname) - Lemmy: instance URL + username (e.g.
https://diggita.com+emanuelegori) - Forgejo / Gitea: instance URL + username (e.g.
https://git.emanuelegori.uno) - Pixelfed: instance URL + username (e.g.
https://pixelfed.uno+emanuelegori) - PeerTube: instance URL + account or channel (e.g.
https://peertube.uno+emanuelegori) - Bluesky: handle alone (e.g.
emanuele.bsky.social, without @) — its public API is the same for everyone
- Mastodon / Pleroma / Akkoma: instance URL + username (e.g.
-
Configure per-platform limits (optional):
- Every source defaults to 5 items, 0 = unlimited
- Mastodon, GoToSocial, Friendica, Lemmy, Bluesky, Pixelfed, PeerTube, Forgejo, ListenBrainz and the RSS feed each have their own limit
-
Adjust cache and display settings
-
Adjust the Appearance section (optional):
- Timeline background: transparent (default) · neutral preset · follow the visitor browser · custom color
- Card background: neutral preset (default) · transparent · follow the visitor browser · custom color
- Platform icon style: platform colors (default) · single color (same as the post text)
Text, borders, badges, links and icons are not configured: they are derived from the contrast of the background you choose. Pick a dark card and they switch to their light variants on their own.
-
Save
Usage
Basic shortcode
[eg_social_timeline]
With custom limit
[eg_social_timeline limit="20"]
Attributes
| Attribute | Values | When omitted |
|---|---|---|
limit |
1–100 | Timeline → Number of Posts to Show |
layout |
list · grid |
Appearance → Layout |
filters |
visible · collapsed · hidden |
Filter Bar → Display |
Several timelines can share a page (a widget and the content, say): each keeps its own filters.
As a grid
For a home page or a dashboard-like page; overrides the layout set in the settings:
[eg_social_timeline layout="grid" limit="20"]
Filter bar folded away or hidden
[eg_social_timeline filters="collapsed"]
[eg_social_timeline layout="grid" filters="hidden"]
Full example
<h2>My recent activity</h2>
[eg_social_timeline limit="50"]
Platform filters
Built-in CSS filter system:
┌──────────────────────────────────────┐
│ Filter by platform: │
│ ☑ Mastodon (12) ☑ Lemmy (8) │
│ ☑ Forgejo (5) ☐ Bluesky (2) │
└──────────────────────────────────────┘
Click a checkbox = posts shown/hidden instantly (zero JavaScript required!)
Customization
Platform icons
Icons are SVG files inside social-icons/:
social-icons/
├── mastodon.svg
├── pleroma.svg # used for Pleroma and Akkoma
├── gotosocial.svg # derived from the official logo, CC BY-SA 4.0
├── friendica.svg # derived from the official logo, public domain
├── lemmy.svg
├── pixelfed.svg
├── forgejo.svg
├── peertube.svg
├── bluesky.svg
├── listenbrainz.svg
├── rss.svg
└── generic.svg # fallback for an unknown source
To customize:
- Replace the SVG file with your icon
- Keep size at 24x24px and
viewBox="0 0 24 24" - Use
fill="currentColor"to inherit the surrounding color
Custom CSS
Colors live in custom properties on the .eg-social-timeline container, on two levels: the source palettes --egst-light-* and --egst-dark-*, and the active tokens that read from them (--egst-text, --egst-card-bg, --egst-chip-bg, --egst-icon-mastodon, …). Redefine either level instead of overriding each rule:
/* Change the colors used on a light surface */
.eg-social-timeline {
--egst-light-text: #1f2937; /* post text */
--egst-light-card-border: #d8deff;
--egst-light-icon-mastodon: #563acc; /* one token per platform */
}
/* Change the colors used on a dark surface */
.eg-social-timeline {
--egst-dark-text: #e8eaf0;
--egst-dark-icon-mastodon: #a5a6ff;
}
/* Or set an active token directly */
.eg-social-timeline {
--egst-canvas: #f0f4ff; /* background behind the cards */
--egst-card-bg: #ffffff; /* card background */
}
The full token list is at the top of eg-social-timeline.css. Which palette each token reads is decided by the plugin from the contrast of your background, and applied as inline CSS after the stylesheet — so an override in a theme stylesheet is best written on the source palettes, which are never rewritten.
Plain rules still work, of course:
/* Customize post cards */
.timeline-item {
background: #YOUR_BG;
}
Development
Requirements
- WordPress 5.0+
- PHP 7.4+
- API access to the configured platforms
File structure
eg-social-timeline/
├── eg-social-timeline.php # Main plugin
├── eg-social-timeline.css # Styles
├── social-icons/ # SVG icons, one per source
│ └── ICONS-LICENSE.md # Provenance and terms of the icons
├── languages/ # Translations
├── README.md
├── readme.txt # WordPress readme
├── changelog.txt # Full history, older than the current line
└── LICENSE.md
APIs used
- Mastodon / Pleroma / Akkoma:
/api/v1/accounts/lookup+/api/v1/accounts/{id}/statuses, and/.well-known/nodeinfoto tell the software apart - GoToSocial: RSS
/@{username}/feed.rss(off by default), plus/.well-known/webfingerwhen saving, to find the server of the account - Friendica: Atom
/feed/{nickname}/(posts without replies) - Lemmy: RSS
/feeds/u/{username}.xml(with stats parsing), on any instance - Pixelfed: Atom
/users/{username}.atom(photos and captions, no counts) - PeerTube:
/api/v1/accounts/{name}/videosor/api/v1/video-channels/{name}/videos - Forgejo:
/api/v1/users/{username}/repos+/api/v1/repos/{owner}/{repo}/commits - Bluesky:
https://public.api.bsky.app/xrpc/app.bsky.feed.getAuthorFeed(public, no token required)
Changelog
[1.17.2] - 2026-09-27
Changed
- New short description for the plugin directory, and the admin plugins list opens the same way.
- "fediverse" replaces "forgejo" among the directory tags.
[1.17.1] - 2026-09-27
Fixed
- Saving the settings no longer re-checks every profile: only the added or changed ones, so a colour change makes no request.
- After a profile change, the diagnostics table no longer shows the last refresh result of the previous profile.
[1.17.0] - 2026-09-27
Added
- Grid layout (Settings → Appearance → Layout), columns of at least 280 px, one on phones, 16:9 cropped images, equal-height cards per row. The
layoutshortcode attribute overrides it per page. - Filter Bar section: display visible / collapsible / hidden (
filtersshortcode attribute), style full / compact, background neutral / transparent / browser / custom color.
Fixed
- Two timelines on the same page no longer share their filters: element IDs are numbered per timeline and the stylesheet works on classes.
Changed
- A custom-coloured filter bar shows that colour; before, the colour only chose between a light and a dark grey.
[1.16.1] - 2026-09-27
Changed
- Settings footer credit reworded: "Developed with ❤️ and maintained by".
[1.16.0] - 2026-09-26
Added
- GoToSocial and Friendica sections, reading the public feed of the profile: RSS on GoToSocial, Atom on Friendica. Own icon, name and colour; images when the feed carries them.
- On GoToSocial the feed is off by default: the settings page says so and links the account settings. When the account domain differs from the server, the server is looked up via webfinger when saving.
- A GoToSocial or Friendica instance entered in the Mastodon field now points to the right section.
- Platform boxes in the settings fold without JavaScript (
<details>), show their state next to the title, and start closed except the ones that need attention.
Fixed
- The readme FAQ said ListenBrainz cards link to MusicBrainz; they link to ListenBrainz.
[1.15.9] - 2026-09-24
Fixed
Tested up tois back to7.1: the plugin directory takes the major version only, and a point release raises theinvalid_tested_upto_minorerror in Plugin Check.
[1.15.8] - 2026-09-24
Changed
- Three cache keys used a short identifier and now carry the plugin's full 18-character prefix, like every other name. They are transients and rebuild themselves; no setting is affected.
- The Italian translation is no longer shipped inside the package; translate.wordpress.org handles translations for hosted plugins. Put the
.moinwp-content/languages/plugins/to keep it on your own site.
[1.15.7] - 2026-09-23
Fixed
- On a fresh install, boosts and image previews started switched off although they are documented as enabled. The old global switches were still among the registered defaults and the per-source lookup found them first. Existing installs keep their saved choices.
- Seven factual errors in the documentation: five sources instead of eight, the FAQ missing ListenBrainz and feeds, image previews credited to three sources instead of five, the old per-platform limits in both READMEs, an incomplete intro line, seven icons listed out of ten, and a stale file tree.
Changed
- The external services intro no longer enumerates the sources; the per-source sections below are the single source of truth.
[1.15.6] - 2026-09-23
Fixed
- Two dead links in the Lemmy section of
readme.txt; terms and privacy on Lemmy are published by the instance, so the readme says that instead of naming one. - The example profile addresses used real instances with placeholder usernames and resolved to missing pages; they now use reserved example domains.
Changed
- Tested up to WordPress 7.1.2.
[1.15.5] - 2026-09-21
Fixed
- The compatibility header declared WordPress 7.1 while the current release is 7.1.1, which made WordPress warn that the plugin had not been tested with the version in use.
- The upgrade notice had been left at 1.15.3; it now carries the two most recent releases.
[1.15.4] - 2026-09-20
Changed
- Installation instructions now start from the WordPress plugin directory; the release ZIP and the source repository remain documented.
- The Lemmy example address no longer names a real account.
Removed
- The section recommending a third-party updater for releases from outside the plugin directory.
Fixed
- Screenshots are referenced by absolute address, so they work outside the repository too; all four are listed.
[1.15.3] - 2026-09-20
Changed
- The changelog in
readme.txtnow covers the current 1.15 line only; the full history moved tochangelog.txt, as the plugin directory asks. The readme went from 524 to 291 lines. - The upgrade notice keeps the two most recent releases instead of every version ever published.
[1.15.2] - 2026-09-20
Fixed
- Eight field descriptions still quoted the defaults from before 1.14.1; they now match the real values (5 per source, 50 posts, 30 minutes of cache).
- The screenshot list in
readme.txtis now in the format the plugin directory reads.
Changed
- Plugin directory assets are no longer shipped inside the plugin package.
[1.15.1] - 2026-09-20
Changed
- Footer links now follow the reader's language: the project page and the support page are translatable strings, so each translation can point at its own localised pages. No locale checks in the code.
Plugin URIandDonate linknow point at the English pages.
[1.15.0] - 2026-09-20
Added
- A proper footer on the settings page, built on the WordPress footer slots: developer and project links on the left, version and licence on the right.
- A donate link on the plugin directory page.
Changed
- The plugin homepage now points at the project page instead of the code repository.
Fixed
- The repository link in the footer was missing
rel="noopener noreferrer".
[1.14.1] - 2026-09-20
Changed
- Clearer switch names: "Include boosted posts" (whether boosted posts join the timeline) and "Interaction counts" (whether counters appear under each card).
- Shorter field descriptions: from 201 characters at most down to 84, average 44.
- Defaults tuned for a first install: 50 posts on the page, 30 minutes of cache, 5 items per source.
[1.14.0] - 2026-09-20
Changed
- One box per platform in the settings, with the platform icon in the title and short labels inside.
- Boosts, statistics, image previews and text length are set per source, and each box offers only the options that have an effect there; Forgejo and ListenBrainz carry none of the three.
- New installs default to 5 items per source with every display option enabled; existing settings are carried over unchanged.
[1.13.0] - 2026-09-20
Changed
- Each platform now carries its own limit right below its fields; the limits no longer sit in a separate section at the other end of the page.
- General options (number of posts, cache, boosts, statistics, text length, image previews) moved from the profiles section into their own "Timeline" section.
Added
- A "Show diagnostics" switch: the "Configured profiles" table is hidden by default, with a one-line warning appearing whenever a configured platform returns nothing.
[1.12.3] - 2026-09-20
Changed
- The settings page alternates row backgrounds: about thirty fields in one column, and WordPress does not stripe
form-tablerows by itself. Colour pickers get a visible frame so they stand out against the shaded rows.
[1.12.2] - 2026-09-20
Security
- All 13 outgoing requests now set
reject_unsafe_urls, so WordPress validates redirect targets as well. The existing private-address check only covered the first hop, leaving a server-side request forgery path through a redirecting feed or instance. Found in a pre-submission audit; no exploitation observed.
[1.12.1] - 2026-09-20
Changed
- The compact bar fits on a single line: "Filter:" beside the icons, no separator underneath.
Fixed
- The tooltip showed the platform name without the count: each icon carries its own SVG title, which the browser preferred. Icons are now inert to the pointer, so the chip's tooltip wins; the click still selects the filter.
- Icons are marked decorative (
aria-hidden), since the platform name is already next to them.
[1.12.0] - 2026-09-20
Added
- Compact filter bar (new "Filter Bar Style" setting): "Filter:" plus the icons alone, 36px targets with a light frame, in colour when included and grey when filtered out. Name and count move to the tooltip and stay in the markup for screen readers.
- A title with platform name and item count on every chip, in both styles.
Changed
- An excluded platform now shows its icon in greyscale, not merely faded, in both styles.
[1.11.1] - 2026-09-20
Changed
- A listen links to its track page on ListenBrainz instead of the MusicBrainz recording; without an identifier it still goes to the profile.
- "Flush Cache Now" rebuilds the cache immediately and reports how many items it retrieved, so the settings table fills as soon as you press it.
Fixed
- The last-fetch column said "nothing fetched yet" after every update: the recorded outcome was cleared on version change, and it is kept now.
- A malformed feed no longer fills the site log with libxml warnings; the three XML parsers keep those errors internal.
[1.11.0] - 2026-09-19
Added
- RSS/Atom source: the address of any feed, with an optional label. One parser reads both formats; the name on the cards comes from the label, the feed title or the domain.
- ListenBrainz: recent listens through the public API, no token needed. "Artist — Track" with the album when present, linking to the MusicBrainz recording when the identifier is available.
- A plain music note icon drawn for the plugin, used for ListenBrainz.
Changed
- Removed the leftover
blogslug, which no fetcher produced and whose icon file did not exist; the feed source takes its place.
Fixed
- The feed fetcher returned silently when the address was unusable; the reason now reaches the settings table.
[1.10.1] - 2026-09-19
Fixed
- A half-filled profile (a username without its instance URL, or the other way round) was skipped silently; it now gets a row in the settings table saying what is missing.
- Packaging:
*.md export-ignorekeptLICENSE.mdandREADME.mdout of the release archive. Only development files are excluded now.
Added
social-icons/ICONS-LICENSE.mdwith the provenance and licence of the platform icons, the trademark notice, and how to replace one.
[1.10.0] - 2026-09-17
Added
- Pixelfed, through the public Atom feed of the profile (
/users/{name}.atom): photos, captions, dates and links, no interaction counts because the feed does not carry them. A dedicated parser (feed/entrywith themedia:namespace), distinct from the RSS 2.0 one used for Lemmy. - The full profile address is accepted in every field and split into instance and username:
/u/name,/@name,/users/name,name@instance,/c/name@host,/profile/handle. A bare instance URL is not mistaken for a profile. - When a name carries its own origin (a remote PeerTube channel seen from another instance) the plugin queries that origin rather than the instance federating it.
- A "Configured profiles" table in the settings: what the plugin sees per platform (instance, software, account or channel, item counts) and what the last fetch returned. Checks run on save and via the Verify profiles button, never while the page loads.
Fixed
- PeerTube channels. Videos on PeerTube almost always live in a channel rather than the account, and the two use different endpoints; only the account one was implemented, so a channel returned nothing. Measured:
/api/v1/accounts/s3nnet/videos→ 404,/api/v1/video-channels/s3nnet/videos→ 200 with 147 videos. - Specific failure messages instead of a generic invitation to check the settings.
[1.9.1] - 2026-09-17
Fixed
- The
[eg_social_timeline]shortcode was no longer registered in 1.9.0 and the tag was printed as plain text: theadd_shortcode()call sat between two rewritten functions and went away with them.
[1.9.0] - 2026-09-17
Changed
- Every platform is configured the same way: instance URL + username. Mastodon asked for a full profile URL while Forgejo and PeerTube asked for two fields, with no technical reason — the code split that URL into the same two values a couple of lines later.
- Diggita becomes generic Lemmy support. The fetcher already spoke Lemmy (
/feeds/u/{username}.xmlis the Lemmy user feed) with the domain hardcoded; the instance is now a setting. The name on the cards comes from the instance domain: diggita.com stays "Diggita", lemmy.ml reads "Lemmy". - Settings from earlier versions are converted on read; the database is rewritten on your first save.
- The real Lemmy logo replaces a hand-drawn placeholder, and the Pleroma icon is added (Simple Icons, CC0).
Added
- Instance software detection via
/.well-known/nodeinfo(cached 7 days), so Pleroma and Akkoma get their own name and icon. The nodeinfo href is followed only when it points at the same host as the instance. - A clear explanation when you save an instance whose software does not serve the public API: measured behaviour — Mastodon and Pleroma/Akkoma answer the lookup unauthenticated, GoToSocial and Friendica return 401, Misskey and Sharkey use their own API, Pixelfed redirects the statuses endpoint to its login page.
- The settings page reports what each configured platform returned on the last refresh, with the reason when it came back empty.
Fixed
- The profile parser accepted only the
/@userform, so a valid/users/useraddress silently produced nothing — the only log sat behind a debug constant disabled in releases. It now reads/users/userand@user@instancetoo. - In that parser the regex delimiter was
#while the character class contained[^/?#], closing the pattern early and rejecting every URL. Caught by the tests before release. - Instance URLs are normalized and validated in one place: HTTPS only, private and reserved hosts rejected.
[1.8.1] - 2026-09-17
Fixed
- Contrast is measured on the chosen color instead of inferred from a color scheme. In 1.8.0 a dark card background left the post text, the borders and the icons dark on dark. The plugin now computes the WCAG contrast ratio of the background and moves text, borders, badges, links and icons to the palette that contrasts more.
- Icons on the filter chips read their own tokens (
--egst-chip-icon-*) instead of following the card, where a dark card used to lighten them while they sat on light chips.
Added
- Transparent card background: a timeline with no card surfaces, only the border delimiting each post (the shadow is dropped).
- A warning in the settings when the chosen color cannot reach the WCAG AA minimum (4.5:1) with either text palette, showing the measured ratio.
Changed
- Simpler Appearance section: the Color Scheme setting and the light/dark color pairs are gone. Each background has one menu (transparent · neutral preset · follow the visitor browser · custom color) and one color.
- Clearer icon labels: "Platform colors" and "Single color (same as the post text)". The SVG icons are monochrome outlines with no color of their own — the stylesheet paints them.
- The stylesheet no longer contains any
prefers-color-schemerule: colors are organized in two source palettes (--egst-light-*,--egst-dark-*) plus the active tokens reading from them. The media query is emitted in the inline CSS only when a background follows the browser, or when both are transparent. - Settings saved with 1.8.0 are converted on read, so nothing is lost; the database is rewritten on your first save.
[1.8.0] - 2026-09-17
Added
- New Appearance settings section: color scheme (always light / always dark / follow the visitor browser), timeline background, card background and platform icon style.
- The timeline background is configurable independently from the card background, with separate colors for the light and the dark scheme.
- Selectable icon style: brand colors or monochrome (monochrome icons follow the text color, so they turn white on dark cards).
Fixed
- Platform icons were always black: the Simple Icons SVG files carry no
fillattribute, so thecolorrules had no effect and the icons became invisible on dark cards. Icons now usefill: currentColor, are colored per platform on the filter chips too, and use lightened brand colors on the dark scheme.
Changed
- ⚠️ The dark theme is no longer forced by the browser. The default is now "always light": the
prefers-color-schememedia query applies only when you choose "follow the visitor browser". Pick that option to restore the 1.7.2 behaviour. - Every color moved to custom properties (
--egst-*) declared on the.eg-social-timelinecontainer, so custom CSS can retheme the plugin from a single place. - The "no posts available" message is now wrapped in the timeline container and inherits the chosen colors.
readme.txt:Tested up tobumped to WordPress 7.1.
Accessibility
- The
<title>element of the SVG icons is no longer stripped by sanitization, so each icon keeps its accessible name.
[1.7.2] - 2026-07-05
Fixed
- Image previews now fill the card width consistently across all platforms — small source images (e.g. Mastodon
preview_urlthumbnails) were rendered at their reduced natural size while larger ones (Bluesky, PeerTube) filled the card; addedwidth: 100%to.post-image img
[1.7.1] - 2026-07-05
Added
- Image previews for Bluesky posts, on par with Mastodon: the first post image (direct image embed or quote-post with media) is shown when "Show Image Previews" is enabled, alt text included. Thumbnails of external link cards are intentionally ignored
Note
- No new settings: reuses the existing "Show Image Previews" toggle
[1.7.0] - 2026-07-05
Added
- PeerTube integration through the public REST API (
GET /api/v1/accounts/{account}/videos, no authentication required): just set the account name and instance URL in the settings - Thumbnail previews for PeerTube videos (honouring the "Show Image Previews" option) and a dedicated "Watch video" link label
- Per-platform limit for PeerTube videos (default 5), platform filter, dedicated icon and brand colour
Security
- The PeerTube instance URL is accepted over HTTPS only, with anti-SSRF validation (private/reserved hosts rejected)
Changed
- Regenerated the
.potand realigned the Italian translation (it_IT.po/.mo) with the new strings
[1.6.7] - 2026-06-18
Changed
- Translated to English the last 3 source strings still in Italian in the "Usage" section of the admin panel (the rest of the plugin was already in English since 1.6.6)
- Regenerated the
.potwithwp i18n make-potand realigned the Italian translation (it_IT.po/.mo) with the current source: added missing strings, fixed wrong fuzzy entries and translated the Description
Note
- No functional, database or settings changes
[1.6.6] - 2026-06-02
Fixed
- translators: comments added to all i18n strings with placeholders
- strip_tags() replaced with wp_strip_all_tags() (×4)
- date() replaced with gmdate() for timezone safety
- wp_unslash() + sanitize_text_field() added to nonce verification
- error_log() calls marked with phpcs:ignore (already gated by EG_SOCIAL_TIMELINE_DEBUG)
- phpcs:ignore on SVG icon output (hardcoded, sanitized internally)
- esc_html() added to EG_SOCIAL_TIMELINE_VERSION constant output
Removed
- load_plugin_textdomain() — not needed since WP 4.6+ with compiled .mo files
Changed
- tags reduced to 5 (Plugin Check limit)
[1.6.1] - 2026-06-02
Fixed
- Plugin action links now use English msgids (
Settings,Documentation) — correctly translated to Italian viait_IT.mo - Added
rel="noopener noreferrer"to the Documentation action link
[1.6.0] - 2026-06-02
Changed
- Full i18n refactor: all PHP strings now use English msgids (WordPress convention)
it_IT.po/.morebuilt with proper English→Italian translationsen_US.po/.moremoved — English is now the native fallback
[1.5.3] - 2026-06-02
Fixed
- "Filter by platform:" (
Filtra per piattaforma:) wrapped inesc_html_e()and added toit_IT.po/.mo
[1.5.1] - 2026-06-02
Fixed
translators:comment moved immediately aboveesc_html__()call (PHPCS compliance)readme.txttranslated to English (Plugin Check compliance)
[1.5.0] - 2026-06-02
Fixed
- All
strip_tags()replaced withwp_strip_all_tags() date()replaced withgmdate()for timezone safety- Nonce verification uses
wp_unslash()+sanitize_text_field() error_log()calls marked withphpcs:ignore(already gated byEG_SOCIAL_TIMELINE_DEBUG)esc_html()added toEG_SOCIAL_TIMELINE_VERSIONconstant output
Removed
load_plugin_textdomain()— no longer needed since WP 4.6+
[1.4.6] - 2026-05-25
Changed
- readme.txt rewritten with clearer structure
- Tested up to bumped to WordPress 7.0
- EG Forgejo Updater replaces Git Updater in installation instructions
[1.4.5] - 2026-05-25
Security
- HTTPS validation on the Forgejo instance URL during sanitization
Added
- Frontend, configuration and post-limits screenshots
[1.4.4] - 2026-05-24
Fixed
- Forgejo: client-side repo sorting by
updated_atusingusort()— thesort=recentupdateparameter is not supported by the/users/{username}/reposendpoint
[1.4.3] - 2026-05-24
Added
- Image preview support with new admin option (default: disabled)
- Mastodon: extraction of the first image from
media_attachmentswithpreview_urland alt text loading="lazy"attribute on images
Fixed
- Forgejo: repos sorted by last push with
?sort=recentupdate; only the necessary repos are queried (min(repo_count, limit)). Previously the most recent repos were excluded because the API returned repos in creation order
Changed
- Unified post structure:
image_urlandimage_altfields available across all platforms
[1.4.2] - 2026-05-24
Added
- Italian (
it_IT) and English (en_US) translations with.pot,.poand.mofiles
Fixed
- "View original post" / "View commit" link always right-aligned in the footer, even without statistics
Changed
- Mastodon account ID cache extended from 24 hours to 30 days
[1.4.1] - 2026-05-02
Added
- Configurable post text length from admin (default: 300, range: 50–600, 0 = full text with no limits)
[1.4.0] - 2026-05-02
Added
- Bluesky integration via public ATP API (
app.bsky.feed.getAuthorFeed) - New admin field: Bluesky handle (e.g.
emanuele.bsky.social, without @) - New admin field: Max Bluesky posts (default: 10, range: 0-100)
- Bluesky platform filter in the timeline (CSS-only)
- Bluesky statistics: likes, reposts, replies
- Repost support, honoring the "Include Boost/Repost" option
- Automatic stripping of the leading
@from the handle during sanitization
Changed
- "At least one profile" validation extended to Bluesky
- Updated admin error messages
[1.3.1] - 2026-04-06
Security
- Added
LIBXML_NONETto the Diggita RSS feed XML parsing (anti-XXE) - Inline SVG sanitization with
wp_kses()ineg_social_timeline_get_icon()(anti-XSS) - Anti-SSRF validation on external API URLs: new function
eg_social_timeline_is_public_url()rejects private, reserved and localhost IPs
Fixed
- Added missing
esc_url()on admin links inside the shortcode
[1.3.0] - 2026-01-11
Added
- Per-platform configurable limits in admin settings
- New fields: Max Mastodon posts, Max Diggita posts, Max Forgejo commits
- Value 0 = no limit (v1.2.x behavior)
- More balanced timeline: prevents a single platform from monopolizing it
Changed
- Fetch logic modified to honor per-platform limits
- Forgejo: TOTAL commit limit instead of per-repo
- Sensible defaults: Mastodon 20, Diggita 10, Forgejo 5
- Total timeline limit raised: 1-100 (was 1-50)
[1.2.5] - 2026-01-11
Fixed
- Diggita stats:
<br>tags converted to\nbeforestrip_tags()for correct parsing - Forgejo repository name: now visible in the timeline ("Commit to {repo}: {message}")
- Filter buttons: automatic width fixes inconsistent heights
- Filter icons: uniform sizes without distortion
Changed
- CSS: removed fixed width on filter buttons (was 145px → auto)
- CSS: removed
object-fit: containon icons for uniform rendering - Diggita: parsing uses
str_replacefor<br>beforestrip_tags()
[1.2.4] - 2026-01-11
Fixed
- Diggita: robust HTML parsing with
strip_tags() - Forgejo: repo name included in the content
[1.2.3] - 2026-01-11
Fixed
- CSS filters: inverted logic
- Forgejo: commits page link
- UI: compact filter box
[1.2.0-1.2.2] - 2026-01-11
- Forgejo integration, various fixes
[1.0.0-1.1.2] - 2026-01-10/11
- Initial releases, Mastodon API
Contributing
Contributions are welcome!
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add AmazingFeature') - Push the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
This project is released under the GPL-2.0-or-later license.
See the LICENSE file for full details.
Author
Emanuele Gori
- Website: emanuelegori.uno
- Mastodon: @emanuelegori@mastodon.uno
- Gitea: git.emanuelegori.uno
Acknowledgements
- The Mastodon community for the well-documented API
- The Lemmy project, and Diggita.com for the Italian instance
- Forgejo/Gitea for the excellent API
- The WordPress community



