From 7fc8985840bf97a434aabf7b19fff04cc876e288 Mon Sep 17 00:00:00 2001 From: Chris Vitalos Date: Tue, 24 Oct 2023 12:24:43 -0400 Subject: [PATCH] remove older mastodon-timeline js and css files --- css/mastodon-timeline-1.0.1.css | 191 ------- css/mastodon-timeline-1.0.2.css | 192 ------- css/mastodon-timeline-1.1.0.css | 198 ------- css/mastodon-timeline-3.10.0-3.css | 406 ------------- css/mastodon-timeline-3.10.1-1.css | 415 -------------- css/mastodon-timeline-3.10.2-1.css | 415 -------------- css/mastodon-timeline-3.8.1-3.css | 490 ---------------- css/mastodon-timeline-3.9.1-3.css | 412 ------------- js/mastodon-timeline-1.1.0.js | 271 --------- js/mastodon-timeline-3.10.0-3.js | 834 --------------------------- js/mastodon-timeline-3.10.1-1.js | 866 ---------------------------- js/mastodon-timeline-3.10.2-1.js | 890 ----------------------------- js/mastodon-timeline-3.7.0.js | 522 ----------------- js/mastodon-timeline-3.8.1-1.js | 666 --------------------- js/mastodon-timeline-3.9.1-3.js | 786 ------------------------- 15 files changed, 7554 deletions(-) delete mode 100644 css/mastodon-timeline-1.0.1.css delete mode 100644 css/mastodon-timeline-1.0.2.css delete mode 100644 css/mastodon-timeline-1.1.0.css delete mode 100644 css/mastodon-timeline-3.10.0-3.css delete mode 100644 css/mastodon-timeline-3.10.1-1.css delete mode 100644 css/mastodon-timeline-3.10.2-1.css delete mode 100644 css/mastodon-timeline-3.8.1-3.css delete mode 100644 css/mastodon-timeline-3.9.1-3.css delete mode 100644 js/mastodon-timeline-1.1.0.js delete mode 100644 js/mastodon-timeline-3.10.0-3.js delete mode 100644 js/mastodon-timeline-3.10.1-1.js delete mode 100644 js/mastodon-timeline-3.10.2-1.js delete mode 100644 js/mastodon-timeline-3.7.0.js delete mode 100644 js/mastodon-timeline-3.8.1-1.js delete mode 100644 js/mastodon-timeline-3.9.1-3.js diff --git a/css/mastodon-timeline-1.0.1.css b/css/mastodon-timeline-1.0.1.css deleted file mode 100644 index 422b324..0000000 --- a/css/mastodon-timeline-1.0.1.css +++ /dev/null @@ -1,191 +0,0 @@ -/* Mastodon embed feed timeline */ -/* More info at: */ -/* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ - - -/* Main container */ -.mt-timeline { - height: calc(100% - 4rem); - padding: .5rem .5rem; - position: relative; - background: white; -} - -.mt-timeline a:link, -.mt-timeline a:active, -.mt-timeline a { - text-decoration: none; - color: #0000EE; -} - -.mt-timeline a:visited { - color: #551ABB; -} - -.mt-body { - height: 100%; - overflow-y: auto; - white-space: pre-wrap; - word-wrap: break-word; -} - -.mt-body .invisible { - display: none; -} - -/* Toot container */ -.mt-toot { - margin: 0 0 0 0; - padding: 1rem 1rem 1rem 1rem; - position: relative; - min-height: 60px; - background-color: transparent; - border-bottom: 1px solid #dee2e6; -} -.mt-toot:hover { - cursor: pointer; - background-color: rgba(124, 124, 124, 0.2); -} -.mt-toot p:last-child { - margin-bottom: 0; -} - -/* User icon */ -.mt-user { - display: inline-block; - font-weight: 600; - position: absolute; - top: 33px; - left: 75px; -} -.mt-avatar { - position: absolute; - top: 20px; - left: 15px; - width: 50px; - height: 50px; - background-color: transparent; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: contain; - background-color: #fff; - border-radius: 5px; -} -.mt-avatar-boosted { - width: 40px; - height: 40px; -} -.mt-avatar-booster { - width: 25px; - height: 25px; - top: 25px; - left: 25px; -} - -/* Message */ -.toot-text { - margin-bottom: 0.25rem; - color: black; - padding-top: 60px; -} -.toot-text .ellipsis::after{ - content:'...'; -} -.mt-error { - color: darkred; - background: lightpink; - margin: 5px; - padding: 10px; -} - -/* Poll */ -.toot-poll { - margin-bottom: 0.25rem; - color: black; -} -.toot-poll ul{ - list-style: none; - padding: 0; - margin: 0; -} -.toot-poll ul li:not(:last-child){ - margin-bottom: 0.25rem; -} -.toot-poll ul li:before { - content: "◯"; - padding-right: 0.5rem; -} - -/* Medias */ -.toot-media { - overflow: hidden; - margin-bottom: 0.25rem; -} -.toot-media-preview { - position: relative; - margin-top: 0.25rem; - height: auto; - text-align: center; - width: 100%; -} -.toot-media-spoiler > img { - filter: blur(2rem); -} -.toot-media-preview a { - display: block; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} -.img-ratio14_7 { -position: relative; -padding-top: 48.95%; /* 14:7 */ -width: 100%; -} -.img-ratio14_7 > img { -width: 100%; -height: auto; -position: absolute; -top: 50%; -left: 50%; -transform: translate(-50%, -50%); -text-align: center; -} - -/* Date */ -.toot-date { - font-size: 0.75rem; - opacity: 0.5; -} - -/* Loading-spinner */ -.loading-spinner { - height: 100%; - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -/* See more btn */ -.mt-seeMore{ - margin: 2rem auto; - padding: 0 2rem; - text-align: center; -} - -/* Hidden element */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} diff --git a/css/mastodon-timeline-1.0.2.css b/css/mastodon-timeline-1.0.2.css deleted file mode 100644 index 78dca46..0000000 --- a/css/mastodon-timeline-1.0.2.css +++ /dev/null @@ -1,192 +0,0 @@ -/* Mastodon embed feed timeline */ -/* More info at: */ -/* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ - - -/* Main container */ -.mt-timeline { - height: calc(100% - 4rem); - padding: .5rem .5rem; - position: relative; - background: white; -} - -.mt-timeline a:link, -.mt-timeline a:active, -.mt-timeline a { - text-decoration: none; - color: #0000EE; -} - -.mt-timeline a:visited { - color: #551ABB; -} - -.mt-body { - height: 100%; - overflow-y: auto; - white-space: pre-wrap; - word-wrap: break-word; -} - -.mt-body .invisible { - display: none; -} - -/* Toot container */ -.mt-toot { - margin: 0 0 0 0; - padding: 1rem 1rem 1rem 1rem; - position: relative; - min-height: 60px; - background-color: transparent; - border-bottom: 1px solid #dee2e6; -} -.mt-toot:hover { - cursor: pointer; - background-color: rgba(124, 124, 124, 0.2); -} -.mt-toot p:last-child { - margin-bottom: 0; -} - -/* User icon */ -.mt-user { - display: inline-block; - font-weight: normal; - position: absolute; - top: 33px; - left: 75px; -} - -.mt-avatar { - position: absolute; - top: 20px; - left: 15px; - width: 50px; - height: 50px; - background-color: transparent; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: contain; - background-color: #fff; - border-radius: 5px; -} -.mt-avatar-boosted { - width: 40px; - height: 40px; -} -.mt-avatar-booster { - width: 25px; - height: 25px; - top: 25px; - left: 25px; -} - -/* Message */ -.toot-text { - margin-bottom: 0.25rem; - color: black; - padding-top: 60px; -} -.toot-text .ellipsis::after{ - content:'...'; -} -.mt-error { - color: darkred; - background: lightpink; - margin: 5px; - padding: 10px; -} - -/* Poll */ -.toot-poll { - margin-bottom: 0.25rem; - color: black; -} -.toot-poll ul{ - list-style: none; - padding: 0; - margin: 0; -} -.toot-poll ul li:not(:last-child){ - margin-bottom: 0.25rem; -} -.toot-poll ul li:before { - content: "◯"; - padding-right: 0.5rem; -} - -/* Medias */ -.toot-media { - overflow: hidden; - margin-bottom: 0.25rem; -} -.toot-media-preview { - position: relative; - margin-top: 0.25rem; - height: auto; - text-align: center; - width: 100%; -} -.toot-media-spoiler > img { - filter: blur(2rem); -} -.toot-media-preview a { - display: block; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} -.img-ratio14_7 { -position: relative; -padding-top: 48.95%; /* 14:7 */ -width: 100%; -} -.img-ratio14_7 > img { -width: 100%; -height: auto; -position: absolute; -top: 50%; -left: 50%; -transform: translate(-50%, -50%); -text-align: center; -} - -/* Date */ -.toot-date { - font-size: 0.75rem; - opacity: 0.5; -} - -/* Loading-spinner */ -.loading-spinner { - height: 100%; - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -/* See more btn */ -.mt-seeMore{ - margin: 2rem auto; - padding: 0 2rem; - text-align: center; -} - -/* Hidden element */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} diff --git a/css/mastodon-timeline-1.1.0.css b/css/mastodon-timeline-1.1.0.css deleted file mode 100644 index c9b8e36..0000000 --- a/css/mastodon-timeline-1.1.0.css +++ /dev/null @@ -1,198 +0,0 @@ -/* Mastodon embed feed timeline */ -/* More info at: */ -/* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ - - -/* Main container */ -.mt-timeline { - height: calc(100% - 4rem); - padding: .5rem .5rem; - position: relative; - background: white; -} - -.mt-timeline a:link, -.mt-timeline a:active, -.mt-timeline a { - text-decoration: none; - color: #0000EE; -} - -.mt-timeline a:visited { - color: #551ABB; -} - -.mt-body { - height: 100%; - overflow-y: auto; - white-space: pre-wrap; - word-wrap: break-word; -} - -.mt-body .invisible { - display: none; -} - -/* Toot container */ -.mt-toot { - margin: 0 0 0 0; - padding: 1rem 1rem 1rem 1rem; - position: relative; - min-height: 60px; - background-color: transparent; - border-bottom: 1px solid #dee2e6; -} -.mt-toot:hover { - cursor: pointer; - background-color: rgba(124, 124, 124, 0.2); -} -.mt-toot p:last-child { - margin-bottom: 0; -} - -/* User icon */ -.mt-user { - display: inline-block; - font-weight: normal; - position: absolute; - top: 33px; - left: 75px; -} - -.mt-avatar { - position: absolute; - top: 20px; - left: 15px; - width: 50px; - height: 50px; - background-color: transparent; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: contain; - background-color: #fff; - border-radius: 5px; -} -.mt-avatar-boosted { - width: 40px; - height: 40px; -} -.mt-avatar-booster { - width: 25px; - height: 25px; - top: 25px; - left: 25px; -} - -/* Message */ -.toot-text { - margin-bottom: 0.25rem; - color: black; - padding-top: 60px; -} -.toot-text .ellipsis::after{ - content:'...'; -} -.mt-error { - color: darkred; - background: lightpink; - margin: 5px; - padding: 10px; -} - -/* Poll */ -.toot-poll { - margin-bottom: 0.25rem; - color: black; -} -.toot-poll ul{ - list-style: none; - padding: 0; - margin: 0; -} -.toot-poll ul li:not(:last-child){ - margin-bottom: 0.25rem; -} -.toot-poll ul li:before { - content: "◯"; - padding-right: 0.5rem; -} - -/* Medias */ -.toot-media { - overflow: hidden; - margin-bottom: 0.25rem; -} -.toot-media-preview { - position: relative; - margin-top: 0.25rem; - height: auto; - text-align: center; - width: 100%; -} -.toot-media-spoiler > img { - filter: blur(2rem); -} -.toot-media-preview a { - display: block; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} -.img-ratio14_7 { -position: relative; -padding-top: 48.95%; /* 14:7 */ -width: 100%; -} -.img-ratio14_7 > img { -width: 100%; -height: auto; -position: absolute; -top: 50%; -left: 50%; -transform: translate(-50%, -50%); -text-align: center; -} - -/* Date */ -.toot-date { - font-size: 0.75rem; - opacity: 0.5; -} - -/* Loading-spinner */ -.loading-spinner { - height: 100%; - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -/* See more btn */ -.mt-seeMore{ - margin: 2rem auto; - padding: 0 2rem; - text-align: center; -} - -/* Hidden element */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} - -.toot-text blockquote { - border-left: 4px solid #777696; - margin-left: 0; /* Reset the default margin */ - padding-left: 8px; /* Add padding for the quoted text */ -} diff --git a/css/mastodon-timeline-3.10.0-3.css b/css/mastodon-timeline-3.10.0-3.css deleted file mode 100644 index 9cededb..0000000 --- a/css/mastodon-timeline-3.10.0-3.css +++ /dev/null @@ -1,406 +0,0 @@ -/* Mastodon embed feed timeline v3.10.0-3 */ -/* More info at: */ -/* https://gitlab.com/clvgt12/mastodon-embed-feed-timeline */ - -/* Variables */ -:root { - --text-max-lines: none; -} - -/* Theme colors */ -:root, -html[data-theme="light"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --contrast-gray-color: #606984; - --error-text-color: #8b0000; -} -html[data-theme="dark"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --contrast-gray-color: #606984; - --error-text-color: #8b0000; -} - -/* Main container */ -.mt-container { - height: 100%; - overflow-y: auto; - position: relative; - background-color: var(--bg-color); - scrollbar-color: var(--line-gray-color) var(--bg-color); - scrollbar-width: thin; -} -.mt-container::-webkit-scrollbar { - width: 0.25rem; - height: 0.25rem; -} -.mt-container::-webkit-scrollbar-thumb { - background-color: var(--line-gray-color); - border: none; - border-radius: 3rem; -} -.mt-container::-webkit-scrollbar-thumb:hover, -.mt-container::-webkit-scrollbar-thumb:active { - background-color: var(--line-gray-color); -} -.mt-container::-webkit-scrollbar-track { - background-color: var(--bg-color); - border: none; - border-radius: 0; -} -.mt-container::-webkit-scrollbar-track:hover, -.mt-container::-webkit-scrollbar-track:active, -.mt-container::-webkit-scrollbar-corner { - background-color: var(--bg-color); -} -.mt-container a:link, -.mt-container a:active, -.mt-container a { - text-decoration: none; - color: var(--link-color); -} -.mt-container a:not(.mt-toot-preview):hover { - text-decoration: underline; -} -.mt-body { - padding: 1rem clamp(0.25rem, 4vw, 1.5rem); - white-space: pre-wrap; - word-wrap: break-word; - background-color: var(--bg-color); -} -.mt-body .invisible { - font-size: 0; - line-height: 0; - display: inline-block; - width: 0; - height: 0; - position: absolute; -} -.mt-body a { - color: var(--link-color); - text-decoration: none; -} -.mt-body a:hover { -color: var(--link-color); -text-decoration: underline; -} - -/* Toot container */ -.mt-toot { - margin: 0.25rem; - padding: 1rem 0.5rem 1.5rem 0.5rem; - position: relative; - min-height: 3.75rem; - border-bottom: 1px solid var(--line-gray-color); - font-family: sans-serif; -} -.mt-toot:hover, -.mt-toot:focus { - cursor: pointer; - background-color: var(--bg-hover-color); -} -.mt-toot p:last-child { - margin-bottom: 0; -} - -/* User avatar */ -.mt-toot-avatar { - margin-right: 0.75rem; -} -.mt-toot-avatar-standard { - width: 2.25rem; - height: 2.25rem; -} -.mt-toot-avatar-boosted { - width: 3rem; - height: 3rem; - position: relative; -} -.mt-toot-avatar-image-big img { - aspect-ratio: 1/1; - width: 2.25rem; - height: 2.25rem; - border-radius: 0.25rem; - overflow: hidden; -} -.mt-toot-avatar-image-small img { - aspect-ratio: 1/1; - width: 1.5rem; - height: 1.5rem; - top: 1.5rem; - left: 1.5rem; - position: absolute; - border-radius: 0.25rem; - overflow: hidden; -} - -/* User name and date */ -.mt-toot-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; -} -.mt-toot-header-user { - font-weight: 600; - padding-right: 1rem; -} -.mt-toot-header-user > a { - display: flex; - align-items: flex-start; - color: var(--content-text) !important; - overflow-wrap: anywhere; - text-decoration: none; -} -.mt-toot-header-date { - font-size: 0.75rem; - text-align: right; - margin: 0 0 0 auto; -} -.mt-toot-header-date > a { - color: var(--contrast-gray-color) !important; - text-decoration: none; -} - -/* Text */ -.mt-toot-text { - margin-bottom: 1rem; - color: var(--content-text); -} -.mt-toot-text .spoiler-btn { - display: inline-block; -} -.mt-toot-text .spoiler-text-hidden { - display: none; -} -.mt-toot-text.truncate { - display: -webkit-box; - overflow: hidden; - -webkit-line-clamp: var(--text-max-lines); - -webkit-box-orient: vertical; -} -.mt-toot-text:not(.truncate) .ellipsis::after { - content: "..."; -} -.mt-toot-text blockquote { - border-left: 0.25rem solid var(--line-gray-color); - margin-left: 0; - padding-left: 0.5rem; -} -.mt-toot-header-user .custom-emoji, -.mt-toot-text .custom-emoji { - height: 1.5rem; - min-width: 1.5rem; - margin-bottom: -0.25rem; - width: auto; -} - -/* Poll */ -.mt-toot-poll { - margin-bottom: 1rem; - color: var(--content-text); -} -.mt-toot-poll ul { - list-style: none; - padding: 0; - margin: 0; -} -.mt-toot-poll ul li { - font-size: 0.9rem; - margin-bottom: 0.5rem; -} -.mt-toot-poll ul li:not(:last-child) { - margin-bottom: 0.25rem; -} -.mt-toot-poll ul li:before { - content: "◯"; - padding-right: 0.5rem; -} - -/* Medias */ -.mt-toot-media { - overflow: hidden; - margin-bottom: 1rem; - border-radius: 0.75rem; -} -.mt-toot-media > .spoiler-btn { - position: absolute; - top: 50%; - left: 50%; - z-index: 1; - transform: translate(-50%, -50%); -} -.mt-toot-media-spoiler > img { - filter: blur(2rem); -} -.img-ratio14_7 { - position: relative; - padding-top: 56.95%; - width: 100%; -} -.img-ratio14_7 > img { - width: 100%; - height: auto; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - text-align: center; -} - -/* Preview link */ -.mt-toot-preview { - min-height: 4rem; - display: flex; - flex-direction: column; - border: 1px solid var(--line-gray-color); - border-radius: 0.75rem; - color: var(--link-color); - font-size: 0.8rem; - margin: 1rem 0; - overflow: hidden; -} -.mt-toot-preview-image { - width: 100%; - align-self: stretch; -} -.mt-toot-preview-image img { - display: block; - width: 100%; - height: 100%; - object-fit: cover; -} -.mt-toot-preview-noImage { - width: 40%; - font-size: 1.5rem; - align-self: inherit; - text-align: left; -} -.mt-toot-preview-content { - width: 95%; - display: flex; - align-self: center; - flex-direction: column; - padding: 0.5rem 1rem; - gap: 0.5rem; -} -.mt-toot-preview-title { - font-weight: 600; - font-size: 1.0rem; - font-family: serif; -} - -/* Spoiler button */ -.spoiler-btn { - border-radius: 2px; - background-color: var(--line-gray-color); - border: 0; - color: var(--content-text); - font-weight: 700; - font-size: 0.7rem; - padding: 0 0.35rem; - text-transform: uppercase; - line-height: 1.25rem; - cursor: pointer; - vertical-align: top; -} - -/* Counter bar */ -.mt-toot-counter-bar { - display: flex; - min-width: 6rem; - max-width: 40rem; - justify-content: space-between; - color: var(--contrast-gray-color); -} -.mt-toot-counter-bar-replies, -.mt-toot-counter-bar-reblog, -.mt-toot-counter-bar-favorites { - display: flex; - font-size: 0.75rem; - gap: 0.25rem; - align-items: center; - opacity: 0.5; -} -.mt-toot-counter-bar-replies > svg, -.mt-toot-counter-bar-reblog > svg, -.mt-toot-counter-bar-favorites > svg { - width: 1rem; - fill: var(--contrast-gray-color); -} - -/* Error */ -.mt-error { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - color: var(--error-text-color); - padding: 0.75rem; - text-align: center; -} -.mt-error-icon { - font-size: 2rem; -} -.mt-error-message { - padding: 1rem 0; -} -.mt-error-message hr { - color: var(--line-gray-color); -} - -/* Loading spinner */ -.mt-body > .loading-spinner { - position: absolute; - width: 3rem; - height: 3rem; - margin: auto; - top: calc(50% - 1.5rem); - right: calc(50% - 1.5rem); -} -.loading-spinner { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -/* Footer (See more link) */ -.mt-footer { - margin: unset; - padding: unset; - text-align: center; - font-family: sans-serif; - font-size: 0.8rem; - height: 3.0rem; - background-color: var(--bg-color); -} -.mt-footer a { - color: var(--link-color); - text-decoration: none; -} -.mt-footer a:hover { - color: var(--link-color); - text-decoration: underline; -} - -/* Hidden elements */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} \ No newline at end of file diff --git a/css/mastodon-timeline-3.10.1-1.css b/css/mastodon-timeline-3.10.1-1.css deleted file mode 100644 index 5b9d616..0000000 --- a/css/mastodon-timeline-3.10.1-1.css +++ /dev/null @@ -1,415 +0,0 @@ -/* Mastodon embed feed timeline v3.10.1-1 */ -/* More info at: */ -/* https://gitlab.com/clvgt12/mastodon-embed-feed-timeline */ - -/* Variables */ -:root { - --text-max-lines: none; -} - -/* Theme colors */ -:root, -html[data-theme="light"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --contrast-gray-color: #606984; - --error-text-color: #8b0000; -} -html[data-theme="dark"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --contrast-gray-color: #606984; - --error-text-color: #8b0000; -} - -/* Main container */ -.mt-container { - height: 100%; - overflow-y: auto; - position: relative; - background-color: var(--bg-color); - scrollbar-color: var(--line-gray-color) var(--bg-color); - scrollbar-width: thin; -} -.mt-container::-webkit-scrollbar { - width: 0.25rem; - height: 0.25rem; -} -.mt-container::-webkit-scrollbar-thumb { - background-color: var(--line-gray-color); - border: none; - border-radius: 3rem; -} -.mt-container::-webkit-scrollbar-thumb:hover, -.mt-container::-webkit-scrollbar-thumb:active { - background-color: var(--line-gray-color); -} -.mt-container::-webkit-scrollbar-track { - background-color: var(--bg-color); - border: none; - border-radius: 0; -} -.mt-container::-webkit-scrollbar-track:hover, -.mt-container::-webkit-scrollbar-track:active, -.mt-container::-webkit-scrollbar-corner { - background-color: var(--bg-color); -} -.mt-container a:link, -.mt-container a:active, -.mt-container a { - text-decoration: none; - color: var(--link-color); -} -.mt-container a:not(.mt-toot-preview):hover { - text-decoration: underline; -} -.mt-body { - padding: 1rem clamp(0.25rem, 4vw, 1.5rem); - white-space: pre-wrap; - word-wrap: break-word; - background-color: var(--bg-color); -} -.mt-body .invisible { - font-size: 0; - line-height: 0; - display: inline-block; - width: 0; - height: 0; - position: absolute; -} -.mt-body a { - color: var(--link-color); - text-decoration: none; -} -.mt-body a:hover { -color: var(--link-color); -text-decoration: underline; -} - -/* Toot container */ -.mt-toot { - margin: 0.25rem; - padding: 1rem 0.5rem 1.5rem 0.5rem; - position: relative; - min-height: 3.75rem; - border-bottom: 1px solid var(--line-gray-color); - font-family: sans-serif; -} -.mt-toot:hover, -.mt-toot:focus { - cursor: pointer; - background-color: var(--bg-hover-color); -} -.mt-toot p:last-child { - margin-bottom: 0; -} - -/* User avatar */ -.mt-toot-avatar { - margin-right: 0.75rem; -} -.mt-toot-avatar-standard { - width: 2.25rem; - height: 2.25rem; -} -.mt-toot-avatar-boosted { - width: 3rem; - height: 3rem; - position: relative; -} -.mt-toot-avatar-image-big img { - aspect-ratio: 1/1; - width: 2.25rem; - height: 2.25rem; - border-radius: 0.25rem; - overflow: hidden; -} -.mt-toot-avatar-image-small img { - aspect-ratio: 1/1; - width: 1.5rem; - height: 1.5rem; - top: 1.5rem; - left: 1.5rem; - position: absolute; - border-radius: 0.25rem; - overflow: hidden; -} - -/* User name and date */ -.mt-toot-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; -} -.mt-toot-header-user { - font-weight: 600; - padding-right: 1rem; -} -.mt-toot-header-user > a { - display: flex; - align-items: flex-start; - color: var(--content-text) !important; - overflow-wrap: anywhere; - text-decoration: none; -} -.mt-toot-header-date { - font-size: 0.75rem; - text-align: right; - margin: 0 0 0 auto; -} -.mt-toot-header-date > a { - color: var(--contrast-gray-color) !important; - text-decoration: none; -} - -/* Text */ -.mt-toot-text { - margin-bottom: 1rem; - color: var(--content-text); -} -.mt-toot-text .spoiler-btn { - display: inline-block; -} -.mt-toot-text .spoiler-text-hidden { - display: none; -} -.mt-toot-text.truncate { - display: -webkit-box; - overflow: hidden; - -webkit-line-clamp: var(--text-max-lines); - -webkit-box-orient: vertical; -} -.mt-toot-text:not(.truncate) .ellipsis::after { - content: "..."; -} -.mt-toot-text blockquote { - border-left: 0.25rem solid var(--line-gray-color); - margin-left: 0; - padding-left: 0.5rem; -} -.mt-toot-header-user .custom-emoji, -.mt-toot-text .custom-emoji { - height: 1.5rem; - min-width: 1.5rem; - margin-bottom: -0.25rem; - width: auto; -} - -/* Poll */ -.mt-toot-poll { - margin-bottom: 1rem; - color: var(--content-text); -} -.mt-toot-poll ul { - list-style: none; - padding: 0; - margin: 0; -} -.mt-toot-poll ul li { - font-size: 0.9rem; - margin-bottom: 0.5rem; -} -.mt-toot-poll.mt-toot-poll-expired ul li { - color: var(--contrast-gray-color); -} -.mt-toot-poll ul li:not(:last-child) { - margin-bottom: 0.25rem; -} -.mt-toot-poll ul li:before { - content: "◯"; - padding-right: 0.5rem; -} -.mt-toot-poll.mt-toot-poll-expired ul li:before { - content: ""; - padding-right: 0; -} - -/* Medias */ -.mt-toot-media { - overflow: hidden; - margin-bottom: 1rem; - border-radius: 0.75rem; -} -.mt-toot-media > .spoiler-btn { - position: absolute; - top: 50%; - left: 50%; - z-index: 1; - transform: translate(-50%, -50%); -} -.mt-toot-media-spoiler > img { - filter: blur(2rem); -} -.img-ratio14_7 { - position: relative; - padding-top: 56.95%; - width: 100%; -} -.img-ratio14_7 > img { - width: 100%; - height: auto; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - text-align: center; - color: var(--content-text); -} - -/* Preview link */ -.mt-toot-preview { - min-height: 4rem; - display: flex; - flex-direction: column; - border: 1px solid var(--line-gray-color); - border-radius: 0.75rem; - color: var(--link-color); - font-size: 0.8rem; - margin: 1rem 0; - overflow: hidden; -} -.mt-toot-preview-image { - width: 100%; - align-self: stretch; -} -.mt-toot-preview-image img { - display: block; - width: 100%; - height: 100%; - object-fit: cover; - color: var(--content-text); -} -.mt-toot-preview-noImage { - width: 40%; - font-size: 1.5rem; - align-self: inherit; - text-align: left; -} -.mt-toot-preview-content { - width: 95%; - display: flex; - align-self: center; - flex-direction: column; - padding: 0.5rem 1rem; - gap: 0.5rem; -} -.mt-toot-preview-title { - font-weight: 600; - font-size: 1.0rem; - font-family: serif; -} - -/* Spoiler button */ -.spoiler-btn { - border-radius: 2px; - background-color: var(--line-gray-color); - border: 0; - color: var(--content-text); - font-weight: 700; - font-size: 0.7rem; - padding: 0 0.35rem; - text-transform: uppercase; - line-height: 1.25rem; - cursor: pointer; - vertical-align: top; -} - -/* Counter bar */ -.mt-toot-counter-bar { - display: flex; - min-width: 6rem; - max-width: 40rem; - justify-content: space-between; - color: var(--contrast-gray-color); -} -.mt-toot-counter-bar-replies, -.mt-toot-counter-bar-reblog, -.mt-toot-counter-bar-favorites { - display: flex; - font-size: 0.75rem; - gap: 0.25rem; - align-items: center; - opacity: 0.5; -} -.mt-toot-counter-bar-replies > svg, -.mt-toot-counter-bar-reblog > svg, -.mt-toot-counter-bar-favorites > svg { - width: 1rem; - fill: var(--contrast-gray-color); -} - -/* Error */ -.mt-error { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - color: var(--error-text-color); - padding: 0.75rem; - text-align: center; -} -.mt-error-icon { - font-size: 2rem; -} -.mt-error-message { - padding: 1rem 0; -} -.mt-error-message hr { - color: var(--line-gray-color); -} - -/* Loading spinner */ -.mt-body > .loading-spinner { - position: absolute; - width: 3rem; - height: 3rem; - margin: auto; - top: calc(50% - 1.5rem); - right: calc(50% - 1.5rem); -} -.loading-spinner { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -/* Footer (See more link) */ -.mt-footer { - margin: unset; - padding: unset; - text-align: center; - font-family: sans-serif; - font-size: 0.8rem; - height: 3.0rem; - background-color: var(--bg-color); -} -.mt-footer a { - color: var(--link-color); - text-decoration: none; -} -.mt-footer a:hover { - color: var(--link-color); - text-decoration: underline; -} - -/* Hidden elements */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} \ No newline at end of file diff --git a/css/mastodon-timeline-3.10.2-1.css b/css/mastodon-timeline-3.10.2-1.css deleted file mode 100644 index d826ebb..0000000 --- a/css/mastodon-timeline-3.10.2-1.css +++ /dev/null @@ -1,415 +0,0 @@ -/* Mastodon embed feed timeline v3.10.2-1 */ -/* More info at: */ -/* https://gitlab.com/clvgt12/mastodon-embed-feed-timeline */ - -/* Variables */ -:root { - --text-max-lines: none; -} - -/* Theme colors */ -:root, -html[data-theme="light"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --contrast-gray-color: #606984; - --error-text-color: #8b0000; -} -html[data-theme="dark"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --contrast-gray-color: #606984; - --error-text-color: #8b0000; -} - -/* Main container */ -.mt-container { - height: 100%; - overflow-y: auto; - position: relative; - background-color: var(--bg-color); - scrollbar-color: var(--line-gray-color) var(--bg-color); - scrollbar-width: thin; -} -.mt-container::-webkit-scrollbar { - width: 0.25rem; - height: 0.25rem; -} -.mt-container::-webkit-scrollbar-thumb { - background-color: var(--line-gray-color); - border: none; - border-radius: 3rem; -} -.mt-container::-webkit-scrollbar-thumb:hover, -.mt-container::-webkit-scrollbar-thumb:active { - background-color: var(--line-gray-color); -} -.mt-container::-webkit-scrollbar-track { - background-color: var(--bg-color); - border: none; - border-radius: 0; -} -.mt-container::-webkit-scrollbar-track:hover, -.mt-container::-webkit-scrollbar-track:active, -.mt-container::-webkit-scrollbar-corner { - background-color: var(--bg-color); -} -.mt-container a:link, -.mt-container a:active, -.mt-container a { - text-decoration: none; - color: var(--link-color); -} -.mt-container a:not(.mt-toot-preview):hover { - text-decoration: underline; -} -.mt-body { - padding: 1rem clamp(0.25rem, 4vw, 1.5rem); - white-space: pre-wrap; - word-wrap: break-word; - background-color: var(--bg-color); -} -.mt-body .invisible { - font-size: 0; - line-height: 0; - display: inline-block; - width: 0; - height: 0; - position: absolute; -} -.mt-body a { - color: var(--link-color); - text-decoration: none; -} -.mt-body a:hover { -color: var(--link-color); -text-decoration: underline; -} - -/* Toot container */ -.mt-toot { - margin: 0.25rem; - padding: 1rem 0.5rem 1.5rem 0.5rem; - position: relative; - min-height: 3.75rem; - border-bottom: 1px solid var(--line-gray-color); - font-family: sans-serif; -} -.mt-toot:hover, -.mt-toot:focus { - cursor: pointer; - background-color: var(--bg-hover-color); -} -.mt-toot p:last-child { - margin-bottom: 0; -} - -/* User avatar */ -.mt-toot-avatar { - margin-right: 0.75rem; -} -.mt-toot-avatar-standard { - width: 2.25rem; - height: 2.25rem; -} -.mt-toot-avatar-boosted { - width: 3rem; - height: 3rem; - position: relative; -} -.mt-toot-avatar-image-big img { - aspect-ratio: 1/1; - width: 2.25rem; - height: 2.25rem; - border-radius: 0.25rem; - overflow: hidden; -} -.mt-toot-avatar-image-small img { - aspect-ratio: 1/1; - width: 1.5rem; - height: 1.5rem; - top: 1.5rem; - left: 1.5rem; - position: absolute; - border-radius: 0.25rem; - overflow: hidden; -} - -/* User name and date */ -.mt-toot-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; -} -.mt-toot-header-user { - font-weight: 600; - padding-right: 1rem; -} -.mt-toot-header-user > a { - display: flex; - align-items: flex-start; - color: var(--content-text) !important; - overflow-wrap: anywhere; - text-decoration: none; -} -.mt-toot-header-date { - font-size: 0.75rem; - text-align: right; - margin: 0 0 0 auto; -} -.mt-toot-header-date > a { - color: var(--contrast-gray-color) !important; - text-decoration: none; -} - -/* Text */ -.mt-toot-text { - margin-bottom: 1rem; - color: var(--content-text); -} -.mt-toot-text .spoiler-btn { - display: inline-block; -} -.mt-toot-text .spoiler-text-hidden { - display: none; -} -.mt-toot-text.truncate { - display: -webkit-box; - overflow: hidden; - -webkit-line-clamp: var(--text-max-lines); - -webkit-box-orient: vertical; -} -.mt-toot-text:not(.truncate) .ellipsis::after { - content: "..."; -} -.mt-toot-text blockquote { - border-left: 0.25rem solid var(--line-gray-color); - margin-left: 0; - padding-left: 0.5rem; -} -.mt-toot-header-user .custom-emoji, -.mt-toot-text .custom-emoji { - height: 1.5rem; - min-width: 1.5rem; - margin-bottom: -0.25rem; - width: auto; -} - -/* Poll */ -.mt-toot-poll { - margin-bottom: 1rem; - color: var(--content-text); -} -.mt-toot-poll ul { - list-style: none; - padding: 0; - margin: 0; -} -.mt-toot-poll ul li { - font-size: 0.9rem; - margin-bottom: 0.5rem; -} -.mt-toot-poll.mt-toot-poll-expired ul li { - color: var(--contrast-gray-color); -} -.mt-toot-poll ul li:not(:last-child) { - margin-bottom: 0.25rem; -} -.mt-toot-poll ul li:before { - content: "◯"; - padding-right: 0.5rem; -} -.mt-toot-poll.mt-toot-poll-expired ul li:before { - content: ""; - padding-right: 0; -} - -/* Medias */ -.mt-toot-media { - overflow: hidden; - margin-bottom: 1rem; - border-radius: 0.75rem; -} -.mt-toot-media > .spoiler-btn { - position: absolute; - top: 50%; - left: 50%; - z-index: 1; - transform: translate(-50%, -50%); -} -.mt-toot-media-spoiler > img { - filter: blur(2rem); -} -.img-ratio14_7 { - position: relative; - padding-top: 56.95%; - width: 100%; -} -.img-ratio14_7 > img { - width: 100%; - height: auto; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - text-align: center; - color: var(--content-text); -} - -/* Preview link */ -.mt-toot-preview { - min-height: 4rem; - display: flex; - flex-direction: column; - border: 1px solid var(--line-gray-color); - border-radius: 0.75rem; - color: var(--link-color); - font-size: 0.8rem; - margin: 1rem 0; - overflow: hidden; -} -.mt-toot-preview-image { - width: 100%; - align-self: stretch; -} -.mt-toot-preview-image img { - display: block; - width: 100%; - height: 100%; - object-fit: cover; - color: var(--content-text); -} -.mt-toot-preview-noImage { - width: 40%; - font-size: 1.5rem; - align-self: inherit; - text-align: left; -} -.mt-toot-preview-content { - width: 95%; - display: flex; - align-self: center; - flex-direction: column; - padding: 0.5rem 1rem; - gap: 0.5rem; -} -.mt-toot-preview-title { - font-weight: 600; - font-size: 1.0rem; - font-family: serif; -} - -/* Spoiler button */ -.spoiler-btn { - border-radius: 2px; - background-color: var(--line-gray-color); - border: 0; - color: var(--content-text); - font-weight: 700; - font-size: 0.7rem; - padding: 0 0.35rem; - text-transform: uppercase; - line-height: 1.25rem; - cursor: pointer; - vertical-align: top; -} - -/* Counter bar */ -.mt-toot-counter-bar { - display: flex; - min-width: 6rem; - max-width: 40rem; - justify-content: space-between; - color: var(--contrast-gray-color); -} -.mt-toot-counter-bar-replies, -.mt-toot-counter-bar-reblog, -.mt-toot-counter-bar-favorites { - display: flex; - font-size: 0.75rem; - gap: 0.25rem; - align-items: center; - opacity: 0.5; -} -.mt-toot-counter-bar-replies > svg, -.mt-toot-counter-bar-reblog > svg, -.mt-toot-counter-bar-favorites > svg { - width: 1rem; - fill: var(--contrast-gray-color); -} - -/* Error */ -.mt-error { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - color: var(--error-text-color); - padding: 0.75rem; - text-align: center; -} -.mt-error-icon { - font-size: 2rem; -} -.mt-error-message { - padding: 1rem 0; -} -.mt-error-message hr { - color: var(--line-gray-color); -} - -/* Loading spinner */ -.mt-body > .loading-spinner { - position: absolute; - width: 3rem; - height: 3rem; - margin: auto; - top: calc(50% - 1.5rem); - right: calc(50% - 1.5rem); -} -.loading-spinner { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -/* Footer (See more link) */ -.mt-footer { - margin: unset; - padding: unset; - text-align: center; - font-family: sans-serif; - font-size: 0.8rem; - height: 3.0rem; - background-color: var(--bg-color); -} -.mt-footer a { - color: var(--link-color); - text-decoration: none; -} -.mt-footer a:hover { - color: var(--link-color); - text-decoration: underline; -} - -/* Hidden elements */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} \ No newline at end of file diff --git a/css/mastodon-timeline-3.8.1-3.css b/css/mastodon-timeline-3.8.1-3.css deleted file mode 100644 index 3e8a01c..0000000 --- a/css/mastodon-timeline-3.8.1-3.css +++ /dev/null @@ -1,490 +0,0 @@ -/* Mastodon embed feed timeline 3.8.1-3 */ -/* More info at: */ -/* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ - - -/* Main container */ -.mt-timeline { - height: calc(100% - 4rem); - padding: .5rem .5rem; - position: relative; - background: white; -} - -.mt-timeline a:link, -.mt-timeline a:active, -.mt-timeline a { - text-decoration: none; - color: #0000EE; -} - -.mt-timeline a:visited { - color: #551ABB; -} - -.mt-body { - height: 100%; - overflow-y: auto; - white-space: pre-wrap; - word-wrap: break-word; -} - -.mt-body .invisible { - display: none; -} - -/* Toot container */ -.mt-toot { - margin: 0 0 0 0; - padding: 1rem 1rem 1rem 1rem; - position: relative; - min-height: 60px; - background-color: transparent; - border-bottom: 1px solid #dee2e6; -} - -.mt-toot:hover { - cursor: pointer; - background-color: rgba(124, 124, 124, 0.2); -} - -.mt-toot p:last-child { - margin-bottom: 0; -} - -/* User icon */ -.mt-user { - display: flex; - align-items: center; - font-weight: 600; - margin-bottom: 1rem; - position: absolute; - top: 26px; - left: 75px; -} - -.mt-avatar { - position: absolute; - top: 20px; - left: 15px; - width: 50px; - height: 50px; - background-color: transparent; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: contain; - background-color: #fff; - border-radius: 5px; -} - -.mt-avatar { - position: absolute; - top: 20px; - left: 15px; - width: 50px; - height: 50px; - background-color: transparent; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: contain; - background-color: #fff; - border-radius: 5px; -} - -.mt-avatar { - position: absolute; - top: 20px; - left: 15px; - width: 50px; - height: 50px; - background-color: transparent; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: contain; - background-color: #fff; - border-radius: 5px; -} - -/* Message */ -.toot-text { - margin-bottom: 0.25rem; - color: black; - padding-top: 60px; -} - -.toot-text .ellipsis::after { - content: '...'; -} - -.mt-error { - color: darkred; - background: lightpink; - margin: 5px; - padding: 10px; -} - -/* Poll */ -.toot-poll { - margin-bottom: 0.25rem; - color: black; -} - -.toot-poll ul { - list-style: none; - padding: 0; - margin: 0; -} - -.toot-poll ul li:not(:last-child) { - margin-bottom: 0.25rem; -} - -.toot-poll ul li:before { - content: "◯"; - padding-right: 0.5rem; -} - -/* Medias */ -.toot-media { - overflow: hidden; - margin-bottom: 0.25rem; -} - -.toot-media-preview { - position: relative; - margin-top: 0.25rem; - height: auto; - text-align: center; - width: 100%; -} - -.toot-media-spoiler>img { - filter: blur(2rem); -} - -.toot-media-preview a { - display: block; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -.img-ratio14_7 { - position: relative; - padding-top: 48.95%; - /* 14:7 */ - width: 100%; -} - -.img-ratio14_7>img { - width: 100%; - height: auto; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - text-align: center; -} - -/* Date */ -.toot-date { - font-size: 0.75rem; - opacity: 0.5; -} - -/* Loading-spinner */ -.loading-spinner { - height: 100%; - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -/* See more btn */ -.mt-seeMore { - margin: 2rem auto; - padding: 0 2rem; - text-align: center; -} - -/* Hidden element */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} - -.toot-text blockquote { - border-left: 4px solid #777696; - margin-left: 0; - /* Reset the default margin */ - padding-left: 8px; - /* Add padding for the quoted text */ -} - -/* Mastodon embed feed timeline v3.8.1-3 */ -/* More info at: */ -/* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ - -/* Variables */ -:root { - --text-max-lines: none; -} - -/* Theme colors */ -:root, -html[data-theme="light"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --error-text-color: #8b0000; -} - -html[data-theme="dark"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --error-text-color: #8b0000; -} - -/* Main container */ -.mt-timeline { - height: 100%; - overflow-y: auto; - position: relative; - background: var(--bg-color); - scrollbar-color: var(--bg-hover-color) rgba(0, 0, 0, 0.1); -} - -.mt-timeline a:not(.toot-preview-link):hover { - text-decoration: underline; -} - -.mt-timeline::-webkit-scrollbar { - width: 0.75rem; - height: 0.75rem; -} - -.mt-timeline::-webkit-scrollbar-corner { - background: transparent; -} - -.mt-timeline::-webkit-scrollbar-thumb { - border: 0 var(--content-text); - border-radius: 2rem; - background: var(--bg-hover-color); -} - -.mt-timeline::-webkit-scrollbar-track { - border: 0 var(--content-text); - border-radius: 0; - background: rgba(0, 0, 0, 0.1); -} - -.mt-toot:hover, -.mt-toot:focus { - cursor: pointer; - background-color: var(--bg-hover-color); -} - -/* User icon */ -.mt-avatar { - position: absolute; - top: 20px; - left: 15px; - width: 50px; - height: 50px; - background-color: transparent; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: contain; - background-color: #fff; - border-radius: 5px; -} - -.mt-user { - display: flex; - align-items: center; - font-weight: normal; - margin-bottom: 1rem; - position: absolute; - top: 28px; - left: 75px; -} - -.mt-user { - display: flex; - align-items: center; - font-weight: normal; - margin: 12px 0 12px 0.75em; - position: absolute; - top: 26px; - left: 75px; -} - -/* Text */ -.toot-text { - margin-bottom: 0.25rem; - color: var(--content-text); -} - -.toot-text .spoiler-link { - display: inline-block; -} - -.toot-text .spoiler-text-hidden { - display: none; -} - -.toot-text.truncate { - display: -webkit-box; - overflow: hidden; - -webkit-line-clamp: var(--text-max-lines); - -webkit-box-orient: vertical; -} - -.toot-text:not(.truncate) .ellipsis::after { - content: "..."; -} - -.mt-error-icon { - font-size: 2rem; -} - -.mt-error-message { - padding: 1rem 0; -} - -.toot-poll ul li { - font-size: 0.9rem; - margin-bottom: 0.5rem; -} - -.toot-media>.spoiler-link { - position: absolute; - top: 50%; - left: 50%; - z-index: 1; - transform: translate(-50%, -50%); -} - -/* Preview link */ -.toot-preview-link { - min-height: 4rem; - display: flex; - flex-direction: row; - flex-wrap: wrap; - border: 1px solid var(--line-gray-color); - border-radius: 0.5rem; - color: var(--link-color); - font-size: 1.0rem; - margin: 1rem 0 0.5rem 0; - overflow: hidden; -} - -.toot-preview-image { - width: 100%; - align-self: stretch; -} - -.toot-preview-image img { - display: block; - width: 100%; - height: 100%; - object-fit: cover; -} - -.toot-preview-noImage { - width: 40%; - font-size: 1.5rem; - align-self: center; - text-align: center; -} - -.toot-preview-content { - width: 60%; - display: flex; - align-self: center; - flex-direction: column; - padding: 0.5rem 1rem; - gap: 0.5rem; -} - -.toot-preview-provider { - font-size: smaller; - font-weight: normal; - margin: 0.25em 0 0 0; -} - -.toot-preview-title { - font-size: smaller; - font-weight: 600; - margin: 0 0 0.25em 0; -} - -/* Spoiler button */ -.spoiler-link { - border-radius: 2px; - background-color: var(--line-gray-color); - border: 0; - color: var(--content-text); - font-weight: 700; - font-size: 0.7rem; - padding: 0 0.35rem; - text-transform: uppercase; - line-height: 1.25rem; - cursor: pointer; - vertical-align: top; -} - -/* Loading-spinner */ -.mt-body>.loading-spinner { - position: absolute; - width: 3rem; - height: 3rem; - margin: auto; - top: calc(50% - 1.5rem); - right: calc(50% - 1.5rem); -} - -.loading-spinner { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -/* Footer (See more link) */ -.mt-footer { - margin: 1rem auto 2rem auto; - padding: 0 2rem; - text-align: center; -} - -/* Hidden element */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} diff --git a/css/mastodon-timeline-3.9.1-3.css b/css/mastodon-timeline-3.9.1-3.css deleted file mode 100644 index e68abe9..0000000 --- a/css/mastodon-timeline-3.9.1-3.css +++ /dev/null @@ -1,412 +0,0 @@ -/* Mastodon embed feed timeline 3.9.1-3 */ -/* More info at: */ -/* https://gitlab.com/clvgt12/mastodon-embed-feed-timeline */ - -/* Variables */ -:root { - --text-max-lines: none; -} - -/* Theme colors */ -:root, -html[data-theme="light"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --error-text-color: #8b0000; -} - -html[data-theme="dark"] { - --bg-color: #fff; - --bg-hover-color: #d9e1e8; - --line-gray-color: #c0cdd9; - --content-text: #000; - --link-color: #3a3bff; - --error-text-color: #8b0000; -} - -/* Main container */ -.mt-timeline { - padding: 0.5rem 0.5rem; - height: 100%; - overflow-y: auto; - position: relative; - background: var(--bg-color); - scrollbar-color: var(--bg-hover-color) rgba(0, 0, 0, 0.1); -} - -.toot-media-preview a { - display: block; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -.mt-timeline a, -.mt-timeline a:link, -.mt-timeline a:active { - text-decoration: none; - color: #0000EE; -} - -.mt-timeline a:visited { - color: #551ABB; -} - -.mt-timeline a:not(.toot-preview-link):hover { - text-decoration: underline; -} - -.mt-timeline::-webkit-scrollbar { - width: 0.75rem; - height: 0.75rem; -} - -.mt-timeline::-webkit-scrollbar-corner { - background: transparent; -} - -.mt-timeline::-webkit-scrollbar-thumb { - border: 0 var(--content-text); - border-radius: 2rem; - background: var(--bg-hover-color); -} - -.mt-timeline::-webkit-scrollbar-track { - border: 0 var(--content-text); - border-radius: 0; - background: rgba(0, 0, 0, 0.1); -} - -.mt-body { - height: 100%; - overflow-y: auto; - white-space: pre-wrap; - word-wrap: break-word; -} - -.mt-body .invisible { - display: none; -} - -/* Loading-spinner */ - -.loading-spinner { - height: 100%; - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.0' viewBox='0 0 128 128' %3E%3Cg%3E%3Cpath d='M64 128A64 64 0 0 1 18.34 19.16L21.16 22a60 60 0 1 0 52.8-17.17l.62-3.95A64 64 0 0 1 64 128z' fill='%23404040'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'%3E%3C/animateTransform%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center center; - background-color: transparent; - background-size: min(2.5rem, calc(100% - 0.5rem)); -} - -.mt-body > .loading-spinner { - position: absolute; - width: 3rem; - height: 3rem; - margin: auto; - top: calc(50% - 1.5rem); - right: calc(50% - 1.5rem); -} - -/* Toot container */ -.mt-toot { - margin: 0 0 0 0; - padding: 1rem 1rem 1rem 1rem; - position: relative; - min-height: 60px; - background-color: transparent; - border-bottom: 1px solid #dee2e6; -} - -.mt-toot:hover { - cursor: pointer; - background-color: rgba(124, 124, 124, 0.2); -} - -.mt-toot p:last-child { - margin-bottom: 0; -} - -.mt-toot:hover, -.mt-toot:focus { - cursor: pointer; - background-color: var(--bg-hover-color); -} - -/* User icon */ - -.mt-user { - display: flex; - align-items: center; - font-weight: normal; - margin: 20px 0 20px 60px; -} - -.mt-avatar { - position: absolute; - top: 20px; - left: 15px; - width: 48px; - height: 48px; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: contain; - background-color: transparent; - border-radius: 4px; -} - -.mt-avatar-image img { - position: absolute; - height: 48px; - width: 48px; - border-radius: 4px; -} - -.mt-avatar-account img { - position: absolute; - height: 24px; - width: 24px; - padding-top: 24px; - padding-left: 24px; - border-radius: 2px; - z-index: 2; -} - -.mt-avatar-boosted img { - position: absolute; - height: 36px; - width: 36px; - padding-bottom: 12px; - padding-right: 12px; - border-radius: 3px; - z-index: 1; -} - - -/* Spoiler button */ -.spoiler-link { - border-radius: 2px; - background-color: var(--line-gray-color); - border: 0; - color: var(--content-text); - font-weight: 700; - font-size: 0.7rem; - padding: 0 0.35rem; - text-transform: uppercase; - line-height: 1.25rem; - cursor: pointer; - vertical-align: top; -} - -/* Text */ -.toot-text { - margin-bottom: 0.75rem; - padding-top: 0.1rem; - color: var(--content-text); -} - -.toot-text .ellipsis::after { - content: '...'; -} - -.toot-text .spoiler-link { - display: inline-block; -} - -.toot-text .spoiler-text-hidden { - display: none; -} - -.toot-text.truncate { - display: -webkit-box; - overflow: hidden; - -webkit-line-clamp: var(--text-max-lines); - -webkit-box-orient: vertical; -} - -.toot-text:not(.truncate) .ellipsis::after { - content: "..."; -} - -.toot-text blockquote { - border-left: 4px solid #777696; - margin-left: 0; - padding-left: 8px; -} - -.mt-error { - color: darkred; - background: lightpink; - margin: 5px; - padding: 10px; -} - -.mt-error-icon { - font-size: 2rem; -} - -.mt-error-message { - padding: 1rem 0; -} - -/* Poll */ -.toot-poll { - margin-bottom: 0.25rem; - color: black; -} - -.toot-poll ul { - list-style: none; - padding: 0; - margin: 0; -} - -.toot-poll ul li { - font-size: 0.9rem; - margin-bottom: 0.5rem; -} - -.toot-poll ul li:not(:last-child) { - margin-bottom: 0.25rem; -} - -.toot-poll ul li::before { - content: "◯"; - padding-right: 0.5rem; -} - -/* Medias */ -.toot-media { - overflow: hidden; - margin-bottom: 0.25rem; -} - -.toot-media > .spoiler-link { - position: absolute; - top: 50%; - left: 50%; - z-index: 1; - transform: translate(-50%, -50%); -} - -.toot-media-preview { - position: relative; - margin-top: 0.25rem; - height: auto; - text-align: center; - width: 100%; -} - -.toot-media-spoiler > img { - filter: blur(2rem); -} - -.img-ratio14_7 { - position: relative; - padding-top: 48.95%; - width: 100%; -} - -.img-ratio14_7 > img { - width: 100%; - height: auto; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - text-align: center; -} - -/* Date */ -.toot-date { - margin-top: 0.75rem; - font-size: 0.75rem; - opacity: 0.5; -} - -/* See more btn */ -.mt-seeMore { - margin: 2rem auto; - padding: 0 2rem; - text-align: center; -} - -/* Hidden element */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} - -/* Preview link */ -.toot-preview-link { - min-height: 4rem; - display: flex; - flex-direction: row; - flex-wrap: wrap; - border: 1px solid var(--line-gray-color); - border-radius: 0.5rem; - color: var(--link-color); - font-size: 1rem; - margin: 1rem 0 0.5rem 0; - overflow: hidden; -} - -.toot-preview-image { - width: 100%; - align-self: stretch; -} - -.toot-preview-image img { - display: block; - width: 100%; - height: 100%; - object-fit: cover; -} - -.toot-preview-noImage { - width: 40%; - font-size: 1.5rem; - align-self: center; - text-align: center; -} - -.toot-preview-content { - width: 100%; - display: flex; - align-self: center; - flex-direction: column; - padding: 0.5rem 1rem; - gap: 0.5rem; -} - -.toot-preview-provider, .toot-preview-author { - font-size: smaller; - font-family: sans-serif; - font-weight: normal; - margin: 0.25em 0 0 0; -} - -.toot-preview-title { - font-family: serif; - font-weight: 600; - margin: 0 0 0.25em 0; -} - -/* Footer (See more link) */ -.mt-footer { - margin: 1rem auto 2rem auto; - padding: 0 2rem; - text-align: center; -} \ No newline at end of file diff --git a/js/mastodon-timeline-1.1.0.js b/js/mastodon-timeline-1.1.0.js deleted file mode 100644 index 43cd52f..0000000 --- a/js/mastodon-timeline-1.1.0.js +++ /dev/null @@ -1,271 +0,0 @@ -// Mastodon embed feed timeline -// More info at: -// https://gitlab.com/idotj/mastodon-embed-feed-timeline - -// Timeline settings - -// this event listener should be embedded into the specific webpage as inline JS code to allow -// better customizations per blog - -//document.addEventListener("DOMContentLoaded", () => { -// let mapi = new MastodonApi({ -// container_id: 'mt-timeline', -// container_body_id: 'mt-body', -// instance_uri: 'https://mastodon.green', -// user_id: '109526206518128162', -// profile_name: '@srrpnj', -// toots_limit: 20, -// hide_reblog: true, -// hide_replies: true, -// btn_see_more: 'Read more of our posts on Mastodon' -// }); -//}); - -let MastodonApi = function(params_) { - - // Endpoint access settings - this.INSTANCE_URI = params_.instance_uri; - this.USER_ID = params_.user_id; - this.PROFILE_NAME = params_.profile_name; - this.TOOTS_LIMIT = params_.toots_limit || 20; - this.HIDE_REBLOG = typeof params_.hide_reblog !== 'undefined' ? params_.hide_reblog : false; - this.HIDE_REPLIES = typeof params_.hide_replies !== 'undefined' ? params_.hide_replies : false; - this.BTN_SEE_MORE = params_.btn_see_more || 'See more' - - // Target selectors - this.mtIdContainer = document.getElementById(params_.container_id); - this.mtBodyContainer = document.getElementById(params_.container_body_id); - // Get the toots - this.mtBodyContainer.style.display='none'; - this.getToots(); - this.mtBodyContainer.style.display=''; - // Toot interactions - this.mtIdContainer.addEventListener('click', function(event) { - let urlToot = event.target.closest('.mt-toot').dataset.location; - // Open Toot in new page avoiding any other natural link - if (event.target.localName != 'a' && event.target.localName != 'span' && urlToot) { - window.open(urlToot, '_blank'); - } - }); -} - -// Listing toots function -MastodonApi.prototype.getToots = function() { - let mapi = this; - - // Get request - fetch(this.INSTANCE_URI + '/api/v1/accounts/' + this.USER_ID + '/statuses?limit=' + this.TOOTS_LIMIT, { - method: 'get', - }) - .then(response => response.json()) - .then(jsonData => { - // console.log('jsonData: ', jsonData); - - // Clear the loading message - this.mtBodyContainer.innerHTML = ''; - - // Add toots - for (let i in jsonData) { - // List only public toots - if (jsonData[i].visibility == 'public') { - if (mapi.HIDE_REBLOG && jsonData[i].reblog || mapi.HIDE_REPLIES && jsonData[i].in_reply_to_id) { - // Nothing here (Don't append boosts and/or replies toots) - } else { - appendToot.call(mapi, jsonData[i]); - } - } - } - - // Add target="_blank" to all hashtags - let allHashtags = document.querySelectorAll("#mt-timeline .hashtag"); - for (let j = 0; j < allHashtags.length; j++) { - allHashtags[j].target = "_blank"; - allHashtags[j].rel = "tag noopener noreferrer"; - } - - // Insert button after last toot to visit account page - this.mtBodyContainer.insertAdjacentHTML('beforeend', '
' + mapi.BTN_SEE_MORE + '
'); - // Fix markdown - this.markdown2Html(); - }) - .catch(err => { - this.mtBodyContainer.innerHTML = '
✖️
Request Failed:
' + err + '
'; - }); - - // Inner function to add each toot content in container - let appendToot = function(status_) { - let avatar, user, content, url, date; - - if (status_.reblog) { - // BOOSTED toot - // Toot url - url = status_.reblog.url; - - // Boosted avatar - avatar = - '' + - '
' + - '
' + - '' + - status_.account.username + ' avatar' + - '' + - '
'; - - // User name and url - user = - '
' + - '' + - status_.reblog.account.username + ' post' + - '' + - '
'; - - // Date - date = this.formatDate(status_.reblog.created_at); - } else { - // STANDARD toot - // Toot url - url = status_.url; - - // Avatar - avatar = - '' + - '' + - status_.account.username + ' avatar' + - '' + - ''; - - // User name and url - user = - '
' + - '' + - status_.account.username + ' post' + - '' + - '
'; - - // Date - date = this.formatDate(status_.created_at); - } - - // Main content - if (status_.spoiler_text != '') { - content = - '
' + - status_.spoiler_text + - ' [Show more...]' + - '
'; - } else if (status_.reblog && status_.reblog.content != '') { - content = - '
' + - status_.reblog.content + - '
'; - } else { - content = - '
' + - status_.content + - '
'; - } - - // Media attachments - let media = ''; - if (status_.media_attachments.length > 0) { - for (let picid in status_.media_attachments) { - media = this.replaceMedias(status_.media_attachments[picid], status_.sensitive); - } - } - if (status_.reblog && status_.reblog.media_attachments.length > 0) { - for (let picid in status_.reblog.media_attachments) { - media = this.replaceMedias(status_.reblog.media_attachments[picid], status_.sensitive); - } - } - - // Poll - let poll = ''; - let pollOption = ''; - if (status_.poll) { - for (let i in status_.poll.options) { - pollOption += - '
  • ' + - status_.poll.options[i].title + - '
  • '; - } - poll = - '
    ' + - '' + - '
    '; - } - - // Date - let timestamp = - '
    ' + - '' + - date + - '' + - '
    '; - - // Add all to main toot container - let toot = - '
    ' + - avatar + - user + - content + - media + - poll + - timestamp + - '
    '; - - this.mtBodyContainer.insertAdjacentHTML('beforeend', toot); - }; - -}; - -// Place media -MastodonApi.prototype.replaceMedias = function(media_, spoiler_) { - let spoiler = spoiler_ || false; - let pic = - '
    ' + - '' + - '
    '; - - return pic; -}; - -// Format date -MastodonApi.prototype.formatDate = function(date_) { - const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" - ]; - - let date = new Date(date_); - - let displayDate = monthNames[date.getMonth()] + - " " + date.getDate() + - ", " + date.getFullYear(); - - return displayDate; -}; - -// Remove '>' markup and replace with
    HTML element in post body -MastodonApi.prototype.markdown2Html = function() { - const mtContainer = this.mtBodyContainer; - const paragraphs = mtContainer.getElementsByTagName('p'); - for (let i = 0; i < paragraphs.length; i++) { - var paragraph = paragraphs[i]; - var innerHTML = paragraph.innerHTML; - if (innerHTML.startsWith('>')) { - var htmlString = innerHTML.replace(/^>/gm, '
    ').replace(/\n$/, '
    '); - paragraph.innerHTML = htmlString; - } - } -} - -// Loading spinner -function removeSpinner(element) { - const spinnerCSS = 'loading-spinner'; - // Find closest parent container (1st, 2nd or 3rd level) - let spinnerContainer = element.closest('.' + spinnerCSS); - if (spinnerContainer) { - spinnerContainer.classList.remove(spinnerCSS); - } -} diff --git a/js/mastodon-timeline-3.10.0-3.js b/js/mastodon-timeline-3.10.0-3.js deleted file mode 100644 index 82a5dfb..0000000 --- a/js/mastodon-timeline-3.10.0-3.js +++ /dev/null @@ -1,834 +0,0 @@ -/** - * Mastodon embed feed timeline v3.10.0-3 - * More info at: - * https://gitlab.com/idotj/mastodon-embed-feed-timeline - */ -/** - * This file contains modifications to the above upstream project. - * The file repository for these modifications can be found here: - * https://gitlab.com/clvgt12/mastodon-embed-feed-timeline - * - * Mastodon embed feed timeline - * Copyright (C) 2022 clvgt12 - * Copyright (C) 2021 i.j - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -/** - * Timeline settings - * Adjust these parameters to customize your timeline - */ -/** ------------------------------------------------------ -window.addEventListener("load", () => { - const mastodonTimeline = new MastodonApi({ - // Id of the
    containing the timeline - container_body_id: "mt-body", - - // Class name for the loading spinner (also used in CSS file) - spinner_class: "loading-spinner", - - // Preferred color theme: 'light', 'dark' or 'auto'. Default: auto - default_theme: "auto", - - // Your Mastodon instance - instance_url: "https://mastodon.online", - - // Choose type of toots to show in the timeline: 'local', 'profile', 'hashtag'. Default: local - timeline_type: "local", - - // Your user ID on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - user_id: "", - - // Your user name on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - profile_name: "", - - // The name of the hashtag. Leave empty if you didn't choose 'hashtag' as type of timeline - hashtag_name: "", - - // Maximum amount of toots to get. Default: 20 - toots_limit: "20", - - // Hide unlisted toots. Default: don't hide - hide_unlisted: false, - - // Hide boosted toots. Default: don't hide - hide_reblog: false, - - // Hide replies toots. Default: don't hide - hide_replies: false, - - // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide - hide_preview_link: false, - - // Hide custom emojis available on the server. Default: don't hide - hide_emojos: false, - - // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag. Ddefault: don't apply - markdown_blockquote: false, - - // Hide replies, boosts and favourites toots counter. Default: don't hide - hide_counter_bar: false, - - // Limit the text content to a maximum number of lines. Default: 0 (unlimited) - text_max_lines: "0", - - // Customize the text of the link pointing to the Mastodon page (appears after the last toot) - link_see_more: "See more posts at Mastodon", - }); -}); ------------------------------ */ -/** - * Set all variables with customized values or use default ones - * @param {object} params_ User customized values - * Trigger main function to build the timeline - */ -const MastodonApi = function (params_) { - this.CONTAINER_BODY_ID = params_.container_body_id || "mt-body"; - this.SPINNER_CLASS = params_.spinner_class || "loading-spinner"; - this.DEFAULT_THEME = params_.default_theme || "auto"; - this.INSTANCE_URL = params_.instance_url; - this.USER_ID = params_.user_id || ""; - this.PROFILE_NAME = this.USER_ID ? params_.profile_name : ""; - this.TIMELINE_TYPE = params_.timeline_type || "local"; - this.HASHTAG_NAME = params_.hashtag_name || ""; - this.TOOTS_LIMIT = params_.toots_limit || "20"; - this.HIDE_UNLISTED = - typeof params_.hide_unlisted !== "undefined" - ? params_.hide_unlisted - : false; - this.HIDE_REBLOG = - typeof params_.hide_reblog !== "undefined" ? params_.hide_reblog : false; - this.HIDE_REPLIES = - typeof params_.hide_replies !== "undefined" ? params_.hide_replies : false; - this.HIDE_PREVIEW_LINK = - typeof params_.hide_preview_link !== "undefined" - ? params_.hide_preview_link - : false; - this.HIDE_EMOJOS = - typeof params_.hide_emojos !== "undefined" ? params_.hide_emojos : false; - this.MARKDOWN_BLOCKQUOTE = - typeof params_.markdown_blockquote !== "undefined" - ? params_.markdown_blockquote - : false; - this.HIDE_COUNTER_BAR = - params_.hide_counter_bar !== "undefined" ? params_.hide_counter_bar : false; - this.TEXT_MAX_LINES = params_.text_max_lines || "0"; - this.LINK_SEE_MORE = params_.link_see_more; - this.FETCHED_DATA = {}; - - this.mtBodyContainer = document.getElementById(this.CONTAINER_BODY_ID); - - this.buildTimeline(); -}; - -/** - * Trigger functions and construct timeline - */ -MastodonApi.prototype.buildTimeline = async function () { - // Apply color theme - this.setTheme(); - - // Get server data - await this.getTimelineData(); - - // Empty the
    container - this.mtBodyContainer.innerHTML = ""; - - for (let i in this.FETCHED_DATA.timeline) { - // First filter (Public / Unlisted) - if ( - this.FETCHED_DATA.timeline[i].visibility == "public" || - (!this.HIDE_UNLISTED && - this.FETCHED_DATA.timeline[i].visibility == "unlisted") - ) { - // Second filter (Reblog / Replies) - if ( - (this.HIDE_REBLOG && this.FETCHED_DATA.timeline[i].reblog) || - (this.HIDE_REPLIES && this.FETCHED_DATA.timeline[i].in_reply_to_id) - ) { - // Nothing here (Don't append toots) - } else { - // Append toots - this.appendToot(this.FETCHED_DATA.timeline[i], Number(i)); - } - } - } - - // Check if there are toots in the container (due to filters applied) - if (this.mtBodyContainer.innerHTML === "") { - this.mtBodyContainer.setAttribute("role", "none"); - this.mtBodyContainer.innerHTML = - '
    📭
    Sorry, no toots to show
    Got ' + - this.FETCHED_DATA.timeline.length + - ' toots from the server but due to the "hide filters" applied, no toot is shown
    '; - } else { - // Insert link after last toot to visit Mastodon page - if (this.LINK_SEE_MORE) { - let linkSeeMorePath = ""; - if (this.TIMELINE_TYPE === "profile") { - linkSeeMorePath = this.PROFILE_NAME; - } else if (this.TIMELINE_TYPE === "hashtag") { - linkSeeMorePath = "tags/" + this.HASHTAG_NAME; - } else if (this.TIMELINE_TYPE === "local") { - linkSeeMorePath = "public/local"; - } - let linkSeeMore = - '"; - this.mtBodyContainer.parentNode.insertAdjacentHTML( - "beforeend", - linkSeeMore - ); - } - - // Control loading spinners - this.manageSpinner(); - } - - // Toot interactions - this.mtBodyContainer.addEventListener("click", function (e) { - // Check if toot cointainer was clicked - if ( - e.target.localName == "article" || - e.target.offsetParent?.localName == "article" || - e.target.localName == "img" - ) { - openTootURL(e); - } - // Check if Show More/Less button was clicked - if (e.target.localName == "button" && e.target.className == "spoiler-btn") { - toogleSpoiler(e); - } - }); - this.mtBodyContainer.addEventListener("keydown", function (e) { - // Check if Enter key was pressed with focus in an article - if (e.key === "Enter" && e.target.localName == "article") { - openTootURL(e); - } - }); - - /** - * Open toot in a new page avoiding any other natural link - * @param {event} e User interaction trigger - */ - const openTootURL = function (e) { - let urlToot = e.target.closest(".mt-toot").dataset.location; - if ( - e.target.localName !== "a" && - e.target.localName !== "span" && - e.target.localName !== "button" && - e.target.localName !== "time" && - e.target.className !== "mt-toot-preview-noImage" && - e.target.parentNode.className !== "mt-toot-avatar-image-big" && - e.target.parentNode.className !== "mt-toot-avatar-image-small" && - e.target.parentNode.className !== "mt-toot-preview-image" && - urlToot - ) { - window.open(urlToot, "_blank"); - } - }; - - /** - * Spoiler button - * @param {event} e User interaction trigger - */ - const toogleSpoiler = function (e) { - const nextSibling = e.target.nextSibling; - if (nextSibling.localName === "img") { - e.target.parentNode.classList.remove("mt-toot-media-spoiler"); - e.target.style.display = "none"; - } else if ( - nextSibling.classList.contains("spoiler-text-hidden") || - nextSibling.classList.contains("spoiler-text-visible") - ) { - if (e.target.textContent == "Show more") { - nextSibling.classList.remove("spoiler-text-hidden"); - nextSibling.classList.add("spoiler-text-visible"); - e.target.setAttribute("aria-expanded", "true"); - e.target.textContent = "Show less"; - } else { - nextSibling.classList.remove("spoiler-text-visible"); - nextSibling.classList.add("spoiler-text-hidden"); - e.target.setAttribute("aria-expanded", "false"); - e.target.textContent = "Show more"; - } - } - }; -}; - -/** - * Set the theme style chosen by the user or by the browser/OS - */ -MastodonApi.prototype.setTheme = function () { - /** - * Set the theme value in the tag using the attribute "data-theme" - * @param {string} theme Type of theme to apply: dark or light - */ - const setTheme = function (theme) { - document.documentElement.setAttribute("data-theme", theme); - }; - - if (this.DEFAULT_THEME === "auto") { - let systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); - systemTheme.matches ? setTheme("dark") : setTheme("light"); - // Update the theme if user change browser/OS preference - systemTheme.addEventListener("change", (e) => { - e.matches ? setTheme("dark") : setTheme("light"); - }); - } else { - setTheme(this.DEFAULT_THEME); - } -}; - -/** - * Requests to the server to get all the data - */ -MastodonApi.prototype.getTimelineData = async function () { - return new Promise((resolve, reject) => { - /** - * Fetch data from server - * @param {string} url address to fetch - * @returns {object} List of objects - */ - async function fetchData(url) { - const response = await fetch(url); - - if (!response.ok) { - throw new Error( - "Failed to fetch the following URL: " + - url + - "
    " + - "Error status: " + - response.status + - "
    " + - "Error message: " + - response.statusText - ); - } - - const data = await response.json(); - return data; - } - - // URLs to fetch - let urls = {}; - if (this.TIMELINE_TYPE === "profile") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/accounts/${this.USER_ID}/statuses?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "hashtag") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/tag/${this.HASHTAG_NAME}?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "local") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/public?local=true&limit=${this.TOOTS_LIMIT}`; - } - if (!this.HIDE_EMOJOS) { - urls.emojos = this.INSTANCE_URL + "/api/v1/custom_emojis"; - } - - const urlsPromises = Object.entries(urls).map(([key, url]) => { - return fetchData(url) - .then((data) => ({ [key]: data })) - .catch((error) => { - reject(new Error("Something went wrong fetching data")); - this.mtBodyContainer.innerHTML = - '

    Sorry, request failed:
    ' + - error.message + - "
    "; - this.mtBodyContainer.setAttribute("role", "none"); - return { [key]: [] }; - }); - }); - - // Fetch all urls simultaneously - Promise.all(urlsPromises).then((dataObjects) => { - this.FETCHED_DATA = dataObjects.reduce((result, dataItem) => { - return { ...result, ...dataItem }; - }, {}); - - // console.log("Timeline data fetched: ", this.FETCHED_DATA); - resolve(); - }); - }); -}; - -/** - * Inner function to add each toot in timeline container - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.appendToot = function (c, i) { - this.mtBodyContainer.insertAdjacentHTML("beforeend", this.assambleToot(c, i)); -}; - -/** - * Build toot structure - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.assambleToot = function (c, i) { - let avatar, user, userName, url, date, formattedDate; - - if (c.reblog) { - // BOOSTED toot - // Toot url - url = c.reblog.url; - - // Boosted avatar - avatar = - '' + - '
    ' + - '
    ' + - '' +
-      c.reblog.account.username +
-      ' avatar' + - "
    " + - '
    ' + - '' +
-      c.account.username +
-      ' avatar' + - "
    " + - "
    " + - "
    "; - - // User name and url - userName = this.showEmojos( - c.reblog.account.display_name - ? c.reblog.account.display_name - : c.reblog.account.username, - this.FETCHED_DATA.emojos - ); - user = - '"; - - // Date - date = c.reblog.created_at; - } else { - // STANDARD toot - // Toot url - url = c.url; - - // Avatar - avatar = - '' + - '
    ' + - '
    ' + - '' +
-      c.account.username +
-      ' avatar' + - "
    " + - "
    " + - "
    "; - - // User name and url - userName = this.showEmojos( - c.account.display_name ? c.account.display_name : c.account.username, - this.FETCHED_DATA.emojos - ); - user = - '"; - - // Date - date = c.created_at; - } - - // Date - formattedDate = this.formatDate(date); - let timestamp = - '"; - - // Main text - let text_css = ""; - if (this.TEXT_MAX_LINES !== "0") { - text_css = "truncate"; - document.documentElement.style.setProperty( - "--text-max-lines", - this.TEXT_MAX_LINES - ); - } - - let content = ""; - if (c.spoiler_text !== "") { - content = - '
    ' + - c.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text !== "" - ) { - content = - '
    ' + - c.reblog.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text === "" - ) { - content = - '
    ' + - '
    ' + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else { - content = - '
    ' + - '
    ' + - this.formatTootText(c.content) + - "
    " + - "
    "; - } - - // Media attachments - let media = ""; - if (c.media_attachments.length > 0) { - for (let picid in c.media_attachments) { - media = this.placeMedias(c.media_attachments[picid], c.sensitive); - } - } - if (c.reblog && c.reblog.media_attachments.length > 0) { - for (let picid in c.reblog.media_attachments) { - media = this.placeMedias( - c.reblog.media_attachments[picid], - c.reblog.sensitive - ); - } - } - - // Preview link - let previewLink = ""; - if (!this.HIDE_PREVIEW_LINK && c.card) { - if (media === "") { - previewLink = this.placePreviewLink(c.card); - } - } - - // Poll - let poll = ""; - let pollOption = ""; - if (c.poll) { - for (let i in c.poll.options) { - pollOption += "
  • " + c.poll.options[i].title + "
  • "; - } - poll = - '
    ' + "
      " + pollOption + "
    " + "
    "; - } - - // Counter bar - let counterBar = ""; - if (!this.HIDE_COUNTER_BAR) { - let repliesCount = - '
    ' + - '' + - c.replies_count + - "
    "; - - let reblogCount = - '
    ' + - '' + - c.reblogs_count + - "
    "; - - let favoritesCount = - '
    ' + - '' + - c.favourites_count + - "
    "; - - counterBar = - '
    ' + - repliesCount + - reblogCount + - favoritesCount + - "
    "; - } - - // Add all to main toot container - let toot = - '
    ' + - '
    ' + - avatar + - user + - timestamp + - "
    " + - content + - media + - previewLink + - poll + - counterBar + - "
    "; - - return toot; -}; - -/** - * Handle text changes made to toots - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.formatTootText = function (c) { - let content = c; - - // Format hashtags and mentions - content = this.addTarget2hashtagMention(content); - - // Convert emojos shortcode into images - if (!this.HIDE_EMOJOS) { - content = this.showEmojos(content, this.FETCHED_DATA.emojos); - } - - // Convert markdown styles into HTML - if (this.MARKDOWN_BLOCKQUOTE) { - content = this.replaceHTMLtag( - content, - "

    >", - "

    ", - "

    ", - "

    " - ); - } - - return content; -}; - -/** - * Add target="_blank" to all #hashtags and @mentions in the toot - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.addTarget2hashtagMention = function (c) { - let content = c.replaceAll('rel="tag"', 'rel="tag" target="_blank"'); - content = content.replaceAll( - 'class="u-url mention"', - 'class="u-url mention" target="_blank"' - ); - - return content; -}; - -/** - * Find all custom emojis shortcode and replace by image - * @param {string} c Text content - * @param {array} e List with all custom emojis - * @returns {string} Text content modified - */ -MastodonApi.prototype.showEmojos = function (c, e) { - if (c.includes(":")) { - for (const emojo of e) { - const regex = new RegExp(`\\:${emojo.shortcode}\\:`, "g"); - c = c.replace( - regex, - `Emoji ${emojo.shortcode}` - ); - } - - return c; - } else { - return c; - } -}; - -/** - * Find all start/end and replace them by another start/end - * @param {string} c Text content - * @param {string} initialTagOpen Start HTML tag to replace - * @param {string} initialTagClose End HTML tag to replace - * @param {string} replacedTagOpen New start HTML tag - * @param {string} replacedTagClose New end HTML tag - * @returns {string} Text in HTML format - */ -MastodonApi.prototype.replaceHTMLtag = function ( - c, - initialTagOpen, - initialTagClose, - replacedTagOpen, - replacedTagClose -) { - if (c.includes(initialTagOpen)) { - const regex = new RegExp(initialTagOpen + "(.*?)" + initialTagClose, "gi"); - - return c.replace(regex, replacedTagOpen + "$1" + replacedTagClose); - } else { - return c; - } -}; - -/** - * Place media - * @param {object} m Media content - * @param {boolean} s Spoiler/Sensitive status - * @returns {string} Media in HTML format - */ -MastodonApi.prototype.placeMedias = function (m, s) { - let spoiler = s || false; - const pic = - '
    ' + - (spoiler ? '' : "") + - '' +
-    (m.description ? m.description : ' + - "
    "; - - return pic; -}; - -/** - * Place preview link - * @param {object} c Preview link content - * @returns {string} Preview link in HTML format - */ -MastodonApi.prototype.placePreviewLink = function (c) { - let card = - '' + - (c.image - ? '
    ' - : '
    ') + - "
    " + - '
    ' + - (c.provider_name - ? '' + c.provider_name + "" - : "") + - '' + - c.title + - "" + - (c.author_name - ? 'By ' + c.author_name + "" - : "") + - "
    " + - "
    "; - - return card; -}; - -/** - * Format date - * @param {string} d Date in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ) - * @returns {string} Date formated (MM DD, YYYY) - */ -MastodonApi.prototype.formatDate = function (d) { - const monthNames = [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ]; - - let date = new Date(d); - - const displayDate = - monthNames[date.getMonth()] + - " " + - date.getDate() + - ", " + - date.getFullYear(); - - return displayDate; -}; - -/** - * Add/Remove event listener for loading spinner - */ -MastodonApi.prototype.manageSpinner = function () { - // Remove CSS class to container and listener to images - const spinnerCSS = this.SPINNER_CLASS; - const removeSpinner = function () { - this.parentNode.classList.remove(spinnerCSS); - this.removeEventListener("load", removeSpinner); - this.removeEventListener("error", removeSpinner); - }; - - // Add listener to images - this.mtBodyContainer - .querySelectorAll(`.${this.SPINNER_CLASS} > img`) - .forEach((e) => { - e.addEventListener("load", removeSpinner); - e.addEventListener("error", removeSpinner); - }); -}; \ No newline at end of file diff --git a/js/mastodon-timeline-3.10.1-1.js b/js/mastodon-timeline-3.10.1-1.js deleted file mode 100644 index e15dafc..0000000 --- a/js/mastodon-timeline-3.10.1-1.js +++ /dev/null @@ -1,866 +0,0 @@ -/** - * Mastodon embed feed timeline v3.10.1-1 - * More info at: - * https://gitlab.com/idotj/mastodon-embed-feed-timeline - */ -/** - * This file contains modifications to the above upstream project. - * The file repository for these modifications can be found here: - * https://gitlab.com/clvgt12/mastodon-embed-feed-timeline - * - * Mastodon embed feed timeline - * Copyright (C) 2022 clvgt12 - * Copyright (C) 2021 i.j - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -/** - * Timeline settings - * Adjust these parameters to customize your timeline - */ -/** ------------------------------------------------------ -window.addEventListener("load", () => { - const mastodonTimeline = new MastodonApi({ - // Id of the
    containing the timeline - container_body_id: "mt-body", - - // Class name for the loading spinner (also used in CSS file) - spinner_class: "loading-spinner", - - // Preferred color theme: 'light', 'dark' or 'auto'. Default: auto - default_theme: "auto", - - // Your Mastodon instance - instance_url: "https://mastodon.online", - - // Choose type of toots to show in the timeline: 'local', 'profile', 'hashtag'. Default: local - timeline_type: "local", - - // Your user ID on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - user_id: "", - - // Your user name on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - profile_name: "", - - // The name of the hashtag. Leave empty if you didn't choose 'hashtag' as type of timeline - hashtag_name: "", - - // Maximum amount of toots to get. Default: 20 - toots_limit: "20", - - // Hide unlisted toots. Default: don't hide - hide_unlisted: false, - - // Hide boosted toots. Default: don't hide - hide_reblog: false, - - // Hide replies toots. Default: don't hide - hide_replies: false, - - // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide - hide_preview_link: false, - - // Hide custom emojis available on the server. Default: don't hide - hide_emojos: false, - - // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag. Ddefault: don't apply - markdown_blockquote: false, - - // Hide replies, boosts and favourites toots counter. Default: don't hide - hide_counter_bar: false, - - // Limit the text content to a maximum number of lines. Default: 0 (unlimited) - text_max_lines: "0", - - // Customize the text of the link pointing to the Mastodon page (appears after the last toot) - link_see_more: "See more posts at Mastodon", - }); -}); ------------------------------ */ -/** - * Set all variables with customized values or use default ones - * @param {object} params_ User customized values - * Trigger main function to build the timeline - */ -const MastodonApi = function (params_) { - this.CONTAINER_BODY_ID = params_.container_body_id || "mt-body"; - this.SPINNER_CLASS = params_.spinner_class || "loading-spinner"; - this.DEFAULT_THEME = params_.default_theme || "auto"; - this.INSTANCE_URL = params_.instance_url; - this.USER_ID = params_.user_id || ""; - this.PROFILE_NAME = this.USER_ID ? params_.profile_name : ""; - this.TIMELINE_TYPE = params_.timeline_type || "local"; - this.HASHTAG_NAME = params_.hashtag_name || ""; - this.TOOTS_LIMIT = params_.toots_limit || "20"; - this.HIDE_UNLISTED = - typeof params_.hide_unlisted !== "undefined" - ? params_.hide_unlisted - : false; - this.HIDE_REBLOG = - typeof params_.hide_reblog !== "undefined" ? params_.hide_reblog : false; - this.HIDE_REPLIES = - typeof params_.hide_replies !== "undefined" ? params_.hide_replies : false; - this.HIDE_PREVIEW_LINK = - typeof params_.hide_preview_link !== "undefined" - ? params_.hide_preview_link - : false; - this.HIDE_EMOJOS = - typeof params_.hide_emojos !== "undefined" ? params_.hide_emojos : false; - this.MARKDOWN_BLOCKQUOTE = - typeof params_.markdown_blockquote !== "undefined" - ? params_.markdown_blockquote - : false; - this.HIDE_COUNTER_BAR = - params_.hide_counter_bar !== "undefined" ? params_.hide_counter_bar : false; - this.TEXT_MAX_LINES = params_.text_max_lines || "0"; - this.LINK_SEE_MORE = params_.link_see_more; - this.FETCHED_DATA = {}; - - this.mtBodyContainer = document.getElementById(this.CONTAINER_BODY_ID); - - this.buildTimeline(); -}; - -/** - * Trigger functions and construct timeline - */ -MastodonApi.prototype.buildTimeline = async function () { - // Apply color theme - this.setTheme(); - - // Get server data - await this.getTimelineData(); - - // Empty the
    container - this.mtBodyContainer.innerHTML = ""; - - for (let i in this.FETCHED_DATA.timeline) { - // First filter (Public / Unlisted) - if ( - this.FETCHED_DATA.timeline[i].visibility == "public" || - (!this.HIDE_UNLISTED && - this.FETCHED_DATA.timeline[i].visibility == "unlisted") - ) { - // Second filter (Reblog / Replies) - if ( - (this.HIDE_REBLOG && this.FETCHED_DATA.timeline[i].reblog) || - (this.HIDE_REPLIES && this.FETCHED_DATA.timeline[i].in_reply_to_id) - ) { - // Nothing here (Don't append toots) - } else { - // Append toots - this.appendToot(this.FETCHED_DATA.timeline[i], Number(i)); - } - } - } - - // Check if there are toots in the container (due to filters applied) - if (this.mtBodyContainer.innerHTML === "") { - this.mtBodyContainer.setAttribute("role", "none"); - this.mtBodyContainer.innerHTML = - '
    📭
    Sorry, no toots to show
    Got ' + - this.FETCHED_DATA.timeline.length + - ' toots from the server but due to the "hide filters" applied, no toot is shown
    '; - } else { - // Insert link after last toot to visit Mastodon page - if (this.LINK_SEE_MORE) { - let linkSeeMorePath = ""; - if (this.TIMELINE_TYPE === "profile") { - linkSeeMorePath = this.PROFILE_NAME; - } else if (this.TIMELINE_TYPE === "hashtag") { - linkSeeMorePath = "tags/" + this.HASHTAG_NAME; - } else if (this.TIMELINE_TYPE === "local") { - linkSeeMorePath = "public/local"; - } - const linkSeeMore = - '"; - this.mtBodyContainer.parentNode.insertAdjacentHTML( - "beforeend", - linkSeeMore - ); - } - - // Control loading spinners - this.manageSpinner(); - } - - // Toot interactions - this.mtBodyContainer.addEventListener("click", function (e) { - // Check if toot cointainer was clicked - if ( - e.target.localName == "article" || - e.target.offsetParent?.localName == "article" || - e.target.localName == "img" - ) { - openTootURL(e); - } - // Check if Show More/Less button was clicked - if (e.target.localName == "button" && e.target.className == "spoiler-btn") { - toogleSpoiler(e); - } - }); - this.mtBodyContainer.addEventListener("keydown", function (e) { - // Check if Enter key was pressed with focus in an article - if (e.key === "Enter" && e.target.localName == "article") { - openTootURL(e); - } - }); - - /** - * Open toot in a new page avoiding any other natural link - * @param {event} e User interaction trigger - */ - const openTootURL = function (e) { - const urlToot = e.target.closest(".mt-toot").dataset.location; - if ( - e.target.localName !== "a" && - e.target.localName !== "span" && - e.target.localName !== "button" && - e.target.localName !== "time" && - e.target.className !== "mt-toot-preview-noImage" && - e.target.parentNode.className !== "mt-toot-avatar-image-big" && - e.target.parentNode.className !== "mt-toot-avatar-image-small" && - e.target.parentNode.className !== "mt-toot-preview-image" && - urlToot - ) { - window.open(urlToot, "_blank"); - } - }; - - /** - * Spoiler button - * @param {event} e User interaction trigger - */ - const toogleSpoiler = function (e) { - const nextSibling = e.target.nextSibling; - if (nextSibling.localName === "img") { - e.target.parentNode.classList.remove("mt-toot-media-spoiler"); - e.target.style.display = "none"; - } else if ( - nextSibling.classList.contains("spoiler-text-hidden") || - nextSibling.classList.contains("spoiler-text-visible") - ) { - if (e.target.textContent == "Show more") { - nextSibling.classList.remove("spoiler-text-hidden"); - nextSibling.classList.add("spoiler-text-visible"); - e.target.setAttribute("aria-expanded", "true"); - e.target.textContent = "Show less"; - } else { - nextSibling.classList.remove("spoiler-text-visible"); - nextSibling.classList.add("spoiler-text-hidden"); - e.target.setAttribute("aria-expanded", "false"); - e.target.textContent = "Show more"; - } - } - }; -}; - -/** - * Set the theme style chosen by the user or by the browser/OS - */ -MastodonApi.prototype.setTheme = function () { - /** - * Set the theme value in the tag using the attribute "data-theme" - * @param {string} theme Type of theme to apply: dark or light - */ - const setTheme = function (theme) { - document.documentElement.setAttribute("data-theme", theme); - }; - - if (this.DEFAULT_THEME === "auto") { - let systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); - systemTheme.matches ? setTheme("dark") : setTheme("light"); - // Update the theme if user change browser/OS preference - systemTheme.addEventListener("change", (e) => { - e.matches ? setTheme("dark") : setTheme("light"); - }); - } else { - setTheme(this.DEFAULT_THEME); - } -}; - -/** - * Requests to the server to get all the data - */ -MastodonApi.prototype.getTimelineData = async function () { - return new Promise((resolve, reject) => { - /** - * Fetch data from server - * @param {string} url address to fetch - * @returns {object} List of objects - */ - async function fetchData(url) { - const response = await fetch(url); - - if (!response.ok) { - throw new Error( - "Failed to fetch the following URL: " + - url + - "
    " + - "Error status: " + - response.status + - "
    " + - "Error message: " + - response.statusText - ); - } - - const data = await response.json(); - return data; - } - - // URLs to fetch - let urls = {}; - if (this.TIMELINE_TYPE === "profile") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/accounts/${this.USER_ID}/statuses?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "hashtag") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/tag/${this.HASHTAG_NAME}?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "local") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/public?local=true&limit=${this.TOOTS_LIMIT}`; - } - if (!this.HIDE_EMOJOS) { - urls.emojos = this.INSTANCE_URL + "/api/v1/custom_emojis"; - } - - const urlsPromises = Object.entries(urls).map(([key, url]) => { - return fetchData(url) - .then((data) => ({ [key]: data })) - .catch((error) => { - reject(new Error("Something went wrong fetching data")); - this.mtBodyContainer.innerHTML = - '

    Sorry, request failed:
    ' + - error.message + - "
    "; - this.mtBodyContainer.setAttribute("role", "none"); - return { [key]: [] }; - }); - }); - - // Fetch all urls simultaneously - Promise.all(urlsPromises).then((dataObjects) => { - this.FETCHED_DATA = dataObjects.reduce((result, dataItem) => { - return { ...result, ...dataItem }; - }, {}); - - console.log("Timeline data fetched: ", this.FETCHED_DATA); - resolve(); - }); - }); -}; - -/** - * Inner function to add each toot in timeline container - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.appendToot = function (c, i) { - this.mtBodyContainer.insertAdjacentHTML("beforeend", this.assambleToot(c, i)); -}; - -/** - * Build toot structure - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.assambleToot = function (c, i) { - let avatar, user, userName, url, date, formattedDate; - - if (c.reblog) { - // BOOSTED toot - // Toot url - url = c.reblog.url; - - // Boosted avatar - avatar = - '' + - '
    ' + - '
    ' + - '' +
-      this.replaceQuotes(c.reblog.account.username) +
-      ' avatar' + - "
    " + - '
    ' + - '' +
-      this.replaceQuotes(c.account.username) +
-      ' avatar' + - "
    " + - "
    " + - "
    "; - - // User name and url - userName = this.showEmojos( - c.reblog.account.display_name - ? c.reblog.account.display_name - : c.reblog.account.username, - this.FETCHED_DATA.emojos - ); - user = - '"; - - // Date - date = c.reblog.created_at; - } else { - // STANDARD toot - // Toot url - url = c.url; - - // Avatar - avatar = - '' + - '
    ' + - '
    ' + - '' +
-      c.account.username +
-      ' avatar' + - "
    " + - "
    " + - "
    "; - - // User name and url - userName = this.showEmojos( - c.account.display_name ? c.account.display_name : c.account.username, - this.FETCHED_DATA.emojos - ); - user = - '"; - - // Date - date = c.created_at; - } - - // Date - formattedDate = this.formatDate(date); - const timestamp = - '"; - - // Main text - let text_css = ""; - if (this.TEXT_MAX_LINES !== "0") { - text_css = "truncate"; - document.documentElement.style.setProperty( - "--text-max-lines", - this.TEXT_MAX_LINES - ); - } - - let content = ""; - if (c.spoiler_text !== "") { - content = - '
    ' + - c.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text !== "" - ) { - content = - '
    ' + - c.reblog.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text === "" - ) { - content = - '
    ' + - '
    ' + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else { - content = - '
    ' + - '
    ' + - this.formatTootText(c.content) + - "
    " + - "
    "; - } - - // Media attachments - let media = ""; - if (c.media_attachments.length > 0) { - for (let picid in c.media_attachments) { - media = this.placeMedias(c.media_attachments[picid], c.sensitive); - } - } - if (c.reblog && c.reblog.media_attachments.length > 0) { - for (let picid in c.reblog.media_attachments) { - media = this.placeMedias( - c.reblog.media_attachments[picid], - c.reblog.sensitive - ); - } - } - - // Preview link - let previewLink = ""; - if (!this.HIDE_PREVIEW_LINK && c.card) { - if (media === "") { - previewLink = this.placePreviewLink(c.card); - } - } - - // Poll - let poll = ""; - if (c.poll) { - let pollOption = ""; - for (let i in c.poll.options) { - pollOption += "
  • " + c.poll.options[i].title + "
  • "; - } - poll = - '
    ' + - "
      " + - pollOption + - "
    " + - "
    "; - } - - // Counter bar - let counterBar = ""; - if (!this.HIDE_COUNTER_BAR) { - const repliesCount = - '
    ' + - '' + - c.replies_count + - "
    "; - - const reblogCount = - '
    ' + - '' + - c.reblogs_count + - "
    "; - - const favoritesCount = - '
    ' + - '' + - c.favourites_count + - "
    "; - - counterBar = - '
    ' + - repliesCount + - reblogCount + - favoritesCount + - "
    "; - } - - // Add all to main toot container - const toot = - '
    ' + - '
    ' + - avatar + - user + - timestamp + - "
    " + - content + - media + - previewLink + - poll + - counterBar + - "
    "; - - return toot; -}; - -/** - * Handle text changes made to toots - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.formatTootText = function (c) { - let content = c; - - // Format hashtags and mentions - content = this.addTarget2hashtagMention(content); - - // Convert emojos shortcode into images - if (!this.HIDE_EMOJOS) { - content = this.showEmojos(content, this.FETCHED_DATA.emojos); - } - - // Convert markdown styles into HTML - if (this.MARKDOWN_BLOCKQUOTE) { - content = this.replaceHTMLtag( - content, - "

    >", - "

    ", - "

    ", - "

    " - ); - } - - return content; -}; - -/** - * Add target="_blank" to all #hashtags and @mentions in the toot - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.addTarget2hashtagMention = function (c) { - let content = c.replaceAll('rel="tag"', 'rel="tag" target="_blank"'); - content = content.replaceAll( - 'class="u-url mention"', - 'class="u-url mention" target="_blank"' - ); - - return content; -}; - -/** - * Find all custom emojis shortcode and replace by image - * @param {string} c Text content - * @param {array} e List with all custom emojis - * @returns {string} Text content modified - */ -MastodonApi.prototype.showEmojos = function (c, e) { - if (c.includes(":")) { - for (const emojo of e) { - const regex = new RegExp(`\\:${emojo.shortcode}\\:`, "g"); - c = c.replace( - regex, - `Emoji ${emojo.shortcode}` - ); - } - - return c; - } else { - return c; - } -}; - -/** - * Find all start/end and replace them by another start/end - * @param {string} c Text content - * @param {string} initialTagOpen Start HTML tag to replace - * @param {string} initialTagClose End HTML tag to replace - * @param {string} replacedTagOpen New start HTML tag - * @param {string} replacedTagClose New end HTML tag - * @returns {string} Text in HTML format - */ -MastodonApi.prototype.replaceHTMLtag = function ( - c, - initialTagOpen, - initialTagClose, - replacedTagOpen, - replacedTagClose -) { - if (c.includes(initialTagOpen)) { - const regex = new RegExp(initialTagOpen + "(.*?)" + initialTagClose, "gi"); - - return c.replace(regex, replacedTagOpen + "$1" + replacedTagClose); - } else { - return c; - } -}; - -/** - * Place media - * @param {object} m Media content - * @param {boolean} s Spoiler/Sensitive status - * @returns {string} Media in HTML format - */ -MastodonApi.prototype.placeMedias = function (m, s) { - const spoiler = s || false; - const pic = - '
    ' + - (spoiler ? '' : "") + - '' +
-    (m.description ? this.replaceQuotes(m.description) : ' + - "
    "; - - return pic; -}; - -/** - * Place preview link - * @param {object} c Preview link content - * @returns {string} Preview link in HTML format - */ -MastodonApi.prototype.placePreviewLink = function (c) { - const card = - '' + - (c.image - ? '
    ' +
-        this.replaceQuotes(c.image_description) +
-        '
    ' - : '
    ') + - "
    " + - '
    ' + - (c.provider_name - ? '' + - this.parseHTMLstring(c.provider_name) + - "" - : "") + - '' + - c.title + - "" + - (c.author_name - ? '' + - this.parseHTMLstring(c.author_name) + - "" - : "") + - "
    " + - "
    "; - - return card; -}; - -/** - * Format date - * @param {string} d Date in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ) - * @returns {string} Date formated (MM DD, YYYY) - */ -MastodonApi.prototype.formatDate = function (d) { - const monthNames = [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ]; - - const date = new Date(d); - - const displayDate = - monthNames[date.getMonth()] + - " " + - date.getDate() + - ", " + - date.getFullYear(); - - return displayDate; -}; - -/** - * Parse HTML string - * @param {string} s HTML string - * @returns {string} Plain text - */ -MastodonApi.prototype.parseHTMLstring = function (s) { - const parser = new DOMParser(); - const txt = parser.parseFromString(s, "text/html"); - return txt.body.textContent; -}; - -/** - * Replace quotes - * @param {string} s String - * @returns {string} String - */ -MastodonApi.prototype.replaceQuotes = function (s) { - return s.replace('"', "'"); -}; - -/** - * Add/Remove event listener for loading spinner - */ -MastodonApi.prototype.manageSpinner = function () { - // Remove CSS class to container and listener to images - const spinnerCSS = this.SPINNER_CLASS; - const removeSpinner = function () { - this.parentNode.classList.remove(spinnerCSS); - this.removeEventListener("load", removeSpinner); - this.removeEventListener("error", removeSpinner); - }; - - // Add listener to images - this.mtBodyContainer - .querySelectorAll(`.${this.SPINNER_CLASS} > img`) - .forEach((e) => { - e.addEventListener("load", removeSpinner); - e.addEventListener("error", removeSpinner); - }); -}; \ No newline at end of file diff --git a/js/mastodon-timeline-3.10.2-1.js b/js/mastodon-timeline-3.10.2-1.js deleted file mode 100644 index a7c9e89..0000000 --- a/js/mastodon-timeline-3.10.2-1.js +++ /dev/null @@ -1,890 +0,0 @@ -/** - * Mastodon embed feed timeline v3.10.2-1 - * More info at: - * https://gitlab.com/idotj/mastodon-embed-feed-timeline - */ -/** - * This file contains modifications to the above upstream project. - * The file repository for these modifications can be found here: - * https://gitlab.com/clvgt12/mastodon-embed-feed-timeline - * - * Mastodon embed feed timeline - * Copyright (C) 2022 clvgt12 - * Copyright (C) 2021 i.j - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -/** - * Timeline settings - * Adjust these parameters to customize your timeline - */ -/** ------------------------------------------------------ -window.addEventListener("load", () => { - const mastodonTimeline = new MastodonApi({ - // Id of the
    containing the timeline - container_body_id: "mt-body", - - // Class name for the loading spinner (also used in CSS file) - spinner_class: "loading-spinner", - - // Preferred color theme: 'light', 'dark' or 'auto'. Default: auto - default_theme: "auto", - - // Your Mastodon instance - instance_url: "https://mastodon.social", - - // Choose type of toots to show in the timeline: 'local', 'profile', 'hashtag'. Default: local - timeline_type: "local", - - // Your user ID on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - user_id: "", - - // Your user name on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - profile_name: "", - - // The name of the hashtag. Leave empty if you didn't choose 'hashtag' as type of timeline - hashtag_name: "", - - // Maximum amount of toots to get. Default: 20 - toots_limit: "20", - - // Hide unlisted toots. Default: don't hide - hide_unlisted: false, - - // Hide boosted toots. Default: don't hide - hide_reblog: false, - - // Hide replies toots. Default: don't hide - hide_replies: false, - - // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide - hide_preview_link: false, - - // Hide custom emojis available on the server. Default: don't hide - hide_emojos: false, - - // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag. Ddefault: don't apply - markdown_blockquote: false, - - // Hide replies, boosts and favourites toots counter. Default: don't hide - hide_counter_bar: false, - - // Limit the text content to a maximum number of lines. Default: 0 (unlimited) - text_max_lines: "0", - - // Customize the text of the link pointing to the Mastodon page (appears after the last toot) - link_see_more: "See more posts at Mastodon", - }); -}); ------------------------------ */ -/** - * Set all variables with customized values or use default ones - * @param {object} params_ User customized values - * Trigger main function to build the timeline - */ -const MastodonApi = function (params_) { - this.CONTAINER_BODY_ID = params_.container_body_id || "mt-body"; - this.SPINNER_CLASS = params_.spinner_class || "loading-spinner"; - this.DEFAULT_THEME = params_.default_theme || "auto"; - this.INSTANCE_URL = params_.instance_url; - this.USER_ID = params_.user_id || ""; - this.PROFILE_NAME = this.USER_ID ? params_.profile_name : ""; - this.TIMELINE_TYPE = params_.timeline_type || "local"; - this.HASHTAG_NAME = params_.hashtag_name || ""; - this.TOOTS_LIMIT = params_.toots_limit || "20"; - this.HIDE_UNLISTED = - typeof params_.hide_unlisted !== "undefined" - ? params_.hide_unlisted - : false; - this.HIDE_REBLOG = - typeof params_.hide_reblog !== "undefined" ? params_.hide_reblog : false; - this.HIDE_REPLIES = - typeof params_.hide_replies !== "undefined" ? params_.hide_replies : false; - this.HIDE_PREVIEW_LINK = - typeof params_.hide_preview_link !== "undefined" - ? params_.hide_preview_link - : false; - this.HIDE_EMOJOS = - typeof params_.hide_emojos !== "undefined" ? params_.hide_emojos : false; - this.MARKDOWN_BLOCKQUOTE = - typeof params_.markdown_blockquote !== "undefined" - ? params_.markdown_blockquote - : false; - this.HIDE_COUNTER_BAR = - params_.hide_counter_bar !== "undefined" ? params_.hide_counter_bar : false; - this.TEXT_MAX_LINES = params_.text_max_lines || "0"; - this.LINK_SEE_MORE = params_.link_see_more; - this.FETCHED_DATA = {}; - - this.mtBodyContainer = document.getElementById(this.CONTAINER_BODY_ID); - - this.buildTimeline(); -}; - -/** - * Trigger functions and construct timeline - */ -MastodonApi.prototype.buildTimeline = async function () { - // Apply color theme - this.setTheme(); - - // Get server data - await this.getTimelineData(); - - // Empty the
    container - this.mtBodyContainer.innerHTML = ""; - - for (let i in this.FETCHED_DATA.timeline) { - // First filter (Public / Unlisted) - if ( - this.FETCHED_DATA.timeline[i].visibility == "public" || - (!this.HIDE_UNLISTED && - this.FETCHED_DATA.timeline[i].visibility == "unlisted") - ) { - // Second filter (Reblog / Replies) - if ( - (this.HIDE_REBLOG && this.FETCHED_DATA.timeline[i].reblog) || - (this.HIDE_REPLIES && this.FETCHED_DATA.timeline[i].in_reply_to_id) - ) { - // Nothing here (Don't append toots) - } else { - // Append toots - this.appendToot(this.FETCHED_DATA.timeline[i], Number(i)); - } - } - } - - // Check if there are toots in the container (due to filters applied) - if (this.mtBodyContainer.innerHTML === "") { - this.mtBodyContainer.setAttribute("role", "none"); - this.mtBodyContainer.innerHTML = - '
    📭
    Sorry, no toots to show
    Got ' + - this.FETCHED_DATA.timeline.length + - ' toots from the server but due to the "hide filters" applied, no toot is shown
    '; - } else { - // Insert link after last toot to visit Mastodon page - if (this.LINK_SEE_MORE) { - let linkSeeMorePath = ""; - if (this.TIMELINE_TYPE === "profile") { - linkSeeMorePath = encodeURIComponent(this.PROFILE_NAME); - } else if (this.TIMELINE_TYPE === "hashtag") { - linkSeeMorePath = "tags/" + encodeURIComponent(this.HASHTAG_NAME); - } else if (this.TIMELINE_TYPE === "local") { - linkSeeMorePath = "public/local"; - } - const linkSeeMore = - '"; - this.mtBodyContainer.parentNode.insertAdjacentHTML( - "beforeend", - linkSeeMore - ); - } - - // Control loading spinners - this.manageSpinner(); - } - - // Toot interactions - this.mtBodyContainer.addEventListener("click", function (e) { - // Check if toot cointainer was clicked - if ( - e.target.localName == "article" || - e.target.offsetParent?.localName == "article" || - e.target.localName == "img" - ) { - openTootURL(e); - } - // Check if Show More/Less button was clicked - if (e.target.localName == "button" && e.target.className == "spoiler-btn") { - toogleSpoiler(e); - } - }); - this.mtBodyContainer.addEventListener("keydown", function (e) { - // Check if Enter key was pressed with focus in an article - if (e.key === "Enter" && e.target.localName == "article") { - openTootURL(e); - } - }); - - /** - * Open toot in a new page avoiding any other natural link - * @param {event} e User interaction trigger - */ - const openTootURL = function (e) { - const urlToot = e.target.closest(".mt-toot").dataset.location; - if ( - e.target.localName !== "a" && - e.target.localName !== "span" && - e.target.localName !== "button" && - e.target.localName !== "time" && - e.target.className !== "mt-toot-preview-noImage" && - e.target.parentNode.className !== "mt-toot-avatar-image-big" && - e.target.parentNode.className !== "mt-toot-avatar-image-small" && - e.target.parentNode.className !== "mt-toot-preview-image" && - urlToot - ) { - window.open(urlToot, "_blank", "noopener"); - } - }; - - /** - * Spoiler button - * @param {event} e User interaction trigger - */ - const toogleSpoiler = function (e) { - const nextSibling = e.target.nextSibling; - if (nextSibling.localName === "img") { - e.target.parentNode.classList.remove("mt-toot-media-spoiler"); - e.target.style.display = "none"; - } else if ( - nextSibling.classList.contains("spoiler-text-hidden") || - nextSibling.classList.contains("spoiler-text-visible") - ) { - if (e.target.textContent == "Show more") { - nextSibling.classList.remove("spoiler-text-hidden"); - nextSibling.classList.add("spoiler-text-visible"); - e.target.setAttribute("aria-expanded", "true"); - e.target.textContent = "Show less"; - } else { - nextSibling.classList.remove("spoiler-text-visible"); - nextSibling.classList.add("spoiler-text-hidden"); - e.target.setAttribute("aria-expanded", "false"); - e.target.textContent = "Show more"; - } - } - }; -}; - -/** - * Set the theme style chosen by the user or by the browser/OS - */ -MastodonApi.prototype.setTheme = function () { - /** - * Set the theme value in the tag using the attribute "data-theme" - * @param {string} theme Type of theme to apply: dark or light - */ - const setTheme = function (theme) { - document.documentElement.setAttribute("data-theme", theme); - }; - - if (this.DEFAULT_THEME === "auto") { - let systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); - systemTheme.matches ? setTheme("dark") : setTheme("light"); - // Update the theme if user change browser/OS preference - systemTheme.addEventListener("change", (e) => { - e.matches ? setTheme("dark") : setTheme("light"); - }); - } else { - setTheme(this.DEFAULT_THEME); - } -}; - -/** - * Requests to the server to get all the data - */ -MastodonApi.prototype.getTimelineData = async function () { - return new Promise((resolve, reject) => { - /** - * Fetch data from server - * @param {string} url address to fetch - * @returns {object} List of objects - */ - async function fetchData(url) { - const response = await fetch(url); - - if (!response.ok) { - throw new Error( - "Failed to fetch the following URL: " + - url + - "
    " + - "Error status: " + - response.status + - "
    " + - "Error message: " + - response.statusText - ); - } - - const data = await response.json(); - return data; - } - - // URLs to fetch - let urls = {}; - if (this.TIMELINE_TYPE === "profile") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/accounts/${this.USER_ID}/statuses?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "hashtag") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/tag/${this.HASHTAG_NAME}?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "local") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/public?local=true&limit=${this.TOOTS_LIMIT}`; - } - if (!this.HIDE_EMOJOS) { - urls.emojos = this.INSTANCE_URL + "/api/v1/custom_emojis"; - } - - const urlsPromises = Object.entries(urls).map(([key, url]) => { - return fetchData(url) - .then((data) => ({ [key]: data })) - .catch((error) => { - reject(new Error("Something went wrong fetching data")); - this.mtBodyContainer.innerHTML = - '

    Sorry, request failed:
    ' + - error.message + - "
    "; - this.mtBodyContainer.setAttribute("role", "none"); - return { [key]: [] }; - }); - }); - - // Fetch all urls simultaneously - Promise.all(urlsPromises).then((dataObjects) => { - this.FETCHED_DATA = dataObjects.reduce((result, dataItem) => { - return { ...result, ...dataItem }; - }, {}); - - console.log("Timeline data fetched: ", this.FETCHED_DATA); - resolve(); - }); - }); -}; - -/** - * Inner function to add each toot in timeline container - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.appendToot = function (c, i) { - this.mtBodyContainer.insertAdjacentHTML("beforeend", this.assambleToot(c, i)); -}; - -/** - * Build toot structure - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.assambleToot = function (c, i) { - let avatar, - user, - userName, - url, - date, - formattedDate, - favoritesCount, - reblogCount, - repliesCount; - - if (c.reblog) { - // BOOSTED toot - // Toot url - url = c.reblog.url; - - // Boosted avatar - avatar = - '' + - '
    ' + - '
    ' + - '' +
-      this.escapeHtml(c.reblog.account.username) +
-      ' avatar' + - "
    " + - '
    ' + - '' +
-      this.escapeHtml(c.account.username) +
-      ' avatar' + - "
    " + - "
    " + - "
    "; - - // User name and url - userName = this.showEmojos( - c.reblog.account.display_name - ? c.reblog.account.display_name - : c.reblog.account.username, - this.FETCHED_DATA.emojos - ); - user = - '"; - - // Date - date = c.reblog.created_at; - - // Counter bar - repliesCount = c.reblog.replies_count; - reblogCount = c.reblog.reblogs_count; - favoritesCount = c.reblog.favourites_count; - } else { - // STANDARD toot - // Toot url - url = c.url; - - // Avatar - avatar = - '' + - '
    ' + - '
    ' + - '' +
-      this.escapeHtml(c.account.username) +
-      ' avatar' + - "
    " + - "
    " + - "
    "; - - // User name and url - userName = this.showEmojos( - c.account.display_name ? c.account.display_name : c.account.username, - this.FETCHED_DATA.emojos - ); - user = - '"; - - // Date - date = c.created_at; - - // Counter bar - repliesCount = c.replies_count; - reblogCount = c.reblogs_count; - favoritesCount = c.favourites_count; - } - - // Date - formattedDate = this.formatDate(date); - const timestamp = - '"; - - // Main text - let text_css = ""; - if (this.TEXT_MAX_LINES !== "0") { - text_css = "truncate"; - document.documentElement.style.setProperty( - "--text-max-lines", - this.TEXT_MAX_LINES - ); - } - - let content = ""; - if (c.spoiler_text !== "") { - content = - '
    ' + - c.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text !== "" - ) { - content = - '
    ' + - c.reblog.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text === "" - ) { - content = - '
    ' + - '
    ' + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else { - content = - '
    ' + - '
    ' + - this.formatTootText(c.content) + - "
    " + - "
    "; - } - - // Media attachments - let media = ""; - if (c.media_attachments.length > 0) { - for (let picid in c.media_attachments) { - media = this.placeMedias(c.media_attachments[picid], c.sensitive); - } - } - if (c.reblog && c.reblog.media_attachments.length > 0) { - for (let picid in c.reblog.media_attachments) { - media = this.placeMedias( - c.reblog.media_attachments[picid], - c.reblog.sensitive - ); - } - } - - // Preview link - let previewLink = ""; - if (!this.HIDE_PREVIEW_LINK && c.card) { - if (media === "") { - previewLink = this.placePreviewLink(c.card); - } - } - - // Poll - let poll = ""; - if (c.poll) { - let pollOption = ""; - for (let i in c.poll.options) { - pollOption += "
  • " + c.poll.options[i].title + "
  • "; - } - poll = - '
    ' + - "
      " + - pollOption + - "
    " + - "
    "; - } - - // Counter bar - let counterBar = ""; - if (!this.HIDE_COUNTER_BAR) { - const repliesTag = - '
    ' + - '' + - repliesCount + - "
    "; - - const reblogTag = - '
    ' + - '' + - reblogCount + - "
    "; - - const favoritesTag = - '
    ' + - '' + - favoritesCount + - "
    "; - - counterBar = - '
    ' + - repliesTag + - reblogTag + - favoritesTag + - "
    "; - } - - // Add all to main toot container - const toot = - '
    ' + - '
    ' + - avatar + - user + - timestamp + - "
    " + - content + - media + - previewLink + - poll + - counterBar + - "
    "; - - return toot; -}; - -/** - * Handle text changes made to toots - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.formatTootText = function (c) { - let content = c; - - // Format hashtags and mentions - content = this.addTarget2hashtagMention(content); - - // Convert emojos shortcode into images - if (!this.HIDE_EMOJOS) { - content = this.showEmojos(content, this.FETCHED_DATA.emojos); - } - - // Convert markdown styles into HTML - if (this.MARKDOWN_BLOCKQUOTE) { - content = this.replaceHTMLtag( - content, - "

    >", - "

    ", - "

    ", - "

    " - ); - } - - return content; -}; - -/** - * Add target="_blank" to all #hashtags and @mentions in the toot - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.addTarget2hashtagMention = function (c) { - let content = c.replaceAll('rel="tag"', 'rel="tag" target="_blank"'); - content = content.replaceAll( - 'class="u-url mention"', - 'class="u-url mention" target="_blank"' - ); - - return content; -}; - -/** - * Find all custom emojis shortcode and replace by image - * @param {string} c Text content - * @param {array} e List with all custom emojis - * @returns {string} Text content modified - */ -MastodonApi.prototype.showEmojos = function (c, e) { - if (c.includes(":")) { - for (const emojo of e) { - const regex = new RegExp(`\\:${emojo.shortcode}\\:`, "g"); - c = c.replace( - regex, - `Emoji ${emojo.shortcode}` - ); - } - - return c; - } else { - return c; - } -}; - -/** - * Find all start/end and replace them by another start/end - * @param {string} c Text content - * @param {string} initialTagOpen Start HTML tag to replace - * @param {string} initialTagClose End HTML tag to replace - * @param {string} replacedTagOpen New start HTML tag - * @param {string} replacedTagClose New end HTML tag - * @returns {string} Text in HTML format - */ -MastodonApi.prototype.replaceHTMLtag = function ( - c, - initialTagOpen, - initialTagClose, - replacedTagOpen, - replacedTagClose -) { - if (c.includes(initialTagOpen)) { - const regex = new RegExp(initialTagOpen + "(.*?)" + initialTagClose, "gi"); - - return c.replace(regex, replacedTagOpen + "$1" + replacedTagClose); - } else { - return c; - } -}; - -/** - * Place media - * @param {object} m Media content - * @param {boolean} s Spoiler/Sensitive status - * @returns {string} Media in HTML format - */ -MastodonApi.prototype.placeMedias = function (m, s) { - const spoiler = s || false; - const pic = - '
    ' + - (spoiler ? '' : "") + - '' +
-    (m.description ? this.escapeHtml(m.description) : ' + - "
    "; - - return pic; -}; - -/** - * Place preview link - * @param {object} c Preview link content - * @returns {string} Preview link in HTML format - */ -MastodonApi.prototype.placePreviewLink = function (c) { - const card = - '' + - (c.image - ? '
    ' +
-        this.escapeHtml(c.image_description) +
-        '
    ' - : '
    ') + - "
    " + - '
    ' + - (c.provider_name - ? '' + - this.parseHTMLstring(c.provider_name) + - "" - : "") + - '' + - c.title + - "" + - (c.author_name - ? '' + - this.parseHTMLstring(c.author_name) + - "" - : "") + - "
    " + - "
    "; - - return card; -}; - -/** - * Format date - * @param {string} d Date in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ) - * @returns {string} Date formated (MM DD, YYYY) - */ -MastodonApi.prototype.formatDate = function (d) { - const monthNames = [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ]; - - const date = new Date(d); - - const displayDate = - monthNames[date.getMonth()] + - " " + - date.getDate() + - ", " + - date.getFullYear(); - - return displayDate; -}; - -/** - * Parse HTML string - * @param {string} s HTML string - * @returns {string} Plain text - */ -MastodonApi.prototype.parseHTMLstring = function (s) { - const parser = new DOMParser(); - const txt = parser.parseFromString(s, "text/html"); - return txt.body.textContent; -}; - -/** - * Escape quotes and other special characters, to make them safe to add - * to HTML content and attributes as plain text - * @param {string} s String - * @returns {string} String - */ -MastodonApi.prototype.escapeHtml = function (s) { - return (s ?? "") - .replaceAll("&", "&") - .replaceAll("<", "<") - .replaceAll(">", ">") - .replaceAll('"', """) - .replaceAll("'", "'"); -}; - -/** - * Add/Remove event listener for loading spinner - */ -MastodonApi.prototype.manageSpinner = function () { - // Remove CSS class to container and listener to images - const spinnerCSS = this.SPINNER_CLASS; - const removeSpinner = function () { - this.parentNode.classList.remove(spinnerCSS); - this.removeEventListener("load", removeSpinner); - this.removeEventListener("error", removeSpinner); - }; - - // Add listener to images - this.mtBodyContainer - .querySelectorAll(`.${this.SPINNER_CLASS} > img`) - .forEach((e) => { - e.addEventListener("load", removeSpinner); - e.addEventListener("error", removeSpinner); - }); -}; \ No newline at end of file diff --git a/js/mastodon-timeline-3.7.0.js b/js/mastodon-timeline-3.7.0.js deleted file mode 100644 index a7b57be..0000000 --- a/js/mastodon-timeline-3.7.0.js +++ /dev/null @@ -1,522 +0,0 @@ -// Mastodon embed feed timeline v3.7.0 -// More info at: -// https://gitlab.com/idotj/mastodon-embed-feed-timeline - -// Timeline settings -/* -document.addEventListener("DOMContentLoaded", () => { - let mapi = new MastodonApi({ - // Id of the
    containing the timeline - container_body_id: "mt-body", - - // Preferred color theme: 'light', 'dark' or 'auto'. Default: auto - default_theme: "auto", - - // Your Mastodon instance - instance_url: "https://mastodon.online", - - // Choose type of toots to show in the timeline: 'local', 'profile', 'hashtag'. Default: local - timeline_type: "local", - - // Your user ID on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - user_id: "", - - // Your user name on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - profile_name: "", - - // The name of the hashtag. Leave empty if you didn't choose 'hashtag' as type of timeline - hashtag_name: "", - - // Maximum amount of toots to get. Default: 20 - toots_limit: "20", - - // Hide unlisted toots. Default: don't hide - hide_unlisted: false, - - // Hide boosted toots. Default: don't hide - hide_reblog: false, - - // Hide replies toots. Default: don't hide - hide_replies: false, - - // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag (default: don't apply) - markdown_blockquote: false, - - // Limit the text content to a maximum number of lines. Default: 0 (unlimited) - text_max_lines: "0", - - // Customize the text of the link pointing to the Mastodon page (appears after the last toot) - link_see_more: "See more posts at Mastodon", - }); -}); -*/ -let MastodonApi = function (params_) { - // Endpoint access settings / default values - this.DEFAULT_THEME = params_.default_theme || "auto"; - this.INSTANCE_URL = params_.instance_url; - this.USER_ID = params_.user_id || ""; - this.PROFILE_NAME = this.USER_ID ? params_.profile_name : ""; - this.TIMELINE_TYPE = params_.timeline_type || "local"; - this.HASHTAG_NAME = params_.hashtag_name || ""; - this.TOOTS_LIMIT = params_.toots_limit || "20"; - this.HIDE_UNLISTED = - typeof params_.hide_unlisted !== "undefined" - ? params_.hide_unlisted - : false; - this.HIDE_REBLOG = - typeof params_.hide_reblog !== "undefined" ? params_.hide_reblog : false; - this.HIDE_REPLIES = - typeof params_.hide_replies !== "undefined" ? params_.hide_replies : false; - this.MARKDOWN_BLOCKQUOTE = - typeof params_.markdown_blockquote !== "undefined" - ? params_.markdown_blockquote - : false; - this.TEXT_MAX_LINES = params_.text_max_lines || "0"; - this.LINK_SEE_MORE = params_.link_see_more; - - // Target selector - this.mtBodyContainer = document.getElementById(params_.container_body_id); - - // Apply selected appearance - this.applyTheme(); - - // Get the toots - this.getToots(); -}; - -// Theme style -MastodonApi.prototype.applyTheme = function () { - const setTheme = function (theme) { - document.documentElement.setAttribute("data-theme", theme); - }; - if (this.DEFAULT_THEME === "auto") { - let systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); - systemTheme.matches ? setTheme("dark") : setTheme("light"); - systemTheme.addEventListener("change", (e) => { - e.matches ? setTheme("dark") : setTheme("light"); - }); - } else { - setTheme(this.DEFAULT_THEME); - } -}; - -// Listing toots function -MastodonApi.prototype.getToots = function () { - let mapi = this; - let requestURL = ""; - - // Get request - if (this.TIMELINE_TYPE === "profile") { - requestURL = `${this.INSTANCE_URL}/api/v1/accounts/${this.USER_ID}/statuses?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "hashtag") { - requestURL = `${this.INSTANCE_URL}/api/v1/timelines/tag/${this.HASHTAG_NAME}?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "local") { - requestURL = `${this.INSTANCE_URL}/api/v1/timelines/public?local=true&limit=${this.TOOTS_LIMIT}`; - } - - fetch(requestURL, { - method: "get", - }) - .then((response) => { - if (response.ok) { - return response.json(); - } else if (response.status === 404) { - throw new Error("404 Not found", { cause: response }); - } else { - throw new Error(response.status); - } - }) - .then((jsonData) => { - // console.log("jsonData: ", jsonData); - - // Empty the
    container - this.mtBodyContainer.innerHTML = ""; - - // Add toots - for (let i in jsonData) { - // First filter (Public / Unlisted) - if ( - jsonData[i].visibility == "public" || - (!this.HIDE_UNLISTED && jsonData[i].visibility == "unlisted") - ) { - // Second filter (Reblog / Replies) - if ( - (mapi.HIDE_REBLOG && jsonData[i].reblog) || - (mapi.HIDE_REPLIES && jsonData[i].in_reply_to_id) - ) { - // Nothing here (Don't append toots) - } else { - // Format and append toots - appendToot.call(mapi, jsonData[i], i); - } - } - } - - // Check if there are toots in the container (due to filters applied) - if (this.mtBodyContainer.innerHTML === "") { - this.mtBodyContainer.setAttribute("role", "none"); - this.mtBodyContainer.innerHTML = - '
    📭
    Sorry, no toots to show
    Got ' + - jsonData.length + - ' toots from the server but due to the "hide filters" applied, no toot is shown
    '; - } else { - // Insert link after last toot to visit Mastodon page - if (mapi.LINK_SEE_MORE) { - let linkSeeMorePath = ""; - if (this.TIMELINE_TYPE === "profile") { - linkSeeMorePath = mapi.PROFILE_NAME; - } else if (this.TIMELINE_TYPE === "hashtag") { - linkSeeMorePath = "tags/" + this.HASHTAG_NAME; - } else if (this.TIMELINE_TYPE === "local") { - linkSeeMorePath = "public/local"; - } - let linkSeeMore = - '"; - this.mtBodyContainer.parentNode.insertAdjacentHTML( - "beforeend", - linkSeeMore - ); - } - } - }) - .catch((err) => { - this.mtBodyContainer.innerHTML = - '

    Sorry, request failed:
    ' + - err + - "
    "; - this.mtBodyContainer.setAttribute("role", "none"); - }); - - // Inner function to add each toot content in container - let appendToot = function (status_, index) { - let avatar, user, content, url, date; - - if (status_.reblog) { - // BOOSTED toot - // Toot url - url = status_.reblog.url; - - // Boosted avatar - avatar = - '' + - '
    ' + - "
    " + - '' + - status_.account.username + - " avatar" + - "" + - "
    "; - - // User name and url - user = - '"; - - // Date - date = this.formatDate(status_.reblog.created_at); - } else { - // STANDARD toot - // Toot url - url = status_.url; - - // Avatar - avatar = - '' + - '' + - status_.account.username + - " avatar" + - "" + - ""; - - // User name and url - user = - '"; - - // Date - date = this.formatDate(status_.created_at); - } - - // Main text - let text_css = ""; - if (this.TEXT_MAX_LINES !== "0") { - text_css = "truncate"; - document.documentElement.style.setProperty( - "--text-max-lines", - this.TEXT_MAX_LINES - ); - } - - if (status_.spoiler_text !== "") { - content = - '
    ' + - status_.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(status_.content) + - "
    " + - "
    "; - } else if (status_.reblog && status_.reblog.content !== "") { - content = - '
    ' + - "
    " + - this.formatTootText(status_.reblog.content) + - "
    " + - "
    "; - } else { - content = - '
    ' + - "
    " + - this.formatTootText(status_.content) + - "
    " + - "
    "; - } - - // Media attachments - let media = ""; - if (status_.media_attachments.length > 0) { - for (let picid in status_.media_attachments) { - media = this.replaceMedias( - status_.media_attachments[picid], - status_.sensitive - ); - } - } - if (status_.reblog && status_.reblog.media_attachments.length > 0) { - for (let picid in status_.reblog.media_attachments) { - media = this.replaceMedias( - status_.reblog.media_attachments[picid], - status_.sensitive - ); - } - } - - // Poll - let poll = ""; - let pollOption = ""; - if (status_.poll) { - for (let i in status_.poll.options) { - pollOption += "
  • " + status_.poll.options[i].title + "
  • "; - } - poll = - '
    ' + "
      " + pollOption + "
    " + "
    "; - } - - // Date - let timestamp = - '
    ' + - '' + - date + - "" + - "
    "; - - // Add all to main toot container - let toot = - '
    ' + - avatar + - user + - content + - media + - poll + - timestamp + - "
    "; - - this.mtBodyContainer.insertAdjacentHTML("beforeend", toot); - }; - - // Toot interactions - this.mtBodyContainer.addEventListener("click", function (e) { - // Check if clicked in a toot - if ( - e.target.localName == "article" || - e.target.offsetParent.localName == "article" || - e.target.localName == "img" - ) { - openTootURL(e); - } - // Check if clicked in Show More/Less button - if ( - e.target.localName == "button" && - e.target.className == "spoiler-link" - ) { - toogleSpoiler(e); - } - }); - this.mtBodyContainer.addEventListener("keydown", function (e) { - // Check if Enter key pressed with focus in an article - if (event.code === "Enter" && e.target.localName == "article") { - openTootURL(e); - } - }); - - // Open Toot in a new page avoiding any other natural link - let openTootURL = function (e) { - let urlToot = e.target.closest(".mt-toot").dataset.location; - if ( - e.target.localName !== "a" && - e.target.localName !== "span" && - e.target.localName !== "button" && - urlToot - ) { - window.open(urlToot, "_blank"); - } - }; - - // Spoiler button - let toogleSpoiler = function (e) { - let spoilerText = e.target.nextSibling; - let spoilerBtnText = e.target.textContent; - spoilerText.classList.toggle("spoiler-text"); - if (spoilerBtnText == "Show more") { - spoilerBtnText = "Show less"; - e.target.setAttribute("aria-expanded", "true"); - } else { - spoilerBtnText = "Show more"; - e.target.setAttribute("aria-expanded", "false"); - } - }; -}; - -// Handle text changes made to Toots -MastodonApi.prototype.formatTootText = function (c) { - let content = c; - - // Format hashtags and mentions - content = this.addTarget2hashtagMention(content); - - // Convert markdown styles into HTML - if (this.MARKDOWN_BLOCKQUOTE) { - content = this.replaceHTMLtag( - content, - "

    >", - "

    ", - "

    ", - "

    " - ); - } - - return content; -}; - -// Add target="_blank" to all #hashtags and @mentions -MastodonApi.prototype.addTarget2hashtagMention = function (c) { - let content = c.replaceAll('rel="tag"', 'rel="tag" target="_blank"'); - content = content.replaceAll( - 'class="u-url mention"', - 'class="u-url mention" target="_blank"' - ); - return content; -}; - -// Find all start/end and replace them by another start/end -MastodonApi.prototype.replaceHTMLtag = function ( - c, - initialTagOpen, - initialTagClose, - replacedTagOpen, - replacedTagClose -) { - if (c.includes(initialTagOpen)) { - const regex = new RegExp(initialTagOpen + "(.*?)" + initialTagClose, "gi"); - return c.replace(regex, replacedTagOpen + "$1" + replacedTagClose); - } else { - return c; - } -}; - -// Place media -MastodonApi.prototype.replaceMedias = function (m, s) { - let spoiler = s || false; - let pic = - '
    ' + - (spoiler - ? '' - : "") + - '' + - "
    "; - - return pic; -}; - -// Format date -MastodonApi.prototype.formatDate = function (d) { - const monthNames = [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ]; - - let date = new Date(d); - - let displayDate = - monthNames[date.getMonth()] + - " " + - date.getDate() + - ", " + - date.getFullYear(); - - return displayDate; -}; - -// Loading spinner -removeSpinner = function (e) { - const spinnerCSS = "loading-spinner"; - // Find closest parent container (1st, 2nd or 3rd level) - let spinnerContainer = e.closest("." + spinnerCSS); - if (spinnerContainer) { - spinnerContainer.classList.remove(spinnerCSS); - } -}; diff --git a/js/mastodon-timeline-3.8.1-1.js b/js/mastodon-timeline-3.8.1-1.js deleted file mode 100644 index 88f3815..0000000 --- a/js/mastodon-timeline-3.8.1-1.js +++ /dev/null @@ -1,666 +0,0 @@ -/** - * Mastodon embed feed timeline v3.8.1-1 - * More info at: - * https://gitlab.com/idotj/mastodon-embed-feed-timeline - */ - -/** - * Timeline settings - * Adjust these parameters to customize your timeline - */ -/* -window.addEventListener("load", () => { - let mapi = new MastodonApi({ - // Id of the
    containing the timeline - container_body_id: "mt-body", - - // Preferred color theme: 'light', 'dark' or 'auto'. Default: auto - default_theme: "auto", - - // Your Mastodon instance - instance_url: "https://mastodon.online", - - // Choose type of toots to show in the timeline: 'local', 'profile', 'hashtag'. Default: local - timeline_type: "local", - - // Your user ID on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - user_id: "", - - // Your user name on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - profile_name: "", - - // The name of the hashtag. Leave empty if you didn't choose 'hashtag' as type of timeline - hashtag_name: "", - - // Maximum amount of toots to get. Default: 20 - toots_limit: "20", - - // Hide unlisted toots. Default: don't hide - hide_unlisted: false, - - // Hide boosted toots. Default: don't hide - hide_reblog: false, - - // Hide replies toots. Default: don't hide - hide_replies: false, - - // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide - hide_preview_link: false, - - // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag (default: don't apply) - markdown_blockquote: false, - - // Limit the text content to a maximum number of lines. Default: 0 (unlimited) - text_max_lines: "0", - - // Customize the text of the link pointing to the Mastodon page (appears after the last toot) - link_see_more: "See more posts at Mastodon", - }); -}); -*/ -/** - * Set all variables with customized values or use default ones - * @param {object} params_ User customized values - * Trigger color theme function - * Trigger main function to build the timeline - */ -const MastodonApi = function(params_) { - this.DEFAULT_THEME = params_.default_theme || "auto"; - this.INSTANCE_URL = params_.instance_url; - this.USER_ID = params_.user_id || ""; - this.PROFILE_NAME = this.USER_ID ? params_.profile_name : ""; - this.TIMELINE_TYPE = params_.timeline_type || "local"; - this.HASHTAG_NAME = params_.hashtag_name || ""; - this.TOOTS_LIMIT = params_.toots_limit || "20"; - this.HIDE_UNLISTED = - typeof params_.hide_unlisted !== "undefined" ? - params_.hide_unlisted : - false; - this.HIDE_REBLOG = - typeof params_.hide_reblog !== "undefined" ? params_.hide_reblog : false; - this.HIDE_REPLIES = - typeof params_.hide_replies !== "undefined" ? params_.hide_replies : false; - this.HIDE_PREVIEW_LINK = - typeof params_.hide_preview_link !== "undefined" ? - params_.hide_preview_link : - false; - this.MARKDOWN_BLOCKQUOTE = - typeof params_.markdown_blockquote !== "undefined" ? - params_.markdown_blockquote : - false; - this.TEXT_MAX_LINES = params_.text_max_lines || "0"; - this.LINK_SEE_MORE = params_.link_see_more; - - this.mtBodyContainer = document.getElementById(params_.container_body_id); - - this.setTheme(); - - this.buildTimeline(); -}; - -/** - * Set the theme style choosen by user or browser/OS - */ -MastodonApi.prototype.setTheme = function() { - /** - * Set the theme value in the tag using the attribute "data-theme" - * @param {string} theme Type of theme to apply: dark or light - */ - const setTheme = function(theme) { - document.documentElement.setAttribute("data-theme", theme); - }; - - if (this.DEFAULT_THEME === "auto") { - let systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); - systemTheme.matches ? setTheme("dark") : setTheme("light"); - // Update the theme if user change browser/OS preference - systemTheme.addEventListener("change", (e) => { - e.matches ? setTheme("dark") : setTheme("light"); - }); - } else { - setTheme(this.DEFAULT_THEME); - } -}; - -/** - * Listing toots function - */ -MastodonApi.prototype.buildTimeline = function() { - let mapi = this; - let requestURL = ""; - - // Get request - if (this.TIMELINE_TYPE === "profile") { - requestURL = `${this.INSTANCE_URL}/api/v1/accounts/${this.USER_ID}/statuses?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "hashtag") { - requestURL = `${this.INSTANCE_URL}/api/v1/timelines/tag/${this.HASHTAG_NAME}?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "local") { - requestURL = `${this.INSTANCE_URL}/api/v1/timelines/public?local=true&limit=${this.TOOTS_LIMIT}`; - } - - fetch(requestURL, { - method: "get", - }) - .then((response) => { - if (response.ok) { - return response.json(); - } else if (response.status === 404) { - throw new Error("404 Not found", { - cause: response - }); - } else { - throw new Error(response.status); - } - }) - .then((jsonData) => { - // console.log("jsonData: ", jsonData); - - // Empty the
    container - this.mtBodyContainer.innerHTML = ""; - - for (let i in jsonData) { - // First filter (Public / Unlisted) - if ( - jsonData[i].visibility == "public" || - (!this.HIDE_UNLISTED && jsonData[i].visibility == "unlisted") - ) { - // Second filter (Reblog / Replies) - if ( - (mapi.HIDE_REBLOG && jsonData[i].reblog) || - (mapi.HIDE_REPLIES && jsonData[i].in_reply_to_id) - ) { - // Nothing here (Don't append toots) - } else { - // Format and append toots - appendToot.call(mapi, jsonData[i], Number(i)); - } - } - } - - // Check if there are toots in the container (due to filters applied) - if (this.mtBodyContainer.innerHTML === "") { - this.mtBodyContainer.setAttribute("role", "none"); - this.mtBodyContainer.innerHTML = - '
    📭
    Sorry, no toots to show
    Got ' + - jsonData.length + - ' toots from the server but due to the "hide filters" applied, no toot is shown
    '; - } else { - // Insert link after last toot to visit Mastodon page - if (mapi.LINK_SEE_MORE) { - let linkSeeMorePath = ""; - if (this.TIMELINE_TYPE === "profile") { - linkSeeMorePath = mapi.PROFILE_NAME; - } else if (this.TIMELINE_TYPE === "hashtag") { - linkSeeMorePath = "tags/" + this.HASHTAG_NAME; - } else if (this.TIMELINE_TYPE === "local") { - linkSeeMorePath = "public/local"; - } - let linkSeeMore = - '"; - this.mtBodyContainer.parentNode.insertAdjacentHTML( - "beforeend", - linkSeeMore - ); - } - } - }) - .catch((err) => { - this.mtBodyContainer.innerHTML = - '

    Sorry, request failed:
    ' + - err + - "
    "; - this.mtBodyContainer.setAttribute("role", "none"); - }); - - /** - * Inner function to add each toot in timeline container - * @param {object} c Toot content - * @param {number} i Index of toot - */ - const appendToot = function(c, i) { - this.mtBodyContainer.insertAdjacentHTML( - "beforeend", - this.assambleToot(c, i) - ); - }; - - // Toot interactions - this.mtBodyContainer.addEventListener("click", function(e) { - // Check if toot cointainer was clicked - if ( - e.target.localName == "article" || - e.target.offsetParent.localName == "article" || - e.target.localName == "img" - ) { - openTootURL(e); - } - // Check if Show More/Less button was clicked - if ( - e.target.localName == "button" && - e.target.className == "spoiler-link" - ) { - toogleSpoiler(e); - } - }); - this.mtBodyContainer.addEventListener("keydown", function(e) { - // Check if Enter key was pressed with focus in an article - if (e.key === "Enter" && e.target.localName == "article") { - openTootURL(e); - } - }); - - /** - * Open toot in a new page avoiding any other natural link - * @param {event} e User interaction trigger - */ - const openTootURL = function(e) { - let urlToot = e.target.closest(".mt-toot").dataset.location; - if ( - e.target.localName !== "a" && - e.target.localName !== "span" && - e.target.localName !== "button" && - e.target.parentNode.className !== "toot-preview-image" && - urlToot - ) { - window.open(urlToot, "_blank"); - } - }; - - /** - * Spoiler button - * @param {event} e User interaction trigger - */ - const toogleSpoiler = function(e) { - const nextSibling = e.target.nextSibling; - if (nextSibling.localName === "img") { - e.target.parentNode.classList.remove("toot-media-spoiler"); - e.target.style.display = "none"; - } else if ( - nextSibling.classList.contains("spoiler-text-hidden") || - nextSibling.classList.contains("spoiler-text-visible") - ) { - if (e.target.textContent == "Show more") { - nextSibling.classList.remove("spoiler-text-hidden"); - nextSibling.classList.add("spoiler-text-visible"); - e.target.setAttribute("aria-expanded", "true"); - e.target.textContent = "Show less"; - } else { - nextSibling.classList.remove("spoiler-text-visible"); - nextSibling.classList.add("spoiler-text-hidden"); - e.target.setAttribute("aria-expanded", "false"); - e.target.textContent = "Show more"; - } - } - }; -}; - -/** - * Build toot structure - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.assambleToot = function(c, i) { - let avatar, user, content, url, date; - - if (c.reblog) { - // BOOSTED toot - // Toot url - url = c.reblog.url; - - // Boosted avatar - avatar = - '' + - '
    ' + - "
    " + - '' + - c.account.username + - " avatar" + - "" + - "
    "; - - // User name and url - user = - '"; - - // Date - date = this.formatDate(c.reblog.created_at); - } else { - // STANDARD toot - // Toot url - url = c.url; - - // Avatar - avatar = - '' + - '' + - c.account.username + - " avatar" + - "" + - ""; - - // User name and url - user = - '"; - - // Date - date = this.formatDate(c.created_at); - } - - // Main text - let text_css = ""; - if (this.TEXT_MAX_LINES !== "0") { - text_css = "truncate"; - document.documentElement.style.setProperty( - "--text-max-lines", - this.TEXT_MAX_LINES - ); - } - - if (c.spoiler_text !== "") { - content = - '
    ' + - c.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text !== "" - ) { - content = - '
    ' + - c.reblog.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text === "" - ) { - content = - '
    ' + - "
    " + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else { - content = - '
    ' + - "
    " + - this.formatTootText(c.content) + - "
    " + - "
    "; - } - - // Media attachments - let media = ""; - if (c.media_attachments.length > 0) { - for (let picid in c.media_attachments) { - media = this.placeMedias(c.media_attachments[picid], c.sensitive); - } - } - if (c.reblog && c.reblog.media_attachments.length > 0) { - for (let picid in c.reblog.media_attachments) { - media = this.placeMedias( - c.reblog.media_attachments[picid], - c.reblog.sensitive - ); - } - } - - // Preview link, but only if no media is present - let preview_link = ""; - if (media === "") { - if (!this.HIDE_PREVIEW_LINK && c.card) { - preview_link = this.placePreviewLink(c.card); - } - } - - // Poll - let poll = ""; - let pollOption = ""; - if (c.poll) { - for (let i in c.poll.options) { - pollOption += "
  • " + c.poll.options[i].title + "
  • "; - } - poll = '
    ' + "
      " + pollOption + "
    " + "
    "; - } - - // Date - const timestamp = - '
    ' + - '' + - date + - "" + - "
    "; - - // Add all to main toot container - const toot = - '
    ' + - avatar + - user + - content + - media + - preview_link + - poll + - timestamp + - "
    "; - - return toot; -}; - -/** - * Handle text changes made to toots - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.formatTootText = function(c) { - let content = c; - - // Format hashtags and mentions - content = this.addTarget2hashtagMention(content); - - // Convert markdown styles into HTML - if (this.MARKDOWN_BLOCKQUOTE) { - content = this.replaceHTMLtag( - content, - "

    >", - "

    ", - "

    ", - "

    " - ); - } - - return content; -}; - -/** - * Add target="_blank" to all #hashtags and @mentions in the toot - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.addTarget2hashtagMention = function(c) { - let content = c.replaceAll('rel="tag"', 'rel="tag" target="_blank"'); - content = content.replaceAll( - 'class="u-url mention"', - 'class="u-url mention" target="_blank"' - ); - - return content; -}; - -/** - * Find all start/end and replace them by another start/end - * @param {string} c Text content - * @param {string} initialTagOpen Start HTML tag to replace - * @param {string} initialTagClose End HTML tag to replace - * @param {string} replacedTagOpen New start HTML tag - * @param {string} replacedTagClose New end HTML tag - * @returns {string} Text in HTML format - */ -MastodonApi.prototype.replaceHTMLtag = function( - c, - initialTagOpen, - initialTagClose, - replacedTagOpen, - replacedTagClose -) { - if (c.includes(initialTagOpen)) { - const regex = new RegExp(initialTagOpen + "(.*?)" + initialTagClose, "gi"); - - return c.replace(regex, replacedTagOpen + "$1" + replacedTagClose); - } else { - return c; - } -}; - -/** - * Place media - * @param {object} m Media content - * @param {boolean} s Spoiler/Sensitive status - * @returns {string} Media in HTML format - */ -MastodonApi.prototype.placeMedias = function(m, s) { - let spoiler = s || false; - const pic = - '
    ' + - (spoiler ? '' : "") + - '' +
-    (m.description ? m.description : ' + - "
    "; - - return pic; -}; - -/** - * Place preview link - * @param {object} c Preview link content - * @returns {string} Preview link in HTML format - */ -MastodonApi.prototype.placePreviewLink = function(c) { - let card = - '' + - (c.image ? - '
    ' : - '
    📄
    ') + - "
    " + - '
    ' + - (c.provider_name ? - '' + c.provider_name + "" : - "") + - '' + - c.title + - "" + - (c.author_name ? - 'By ' + c.author_name + "" : - "") + - "
    " + - "
    "; - - return card; -}; - -/** - * Format date - * @param {string} d Date in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ) - * @returns {string} Date formated (MM DD, YYYY) - */ -MastodonApi.prototype.formatDate = function(d) { - const monthNames = [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ]; - - let date = new Date(d); - - const displayDate = - monthNames[date.getMonth()] + - " " + - date.getDate() + - ", " + - date.getFullYear(); - - return displayDate; -}; - -/** - * Loading spinner - * @param {object} e Image containing the spinner - */ -const removeSpinner = function(e) { - const spinnerCSS = "loading-spinner"; - - // Find closest parent container (1st, 2nd or 3rd level) - let spinnerContainer = e.closest("." + spinnerCSS); - - if (spinnerContainer) { - spinnerContainer.classList.remove(spinnerCSS); - } -}; diff --git a/js/mastodon-timeline-3.9.1-3.js b/js/mastodon-timeline-3.9.1-3.js deleted file mode 100644 index 72e8027..0000000 --- a/js/mastodon-timeline-3.9.1-3.js +++ /dev/null @@ -1,786 +0,0 @@ -/** - * Mastodon embed feed timeline v3.9.1-3 - * More info at: - * https://gitlab.com/idotj/mastodon-embed-feed-timeline - */ -/** - * This file contains modifications to the above upstream project. - * The file repository for these modifications can be found here: - * https://gitlab.com/clvgt12/mastodon-embed-feed-timeline - * - * Mastodon embed feed timeline - * Copyright (C) 2022 clvgt12 - * Copyright (C) 2021 i.j - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -/** - * Timeline settings - * Adjust these parameters to customize your timeline - */ -/** - * Place the following eventListener within the webpage itself for per blog customization - * -window.addEventListener("load", () => { - const mastodonTimeline = new MastodonApi({ - // Id of the
    containing the timeline - container_body_id: "mt-body", - - // Class name for the loading spinner (also used in CSS file) - spinner_class: "loading-spinner", - - // Preferred color theme: 'light', 'dark' or 'auto'. Default: auto - default_theme: "auto", - - // Your Mastodon instance - instance_url: "https://mastodon.online", - - // Choose type of toots to show in the timeline: 'local', 'profile', 'hashtag'. Default: local - timeline_type: "local", - - // Your user ID on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - user_id: "", - - // Your user name on Mastodon instance. Leave empty if you didn't choose 'profile' as type of timeline - profile_name: "", - - // The name of the hashtag. Leave empty if you didn't choose 'hashtag' as type of timeline - hashtag_name: "", - - // Maximum amount of toots to get. Default: 20 - toots_limit: "20", - - // Hide unlisted toots. Default: don't hide - hide_unlisted: false, - - // Hide boosted toots. Default: don't hide - hide_reblog: false, - - // Hide replies toots. Default: don't hide - hide_replies: false, - - // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide - hide_preview_link: false, - - // Hide custom emojis available on the server. Default: don't hide - hide_emojos: false, - - // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag. Ddefault: don't apply - markdown_blockquote: false, - - // Limit the text content to a maximum number of lines. Default: 0 (unlimited) - text_max_lines: "0", - - // Customize the text of the link pointing to the Mastodon page (appears after the last toot) - link_see_more: "See more posts at Mastodon", - }); -}); -*/ -/** - * Set all variables with customized values or use default ones - * @param {object} params_ User customized values - * Trigger main function to build the timeline - */ -const MastodonApi = function (params_) { - this.CONTAINER_BODY_ID = params_.container_body_id || "mt-body"; - this.SPINNER_CLASS = params_.spinner_class || "loading-spinner"; - this.DEFAULT_THEME = params_.default_theme || "auto"; - this.INSTANCE_URL = params_.instance_url; - this.USER_ID = params_.user_id || ""; - this.PROFILE_NAME = this.USER_ID ? params_.profile_name : ""; - this.TIMELINE_TYPE = params_.timeline_type || "local"; - this.HASHTAG_NAME = params_.hashtag_name || ""; - this.TOOTS_LIMIT = params_.toots_limit || "20"; - this.HIDE_UNLISTED = - typeof params_.hide_unlisted !== "undefined" - ? params_.hide_unlisted - : false; - this.HIDE_REBLOG = - typeof params_.hide_reblog !== "undefined" ? params_.hide_reblog : false; - this.HIDE_REPLIES = - typeof params_.hide_replies !== "undefined" ? params_.hide_replies : false; - this.HIDE_PREVIEW_LINK = - typeof params_.hide_preview_link !== "undefined" - ? params_.hide_preview_link - : false; - this.HIDE_EMOJOS = - typeof params_.hide_emojos !== "undefined" ? params_.hide_emojos : false; - this.MARKDOWN_BLOCKQUOTE = - typeof params_.markdown_blockquote !== "undefined" - ? params_.markdown_blockquote - : false; - this.TEXT_MAX_LINES = params_.text_max_lines || "0"; - this.LINK_SEE_MORE = params_.link_see_more; - this.FETCHED_DATA = {}; - - this.mtBodyContainer = document.getElementById(this.CONTAINER_BODY_ID); - - this.buildTimeline(); -}; - -/** - * Trigger functions and construct timeline - */ -MastodonApi.prototype.buildTimeline = async function () { - // Apply color theme - this.setTheme(); - - // Get server data - await this.getTimelineData(); - - // Empty the
    container - this.mtBodyContainer.innerHTML = ""; - - for (let i in this.FETCHED_DATA.timeline) { - // First filter (Public / Unlisted) - if ( - this.FETCHED_DATA.timeline[i].visibility == "public" || - (!this.HIDE_UNLISTED && - this.FETCHED_DATA.timeline[i].visibility == "unlisted") - ) { - // Second filter (Reblog / Replies) - if ( - (this.HIDE_REBLOG && this.FETCHED_DATA.timeline[i].reblog) || - (this.HIDE_REPLIES && this.FETCHED_DATA.timeline[i].in_reply_to_id) - ) { - // Nothing here (Don't append toots) - } else { - // Append toots - this.appendToot(this.FETCHED_DATA.timeline[i], Number(i)); - } - } - } - - // Check if there are toots in the container (due to filters applied) - if (this.mtBodyContainer.innerHTML === "") { - this.mtBodyContainer.setAttribute("role", "none"); - this.mtBodyContainer.innerHTML = - '
    📭
    Sorry, no toots to show
    Got ' + - this.FETCHED_DATA.timeline.length + - ' toots from the server but due to the "hide filters" applied, no toot is shown
    '; - } else { - // Insert link after last toot to visit Mastodon page - if (this.LINK_SEE_MORE) { - let linkSeeMorePath = ""; - if (this.TIMELINE_TYPE === "profile") { - linkSeeMorePath = this.PROFILE_NAME; - } else if (this.TIMELINE_TYPE === "hashtag") { - linkSeeMorePath = "tags/" + this.HASHTAG_NAME; - } else if (this.TIMELINE_TYPE === "local") { - linkSeeMorePath = "public/local"; - } - let linkSeeMore = - '"; - this.mtBodyContainer.parentNode.insertAdjacentHTML( - "beforeend", - linkSeeMore - ); - } - - // Control loading spinners - this.manageSpinner(); - } - - // Toot interactions - this.mtBodyContainer.addEventListener("click", function (e) { - // Check if toot cointainer was clicked - if ( - e.target.localName == "article" || - e.target.offsetParent.localName == "article" || - (e.target.localName == "img" && - e.target.offsetParent.className !== "mt-avatar" && - e.target.offsetParent.className !== "mt-avatar-account") - ) { - openTootURL(e); - } - // Check if Show More/Less button was clicked - if ( - e.target.localName == "button" && - e.target.className == "spoiler-link" - ) { - toogleSpoiler(e); - } - }); - this.mtBodyContainer.addEventListener("keydown", function (e) { - // Check if Enter key was pressed with focus in an article - if (e.key === "Enter" && e.target.localName == "article") { - openTootURL(e); - } - }); - - /** - * Open toot in a new page avoiding any other natural link - * @param {event} e User interaction trigger - */ - const openTootURL = function (e) { - let urlToot = e.target.closest(".mt-toot").dataset.location; - if ( - e.target.localName !== "a" && - e.target.localName !== "span" && - e.target.localName !== "button" && - e.target.parentNode.className !== "toot-preview-image" && - urlToot - ) { - window.open(urlToot, "_blank"); - } - }; - - /** - * Spoiler button - * @param {event} e User interaction trigger - */ - const toogleSpoiler = function (e) { - const nextSibling = e.target.nextSibling; - if (nextSibling.localName === "img") { - e.target.parentNode.classList.remove("toot-media-spoiler"); - e.target.style.display = "none"; - } else if ( - nextSibling.classList.contains("spoiler-text-hidden") || - nextSibling.classList.contains("spoiler-text-visible") - ) { - if (e.target.textContent == "Show more") { - nextSibling.classList.remove("spoiler-text-hidden"); - nextSibling.classList.add("spoiler-text-visible"); - e.target.setAttribute("aria-expanded", "true"); - e.target.textContent = "Show less"; - } else { - nextSibling.classList.remove("spoiler-text-visible"); - nextSibling.classList.add("spoiler-text-hidden"); - e.target.setAttribute("aria-expanded", "false"); - e.target.textContent = "Show more"; - } - } - }; -}; - -/** - * Set the theme style chosen by the user or by the browser/OS - */ -MastodonApi.prototype.setTheme = function () { - /** - * Set the theme value in the tag using the attribute "data-theme" - * @param {string} theme Type of theme to apply: dark or light - */ - const setTheme = function (theme) { - document.documentElement.setAttribute("data-theme", theme); - }; - - if (this.DEFAULT_THEME === "auto") { - let systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); - systemTheme.matches ? setTheme("dark") : setTheme("light"); - // Update the theme if user change browser/OS preference - systemTheme.addEventListener("change", (e) => { - e.matches ? setTheme("dark") : setTheme("light"); - }); - } else { - setTheme(this.DEFAULT_THEME); - } -}; - -/** - * Requests to the server to get all the data - */ -MastodonApi.prototype.getTimelineData = async function () { - return new Promise((resolve, reject) => { - /** - * Fetch data from server - * @param {string} url address to fetch - * @returns {object} List of objects - */ - async function fetchData(url) { - const response = await fetch(url); - - if (!response.ok) { - throw new Error( - "Failed to fetch the following URL: " + - url + - "
    " + - "Error status: " + - response.status + - "
    " + - "Error message: " + - response.statusText - ); - } - - const data = await response.json(); - return data; - } - - // URLs to fetch - let urls = {}; - if (this.TIMELINE_TYPE === "profile") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/accounts/${this.USER_ID}/statuses?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "hashtag") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/tag/${this.HASHTAG_NAME}?limit=${this.TOOTS_LIMIT}`; - } else if (this.TIMELINE_TYPE === "local") { - urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/public?local=true&limit=${this.TOOTS_LIMIT}`; - } - if (!this.HIDE_EMOJOS) { - urls.emojos = this.INSTANCE_URL + "/api/v1/custom_emojis"; - } - - const urlsPromises = Object.entries(urls).map(([key, url]) => { - return fetchData(url) - .then((data) => ({ [key]: data })) - .catch((error) => { - reject(new Error("Something went wrong fetching data")); - this.mtBodyContainer.innerHTML = - '

    Sorry, request failed:
    ' + - error.message + - "
    "; - this.mtBodyContainer.setAttribute("role", "none"); - return { [key]: [] }; - }); - }); - - // Fetch all urls simultaneously - Promise.all(urlsPromises).then((dataObjects) => { - this.FETCHED_DATA = dataObjects.reduce((result, dataItem) => { - return { ...result, ...dataItem }; - }, {}); - - // console.log("Timeline data: ", this.FETCHED_DATA); - resolve(); - }); - }); -}; - -/** - * Inner function to add each toot in timeline container - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.appendToot = function (c, i) { - this.mtBodyContainer.insertAdjacentHTML("beforeend", this.assambleToot(c, i)); -}; - -/** - * Build toot structure - * @param {object} c Toot content - * @param {number} i Index of toot - */ -MastodonApi.prototype.assambleToot = function (c, i) { - let avatar, user, content, url, date; - - if (c.reblog) { - // BOOSTED toot - // Toot url - url = c.reblog.url; - - // Boosted avatar - avatar = - '' + - '
    ' + - '
    ' + - '' +
-      c.reblog.account.username +
-      ' avatar' + - "
    " + - '" + - "
    " + - "
    "; - - // User name and url - user = - '"; - - // Date - date = this.formatDate(c.reblog.created_at); - } else { - // STANDARD toot - // Toot url - url = c.url; - - // Avatar - avatar = - '' + - '
    ' + - '' +
-      c.account.username +
-      ' avatar' + - "
    " + - "
    "; - - // User name and url - user = - '"; - - // Date - date = this.formatDate(c.created_at); - } - - // Main text - let text_css = ""; - if (this.TEXT_MAX_LINES !== "0") { - text_css = "truncate"; - document.documentElement.style.setProperty( - "--text-max-lines", - this.TEXT_MAX_LINES - ); - } - - if (c.spoiler_text !== "") { - content = - '
    ' + - c.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text !== "" - ) { - content = - '
    ' + - c.reblog.spoiler_text + - ' ' + - '
    ' + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else if ( - c.reblog && - c.reblog.content !== "" && - c.reblog.spoiler_text === "" - ) { - content = - '
    ' + - "
    " + - this.formatTootText(c.reblog.content) + - "
    " + - "
    "; - } else { - content = - '
    ' + - "
    " + - this.formatTootText(c.content) + - "
    " + - "
    "; - } - - // Media attachments - let media = ""; - if (c.media_attachments.length > 0) { - for (let picid in c.media_attachments) { - media = this.placeMedias(c.media_attachments[picid], c.sensitive); - } - } - if (c.reblog && c.reblog.media_attachments.length > 0) { - for (let picid in c.reblog.media_attachments) { - media = this.placeMedias( - c.reblog.media_attachments[picid], - c.reblog.sensitive - ); - } - } - - // Preview link - let preview_link = ""; - if(media === "") { - if (!this.HIDE_PREVIEW_LINK && c.card) { - preview_link = this.placePreviewLink(c.card); - } - } - - // Poll - let poll = ""; - let pollOption = ""; - if (c.poll) { - for (let i in c.poll.options) { - pollOption += "
  • " + c.poll.options[i].title + "
  • "; - } - poll = '
    ' + "
      " + pollOption + "
    " + "
    "; - } - - // Date - const timestamp = - '
    ' + - '' + - date + - "" + - "
    "; - - // Add all to main toot container - const toot = - '
    ' + - '
    ' + - avatar + - user + - '
    ' + - content + - media + - preview_link + - poll + - timestamp + - "
    "; - - return toot; -}; - -/** - * Handle text changes made to toots - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.formatTootText = function (c) { - let content = c; - - // Format hashtags and mentions - content = this.addTarget2hashtagMention(content); - - // Convert emojos shortcode into images - if (!this.HIDE_EMOJOS) { - content = this.showEmojos(content, this.FETCHED_DATA.emojos); - } - - // Convert markdown styles into HTML - if (this.MARKDOWN_BLOCKQUOTE) { - content = this.replaceHTMLtag( - content, - "

    >", - "

    ", - "

    ", - "

    " - ); - } - - return content; -}; - -/** - * Add target="_blank" to all #hashtags and @mentions in the toot - * @param {string} c Text content - * @returns {string} Text content modified - */ -MastodonApi.prototype.addTarget2hashtagMention = function (c) { - let content = c.replaceAll('rel="tag"', 'rel="tag" target="_blank"'); - content = content.replaceAll( - 'class="u-url mention"', - 'class="u-url mention" target="_blank"' - ); - - return content; -}; - -/** - * Find all custom emojis shortcode and replace by image - * @param {string} c Text content - * @param {array} e List with all custom emojis - * @returns {string} Text content modified - */ -MastodonApi.prototype.showEmojos = function (c, e) { - if (c.includes(":")) { - for (const emojo of e) { - const regex = new RegExp(`\\:${emojo.shortcode}\\:`, "g"); - c = c.replace( - regex, - `Emoji ${emojo.shortcode}` - ); - } - - return c; - } else { - return c; - } -}; - -/** - * Find all start/end and replace them by another start/end - * @param {string} c Text content - * @param {string} initialTagOpen Start HTML tag to replace - * @param {string} initialTagClose End HTML tag to replace - * @param {string} replacedTagOpen New start HTML tag - * @param {string} replacedTagClose New end HTML tag - * @returns {string} Text in HTML format - */ -MastodonApi.prototype.replaceHTMLtag = function ( - c, - initialTagOpen, - initialTagClose, - replacedTagOpen, - replacedTagClose -) { - if (c.includes(initialTagOpen)) { - const regex = new RegExp(initialTagOpen + "(.*?)" + initialTagClose, "gi"); - - return c.replace(regex, replacedTagOpen + "$1" + replacedTagClose); - } else { - return c; - } -}; - -/** - * Place media - * @param {object} m Media content - * @param {boolean} s Spoiler/Sensitive status - * @returns {string} Media in HTML format - */ -MastodonApi.prototype.placeMedias = function (m, s) { - let spoiler = s || false; - const pic = - '
    ' + - (spoiler ? '' : "") + - '' +
-    (m.description ? m.description : ' + - "
    "; - - return pic; -}; - -/** - * Place preview link - * @param {object} c Preview link content - * @returns {string} Preview link in HTML format - */ -MastodonApi.prototype.placePreviewLink = function (c) { - let card = - '' + - (c.image - ? '
    ' - : '
    📄
    ') + - "
    " + - '
    ' + - (c.provider_name - ? '' + c.provider_name + "" - : "") + - '' + - c.title + - "" + - (c.author_name - ? 'By ' + c.author_name + "" - : "") + - "
    " + - "
    "; - - return card; -}; - -/** - * Format date - * @param {string} d Date in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ) - * @returns {string} Date formated (MM DD, YYYY) - */ -MastodonApi.prototype.formatDate = function (d) { - const monthNames = [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ]; - - let date = new Date(d); - - const displayDate = - monthNames[date.getMonth()] + - " " + - date.getDate() + - ", " + - date.getFullYear(); - - return displayDate; -}; - -/** - * Add/Remove event listener for loading spinner - */ -MastodonApi.prototype.manageSpinner = function () { - // Remove CSS class to container and listener to images - const spinnerCSS = this.SPINNER_CLASS; - const removeSpinner = function () { - this.parentNode.classList.remove(spinnerCSS); - this.removeEventListener("load", removeSpinner); - this.removeEventListener("error", removeSpinner); - }; - - // Add listener to images - this.mtBodyContainer - .querySelectorAll(`.${this.SPINNER_CLASS} > img`) - .forEach((e) => { - e.addEventListener("load", removeSpinner); - e.addEventListener("error", removeSpinner); - }); -};