From cd42ea46d601463d199f56efe4a116ce362b146c Mon Sep 17 00:00:00 2001 From: "i.j" Date: Fri, 7 Mar 2025 14:52:56 +0100 Subject: [PATCH] 4.6.0 --- CHANGELOG | 8 + dist/mastodon-timeline.esm.js | 4 +- dist/mastodon-timeline.min.css | 2 +- dist/mastodon-timeline.umd.js | 4 +- docs/INSTALLATION.md | 4 +- package-lock.json | 4 +- package.json | 2 +- src/mastodon-timeline.css | 45 ++-- src/mastodon-timeline.js | 394 ++++++++++++++++----------------- 9 files changed, 232 insertions(+), 235 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0b863c6..18d9a69 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,11 @@ +v4.6.0 - 07/03/2025 +- Show preview link content in boosted posts +- Fix spoiler text switch button +- Add CSS styles to #hashtags +- Improve dark theme +- CSS refactoring +- JS refactoring + v4.5.1 - 05/03/2025 - Fix profile name alignment for pinned post diff --git a/dist/mastodon-timeline.esm.js b/dist/mastodon-timeline.esm.js index 0d0758b..26fa9ff 100644 --- a/dist/mastodon-timeline.esm.js +++ b/dist/mastodon-timeline.esm.js @@ -1,8 +1,8 @@ /** * Mastodon embed timeline * @author idotj - * @version 4.5.1 + * @version 4.6.0 * @url https://gitlab.com/idotj/mastodon-embed-timeline * @license GNU AGPLv3 */ -class t{constructor(t={}){this.defaultSettings={mtContainerId:"mt-container",instanceUrl:"https://mastodon.social",timelineType:"local",userId:"",profileName:"",hashtagName:"",spinnerClass:"mt-loading-spinner",defaultTheme:"auto",maxNbPostFetch:"20",maxNbPostShow:"20",dateFormatLocale:"en-GB",dateFormatOptions:{day:"2-digit",month:"short",year:"numeric"},hideUnlisted:!1,hideReblog:!1,hideReplies:!1,hidePinnedPosts:!1,hideUserAccount:!1,txtMaxLines:"",filterByLanguage:"",btnShowMore:"SHOW MORE",btnShowLess:"SHOW LESS",markdownBlockquote:!1,hideEmojos:!1,btnShowContent:"SHOW CONTENT",hideVideoPreview:!1,btnPlayVideoTxt:"Load and play video",hidePreviewLink:!1,previewMaxLines:"",hideCounterBar:!1,disableCarousel:!1,carouselCloseTxt:"Close carousel",carouselPrevTxt:"Previous media item",carouselNextTxt:"Next media item",btnSeeMore:"See more posts at Mastodon",btnReload:"Refresh",insistSearchContainer:!1,insistSearchContainerTime:"3000"},this.mtSettings={...this.defaultSettings,...t},this.#t(),this.linkHeader={},this.mtContainerNode="",this.mtBodyNode="",this.fetchedData={},this.#e((()=>{this.#i()}))}#t(){Number(this.mtSettings.maxNbPostShow)>Number(this.mtSettings.maxNbPostFetch)&&(console.error(`Please check your settings! The maximum number of posts to show is bigger than the maximum number of posts to fetch. Changing the value of "maxNbPostFetch" to: ${this.mtSettings.maxNbPostShow}`),this.mtSettings.maxNbPostFetch=this.mtSettings.maxNbPostShow)}#e(t){"undefined"!=typeof document&&"complete"===document.readyState?t():"undefined"!=typeof document&&"complete"!==document.readyState&&document.addEventListener("DOMContentLoaded",t())}#i(){const t=()=>{this.mtContainerNode=document.getElementById(this.mtSettings.mtContainerId),this.mtBodyNode=this.mtContainerNode.getElementsByClassName("mt-body")[0],this.#s(),this.#a("newTimeline")};if(this.mtSettings.insistSearchContainer){const e=performance.now(),i=()=>{if(document.getElementById(this.mtSettings.mtContainerId))t();else{performance.now()-e container with id: "${this.mtSettings.mtContainerId}" after several attempts for ${this.mtSettings.insistSearchContainerTime/1e3} seconds`)}};i()}else document.getElementById(this.mtSettings.mtContainerId)?t():console.error(`Impossible to find the
container with id: "${this.mtSettings.mtContainerId}". Please try to add the option 'insistSearchContainer: true' when initializing the script`)}mtUpdate(){this.#e((()=>{this.mtBodyNode.replaceChildren(),this.mtBodyNode.insertAdjacentHTML("afterbegin",'
'),this.#a("updateTimeline")}))}mtColorTheme(t){this.#e((()=>{this.mtContainerNode.setAttribute("data-theme",t)}))}#s(){if("auto"===this.mtSettings.defaultTheme){let t=window.matchMedia("(prefers-color-scheme: dark)");t.matches?this.mtColorTheme("dark"):this.mtColorTheme("light"),t.addEventListener("change",(t=>{t.matches?this.mtColorTheme("dark"):this.mtColorTheme("light")}))}else this.mtColorTheme(this.mtSettings.defaultTheme)}#n(){return new Promise(((t,e)=>{const i=this.mtSettings.instanceUrl?`${this.mtSettings.instanceUrl}/api/v1/`:this.#o("Please check your instanceUrl value","⚠️"),s=this.#r(i),a=Object.entries(s).map((([t,i])=>{const s="timeline"===t;return this.#l(i,s).then((e=>({[t]:e}))).catch((s=>(e(new Error(`Something went wrong fetching data from: ${i}`)),this.#o(s.message),{[t]:[]})))}));Promise.all(a).then((async e=>{if(this.fetchedData=e.reduce(((t,e)=>({...t,...e})),{}),!this.mtSettings.hidePinnedPosts&&void 0!==this.fetchedData.pinned?.length&&0!==this.fetchedData.pinned.length){const t=this.fetchedData.pinned.map((t=>({...t,pinned:!0})));this.fetchedData.timeline=[...t,...this.fetchedData.timeline]}if(this.#d())t();else{do{await this.#m()}while(!this.#d()&&this.linkHeader.next);t()}}))}))}#r(t){const{timelineType:e,userId:i,hashtagName:s,maxNbPostFetch:a,hidePinnedPosts:n,hideEmojos:o}=this.mtSettings,r={};switch(e){case"profile":if(!i){this.#o("Please check your userId value","⚠️");break}r.timeline=`${t}accounts/${i}/statuses?limit=${a}`,n||(r.pinned=`${t}accounts/${i}/statuses?pinned=true`);break;case"hashtag":if(!s){this.#o("Please check your hashtagName value","⚠️");break}r.timeline=`${t}timelines/tag/${s}?limit=${a}`;break;case"local":r.timeline=`${t}timelines/public?local=true&limit=${a}`;break;default:this.#o("Please check your timelineType value","⚠️")}return o||(r.emojos=`${t}custom_emojis`),r}async#l(t,e=!1){const i=await fetch(t);if(!i.ok)throw new Error(`\n Failed to fetch the following Url:
${t}
Error status: ${i.status}
Error message: ${i.statusText}\n `);const s=await i.json();return e&&i.headers.get("Link")&&(this.linkHeader=this.#h(i.headers.get("Link"))),s}#d(){return this.fetchedData.timeline.length>=Number(this.mtSettings.maxNbPostFetch)}#m(){return new Promise((t=>{this.linkHeader.next?this.#l(this.linkHeader.next,!0).then((e=>{this.fetchedData.timeline=[...this.fetchedData.timeline,...e],t()})):t()}))}#h(t){const e=t.split(", ").map((t=>t.split("; "))).map((t=>[t[1].replace(/"/g,"").replace("rel=",""),t[0].slice(1,-1)]));return Object.fromEntries(e)}async#a(t){await this.#n();const{hideUnlisted:e,hideReblog:i,hideReplies:s,maxNbPostShow:a,filterByLanguage:n}=this.mtSettings,o=this.fetchedData.timeline;this.mtBodyNode.replaceChildren();if(o.filter((t=>{const a="public"===t.visibility||!e&&"unlisted"===t.visibility,o=i&&t.reblog,r=s&&t.in_reply_to_id,l=t.language||(t.reblog?t.reblog.language:null);return a&&!o&&!r&&(""===n||l===n)})).forEach(((t,e)=>{e${o?.length||0} posts have been fetched from the server
This may be due to an incorrect configuration with the parameters or with the filters applied (to hide certains type of posts)`;this.#o(t,"📭")}}#g(){"0"!==this.mtSettings.txtMaxLines&&0!==this.mtSettings.txtMaxLines.length&&this.mtBodyNode.parentNode.style.setProperty("--mt-txt-max-lines",this.mtSettings.txtMaxLines),"0"!==this.mtSettings.previewMaxLines&&0!==this.mtSettings.previewMaxLines.length&&this.mtBodyNode.parentNode.style.setProperty("--mt-preview-max-lines",this.mtSettings.previewMaxLines)}#u(t){const e=this.mtBodyNode.getElementsByTagName("article");for(let i=0;i
'+this.#f(h)+' avatar
'+(i?'
'+this.#f(t.account.username)+' avatar
':"")+"
",u='
'+(!this.mtSettings.hideEmojos&&c?this.#S(c,p):c||h)+""+(this.mtSettings.hideUserAccount?"":'
")+"
",v=this.#x(n),w='
'+(t.pinned?'':"")+'"+(t.edited_at?" *":"")+"
",b="0"!==this.mtSettings.txtMaxLines?" truncate":"";let f="";const S=s.spoiler_text?s.spoiler_text:s.content;S&&(f='
'+this.#y(S)+"
");const x=[...t.media_attachments,...t.reblog?.media_attachments||[]].map((t=>this.#L(t,s.sensitive))).join("");return'
'+g+u+w+"
"+f+(x?`
${x}
`:"")+(!this.mtSettings.hidePreviewLink&&t.card?this.#T(t.card):"")+(t.poll?'
    '+t.poll.options.map((function(t){return"
  • "+t.title+"
  • "})).join("")+"
":"")+(this.mtSettings.hideCounterBar?"":'
'+this.#N("replies",o)+this.#N("reblog",r)+this.#N("favorites",l)+"
")+"
"}#N(t,e){return`
${{replies:'',reblog:'',favorites:''}[t]}${e}
`}#M(t,e){function i(t,e){let i=e.replace(/\s+/g,"").toLowerCase();return!(!["src","href","xlink:href"].includes(t)||!i.includes("javascript:")&&!i.includes("data:"))||(!!t.startsWith("on")||void 0)}function s(t){let e=t.attributes;for(let{name:s,value:a}of e)i(s,a)&&t.removeAttribute(s)}let a=(new DOMParser).parseFromString(t,"text/html").body||document.createElement("body");return function(t){let e=t.querySelectorAll("script");for(let t of e)t.remove()}(a),function t(e){let i=e.children;for(let e of i)s(e),t(e)}(a),e?a.childNodes:a.innerHTML}#y(t){let e=t;return e=this.#M(e,!1),e=this.#C(e),this.mtSettings.hideEmojos||(e=this.#S(e,this.fetchedData.emojos)),this.mtSettings.markdownBlockquote&&(e=this.#P(e,"

>","

","

","

")),e}#C(t){let e=t.replaceAll('rel="tag"','rel="tag" target="_blank"');return e=e.replaceAll('class="u-url mention"','class="u-url mention" target="_blank"'),e}#P(t,e,i,s,a){if(t.includes(e)){const n=new RegExp(e+"(.*?)"+i,"gi");return t.replace(n,s+"$1"+a)}return t}#f(t){return(t??"").replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}#S(t,e){if(t.includes(":")){for(const i of e){const e=new RegExp(`\\:${i.shortcode}\\:`,"g");t=t.replace(e,`Emoji ${i.shortcode}`)}return t}return t}#x(t){const e=new Date(t);return new Intl.DateTimeFormat(this.mtSettings.dateFormatLocale,this.mtSettings.dateFormatOptions).format(e)}#L(t,e=!1){const i=t.type,s=e;let a="";const n='";return"image"===i&&(a='
'+(s?n:"")+''+(t.description?this.#f(t.description):
'),"audio"===i&&(a=t.preview_url?'
'+(s?n:"")+''+(t.description?this.#f(t.description):
':'
'+(s?n:"")+'
'),"video"!==i&&"gifv"!==i||(a=this.mtSettings.hideVideoPreview?'
'+(s?n:"")+'
':'
'+(s?n:"")+''+(t.description?this.#f(t.description):
'),a}#k(t,e){let i=document.createElement("dialog");i.id=t,i.classList.add("mt-dialog"),i.dataset.theme=this.mtContainerNode.getAttribute("data-theme"),i.innerHTML=e,document.body.prepend(i),i.showModal(),i.addEventListener("close",(()=>{document.body.removeChild(i)}))}#E(t){const e=Array.from(t.target.parentNode.parentNode.children).filter((t=>!t.classList.contains("mt-post-media-spoiler"))),i=e.indexOf(t.target.parentNode)+1;let s=[];e.forEach(((t,e)=>{let i="";i="gifv"===t.getAttribute("data-media-type")||"video"===t.getAttribute("data-media-type")?`\n \n `:`\n ${t.getAttribute(\n `;const a=`\n \n `;s.push(a)}));const a=`\n \n\n \n\n \n\n \n `;this.#k("mt-carousel",a),s.length>=2&&this.#$(e.length,i)}#$(t,e){let i=e;const s=document.getElementById("mt-carousel-scroll");let a=0,n=!1;const o=document.getElementById("mt-carousel-prev"),r=document.getElementById("mt-carousel-next"),l=(t,e="smooth")=>{document.getElementById("mt-carousel-"+t).scrollIntoView({behavior:e})};l(i,"instant");const d=()=>{clearTimeout(a),a=setTimeout((()=>{n&&(i=(()=>{const t=(s.scrollLeft+s.clientWidth)/s.clientWidth;return Math.round(t+Number.EPSILON)})(),m()),n=!0}),60)};s.addEventListener("scroll",d);const m=()=>{o.hidden=1===i,r.hidden=i===t},h=e=>{const s=e.target.closest("button")?.id;"mt-carousel-next"===s?(n=!1,++i,i>t&&(i=t),l(i),m()):"mt-carousel-prev"===s&&(n=!1,--i,i<1&&(i=1),l(i),m()),"mt-carousel-close"===s&&p()};document.addEventListener("click",h);const c=t=>{"Escape"!==t.key&&27!==t.keyCode||p()};document.addEventListener("keydown",c);const p=()=>{s.removeEventListener("scroll",d),document.removeEventListener("click",h),document.removeEventListener("keydown",c)}}#B(t){const e=t.target.closest("[data-media-type]"),i=e.dataset.mediaUrlHd;e.replaceChildren(),e.innerHTML=``}#H(t){const e=t.target,i=e.nextSibling;e.textContent==this.mtSettings.btnShowMore?(i.classList.remove("spoiler-txt-hidden"),i.classList.add("spoiler-txt-visible"),e.setAttribute("aria-expanded","true"),e.textContent=this.mtSettings.btnShowLess):(i.classList.remove("spoiler-txt-visible"),i.classList.add("spoiler-txt-hidden"),e.setAttribute("aria-expanded","false"),e.textContent=this.mtSettings.btnShowMore)}#A(t){const e=t.target;e.classList.contains("mt-btn-spoiler-media-show")?e.parentNode.classList.remove("mt-post-media-spoiler"):e.parentNode.classList.add("mt-post-media-spoiler")}#T(t){let e="";if("0"!==this.mtSettings.previewMaxLines&&t.description){e=''+this.#_(t.description)+""}return''+(t.image?'
'+this.#f(t.image_description)+'
':'
📄
')+'
'+(t.provider_name?''+this.#_(t.provider_name)+"":"")+''+t.title+""+e+(t.author_name?''+this.#_(t.author_name)+"":"")+"
"}#_(t){return(new DOMParser).parseFromString(t,"text/html").body.textContent}#w(){let t="",e="";if(this.mtSettings.btnSeeMore){let e="";"profile"===this.mtSettings.timelineType?this.mtSettings.profileName?e=this.mtSettings.profileName:this.#o("Please check your profileName value","⚠️"):"hashtag"===this.mtSettings.timelineType?e="tags/"+this.mtSettings.hashtagName:"local"===this.mtSettings.timelineType&&(e="public/local"),t=`\n \n ${this.mtSettings.btnSeeMore}\n `}if(this.mtSettings.btnReload&&(e=`\n `),this.mtBodyNode.parentNode.insertAdjacentHTML("beforeend",'"),this.mtSettings.btnReload){this.mtContainerNode.getElementsByClassName("btn-refresh")[0].addEventListener("click",(()=>{this.mtUpdate()}))}}#v(){this.mtBodyNode.addEventListener("click",(t=>{const e=t.target,i=e.localName,s=e.parentNode;("article"==i||"article"==e.offsetParent?.localName||this.mtSettings.disableCarousel&&"image"===s.getAttribute("data-media-type"))&&this.#D(t),e.classList.contains("mt-btn-spoiler-txt")&&this.#H(t),e.classList.contains("mt-btn-spoiler-media")&&this.#A(t),this.mtSettings.disableCarousel||"img"!=i||"image"!==s.getAttribute("data-media-type")&&"audio"!==s.getAttribute("data-media-type")||this.#E(t),("mt-btn-play"==e.className||"svg"==i&&"mt-btn-play"==s.className||"path"==i&&"mt-btn-play"==s.parentNode.className||"img"==i&&("video"===s.getAttribute("data-media-type")||"gifv"===s.getAttribute("data-media-type")))&&this.#B(t)})),this.mtBodyNode.addEventListener("keydown",(t=>{const e=t.target.localName;"Enter"===t.key&&"article"==e&&this.#D(t)}))}#D(t){const e=t.target.closest(".mt-post")?.dataset.location;if(!e)return;const i=t.target.localName;if("a"===i||"span"===i||"button"===i||"bdi"===i||"time"===i)return;const s=t.target.className;if("mt-post-media-spoiler"===s||"mt-post-preview-noImage"===s)return;const a=t.target.parentNode?.className;"mt-post-avatar-image-big"!==a&&"mt-post-avatar-image-small"!==a&&"mt-post-header-user-name"!==a&&"mt-post-preview-image"!==a&&"mt-post-preview"!==a&&window.open(e,"_blank","noopener")}#p(){const t=e=>{e.target.parentNode.classList.remove(this.mtSettings.spinnerClass),e.target.removeEventListener("load",t),e.target.removeEventListener("error",t)};this.mtBodyNode.querySelectorAll(`.${this.mtSettings.spinnerClass} > img`).forEach((e=>{e.addEventListener("load",t),e.addEventListener("error",t)}))}#o(t,e){const i=e||"❌";throw this.mtBodyNode.innerHTML=`\n
\n ${i}\n Oops, something's happened:\n
${t}
\n
`,this.mtBodyNode.setAttribute("role","none"),new Error("Stopping the script due to an error building the timeline.")}}export{t as Init}; +class t{constructor(t={}){this.defaultSettings={mtContainerId:"mt-container",instanceUrl:"https://mastodon.social",timelineType:"local",userId:"",profileName:"",hashtagName:"",spinnerClass:"mt-loading-spinner",defaultTheme:"auto",maxNbPostFetch:"20",maxNbPostShow:"20",dateFormatLocale:"en-GB",dateFormatOptions:{day:"2-digit",month:"short",year:"numeric"},hideUnlisted:!1,hideReblog:!1,hideReplies:!1,hidePinnedPosts:!1,hideUserAccount:!1,txtMaxLines:"",filterByLanguage:"",btnShowMore:"SHOW MORE",btnShowLess:"SHOW LESS",markdownBlockquote:!1,hideEmojos:!1,btnShowContent:"SHOW CONTENT",hideVideoPreview:!1,btnPlayVideoTxt:"Load and play video",hidePreviewLink:!1,previewMaxLines:"",hideCounterBar:!1,disableCarousel:!1,carouselCloseTxt:"Close carousel",carouselPrevTxt:"Previous media item",carouselNextTxt:"Next media item",btnSeeMore:"See more posts at Mastodon",btnReload:"Refresh",insistSearchContainer:!1,insistSearchContainerTime:"3000"},this.mtSettings={...this.defaultSettings,...t},this.#t(),this.linkHeader={},this.mtContainerNode="",this.mtBodyNode="",this.fetchedData={},this.#e((()=>{this.#i()}))}#t(){Number(this.mtSettings.maxNbPostShow)>Number(this.mtSettings.maxNbPostFetch)&&(console.error(`Please check your settings! The maximum number of posts to show is bigger than the maximum number of posts to fetch. Changing the value of "maxNbPostFetch" to: ${this.mtSettings.maxNbPostShow}`),this.mtSettings.maxNbPostFetch=this.mtSettings.maxNbPostShow)}#e(t){"undefined"!=typeof document&&"complete"===document.readyState?t():"undefined"!=typeof document&&"complete"!==document.readyState&&document.addEventListener("DOMContentLoaded",t())}#i(){const t=()=>{this.mtContainerNode=document.getElementById(this.mtSettings.mtContainerId),this.mtBodyNode=this.mtContainerNode.getElementsByClassName("mt-body")[0],this.#s(),this.#a("newTimeline")};if(this.mtSettings.insistSearchContainer){const e=performance.now(),i=()=>{if(document.getElementById(this.mtSettings.mtContainerId))t();else{performance.now()-e container with id: "${this.mtSettings.mtContainerId}" after several attempts for ${this.mtSettings.insistSearchContainerTime/1e3} seconds`)}};i()}else document.getElementById(this.mtSettings.mtContainerId)?t():console.error(`Impossible to find the
container with id: "${this.mtSettings.mtContainerId}". Please try to add the option 'insistSearchContainer: true' when initializing the script`)}mtUpdate(){this.#e((()=>{this.mtBodyNode.replaceChildren(),this.mtBodyNode.insertAdjacentHTML("afterbegin",'
'),this.#a("updateTimeline")}))}mtColorTheme(t){this.#e((()=>{this.mtContainerNode.setAttribute("data-theme",t)}))}#s(){if("auto"===this.mtSettings.defaultTheme){let t=window.matchMedia("(prefers-color-scheme: dark)");t.matches?this.mtColorTheme("dark"):this.mtColorTheme("light"),t.addEventListener("change",(t=>{t.matches?this.mtColorTheme("dark"):this.mtColorTheme("light")}))}else this.mtColorTheme(this.mtSettings.defaultTheme)}#o(){return new Promise(((t,e)=>{const i=this.mtSettings.instanceUrl?`${this.mtSettings.instanceUrl}/api/v1/`:this.#n("Please check your instanceUrl value","⚠️"),s=this.#r(i),a=Object.entries(s).map((([t,i])=>{const s="timeline"===t;return this.#l(i,s).then((e=>({[t]:e}))).catch((s=>(e(new Error(`Something went wrong fetching data from: ${i}`)),this.#n(s.message),{[t]:[]})))}));Promise.all(a).then((async e=>{if(this.fetchedData=e.reduce(((t,e)=>({...t,...e})),{}),!this.mtSettings.hidePinnedPosts&&void 0!==this.fetchedData.pinned?.length&&0!==this.fetchedData.pinned.length){const t=this.fetchedData.pinned.map((t=>({...t,pinned:!0})));this.fetchedData.timeline=[...t,...this.fetchedData.timeline]}if(this.#d())t();else{do{await this.#m()}while(!this.#d()&&this.linkHeader.next);t()}}))}))}#r(t){const{timelineType:e,userId:i,hashtagName:s,maxNbPostFetch:a,hidePinnedPosts:o,hideEmojos:n}=this.mtSettings,r={};switch(e){case"profile":if(!i){this.#n("Please check your userId value","⚠️");break}r.timeline=`${t}accounts/${i}/statuses?limit=${a}`,o||(r.pinned=`${t}accounts/${i}/statuses?pinned=true`);break;case"hashtag":if(!s){this.#n("Please check your hashtagName value","⚠️");break}r.timeline=`${t}timelines/tag/${s}?limit=${a}`;break;case"local":r.timeline=`${t}timelines/public?local=true&limit=${a}`;break;default:this.#n("Please check your timelineType value","⚠️")}return n||(r.emojos=`${t}custom_emojis`),r}async#l(t,e=!1){const i=await fetch(t);if(!i.ok)throw new Error(`\n Failed to fetch the following Url:
${t}
Error status: ${i.status}
Error message: ${i.statusText}\n `);const s=await i.json();return e&&i.headers.get("Link")&&(this.linkHeader=this.#h(i.headers.get("Link"))),s}#d(){return this.fetchedData.timeline.length>=Number(this.mtSettings.maxNbPostFetch)}#m(){return new Promise((t=>{this.linkHeader.next?this.#l(this.linkHeader.next,!0).then((e=>{this.fetchedData.timeline=[...this.fetchedData.timeline,...e],t()})):t()}))}#h(t){const e=t.split(", ").map((t=>t.split("; "))).map((t=>[t[1].replace(/"/g,"").replace("rel=",""),t[0].slice(1,-1)]));return Object.fromEntries(e)}async#a(t){await this.#o();const{hideUnlisted:e,hideReblog:i,hideReplies:s,maxNbPostShow:a,filterByLanguage:o}=this.mtSettings,n=this.fetchedData.timeline;this.mtBodyNode.replaceChildren();if(n.filter((t=>{const a="public"===t.visibility||!e&&"unlisted"===t.visibility,n=i&&t.reblog,r=s&&t.in_reply_to_id,l=t.language||(t.reblog?t.reblog.language:null);return a&&!n&&!r&&(""===o||l===o)})).forEach(((t,e)=>{e${n?.length||0} posts have been fetched from the server
This may be due to an incorrect configuration with the parameters or with the filters applied (to hide certains type of posts)`;this.#n(t,"📭")}}#g(){"0"!==this.mtSettings.txtMaxLines&&0!==this.mtSettings.txtMaxLines.length&&this.mtBodyNode.parentNode.style.setProperty("--mt-txt-max-lines",this.mtSettings.txtMaxLines),"0"!==this.mtSettings.previewMaxLines&&0!==this.mtSettings.previewMaxLines.length&&this.mtBodyNode.parentNode.style.setProperty("--mt-preview-max-lines",this.mtSettings.previewMaxLines)}#u(t){const e=this.mtBodyNode.getElementsByTagName("article");for(let i=0;i
'+this.#f(h)+' avatar
'+(i?'
'+this.#f(t.account.username)+' avatar
':"")+"
",u='
'+(!this.mtSettings.hideEmojos&&c?this.#x(c,p):c||h)+""+(this.mtSettings.hideUserAccount?"":'
")+"
",v=this.#y(o),b='
'+(t.pinned?'':"")+'"+(t.edited_at?" *":"")+"
",w="0"!==this.mtSettings.txtMaxLines&&this.mtSettings.txtMaxLines.length?" truncate":"";let f="";const x=s.spoiler_text?s.spoiler_text:s.content,y='
'+this.#S(s.content)+"
";x&&(f='
'+this.#S(x)+(s.spoiler_text?y:"")+"
");const S=[...t.media_attachments,...t.reblog?.media_attachments||[]].map((t=>this.#L(t,s.sensitive))).join("");return'
'+g+u+b+"
"+f+(S?`
${S}
`:"")+(this.mtSettings.hidePreviewLink||!t.card&&!t.reblog?.card?"":this.#T(i?t.reblog.card:t.card))+(t.poll?'
    '+t.poll.options.map((function(t){return"
  • "+t.title+"
  • "})).join("")+"
":"")+(this.mtSettings.hideCounterBar?"":'
'+this.#N("replies",n)+this.#N("reblog",r)+this.#N("favorites",l)+"
")+"
"}#N(t,e){return`
${{replies:'',reblog:'',favorites:''}[t]}${e}
`}#M(t,e){function i(t,e){let i=e.replace(/\s+/g,"").toLowerCase();return!(!["src","href","xlink:href"].includes(t)||!i.includes("javascript:")&&!i.includes("data:"))||(!!t.startsWith("on")||void 0)}function s(t){let e=t.attributes;for(let{name:s,value:a}of e)i(s,a)&&t.removeAttribute(s)}let a=(new DOMParser).parseFromString(t,"text/html").body||document.createElement("body");return function(t){let e=t.querySelectorAll("script");for(let t of e)t.remove()}(a),function t(e){let i=e.children;for(let e of i)s(e),t(e)}(a),e?a.childNodes:a.innerHTML}#S(t){let e=t;return e=this.#M(e,!1),e=this.#C(e),this.mtSettings.hideEmojos||(e=this.#x(e,this.fetchedData.emojos)),this.mtSettings.markdownBlockquote&&(e=this.#k(e,"

>","

","

","

")),e}#C(t){let e=t.replaceAll('rel="tag"','rel="tag" target="_blank"');return e=e.replaceAll('class="u-url mention"','class="u-url mention" target="_blank"'),e}#k(t,e,i,s,a){if(t.includes(e)){const o=new RegExp(e+"(.*?)"+i,"gi");return t.replace(o,s+"$1"+a)}return t}#f(t){return(t??"").replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}#x(t,e){if(t.includes(":")){for(const i of e){const e=new RegExp(`\\:${i.shortcode}\\:`,"g");t=t.replace(e,`Emoji ${i.shortcode}`)}return t}return t}#y(t){const e=new Date(t);return new Intl.DateTimeFormat(this.mtSettings.dateFormatLocale,this.mtSettings.dateFormatOptions).format(e)}#L(t,e=!1){const{type:i,url:s,preview_url:a,description:o,meta:n}=t,{original:r,small:l}=n,{spinnerClass:d,btnShowContent:m,btnPlayVideoTxt:h,hideVideoPreview:c}=this.mtSettings,p='",g=' class="mt-post-media '+(e?"mt-post-media-spoiler ":"")+(d||"")+'" data-media-type="'+i+'" data-media-url-hd="'+s+'"'+(o?' data-media-alt-txt="'+this.#f(o)+'"':"")+' data-media-width-hd="'+r.width+'" data-media-height-hd="'+r.height+'" style="padding-top: calc(100%/'+l?.aspect+')">';return"image"===i?"
':"audio"===i?'
'+(e?p:"")+''+(a?''+(o?this.#f(o):':"")+"
":"video"===i||"gifv"===i?c?"':"':""}#P(t,e){let i=document.createElement("dialog");i.id=t,i.classList.add("mt-dialog"),i.dataset.theme=this.mtContainerNode.getAttribute("data-theme"),i.innerHTML=e,document.body.prepend(i),i.showModal(),i.addEventListener("close",(()=>{document.body.removeChild(i)}))}#E(t){const e=Array.from(t.target.parentNode.parentNode.children).filter((t=>!t.classList.contains("mt-post-media-spoiler"))),i=e.indexOf(t.target.parentNode)+1;let s=[];e.forEach(((t,e)=>{let i="";i="gifv"===t.getAttribute("data-media-type")||"video"===t.getAttribute("data-media-type")?`\n \n `:`\n ${t.getAttribute(\n `;const a=`\n \n `;s.push(a)}));const a=`\n \n\n \n\n \n\n \n `;this.#P("mt-carousel",a),s.length>=2&&this.#$(e.length,i)}#$(t,e){let i=e;const s=document.getElementById("mt-carousel-scroll");let a=0,o=!1;const n=document.getElementById("mt-carousel-prev"),r=document.getElementById("mt-carousel-next"),l=(t,e="smooth")=>{document.getElementById("mt-carousel-"+t).scrollIntoView({behavior:e})};l(i,"instant");const d=()=>{clearTimeout(a),a=setTimeout((()=>{o&&(i=(()=>{const t=(s.scrollLeft+s.clientWidth)/s.clientWidth;return Math.round(t+Number.EPSILON)})(),m()),o=!0}),60)};s.addEventListener("scroll",d);const m=()=>{n.hidden=1===i,r.hidden=i===t},h=e=>{const s=e.target.closest("button")?.id;"mt-carousel-next"===s?(o=!1,++i,i>t&&(i=t),l(i),m()):"mt-carousel-prev"===s&&(o=!1,--i,i<1&&(i=1),l(i),m()),"mt-carousel-close"===s&&p()};document.addEventListener("click",h);const c=t=>{"Escape"!==t.key&&27!==t.keyCode||p()};document.addEventListener("keydown",c);const p=()=>{s.removeEventListener("scroll",d),document.removeEventListener("click",h),document.removeEventListener("keydown",c)}}#B(t){const e=t.target.closest("[data-media-type]"),i=e.dataset.mediaUrlHd;e.replaceChildren(),e.innerHTML=``}#A(t){const e=t.target,i=e.nextSibling,s="true"===e.getAttribute("aria-expanded");i.classList.toggle("spoiler-txt-hidden",s),i.classList.toggle("spoiler-txt-visible",!s),e.setAttribute("aria-expanded",!s),e.textContent=s?this.mtSettings.btnShowMore:this.mtSettings.btnShowLess}#H(t){const e=t.target;e.parentNode.classList.toggle("mt-post-media-spoiler",!e.classList.contains("mt-btn-spoiler-media-show"))}#T(t){const{url:e,image:i,image_description:s,provider_name:a,title:o,description:n,author_name:r}=t,{previewMaxLines:l,spinnerClass:d}=this.mtSettings;let m="";return"0"!==l&&n&&(m=''+this.#q(n)+""),''+(i?'
'+this.#f(s)+'
':'
📄
')+'
'+(a?''+this.#q(a)+"":"")+''+o+""+m+(r?''+this.#q(r)+"":"")+"
"}#q(t){return(new DOMParser).parseFromString(t,"text/html").body.textContent}#b(){const{btnSeeMore:t,btnReload:e,timelineType:i,profileName:s,hashtagName:a,instanceUrl:o}=this.mtSettings;let n="",r="";if(t){let e="";switch(i){case"profile":s?e=s:this.#n("Please check your profileName value","⚠️");break;case"hashtag":e="tags/"+a;break;case"local":e="public/local"}n=''+t+""}if(e&&(r='"),this.mtBodyNode.parentNode.insertAdjacentHTML("beforeend",'"),e){const t=this.mtContainerNode.querySelector(".btn-refresh");t&&t.addEventListener("click",(()=>this.mtUpdate()))}}#v(){this.mtBodyNode.addEventListener("click",(t=>{const e=t.target,i=e.localName,s=e.parentNode;("article"==i||"article"==e.offsetParent?.localName||this.mtSettings.disableCarousel&&"image"===s.getAttribute("data-media-type"))&&this.#D(t),e.classList.contains("mt-btn-spoiler-txt")&&this.#A(t),e.classList.contains("mt-btn-spoiler-media")&&this.#H(t),this.mtSettings.disableCarousel||"img"!=i||"image"!==s.getAttribute("data-media-type")&&"audio"!==s.getAttribute("data-media-type")||this.#E(t),("mt-btn-play"==e.className||"svg"==i&&"mt-btn-play"==s.className||"path"==i&&"mt-btn-play"==s.parentNode.className||"img"==i&&("video"===s.getAttribute("data-media-type")||"gifv"===s.getAttribute("data-media-type")))&&this.#B(t)})),this.mtBodyNode.addEventListener("keydown",(t=>{const e=t.target.localName;"Enter"===t.key&&"article"==e&&this.#D(t)}))}#D(t){const e=t.target.closest(".mt-post")?.dataset.location;if(!e)return;const i=t.target.localName;if("a"===i||"span"===i||"button"===i||"bdi"===i||"time"===i)return;const s=t.target.className;if("mt-post-media-spoiler"===s||"mt-post-preview-noImage"===s)return;const a=t.target.parentNode?.className;"mt-post-avatar-image-big"!==a&&"mt-post-avatar-image-small"!==a&&"mt-post-header-user-name"!==a&&"mt-post-preview-image"!==a&&"mt-post-preview"!==a&&window.open(e,"_blank","noopener")}#p(){const t=e=>{e.target.parentNode.classList.remove(this.mtSettings.spinnerClass),e.target.removeEventListener("load",t),e.target.removeEventListener("error",t)};this.mtBodyNode.querySelectorAll(`.${this.mtSettings.spinnerClass} > img`).forEach((e=>{e.addEventListener("load",t),e.addEventListener("error",t)}))}#n(t,e){const i=e||"❌";throw this.mtBodyNode.innerHTML=`\n
\n ${i}\n Oops, something's happened:\n
${t}
\n
`,this.mtBodyNode.setAttribute("role","none"),new Error("Stopping the script due to an error building the timeline.")}}export{t as Init}; diff --git a/dist/mastodon-timeline.min.css b/dist/mastodon-timeline.min.css index 080ede4..3007ca3 100644 --- a/dist/mastodon-timeline.min.css +++ b/dist/mastodon-timeline.min.css @@ -1 +1 @@ -.mt-container,.mt-container[data-theme=light],.mt-dialog,.mt-dialog[data-theme=light]{--mt-txt-max-lines:none;--mt-preview-max-lines:none;--mt-color-bg:#fff;--mt-color-bg-hover:#d9e1e8;--mt-color-line-gray:#c0cdd9;--mt-color-contrast-gray:#606984;--mt-color-content-txt:#000;--mt-color-link:#3a3bff;--mt-color-error-txt:#8b0000;--mt-color-btn-bg:#6364ff;--mt-color-btn-bg-hover:#563acc;--mt-color-btn-txt:#fff;--mt-color-backdrop:#00000090;--mt-color-placeholder:#60698425}.mt-container[data-theme=dark],.mt-dialog[data-theme=dark]{--mt-color-bg:#282c37;--mt-color-bg-hover:#313543;--mt-color-line-gray:#393f4f;--mt-color-contrast-gray:#606984;--mt-color-content-txt:#fff;--mt-color-link:#8c8dff;--mt-color-error-txt:#fe6c6c}.mt-container button,.mt-dialog button{font:inherit}.mt-container a,.mt-container button,.mt-dialog button{cursor:pointer}.mt-container{display:flex;flex-direction:column;height:100%;overflow-y:auto;position:relative;background-color:var(--mt-color-bg);scrollbar-color:var(--mt-color-contrast-gray) var(--mt-color-bg);scrollbar-width:auto;container:mt-container/inline-size}.mt-container::-webkit-scrollbar{width:.25rem;height:.25rem}.mt-container::-webkit-scrollbar-thumb{background-color:var(--mt-color-contrast-gray);border:none;border-radius:3rem}.mt-container::-webkit-scrollbar-thumb:active,.mt-container::-webkit-scrollbar-thumb:hover{background-color:var(--mt-color-contrast-gray)}.mt-container::-webkit-scrollbar-track{background-color:var(--mt-color-bg);border:none;border-radius:0}.mt-container::-webkit-scrollbar-corner,.mt-container::-webkit-scrollbar-track:active,.mt-container::-webkit-scrollbar-track:hover{background-color:var(--mt-color-bg)}.mt-container a,.mt-container a:active,.mt-container a:link{text-decoration:none;color:var(--mt-color-link)}.mt-container a:not(.mt-post-preview):hover{text-decoration:underline}.mt-body{padding:1rem;white-space:pre-wrap;word-wrap:break-word;margin-bottom:1rem}.mt-body .invisible{font-size:0;line-height:0;display:inline-block;width:0;height:0;position:absolute}.mt-post{margin:.25rem;padding:1rem .5rem;position:relative;min-height:3.75rem;background-color:transparent;border-bottom:1px solid var(--mt-color-line-gray)}.mt-post:focus,.mt-post:hover{cursor:pointer;background-color:var(--mt-color-bg-hover)}.mt-post p:last-child{margin-bottom:0}.mt-post-avatar{margin-right:.75rem}.mt-post-avatar-standard{width:2.25rem;height:2.25rem}.mt-post-avatar-boosted{width:3rem;height:3rem;position:relative}.mt-post-avatar-image-big img{aspect-ratio:1/1;width:2.25rem;height:2.25rem;border-radius:.25rem;overflow:hidden}.mt-post-avatar-image-small img{aspect-ratio:1/1;width:1.5rem;height:1.5rem;top:1.5rem;left:1.5rem;position:absolute;border-radius:.25rem;overflow:hidden}.mt-post-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:1rem}.mt-post-header-user{overflow:hidden;padding-right:.75rem}.mt-post-header-user .mt-custom-emoji{height:1rem;min-width:1rem;width:auto}.mt-post-header-user>a{color:var(--mt-color-content-txt)!important;overflow-wrap:anywhere}.mt-container .mt-post-header-user>a:hover{text-decoration:none}.mt-post-header-user-name{font-weight:600}.mt-container .mt-post-header-user:hover .mt-post-header-user-name{text-decoration:underline}.mt-post-header-user-account{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--mt-color-contrast-gray)}.mt-post-header-date{display:flex;font-size:.75rem;text-align:right;margin-left:auto}.mt-post-header-date .mt-post-pinned{width:1.25rem;margin-top:-.25rem;fill:var(--mt-color-contrast-gray)}.mt-container .mt-post-header-date>a{white-space:nowrap;color:var(--mt-color-contrast-gray)!important}.mt-post-txt{margin-bottom:1rem;color:var(--mt-color-content-txt)}.mt-post-txt .spoiler-txt-hidden{display:none}.mt-post-txt.truncate{display:-webkit-box;overflow:hidden;-webkit-line-clamp:var(--mt-txt-max-lines);-webkit-box-orient:vertical}.mt-post-txt:not(.truncate) .ellipsis::after{content:"..."}.mt-post-txt blockquote{border-left:.25rem solid var(--mt-color-line-gray);margin-left:0;padding-left:.5rem}.mt-post-txt .mt-custom-emoji{height:1.5rem;min-width:1.5rem;margin-bottom:-.25rem;width:auto}.mt-post-poll{margin-bottom:1rem;color:var(--mt-color-content-txt)}.mt-post-poll ul{list-style:none;padding:0;margin:0}.mt-post-poll ul li{font-size:.9rem;margin-bottom:.5rem}.mt-post-poll.mt-post-poll-expired ul li{color:var(--mt-color-contrast-gray)}.mt-post-poll ul li:not(:last-child){margin-bottom:.25rem}.mt-post-poll ul li:before{content:"◯";padding-right:.5rem}.mt-post-poll.mt-post-poll-expired ul li:before{content:"";padding-right:0}.mt-post-media-wrapper{display:grid;grid-template-columns:repeat(2,1fr);gap:.5rem;margin-bottom:1rem}.mt-post-media{position:relative;overflow:hidden;width:100%}.mt-post-media-wrapper:has(> :last-child:nth-child(odd)) .mt-post-media:not(:only-child):first-child{grid-column:1/3}.mt-post-media:only-child{grid-column:1/3}.mt-post-media-spoiler>.mt-btn-play,.mt-post-media-spoiler>audio,.mt-post-media-spoiler>img,.mt-post-media-spoiler>video{filter:blur(2rem);pointer-events:none}.mt-post-media,.mt-post-media-spoiler>audio,.mt-post-media-spoiler>img,.mt-post-media>img,.mt-post-media>video{border-radius:.5rem}.mt-post-media>audio{width:100%;position:relative;z-index:1}.mt-post-media>img,.mt-post-media>video{width:100%;height:100%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);object-fit:cover;text-align:center;color:var(--mt-color-content-txt);background-color:var(--mt-color-placeholder)}body:has(dialog.mt-dialog[open]){overflow:hidden}.mt-dialog{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:100%;border:none;color:var(--mt-color-content-txt);background-color:transparent;padding:0;margin:1rem;overflow:hidden}.mt-dialog::backdrop{background-color:var(--mt-color-backdrop);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.mt-carousel-header{position:absolute;top:0;right:0;z-index:2}.mt-carousel-body{width:100%;height:100%}.mt-carousel-scroll{display:flex;width:100%;height:100%;margin:0;padding:0;list-style:none;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:none}.mt-carousel-scroll::-webkit-scrollbar{display:none;-webkit-appearance:none}.mt-carousel-item{scroll-snap-align:center;width:100%;height:100%}.mt-carousel-media-wrapper{width:calc(100vw - 2.5rem);height:100%;display:flex;align-items:center;justify-content:center;text-align:center}.mt-carousel-media{width:100%;height:100%;object-fit:contain;padding:2rem}.mt-carousel-next,.mt-carousel-prev{position:absolute;background-color:transparent;border:none;padding:.5rem;z-index:2}.mt-carousel-prev{left:0;padding-left:0}.mt-carousel-next{right:0;padding-right:0}.mt-post-preview{min-height:4rem;display:flex;flex-direction:row;border:1px solid var(--mt-color-line-gray);border-radius:.5rem;color:var(--mt-color-link);font-size:.8rem;margin:1rem 0;overflow:hidden}.mt-post-preview-image{width:40%;align-self:stretch}.mt-post-preview-image img{display:block;width:100%;height:100%;object-fit:cover;color:var(--mt-color-content-txt)}.mt-post-preview-noImage{width:40%;font-size:1.5rem;align-self:center;text-align:center}.mt-post-preview-content{width:60%;display:flex;align-self:center;flex-direction:column;padding:.5rem 1rem;gap:.5rem}.mt-post-preview-content:has(.mt-post-preview-description.truncate){align-self:unset}.mt-post-preview-description{display:block;color:var(--mt-color-contrast-gray)}.mt-post-preview-description.truncate{display:-webkit-box;overflow:hidden;-webkit-line-clamp:var(--mt-preview-max-lines);-webkit-box-orient:vertical}.mt-post-preview-description:not(.truncate) .ellipsis::after{content:"..."}.mt-post-preview-title{font-weight:600}.mt-post-counter-bar{display:flex;min-width:6rem;max-width:40rem;justify-content:space-between;color:var(--mt-color-contrast-gray)}.mt-post-counter-bar-favorites,.mt-post-counter-bar-reblog,.mt-post-counter-bar-replies{display:flex;font-size:.75rem;gap:.25rem;align-items:center;opacity:.5;cursor:default}.mt-post-counter-bar-favorites>svg,.mt-post-counter-bar-reblog>svg,.mt-post-counter-bar-replies>svg{width:1rem;fill:var(--mt-color-contrast-gray)}.mt-btn-play{display:flex;position:absolute;width:3rem;height:3rem;top:calc(50% - 1.5rem);left:calc(50% - 1.5rem);justify-content:center;align-items:center;background-color:transparent;border:none;cursor:pointer}.mt-btn-play>svg{width:2.5rem;height:2.5rem;fill:var(--mt-color-bg);stroke:var(--mt-color-content-txt);stroke-width:1px}.mt-post-media.mt-loading-spinner .mt-btn-play{display:none}.mt-container .mt-btn-dark,.mt-dialog .mt-btn-dark{display:flex;border-radius:.25rem;background-color:var(--mt-color-line-gray);border:0;color:var(--mt-color-content-txt);font-weight:600;font-size:.75rem;text-align:center;padding:.25rem .5rem;line-height:1.25rem;vertical-align:top}.mt-dialog .mt-btn-dark{margin-left:auto}.mt-container .mt-btn-violet,.mt-container a.mt-btn-violet,.mt-dialog .mt-btn-violet,.mt-dialog a.mt-btn-violet{display:flex;align-items:center;gap:.5rem;border-radius:.25rem;border:.5rem;padding:.5rem .75rem;font-size:1rem;font-weight:600;text-align:center;background-color:var(--mt-color-btn-bg);color:var(--mt-color-btn-txt)}.mt-container .mt-btn-violet:hover,.mt-container a.mt-btn-violet:hover,.mt-dialog .mt-btn-violet:hover,.mt-dialog a.mt-btn-violet:hover{background-color:var(--mt-color-btn-bg-hover);text-decoration:none}.mt-post-txt .mt-btn-spoiler-txt{display:inline-block;vertical-align:middle}.mt-post-media.mt-loading-spinner>.mt-btn-spoiler-media{display:none}.mt-post-media>.mt-btn-spoiler-media-show{position:absolute;top:50%;left:50%;z-index:2;transform:translate(-50%,-50%)}.mt-post-media.mt-post-media-spoiler>.mt-btn-spoiler-media-hide,.mt-post-media:not([data-media-width-hd])>.mt-btn-spoiler-media-hide{display:none}.mt-post-media:not(.mt-post-media-spoiler)>.mt-btn-spoiler-media-show{display:none}.mt-post-media>.mt-btn-spoiler-media-hide{position:absolute;top:.5rem;left:.5rem;z-index:2}.mt-post-media>.mt-btn-spoiler-media-hide>svg{fill:var(--mt-color-content-txt);pointer-events:none}.mt-error{position:absolute;left:50%;transform:translateX(-50%);display:flex;flex-direction:column;height:calc(100% - 3.5rem);width:calc(100% - 4.5rem);justify-content:center;align-items:center;color:var(--mt-color-error-txt);padding:.75rem;text-align:center}.mt-error-icon{font-size:2rem;margin-bottom:1rem}.mt-error-message{width:100%;padding:1rem 0}.mt-error-message hr{color:var(--mt-color-line-gray)}.mt-body>.mt-loading-spinner{position:absolute;width:3rem;height:3rem;margin:auto;top:calc(50% - 1.5rem);right:calc(50% - 1.5rem)}.mt-loading-spinner{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Cg%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'/%3E%3Cpath d='M64 6.69a57.3 57.3 0 1 1 0 114.61A57.3 57.3 0 0 1 6.69 64' fill='none' stroke='%23404040' stroke-width='12'/%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% - .5rem))}.mt-footer{display:flex;flex-flow:wrap;margin:auto auto 2rem auto;padding:0 1rem;gap:1.5rem;align-items:center;justify-content:center}.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}@supports (container-type:inline-size){@container mt-container (max-width:20rem){.mt-body{padding:0 .5rem}.mt-container .mt-post-header-date>a{white-space:normal}.mt-post-media-wrapper .mt-post-media{grid-column:1/3}}}@supports not (container-type:inline-size){@media screen and (max-width:clamp(20rem,40rem,60rem)){.mt-body{padding:0 .5rem}.mt-container .mt-post-header-date>a{white-space:normal}.mt-post-media-wrapper .mt-post-media{grid-column:1/3}}} \ No newline at end of file +.mt-container,.mt-container[data-theme=light],.mt-dialog,.mt-dialog[data-theme=light]{--mt-txt-max-lines:none;--mt-preview-max-lines:none;--mt-color-bg:#fff;--mt-color-bg-hover:#e9eef1;--mt-color-line-gray:#c0cdd9;--mt-color-contrast-gray:#606984;--mt-color-content-txt:#000;--mt-color-hashtag:#d7e1e9;--mt-color-link:#3a3bff;--mt-color-error-txt:#8b0000;--mt-color-btn-bg:#6364ff;--mt-color-btn-bg-hover:#563acc;--mt-color-btn-txt:#fff;--mt-color-backdrop:#00000090;--mt-color-placeholder:#60698425}.mt-container[data-theme=dark],.mt-dialog[data-theme=dark]{--mt-color-bg:#181821;--mt-color-bg-hover:#21232c;--mt-color-line-gray:#393f4f;--mt-color-contrast-gray:#606984;--mt-color-content-txt:#fff;--mt-color-hashtag:#292c38;--mt-color-link:#8c8dff;--mt-color-error-txt:#fe6c6c}.mt-container button,.mt-dialog button{font:inherit}.mt-container a,.mt-container button,.mt-dialog button{cursor:pointer}.mt-container{display:flex;flex-direction:column;height:100%;overflow-y:auto;position:relative;background-color:var(--mt-color-bg);scrollbar-color:var(--mt-color-contrast-gray) var(--mt-color-bg);scrollbar-width:auto;container:mt-container/inline-size}.mt-container::-webkit-scrollbar{width:.25rem;height:.25rem}.mt-container::-webkit-scrollbar-thumb{background-color:var(--mt-color-contrast-gray);border:none;border-radius:3rem}.mt-container::-webkit-scrollbar-thumb:active,.mt-container::-webkit-scrollbar-thumb:hover{background-color:var(--mt-color-contrast-gray)}.mt-container::-webkit-scrollbar-track{background-color:var(--mt-color-bg);border:none;border-radius:0}.mt-container::-webkit-scrollbar-corner,.mt-container::-webkit-scrollbar-track:active,.mt-container::-webkit-scrollbar-track:hover{background-color:var(--mt-color-bg)}.mt-container a{text-decoration:none;color:var(--mt-color-link)}.mt-container a:not(.mt-post-preview):hover{text-decoration:underline}.mt-body{padding:1rem;white-space:pre-wrap;word-wrap:break-word;margin-bottom:1rem}.mt-body .invisible{font-size:0;line-height:0;display:inline-block;width:0;height:0;position:absolute}.mt-post{margin:.25rem;padding:1rem .5rem;position:relative;min-height:3.75rem;background-color:transparent;border-bottom:1px solid var(--mt-color-line-gray)}.mt-post:focus,.mt-post:hover{cursor:pointer;background-color:var(--mt-color-bg-hover)}.mt-container:not(:has(.mt-footer)) .mt-post:last-child{border-bottom:none}.mt-post p:last-child{margin-bottom:0}.mt-post-avatar{margin-right:.75rem}.mt-post-avatar-standard{width:2.25rem;height:2.25rem}.mt-post-avatar-boosted{width:3rem;height:3rem;position:relative}.mt-post-avatar-image-big img,.mt-post-avatar-image-small img{aspect-ratio:1/1;border-radius:.25rem;overflow:hidden}.mt-post-avatar-image-big img{width:2.25rem;height:2.25rem}.mt-post-avatar-image-small img{width:1.5rem;height:1.5rem;top:1.5rem;left:1.5rem;position:absolute}.mt-post-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:1rem}.mt-post-header-user{overflow:hidden;padding-right:.75rem}.mt-post-header-user .mt-custom-emoji{height:1rem;min-width:1rem;width:auto}.mt-container .mt-post-header-user>a{color:var(--mt-color-content-txt);overflow-wrap:anywhere}.mt-container .mt-post-header-user>a:hover{text-decoration:none}.mt-post-header-user-name{font-weight:600}.mt-container .mt-post-header-user:hover .mt-post-header-user-name{text-decoration:underline}.mt-post-header-user-account{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--mt-color-contrast-gray)}.mt-post-header-date{display:flex;font-size:.75rem;text-align:right;margin-left:auto}.mt-post-header-date .mt-post-pinned{width:1.25rem;margin-top:-.25rem;fill:var(--mt-color-contrast-gray)}.mt-container .mt-post-header-date>a{white-space:nowrap;color:var(--mt-color-contrast-gray)!important}.mt-post-txt{margin-bottom:1rem;color:var(--mt-color-content-txt)}.mt-post-txt .spoiler-txt-hidden{display:none}.mt-post-txt.truncate{display:-webkit-box;overflow:hidden;-webkit-line-clamp:var(--mt-txt-max-lines);-webkit-box-orient:vertical}.mt-post-txt:not(.truncate) .ellipsis::after{content:"..."}.mt-post-txt blockquote{border-left:.25rem solid var(--mt-color-line-gray);margin-left:0;padding-left:.5rem}.mt-post-txt .mt-custom-emoji{height:1.5rem;min-width:1.5rem;margin-bottom:-.25rem;width:auto}.mt-post-txt .mention.hashtag{display:inline-block;font-size:.8rem;border-radius:.25rem;background-color:var(--mt-color-hashtag);padding:.25rem .5rem;margin:0 .25rem .25rem 0}.mt-post-txt .mention.hashtag:only-child{margin:0}.mt-post-poll{margin-bottom:1rem;color:var(--mt-color-content-txt)}.mt-post-poll ul{list-style:none;padding:0;margin:0}.mt-post-poll ul li{font-size:.9rem;margin-bottom:.5rem}.mt-post-poll.mt-post-poll-expired ul li{color:var(--mt-color-contrast-gray)}.mt-post-poll ul li:not(:last-child){margin-bottom:.25rem}.mt-post-poll ul li:before{content:"◯";padding-right:.5rem}.mt-post-poll.mt-post-poll-expired ul li:before{content:"";padding-right:0}.mt-post-media-wrapper{display:grid;grid-template-columns:repeat(2,1fr);gap:.5rem;margin-bottom:1rem}.mt-post-media{position:relative;overflow:hidden;width:100%}.mt-post-media-wrapper:has(> :last-child:nth-child(odd)) .mt-post-media:not(:only-child):first-child{grid-column:1/3}.mt-post-media:only-child{grid-column:1/3}.mt-post-media-spoiler>.mt-btn-play,.mt-post-media-spoiler>audio,.mt-post-media-spoiler>img,.mt-post-media-spoiler>video{filter:blur(2rem);pointer-events:none}.mt-post-media,.mt-post-media-spoiler>audio,.mt-post-media-spoiler>img,.mt-post-media>img,.mt-post-media>video{border-radius:.5rem}.mt-post-media>audio{width:100%;position:relative;z-index:1}.mt-post-media>img,.mt-post-media>video{width:100%;height:100%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);object-fit:cover;text-align:center;color:var(--mt-color-content-txt);background-color:var(--mt-color-placeholder)}body:has(dialog.mt-dialog[open]){overflow:hidden}.mt-dialog{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:100%;border:none;color:var(--mt-color-content-txt);background-color:transparent;padding:0;margin:1rem;overflow:hidden}.mt-dialog::backdrop{background-color:var(--mt-color-backdrop);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.mt-carousel-header{position:absolute;top:0;right:0;z-index:2}.mt-carousel-body{width:100%;height:100%}.mt-carousel-scroll{display:flex;width:100%;height:100%;margin:0;padding:0;list-style:none;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:none}.mt-carousel-scroll::-webkit-scrollbar{display:none;-webkit-appearance:none}.mt-carousel-item{scroll-snap-align:center;width:100%;height:100%}.mt-carousel-media-wrapper{width:calc(100vw - 2.5rem);height:100%;display:flex;align-items:center;justify-content:center;text-align:center}.mt-carousel-media{width:100%;height:100%;object-fit:contain;padding:2rem}.mt-carousel-next,.mt-carousel-prev{position:absolute;background-color:transparent;border:none;padding:.5rem;z-index:2}.mt-carousel-prev{left:0;padding-left:0}.mt-carousel-next{right:0;padding-right:0}.mt-post-preview{min-height:4rem;display:flex;flex-direction:row;border:1px solid var(--mt-color-line-gray);border-radius:.5rem;color:var(--mt-color-link);font-size:.8rem;margin:1rem 0;overflow:hidden}.mt-post-preview-image{width:40%;align-self:stretch}.mt-post-preview-image img{display:block;width:100%;height:100%;object-fit:cover;color:var(--mt-color-content-txt)}.mt-post-preview-noImage{width:40%;font-size:1.5rem;align-self:center;text-align:center}.mt-post-preview-content{width:60%;display:flex;align-self:center;flex-direction:column;padding:.5rem 1rem;gap:.5rem}.mt-post-preview-content:has(.mt-post-preview-description.truncate){align-self:unset}.mt-post-preview-description{display:block;color:var(--mt-color-contrast-gray)}.mt-post-preview-description.truncate{display:-webkit-box;overflow:hidden;-webkit-line-clamp:var(--mt-preview-max-lines);-webkit-box-orient:vertical}.mt-post-preview-description:not(.truncate) .ellipsis::after{content:"..."}.mt-post-preview-title{font-weight:600}.mt-post-counter-bar{display:flex;min-width:6rem;max-width:40rem;justify-content:space-between;color:var(--mt-color-contrast-gray)}.mt-post-counter-bar-favorites,.mt-post-counter-bar-reblog,.mt-post-counter-bar-replies{display:flex;font-size:.75rem;gap:.25rem;align-items:center;opacity:.6;cursor:default}.mt-post-counter-bar-favorites>svg,.mt-post-counter-bar-reblog>svg,.mt-post-counter-bar-replies>svg{width:1rem;fill:var(--mt-color-contrast-gray)}.mt-btn-play{display:flex;position:absolute;width:3rem;height:3rem;top:calc(50% - 1.5rem);left:calc(50% - 1.5rem);justify-content:center;align-items:center;background-color:transparent;border:none;cursor:pointer}.mt-btn-play>svg{width:2.5rem;height:2.5rem;fill:var(--mt-color-bg);stroke:var(--mt-color-content-txt);stroke-width:1px}.mt-post-media.mt-loading-spinner .mt-btn-play{display:none}.mt-container .mt-btn-dark,.mt-dialog .mt-btn-dark{display:flex;border-radius:.25rem;background-color:var(--mt-color-line-gray);border:0;color:var(--mt-color-content-txt);font-weight:600;font-size:.75rem;text-align:center;padding:.25rem .5rem;line-height:1.25rem;vertical-align:top}.mt-dialog .mt-btn-dark{margin-left:auto}.mt-container .mt-btn-violet,.mt-container a.mt-btn-violet,.mt-dialog .mt-btn-violet,.mt-dialog a.mt-btn-violet{display:flex;align-items:center;gap:.5rem;border-radius:.25rem;border:.5rem;padding:.5rem .75rem;font-size:1rem;font-weight:600;text-align:center;background-color:var(--mt-color-btn-bg);color:var(--mt-color-btn-txt)}.mt-container .mt-btn-violet:hover,.mt-container a.mt-btn-violet:hover,.mt-dialog .mt-btn-violet:hover,.mt-dialog a.mt-btn-violet:hover{background-color:var(--mt-color-btn-bg-hover);text-decoration:none}.mt-post-txt .mt-btn-spoiler-txt{display:inline-block;vertical-align:middle}.mt-post-media.mt-loading-spinner>.mt-btn-spoiler-media{display:none}.mt-post-media>.mt-btn-spoiler-media-show{position:absolute;top:50%;left:50%;z-index:2;transform:translate(-50%,-50%)}.mt-post-media.mt-post-media-spoiler>.mt-btn-spoiler-media-hide,.mt-post-media:not([data-media-width-hd])>.mt-btn-spoiler-media-hide{display:none}.mt-post-media:not(.mt-post-media-spoiler)>.mt-btn-spoiler-media-show{display:none}.mt-post-media>.mt-btn-spoiler-media-hide{position:absolute;top:.5rem;left:.5rem;z-index:2}.mt-post-media>.mt-btn-spoiler-media-hide>svg{fill:var(--mt-color-content-txt);pointer-events:none}.mt-error{position:absolute;left:50%;transform:translateX(-50%);display:flex;flex-direction:column;height:calc(100% - 3.5rem);width:calc(100% - 4.5rem);justify-content:center;align-items:center;color:var(--mt-color-error-txt);padding:.75rem;text-align:center}.mt-error-icon{font-size:2rem;margin-bottom:1rem}.mt-error-message{width:100%;padding:1rem 0}.mt-error-message hr{color:var(--mt-color-line-gray)}.mt-body>.mt-loading-spinner{position:absolute;width:3rem;height:3rem;margin:auto;top:calc(50% - 1.5rem);right:calc(50% - 1.5rem)}.mt-loading-spinner{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Cg%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 64 64' to='360 64 64' dur='1000ms' repeatCount='indefinite'/%3E%3Cpath d='M64 6.69a57.3 57.3 0 1 1 0 114.61A57.3 57.3 0 0 1 6.69 64' fill='none' stroke='%23404040' stroke-width='12'/%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% - .5rem))}.mt-footer{display:flex;flex-flow:wrap;margin:auto auto 2rem auto;padding:0 1rem;gap:1.5rem;align-items:center;justify-content:center}.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}@supports (container-type:inline-size){@container mt-container (max-width:20rem){.mt-body{padding:0 .5rem}.mt-container .mt-post-header-date>a{white-space:normal}.mt-post-media-wrapper .mt-post-media{grid-column:1/3}}}@supports not (container-type:inline-size){@media screen and (max-width:clamp(20rem,40rem,60rem)){.mt-body{padding:0 .5rem}.mt-container .mt-post-header-date>a{white-space:normal}.mt-post-media-wrapper .mt-post-media{grid-column:1/3}}} \ No newline at end of file diff --git a/dist/mastodon-timeline.umd.js b/dist/mastodon-timeline.umd.js index 09b3eb9..a6aed99 100644 --- a/dist/mastodon-timeline.umd.js +++ b/dist/mastodon-timeline.umd.js @@ -2,7 +2,7 @@ /** * Mastodon embed timeline * @author idotj - * @version 4.5.1 + * @version 4.6.0 * @url https://gitlab.com/idotj/mastodon-embed-timeline * @license GNU AGPLv3 - */t.Init=class{constructor(t={}){this.defaultSettings={mtContainerId:"mt-container",instanceUrl:"https://mastodon.social",timelineType:"local",userId:"",profileName:"",hashtagName:"",spinnerClass:"mt-loading-spinner",defaultTheme:"auto",maxNbPostFetch:"20",maxNbPostShow:"20",dateFormatLocale:"en-GB",dateFormatOptions:{day:"2-digit",month:"short",year:"numeric"},hideUnlisted:!1,hideReblog:!1,hideReplies:!1,hidePinnedPosts:!1,hideUserAccount:!1,txtMaxLines:"",filterByLanguage:"",btnShowMore:"SHOW MORE",btnShowLess:"SHOW LESS",markdownBlockquote:!1,hideEmojos:!1,btnShowContent:"SHOW CONTENT",hideVideoPreview:!1,btnPlayVideoTxt:"Load and play video",hidePreviewLink:!1,previewMaxLines:"",hideCounterBar:!1,disableCarousel:!1,carouselCloseTxt:"Close carousel",carouselPrevTxt:"Previous media item",carouselNextTxt:"Next media item",btnSeeMore:"See more posts at Mastodon",btnReload:"Refresh",insistSearchContainer:!1,insistSearchContainerTime:"3000"},this.mtSettings={...this.defaultSettings,...t},this.#t(),this.linkHeader={},this.mtContainerNode="",this.mtBodyNode="",this.fetchedData={},this.#e((()=>{this.#i()}))}#t(){Number(this.mtSettings.maxNbPostShow)>Number(this.mtSettings.maxNbPostFetch)&&(console.error(`Please check your settings! The maximum number of posts to show is bigger than the maximum number of posts to fetch. Changing the value of "maxNbPostFetch" to: ${this.mtSettings.maxNbPostShow}`),this.mtSettings.maxNbPostFetch=this.mtSettings.maxNbPostShow)}#e(t){"undefined"!=typeof document&&"complete"===document.readyState?t():"undefined"!=typeof document&&"complete"!==document.readyState&&document.addEventListener("DOMContentLoaded",t())}#i(){const t=()=>{this.mtContainerNode=document.getElementById(this.mtSettings.mtContainerId),this.mtBodyNode=this.mtContainerNode.getElementsByClassName("mt-body")[0],this.#s(),this.#a("newTimeline")};if(this.mtSettings.insistSearchContainer){const e=performance.now(),i=()=>{if(document.getElementById(this.mtSettings.mtContainerId))t();else{performance.now()-e container with id: "${this.mtSettings.mtContainerId}" after several attempts for ${this.mtSettings.insistSearchContainerTime/1e3} seconds`)}};i()}else document.getElementById(this.mtSettings.mtContainerId)?t():console.error(`Impossible to find the
container with id: "${this.mtSettings.mtContainerId}". Please try to add the option 'insistSearchContainer: true' when initializing the script`)}mtUpdate(){this.#e((()=>{this.mtBodyNode.replaceChildren(),this.mtBodyNode.insertAdjacentHTML("afterbegin",'
'),this.#a("updateTimeline")}))}mtColorTheme(t){this.#e((()=>{this.mtContainerNode.setAttribute("data-theme",t)}))}#s(){if("auto"===this.mtSettings.defaultTheme){let t=window.matchMedia("(prefers-color-scheme: dark)");t.matches?this.mtColorTheme("dark"):this.mtColorTheme("light"),t.addEventListener("change",(t=>{t.matches?this.mtColorTheme("dark"):this.mtColorTheme("light")}))}else this.mtColorTheme(this.mtSettings.defaultTheme)}#n(){return new Promise(((t,e)=>{const i=this.mtSettings.instanceUrl?`${this.mtSettings.instanceUrl}/api/v1/`:this.#o("Please check your instanceUrl value","⚠️"),s=this.#r(i),a=Object.entries(s).map((([t,i])=>{const s="timeline"===t;return this.#l(i,s).then((e=>({[t]:e}))).catch((s=>(e(new Error(`Something went wrong fetching data from: ${i}`)),this.#o(s.message),{[t]:[]})))}));Promise.all(a).then((async e=>{if(this.fetchedData=e.reduce(((t,e)=>({...t,...e})),{}),!this.mtSettings.hidePinnedPosts&&void 0!==this.fetchedData.pinned?.length&&0!==this.fetchedData.pinned.length){const t=this.fetchedData.pinned.map((t=>({...t,pinned:!0})));this.fetchedData.timeline=[...t,...this.fetchedData.timeline]}if(this.#d())t();else{do{await this.#m()}while(!this.#d()&&this.linkHeader.next);t()}}))}))}#r(t){const{timelineType:e,userId:i,hashtagName:s,maxNbPostFetch:a,hidePinnedPosts:n,hideEmojos:o}=this.mtSettings,r={};switch(e){case"profile":if(!i){this.#o("Please check your userId value","⚠️");break}r.timeline=`${t}accounts/${i}/statuses?limit=${a}`,n||(r.pinned=`${t}accounts/${i}/statuses?pinned=true`);break;case"hashtag":if(!s){this.#o("Please check your hashtagName value","⚠️");break}r.timeline=`${t}timelines/tag/${s}?limit=${a}`;break;case"local":r.timeline=`${t}timelines/public?local=true&limit=${a}`;break;default:this.#o("Please check your timelineType value","⚠️")}return o||(r.emojos=`${t}custom_emojis`),r}async#l(t,e=!1){const i=await fetch(t);if(!i.ok)throw new Error(`\n Failed to fetch the following Url:
${t}
Error status: ${i.status}
Error message: ${i.statusText}\n `);const s=await i.json();return e&&i.headers.get("Link")&&(this.linkHeader=this.#h(i.headers.get("Link"))),s}#d(){return this.fetchedData.timeline.length>=Number(this.mtSettings.maxNbPostFetch)}#m(){return new Promise((t=>{this.linkHeader.next?this.#l(this.linkHeader.next,!0).then((e=>{this.fetchedData.timeline=[...this.fetchedData.timeline,...e],t()})):t()}))}#h(t){const e=t.split(", ").map((t=>t.split("; "))).map((t=>[t[1].replace(/"/g,"").replace("rel=",""),t[0].slice(1,-1)]));return Object.fromEntries(e)}async#a(t){await this.#n();const{hideUnlisted:e,hideReblog:i,hideReplies:s,maxNbPostShow:a,filterByLanguage:n}=this.mtSettings,o=this.fetchedData.timeline;this.mtBodyNode.replaceChildren();if(o.filter((t=>{const a="public"===t.visibility||!e&&"unlisted"===t.visibility,o=i&&t.reblog,r=s&&t.in_reply_to_id,l=t.language||(t.reblog?t.reblog.language:null);return a&&!o&&!r&&(""===n||l===n)})).forEach(((t,e)=>{e${o?.length||0} posts have been fetched from the server
This may be due to an incorrect configuration with the parameters or with the filters applied (to hide certains type of posts)`;this.#o(t,"📭")}}#g(){"0"!==this.mtSettings.txtMaxLines&&0!==this.mtSettings.txtMaxLines.length&&this.mtBodyNode.parentNode.style.setProperty("--mt-txt-max-lines",this.mtSettings.txtMaxLines),"0"!==this.mtSettings.previewMaxLines&&0!==this.mtSettings.previewMaxLines.length&&this.mtBodyNode.parentNode.style.setProperty("--mt-preview-max-lines",this.mtSettings.previewMaxLines)}#u(t){const e=this.mtBodyNode.getElementsByTagName("article");for(let i=0;i
'+this.#f(h)+' avatar
'+(i?'
'+this.#f(t.account.username)+' avatar
':"")+"
",u='
'+(!this.mtSettings.hideEmojos&&c?this.#x(c,p):c||h)+""+(this.mtSettings.hideUserAccount?"":'
")+"
",v=this.#S(n),b='
'+(t.pinned?'':"")+'"+(t.edited_at?" *":"")+"
",w="0"!==this.mtSettings.txtMaxLines?" truncate":"";let f="";const x=s.spoiler_text?s.spoiler_text:s.content;x&&(f='
'+this.#y(x)+"
");const S=[...t.media_attachments,...t.reblog?.media_attachments||[]].map((t=>this.#L(t,s.sensitive))).join("");return'
'+g+u+b+"
"+f+(S?`
${S}
`:"")+(!this.mtSettings.hidePreviewLink&&t.card?this.#T(t.card):"")+(t.poll?'
    '+t.poll.options.map((function(t){return"
  • "+t.title+"
  • "})).join("")+"
":"")+(this.mtSettings.hideCounterBar?"":'
'+this.#N("replies",o)+this.#N("reblog",r)+this.#N("favorites",l)+"
")+"
"}#N(t,e){return`
${{replies:'',reblog:'',favorites:''}[t]}${e}
`}#M(t,e){function i(t,e){let i=e.replace(/\s+/g,"").toLowerCase();return!(!["src","href","xlink:href"].includes(t)||!i.includes("javascript:")&&!i.includes("data:"))||(!!t.startsWith("on")||void 0)}function s(t){let e=t.attributes;for(let{name:s,value:a}of e)i(s,a)&&t.removeAttribute(s)}let a=(new DOMParser).parseFromString(t,"text/html").body||document.createElement("body");return function(t){let e=t.querySelectorAll("script");for(let t of e)t.remove()}(a),function t(e){let i=e.children;for(let e of i)s(e),t(e)}(a),e?a.childNodes:a.innerHTML}#y(t){let e=t;return e=this.#M(e,!1),e=this.#C(e),this.mtSettings.hideEmojos||(e=this.#x(e,this.fetchedData.emojos)),this.mtSettings.markdownBlockquote&&(e=this.#P(e,"

>","

","

","

")),e}#C(t){let e=t.replaceAll('rel="tag"','rel="tag" target="_blank"');return e=e.replaceAll('class="u-url mention"','class="u-url mention" target="_blank"'),e}#P(t,e,i,s,a){if(t.includes(e)){const n=new RegExp(e+"(.*?)"+i,"gi");return t.replace(n,s+"$1"+a)}return t}#f(t){return(t??"").replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}#x(t,e){if(t.includes(":")){for(const i of e){const e=new RegExp(`\\:${i.shortcode}\\:`,"g");t=t.replace(e,`Emoji ${i.shortcode}`)}return t}return t}#S(t){const e=new Date(t);return new Intl.DateTimeFormat(this.mtSettings.dateFormatLocale,this.mtSettings.dateFormatOptions).format(e)}#L(t,e=!1){const i=t.type,s=e;let a="";const n='";return"image"===i&&(a='
'+(s?n:"")+''+(t.description?this.#f(t.description):
'),"audio"===i&&(a=t.preview_url?'
'+(s?n:"")+''+(t.description?this.#f(t.description):
':'
'+(s?n:"")+'
'),"video"!==i&&"gifv"!==i||(a=this.mtSettings.hideVideoPreview?'
'+(s?n:"")+'
':'
'+(s?n:"")+''+(t.description?this.#f(t.description):
'),a}#k(t,e){let i=document.createElement("dialog");i.id=t,i.classList.add("mt-dialog"),i.dataset.theme=this.mtContainerNode.getAttribute("data-theme"),i.innerHTML=e,document.body.prepend(i),i.showModal(),i.addEventListener("close",(()=>{document.body.removeChild(i)}))}#E(t){const e=Array.from(t.target.parentNode.parentNode.children).filter((t=>!t.classList.contains("mt-post-media-spoiler"))),i=e.indexOf(t.target.parentNode)+1;let s=[];e.forEach(((t,e)=>{let i="";i="gifv"===t.getAttribute("data-media-type")||"video"===t.getAttribute("data-media-type")?`\n \n `:`\n ${t.getAttribute(\n `;const a=`\n \n `;s.push(a)}));const a=`\n \n\n \n\n \n\n \n `;this.#k("mt-carousel",a),s.length>=2&&this.#$(e.length,i)}#$(t,e){let i=e;const s=document.getElementById("mt-carousel-scroll");let a=0,n=!1;const o=document.getElementById("mt-carousel-prev"),r=document.getElementById("mt-carousel-next"),l=(t,e="smooth")=>{document.getElementById("mt-carousel-"+t).scrollIntoView({behavior:e})};l(i,"instant");const d=()=>{clearTimeout(a),a=setTimeout((()=>{n&&(i=(()=>{const t=(s.scrollLeft+s.clientWidth)/s.clientWidth;return Math.round(t+Number.EPSILON)})(),m()),n=!0}),60)};s.addEventListener("scroll",d);const m=()=>{o.hidden=1===i,r.hidden=i===t},h=e=>{const s=e.target.closest("button")?.id;"mt-carousel-next"===s?(n=!1,++i,i>t&&(i=t),l(i),m()):"mt-carousel-prev"===s&&(n=!1,--i,i<1&&(i=1),l(i),m()),"mt-carousel-close"===s&&p()};document.addEventListener("click",h);const c=t=>{"Escape"!==t.key&&27!==t.keyCode||p()};document.addEventListener("keydown",c);const p=()=>{s.removeEventListener("scroll",d),document.removeEventListener("click",h),document.removeEventListener("keydown",c)}}#B(t){const e=t.target.closest("[data-media-type]"),i=e.dataset.mediaUrlHd;e.replaceChildren(),e.innerHTML=``}#H(t){const e=t.target,i=e.nextSibling;e.textContent==this.mtSettings.btnShowMore?(i.classList.remove("spoiler-txt-hidden"),i.classList.add("spoiler-txt-visible"),e.setAttribute("aria-expanded","true"),e.textContent=this.mtSettings.btnShowLess):(i.classList.remove("spoiler-txt-visible"),i.classList.add("spoiler-txt-hidden"),e.setAttribute("aria-expanded","false"),e.textContent=this.mtSettings.btnShowMore)}#A(t){const e=t.target;e.classList.contains("mt-btn-spoiler-media-show")?e.parentNode.classList.remove("mt-post-media-spoiler"):e.parentNode.classList.add("mt-post-media-spoiler")}#T(t){let e="";if("0"!==this.mtSettings.previewMaxLines&&t.description){e=''+this.#_(t.description)+""}return''+(t.image?'
'+this.#f(t.image_description)+'
':'
📄
')+'
'+(t.provider_name?''+this.#_(t.provider_name)+"":"")+''+t.title+""+e+(t.author_name?''+this.#_(t.author_name)+"":"")+"
"}#_(t){return(new DOMParser).parseFromString(t,"text/html").body.textContent}#b(){let t="",e="";if(this.mtSettings.btnSeeMore){let e="";"profile"===this.mtSettings.timelineType?this.mtSettings.profileName?e=this.mtSettings.profileName:this.#o("Please check your profileName value","⚠️"):"hashtag"===this.mtSettings.timelineType?e="tags/"+this.mtSettings.hashtagName:"local"===this.mtSettings.timelineType&&(e="public/local"),t=`\n \n ${this.mtSettings.btnSeeMore}\n `}if(this.mtSettings.btnReload&&(e=`\n `),this.mtBodyNode.parentNode.insertAdjacentHTML("beforeend",'"),this.mtSettings.btnReload){this.mtContainerNode.getElementsByClassName("btn-refresh")[0].addEventListener("click",(()=>{this.mtUpdate()}))}}#v(){this.mtBodyNode.addEventListener("click",(t=>{const e=t.target,i=e.localName,s=e.parentNode;("article"==i||"article"==e.offsetParent?.localName||this.mtSettings.disableCarousel&&"image"===s.getAttribute("data-media-type"))&&this.#D(t),e.classList.contains("mt-btn-spoiler-txt")&&this.#H(t),e.classList.contains("mt-btn-spoiler-media")&&this.#A(t),this.mtSettings.disableCarousel||"img"!=i||"image"!==s.getAttribute("data-media-type")&&"audio"!==s.getAttribute("data-media-type")||this.#E(t),("mt-btn-play"==e.className||"svg"==i&&"mt-btn-play"==s.className||"path"==i&&"mt-btn-play"==s.parentNode.className||"img"==i&&("video"===s.getAttribute("data-media-type")||"gifv"===s.getAttribute("data-media-type")))&&this.#B(t)})),this.mtBodyNode.addEventListener("keydown",(t=>{const e=t.target.localName;"Enter"===t.key&&"article"==e&&this.#D(t)}))}#D(t){const e=t.target.closest(".mt-post")?.dataset.location;if(!e)return;const i=t.target.localName;if("a"===i||"span"===i||"button"===i||"bdi"===i||"time"===i)return;const s=t.target.className;if("mt-post-media-spoiler"===s||"mt-post-preview-noImage"===s)return;const a=t.target.parentNode?.className;"mt-post-avatar-image-big"!==a&&"mt-post-avatar-image-small"!==a&&"mt-post-header-user-name"!==a&&"mt-post-preview-image"!==a&&"mt-post-preview"!==a&&window.open(e,"_blank","noopener")}#p(){const t=e=>{e.target.parentNode.classList.remove(this.mtSettings.spinnerClass),e.target.removeEventListener("load",t),e.target.removeEventListener("error",t)};this.mtBodyNode.querySelectorAll(`.${this.mtSettings.spinnerClass} > img`).forEach((e=>{e.addEventListener("load",t),e.addEventListener("error",t)}))}#o(t,e){const i=e||"❌";throw this.mtBodyNode.innerHTML=`\n
\n ${i}\n Oops, something's happened:\n
${t}
\n
`,this.mtBodyNode.setAttribute("role","none"),new Error("Stopping the script due to an error building the timeline.")}}})); + */t.Init=class{constructor(t={}){this.defaultSettings={mtContainerId:"mt-container",instanceUrl:"https://mastodon.social",timelineType:"local",userId:"",profileName:"",hashtagName:"",spinnerClass:"mt-loading-spinner",defaultTheme:"auto",maxNbPostFetch:"20",maxNbPostShow:"20",dateFormatLocale:"en-GB",dateFormatOptions:{day:"2-digit",month:"short",year:"numeric"},hideUnlisted:!1,hideReblog:!1,hideReplies:!1,hidePinnedPosts:!1,hideUserAccount:!1,txtMaxLines:"",filterByLanguage:"",btnShowMore:"SHOW MORE",btnShowLess:"SHOW LESS",markdownBlockquote:!1,hideEmojos:!1,btnShowContent:"SHOW CONTENT",hideVideoPreview:!1,btnPlayVideoTxt:"Load and play video",hidePreviewLink:!1,previewMaxLines:"",hideCounterBar:!1,disableCarousel:!1,carouselCloseTxt:"Close carousel",carouselPrevTxt:"Previous media item",carouselNextTxt:"Next media item",btnSeeMore:"See more posts at Mastodon",btnReload:"Refresh",insistSearchContainer:!1,insistSearchContainerTime:"3000"},this.mtSettings={...this.defaultSettings,...t},this.#t(),this.linkHeader={},this.mtContainerNode="",this.mtBodyNode="",this.fetchedData={},this.#e((()=>{this.#i()}))}#t(){Number(this.mtSettings.maxNbPostShow)>Number(this.mtSettings.maxNbPostFetch)&&(console.error(`Please check your settings! The maximum number of posts to show is bigger than the maximum number of posts to fetch. Changing the value of "maxNbPostFetch" to: ${this.mtSettings.maxNbPostShow}`),this.mtSettings.maxNbPostFetch=this.mtSettings.maxNbPostShow)}#e(t){"undefined"!=typeof document&&"complete"===document.readyState?t():"undefined"!=typeof document&&"complete"!==document.readyState&&document.addEventListener("DOMContentLoaded",t())}#i(){const t=()=>{this.mtContainerNode=document.getElementById(this.mtSettings.mtContainerId),this.mtBodyNode=this.mtContainerNode.getElementsByClassName("mt-body")[0],this.#s(),this.#a("newTimeline")};if(this.mtSettings.insistSearchContainer){const e=performance.now(),i=()=>{if(document.getElementById(this.mtSettings.mtContainerId))t();else{performance.now()-e container with id: "${this.mtSettings.mtContainerId}" after several attempts for ${this.mtSettings.insistSearchContainerTime/1e3} seconds`)}};i()}else document.getElementById(this.mtSettings.mtContainerId)?t():console.error(`Impossible to find the
container with id: "${this.mtSettings.mtContainerId}". Please try to add the option 'insistSearchContainer: true' when initializing the script`)}mtUpdate(){this.#e((()=>{this.mtBodyNode.replaceChildren(),this.mtBodyNode.insertAdjacentHTML("afterbegin",'
'),this.#a("updateTimeline")}))}mtColorTheme(t){this.#e((()=>{this.mtContainerNode.setAttribute("data-theme",t)}))}#s(){if("auto"===this.mtSettings.defaultTheme){let t=window.matchMedia("(prefers-color-scheme: dark)");t.matches?this.mtColorTheme("dark"):this.mtColorTheme("light"),t.addEventListener("change",(t=>{t.matches?this.mtColorTheme("dark"):this.mtColorTheme("light")}))}else this.mtColorTheme(this.mtSettings.defaultTheme)}#o(){return new Promise(((t,e)=>{const i=this.mtSettings.instanceUrl?`${this.mtSettings.instanceUrl}/api/v1/`:this.#n("Please check your instanceUrl value","⚠️"),s=this.#r(i),a=Object.entries(s).map((([t,i])=>{const s="timeline"===t;return this.#l(i,s).then((e=>({[t]:e}))).catch((s=>(e(new Error(`Something went wrong fetching data from: ${i}`)),this.#n(s.message),{[t]:[]})))}));Promise.all(a).then((async e=>{if(this.fetchedData=e.reduce(((t,e)=>({...t,...e})),{}),!this.mtSettings.hidePinnedPosts&&void 0!==this.fetchedData.pinned?.length&&0!==this.fetchedData.pinned.length){const t=this.fetchedData.pinned.map((t=>({...t,pinned:!0})));this.fetchedData.timeline=[...t,...this.fetchedData.timeline]}if(this.#d())t();else{do{await this.#m()}while(!this.#d()&&this.linkHeader.next);t()}}))}))}#r(t){const{timelineType:e,userId:i,hashtagName:s,maxNbPostFetch:a,hidePinnedPosts:o,hideEmojos:n}=this.mtSettings,r={};switch(e){case"profile":if(!i){this.#n("Please check your userId value","⚠️");break}r.timeline=`${t}accounts/${i}/statuses?limit=${a}`,o||(r.pinned=`${t}accounts/${i}/statuses?pinned=true`);break;case"hashtag":if(!s){this.#n("Please check your hashtagName value","⚠️");break}r.timeline=`${t}timelines/tag/${s}?limit=${a}`;break;case"local":r.timeline=`${t}timelines/public?local=true&limit=${a}`;break;default:this.#n("Please check your timelineType value","⚠️")}return n||(r.emojos=`${t}custom_emojis`),r}async#l(t,e=!1){const i=await fetch(t);if(!i.ok)throw new Error(`\n Failed to fetch the following Url:
${t}
Error status: ${i.status}
Error message: ${i.statusText}\n `);const s=await i.json();return e&&i.headers.get("Link")&&(this.linkHeader=this.#h(i.headers.get("Link"))),s}#d(){return this.fetchedData.timeline.length>=Number(this.mtSettings.maxNbPostFetch)}#m(){return new Promise((t=>{this.linkHeader.next?this.#l(this.linkHeader.next,!0).then((e=>{this.fetchedData.timeline=[...this.fetchedData.timeline,...e],t()})):t()}))}#h(t){const e=t.split(", ").map((t=>t.split("; "))).map((t=>[t[1].replace(/"/g,"").replace("rel=",""),t[0].slice(1,-1)]));return Object.fromEntries(e)}async#a(t){await this.#o();const{hideUnlisted:e,hideReblog:i,hideReplies:s,maxNbPostShow:a,filterByLanguage:o}=this.mtSettings,n=this.fetchedData.timeline;this.mtBodyNode.replaceChildren();if(n.filter((t=>{const a="public"===t.visibility||!e&&"unlisted"===t.visibility,n=i&&t.reblog,r=s&&t.in_reply_to_id,l=t.language||(t.reblog?t.reblog.language:null);return a&&!n&&!r&&(""===o||l===o)})).forEach(((t,e)=>{e${n?.length||0} posts have been fetched from the server
This may be due to an incorrect configuration with the parameters or with the filters applied (to hide certains type of posts)`;this.#n(t,"📭")}}#g(){"0"!==this.mtSettings.txtMaxLines&&0!==this.mtSettings.txtMaxLines.length&&this.mtBodyNode.parentNode.style.setProperty("--mt-txt-max-lines",this.mtSettings.txtMaxLines),"0"!==this.mtSettings.previewMaxLines&&0!==this.mtSettings.previewMaxLines.length&&this.mtBodyNode.parentNode.style.setProperty("--mt-preview-max-lines",this.mtSettings.previewMaxLines)}#u(t){const e=this.mtBodyNode.getElementsByTagName("article");for(let i=0;i
'+this.#f(h)+' avatar
'+(i?'
'+this.#f(t.account.username)+' avatar
':"")+"
",u='
'+(!this.mtSettings.hideEmojos&&c?this.#x(c,p):c||h)+""+(this.mtSettings.hideUserAccount?"":'
")+"
",v=this.#y(o),b='
'+(t.pinned?'':"")+'"+(t.edited_at?" *":"")+"
",w="0"!==this.mtSettings.txtMaxLines&&this.mtSettings.txtMaxLines.length?" truncate":"";let f="";const x=s.spoiler_text?s.spoiler_text:s.content,y='
'+this.#S(s.content)+"
";x&&(f='
'+this.#S(x)+(s.spoiler_text?y:"")+"
");const S=[...t.media_attachments,...t.reblog?.media_attachments||[]].map((t=>this.#L(t,s.sensitive))).join("");return'
'+g+u+b+"
"+f+(S?`
${S}
`:"")+(this.mtSettings.hidePreviewLink||!t.card&&!t.reblog?.card?"":this.#T(i?t.reblog.card:t.card))+(t.poll?'
    '+t.poll.options.map((function(t){return"
  • "+t.title+"
  • "})).join("")+"
":"")+(this.mtSettings.hideCounterBar?"":'
'+this.#N("replies",n)+this.#N("reblog",r)+this.#N("favorites",l)+"
")+"
"}#N(t,e){return`
${{replies:'',reblog:'',favorites:''}[t]}${e}
`}#M(t,e){function i(t,e){let i=e.replace(/\s+/g,"").toLowerCase();return!(!["src","href","xlink:href"].includes(t)||!i.includes("javascript:")&&!i.includes("data:"))||(!!t.startsWith("on")||void 0)}function s(t){let e=t.attributes;for(let{name:s,value:a}of e)i(s,a)&&t.removeAttribute(s)}let a=(new DOMParser).parseFromString(t,"text/html").body||document.createElement("body");return function(t){let e=t.querySelectorAll("script");for(let t of e)t.remove()}(a),function t(e){let i=e.children;for(let e of i)s(e),t(e)}(a),e?a.childNodes:a.innerHTML}#S(t){let e=t;return e=this.#M(e,!1),e=this.#C(e),this.mtSettings.hideEmojos||(e=this.#x(e,this.fetchedData.emojos)),this.mtSettings.markdownBlockquote&&(e=this.#k(e,"

>","

","

","

")),e}#C(t){let e=t.replaceAll('rel="tag"','rel="tag" target="_blank"');return e=e.replaceAll('class="u-url mention"','class="u-url mention" target="_blank"'),e}#k(t,e,i,s,a){if(t.includes(e)){const o=new RegExp(e+"(.*?)"+i,"gi");return t.replace(o,s+"$1"+a)}return t}#f(t){return(t??"").replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}#x(t,e){if(t.includes(":")){for(const i of e){const e=new RegExp(`\\:${i.shortcode}\\:`,"g");t=t.replace(e,`Emoji ${i.shortcode}`)}return t}return t}#y(t){const e=new Date(t);return new Intl.DateTimeFormat(this.mtSettings.dateFormatLocale,this.mtSettings.dateFormatOptions).format(e)}#L(t,e=!1){const{type:i,url:s,preview_url:a,description:o,meta:n}=t,{original:r,small:l}=n,{spinnerClass:d,btnShowContent:m,btnPlayVideoTxt:h,hideVideoPreview:c}=this.mtSettings,p='",g=' class="mt-post-media '+(e?"mt-post-media-spoiler ":"")+(d||"")+'" data-media-type="'+i+'" data-media-url-hd="'+s+'"'+(o?' data-media-alt-txt="'+this.#f(o)+'"':"")+' data-media-width-hd="'+r.width+'" data-media-height-hd="'+r.height+'" style="padding-top: calc(100%/'+l?.aspect+')">';return"image"===i?"
':"audio"===i?'
'+(e?p:"")+''+(a?''+(o?this.#f(o):':"")+"
":"video"===i||"gifv"===i?c?"':"':""}#P(t,e){let i=document.createElement("dialog");i.id=t,i.classList.add("mt-dialog"),i.dataset.theme=this.mtContainerNode.getAttribute("data-theme"),i.innerHTML=e,document.body.prepend(i),i.showModal(),i.addEventListener("close",(()=>{document.body.removeChild(i)}))}#E(t){const e=Array.from(t.target.parentNode.parentNode.children).filter((t=>!t.classList.contains("mt-post-media-spoiler"))),i=e.indexOf(t.target.parentNode)+1;let s=[];e.forEach(((t,e)=>{let i="";i="gifv"===t.getAttribute("data-media-type")||"video"===t.getAttribute("data-media-type")?`\n \n `:`\n ${t.getAttribute(\n `;const a=`\n \n `;s.push(a)}));const a=`\n \n\n \n\n \n\n \n `;this.#P("mt-carousel",a),s.length>=2&&this.#$(e.length,i)}#$(t,e){let i=e;const s=document.getElementById("mt-carousel-scroll");let a=0,o=!1;const n=document.getElementById("mt-carousel-prev"),r=document.getElementById("mt-carousel-next"),l=(t,e="smooth")=>{document.getElementById("mt-carousel-"+t).scrollIntoView({behavior:e})};l(i,"instant");const d=()=>{clearTimeout(a),a=setTimeout((()=>{o&&(i=(()=>{const t=(s.scrollLeft+s.clientWidth)/s.clientWidth;return Math.round(t+Number.EPSILON)})(),m()),o=!0}),60)};s.addEventListener("scroll",d);const m=()=>{n.hidden=1===i,r.hidden=i===t},h=e=>{const s=e.target.closest("button")?.id;"mt-carousel-next"===s?(o=!1,++i,i>t&&(i=t),l(i),m()):"mt-carousel-prev"===s&&(o=!1,--i,i<1&&(i=1),l(i),m()),"mt-carousel-close"===s&&p()};document.addEventListener("click",h);const c=t=>{"Escape"!==t.key&&27!==t.keyCode||p()};document.addEventListener("keydown",c);const p=()=>{s.removeEventListener("scroll",d),document.removeEventListener("click",h),document.removeEventListener("keydown",c)}}#B(t){const e=t.target.closest("[data-media-type]"),i=e.dataset.mediaUrlHd;e.replaceChildren(),e.innerHTML=``}#A(t){const e=t.target,i=e.nextSibling,s="true"===e.getAttribute("aria-expanded");i.classList.toggle("spoiler-txt-hidden",s),i.classList.toggle("spoiler-txt-visible",!s),e.setAttribute("aria-expanded",!s),e.textContent=s?this.mtSettings.btnShowMore:this.mtSettings.btnShowLess}#H(t){const e=t.target;e.parentNode.classList.toggle("mt-post-media-spoiler",!e.classList.contains("mt-btn-spoiler-media-show"))}#T(t){const{url:e,image:i,image_description:s,provider_name:a,title:o,description:n,author_name:r}=t,{previewMaxLines:l,spinnerClass:d}=this.mtSettings;let m="";return"0"!==l&&n&&(m=''+this.#q(n)+""),''+(i?'
'+this.#f(s)+'
':'
📄
')+'
'+(a?''+this.#q(a)+"":"")+''+o+""+m+(r?''+this.#q(r)+"":"")+"
"}#q(t){return(new DOMParser).parseFromString(t,"text/html").body.textContent}#b(){const{btnSeeMore:t,btnReload:e,timelineType:i,profileName:s,hashtagName:a,instanceUrl:o}=this.mtSettings;let n="",r="";if(t){let e="";switch(i){case"profile":s?e=s:this.#n("Please check your profileName value","⚠️");break;case"hashtag":e="tags/"+a;break;case"local":e="public/local"}n=''+t+""}if(e&&(r='"),this.mtBodyNode.parentNode.insertAdjacentHTML("beforeend",'"),e){const t=this.mtContainerNode.querySelector(".btn-refresh");t&&t.addEventListener("click",(()=>this.mtUpdate()))}}#v(){this.mtBodyNode.addEventListener("click",(t=>{const e=t.target,i=e.localName,s=e.parentNode;("article"==i||"article"==e.offsetParent?.localName||this.mtSettings.disableCarousel&&"image"===s.getAttribute("data-media-type"))&&this.#D(t),e.classList.contains("mt-btn-spoiler-txt")&&this.#A(t),e.classList.contains("mt-btn-spoiler-media")&&this.#H(t),this.mtSettings.disableCarousel||"img"!=i||"image"!==s.getAttribute("data-media-type")&&"audio"!==s.getAttribute("data-media-type")||this.#E(t),("mt-btn-play"==e.className||"svg"==i&&"mt-btn-play"==s.className||"path"==i&&"mt-btn-play"==s.parentNode.className||"img"==i&&("video"===s.getAttribute("data-media-type")||"gifv"===s.getAttribute("data-media-type")))&&this.#B(t)})),this.mtBodyNode.addEventListener("keydown",(t=>{const e=t.target.localName;"Enter"===t.key&&"article"==e&&this.#D(t)}))}#D(t){const e=t.target.closest(".mt-post")?.dataset.location;if(!e)return;const i=t.target.localName;if("a"===i||"span"===i||"button"===i||"bdi"===i||"time"===i)return;const s=t.target.className;if("mt-post-media-spoiler"===s||"mt-post-preview-noImage"===s)return;const a=t.target.parentNode?.className;"mt-post-avatar-image-big"!==a&&"mt-post-avatar-image-small"!==a&&"mt-post-header-user-name"!==a&&"mt-post-preview-image"!==a&&"mt-post-preview"!==a&&window.open(e,"_blank","noopener")}#p(){const t=e=>{e.target.parentNode.classList.remove(this.mtSettings.spinnerClass),e.target.removeEventListener("load",t),e.target.removeEventListener("error",t)};this.mtBodyNode.querySelectorAll(`.${this.mtSettings.spinnerClass} > img`).forEach((e=>{e.addEventListener("load",t),e.addEventListener("error",t)}))}#n(t,e){const i=e||"❌";throw this.mtBodyNode.innerHTML=`\n
\n ${i}\n Oops, something's happened:\n
${t}
\n
`,this.mtBodyNode.setAttribute("role","none"),new Error("Stopping the script due to an error building the timeline.")}}})); diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 33f0140..64de9a3 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -45,11 +45,11 @@ This option allows you to start without the need to upload any files on your ser Copy the following CSS and JS links to include them in your project: ```html - + ``` ```html - + ``` ## Package manager diff --git a/package-lock.json b/package-lock.json index 8f00792..33130c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@idotj/mastodon-embed-timeline", - "version": "4.5.1", + "version": "4.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@idotj/mastodon-embed-timeline", - "version": "4.5.1", + "version": "4.6.0", "license": "GNU", "devDependencies": { "@rollup/plugin-terser": "^0.4.4", diff --git a/package.json b/package.json index ba00fa2..74e7d18 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@idotj/mastodon-embed-timeline", - "version": "4.5.1", + "version": "4.6.0", "description": "Displays a Mastodon timeline with posts embed in your website. Very easy to setup, no dependencies, no trackers, cross-browser, WCAG compliant and fully responsive.", "license": "GNU", "author": { diff --git a/src/mastodon-timeline.css b/src/mastodon-timeline.css index 5b35203..c4b82c8 100644 --- a/src/mastodon-timeline.css +++ b/src/mastodon-timeline.css @@ -1,4 +1,4 @@ -/* Mastodon embed timeline v4.5.1 */ +/* Mastodon embed timeline v4.6.0 */ /* More info at: */ /* https://gitlab.com/idotj/mastodon-embed-timeline */ @@ -10,10 +10,11 @@ --mt-txt-max-lines: none; --mt-preview-max-lines: none; --mt-color-bg: #fff; - --mt-color-bg-hover: #d9e1e8; + --mt-color-bg-hover: #e9eef1; --mt-color-line-gray: #c0cdd9; --mt-color-contrast-gray: #606984; --mt-color-content-txt: #000; + --mt-color-hashtag: #d7e1e9; --mt-color-link: #3a3bff; --mt-color-error-txt: #8b0000; --mt-color-btn-bg: #6364ff; @@ -24,11 +25,12 @@ } .mt-container[data-theme="dark"], .mt-dialog[data-theme="dark"] { - --mt-color-bg: #282c37; - --mt-color-bg-hover: #313543; + --mt-color-bg: #181821; + --mt-color-bg-hover: #21232c; --mt-color-line-gray: #393f4f; --mt-color-contrast-gray: #606984; --mt-color-content-txt: #fff; + --mt-color-hashtag: #292c38; --mt-color-link: #8c8dff; --mt-color-error-txt: #fe6c6c; } @@ -79,8 +81,6 @@ .mt-container::-webkit-scrollbar-corner { background-color: var(--mt-color-bg); } -.mt-container a:link, -.mt-container a:active, .mt-container a { text-decoration: none; color: var(--mt-color-link); @@ -117,6 +117,9 @@ cursor: pointer; background-color: var(--mt-color-bg-hover); } +.mt-container:not(:has(.mt-footer)) .mt-post:last-child { + border-bottom: none; +} .mt-post p:last-child { margin-bottom: 0; } @@ -134,22 +137,22 @@ height: 3rem; position: relative; } -.mt-post-avatar-image-big img { +.mt-post-avatar-image-big img, +.mt-post-avatar-image-small img { aspect-ratio: 1/1; - width: 2.25rem; - height: 2.25rem; border-radius: 0.25rem; overflow: hidden; } +.mt-post-avatar-image-big img { + width: 2.25rem; + height: 2.25rem; +} .mt-post-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 */ @@ -168,8 +171,8 @@ min-width: 1rem; width: auto; } -.mt-post-header-user > a { - color: var(--mt-color-content-txt) !important; +.mt-container .mt-post-header-user > a { + color: var(--mt-color-content-txt); overflow-wrap: anywhere; } .mt-container .mt-post-header-user > a:hover { @@ -232,6 +235,17 @@ margin-bottom: -0.25rem; width: auto; } +.mt-post-txt .mention.hashtag { + display: inline-block; + font-size: 0.8rem; + border-radius: 0.25rem; + background-color: var(--mt-color-hashtag); + padding: 0.25rem 0.5rem; + margin: 0 0.25rem 0.25rem 0; +} +.mt-post-txt .mention.hashtag:only-child { + margin: 0; +} /* Poll */ .mt-post-poll { @@ -455,7 +469,6 @@ body:has(dialog.mt-dialog[open]) { .mt-post-preview-description:not(.truncate) .ellipsis::after { content: "..."; } - .mt-post-preview-title { font-weight: 600; } @@ -475,7 +488,7 @@ body:has(dialog.mt-dialog[open]) { font-size: 0.75rem; gap: 0.25rem; align-items: center; - opacity: 0.5; + opacity: 0.6; cursor: default; } .mt-post-counter-bar-replies > svg, diff --git a/src/mastodon-timeline.js b/src/mastodon-timeline.js index 1111afe..a1afae4 100644 --- a/src/mastodon-timeline.js +++ b/src/mastodon-timeline.js @@ -1,7 +1,7 @@ /** * Mastodon embed timeline * @author idotj - * @version 4.5.1 + * @version 4.6.0 * @url https://gitlab.com/idotj/mastodon-embed-timeline * @license GNU AGPLv3 */ @@ -392,7 +392,6 @@ export class Init { */ async #buildTimeline(t) { await this.#getTimelineData(); - // console.log("Mastodon timeline data fetched: ", this.fetchedData); const { @@ -454,7 +453,7 @@ export class Init { } /** - * Establishes the defined CSS variables + * Set the defined CSS variables */ #setCSSvariables() { if ( @@ -578,7 +577,9 @@ export class Init { const formattedDate = this.#formatDate(date); const dateHTML = '
' + - (c.pinned ? '' : "") + + (c.pinned + ? '' + : "") + '' + @@ -592,10 +593,18 @@ export class Init { "
"; // Post text + const hasTxtMaxLines = this.mtSettings.txtMaxLines !== "0"; const txtTruncateCss = - this.mtSettings.txtMaxLines !== "0" ? " truncate" : ""; + hasTxtMaxLines && this.mtSettings.txtMaxLines.length ? " truncate" : ""; let postTxt = ""; const textSource = post.spoiler_text ? post.spoiler_text : post.content; + const spoilerContent = + ' " + + '
' + + this.#formatPostText(post.content) + + "
"; if (textSource) { postTxt = @@ -604,6 +613,7 @@ export class Init { '">' + '
' + this.#formatPostText(textSource) + + (post.spoiler_text ? spoilerContent : "") + "
" + ""; } @@ -622,8 +632,8 @@ export class Init { // Preview link const previewLinkHTML = - !this.mtSettings.hidePreviewLink && c.card - ? this.#createPreviewLink(c.card) + !this.mtSettings.hidePreviewLink && (c.card || c.reblog?.card) + ? this.#createPreviewLink(!isReblog ? c.card : c.reblog.card) : ""; // Poll @@ -874,7 +884,6 @@ export class Init { `Emoji ${emojo.shortcode}` ); } - return c; } else { return c; @@ -888,12 +897,10 @@ export class Init { */ #formatDate(d) { const originalDate = new Date(d); - const formattedDate = new Intl.DateTimeFormat( this.mtSettings.dateFormatLocale, this.mtSettings.dateFormatOptions ).format(originalDate); - return formattedDate; } @@ -904,143 +911,101 @@ export class Init { * @returns {String} Media in HTML format */ #createMedia(m, s = false) { - const type = m.type; - const spoiler = s; - let media = ""; + const { type, url, preview_url, description, meta } = m; + const { original, small } = meta; + const { spinnerClass, btnShowContent, btnPlayVideoTxt, hideVideoPreview } = + this.mtSettings; const spoilerBtns = '" + - '"; + const commonAttributes = + ' class="mt-post-media ' + + (s ? "mt-post-media-spoiler " : "") + + (spinnerClass || "") + + '" data-media-type="' + + type + + '" data-media-url-hd="' + + url + + '"' + + (description + ? ' data-media-alt-txt="' + this.#escapeHTML(description) + '"' + : "") + + ' data-media-width-hd="' + + original.width + + '" data-media-height-hd="' + + original.height + + '"' + + ' style="padding-top: calc(100%/' + + small?.aspect + + ')">'; + if (type === "image") { - media = - '
' + - (spoiler ? spoilerBtns : "") + + return ( + "' + - "
"; + (description ? this.#escapeHTML(description) : "") + + '" loading="lazy" />' + ); } if (type === "audio") { - if (m.preview_url) { - media = - '
' + - (spoiler ? spoilerBtns : "") + - '' + - '' +
-          (m.description ? this.#escapeHTML(m.description) : ' + - "
"; - } else { - media = - '
' + - (spoiler ? spoilerBtns : "") + - '' + - "
"; - } + return ( + '
' + + (s ? spoilerBtns : "") + + '' + + (preview_url + ? '' +
+            (description ? this.#escapeHTML(description) : ' + : "") + + "
" + ); } if (type === "video" || type === "gifv") { - if (!this.mtSettings.hideVideoPreview) { - media = - '
' + - (spoiler ? spoilerBtns : "") + + if (!hideVideoPreview) { + return ( + "' + '' + - "
"; - } else { - media = - '
' + - (spoiler ? spoilerBtns : "") + - '' + - "
"; + btnPlayVideoTxt + + '">' + + '' + ); } + return ( + "' + ); } - return media; + return ""; } /** @@ -1277,34 +1242,30 @@ export class Init { * Spoiler toggle for text * @param {Event} e User interaction trigger */ - #toogleTxtSpoiler(e) { - const target = e.target; - const nextSibling = target.nextSibling; + #toggleTxtSpoiler(e) { + const button = e.target; + const spoilerText = button.nextSibling; + const isExpanded = button.getAttribute("aria-expanded") === "true"; - if (target.textContent == this.mtSettings.btnShowMore) { - nextSibling.classList.remove("spoiler-txt-hidden"); - nextSibling.classList.add("spoiler-txt-visible"); - target.setAttribute("aria-expanded", "true"); - target.textContent = this.mtSettings.btnShowLess; - } else { - nextSibling.classList.remove("spoiler-txt-visible"); - nextSibling.classList.add("spoiler-txt-hidden"); - target.setAttribute("aria-expanded", "false"); - target.textContent = this.mtSettings.btnShowMore; - } + spoilerText.classList.toggle("spoiler-txt-hidden", isExpanded); + spoilerText.classList.toggle("spoiler-txt-visible", !isExpanded); + button.setAttribute("aria-expanded", !isExpanded); + button.textContent = isExpanded + ? this.mtSettings.btnShowMore + : this.mtSettings.btnShowLess; } /** * Spoiler toggle for image/video * @param {Event} e User interaction trigger */ - #toogleMediaSpoiler(e) { - const target = e.target; - if (target.classList.contains("mt-btn-spoiler-media-show")) { - target.parentNode.classList.remove("mt-post-media-spoiler"); - } else { - target.parentNode.classList.add("mt-post-media-spoiler"); - } + #toggleMediaSpoiler(e) { + const button = e.target; + const mediaContainer = button.parentNode; + mediaContainer.classList.toggle( + "mt-post-media-spoiler", + !button.classList.contains("mt-btn-spoiler-media-show") + ); } /** @@ -1313,52 +1274,57 @@ export class Init { * @returns {String} Preview link in HTML format */ #createPreviewLink(c) { - let previewDescription = ""; - if (this.mtSettings.previewMaxLines !== "0" && c.description) { - const txtTruncateCss = - this.mtSettings.previewMaxLines.length !== 0 ? " truncate" : ""; + const { + url, + image, + image_description, + provider_name, + title, + description, + author_name, + } = c; + const { previewMaxLines, spinnerClass } = this.mtSettings; + let previewDescription = ""; + if (previewMaxLines !== "0" && description) { previewDescription = '' + - this.#parseHTMLstring(c.description) + + this.#parseHTMLstring(description) + ""; } - const card = + return ( '
' + - (c.image + (image ? '
' +
-          this.#escapeHTML(c.image_description) +
+          this.#escapeHTML(image_description) +
           '
' : '
📄
') + - "" + '
' + - (c.provider_name + (provider_name ? '' + - this.#parseHTMLstring(c.provider_name) + + this.#parseHTMLstring(provider_name) + "" : "") + '' + - c.title + + title + "" + previewDescription + - (c.author_name + (author_name ? '' + - this.#parseHTMLstring(c.author_name) + + this.#parseHTMLstring(author_name) + "" : "") + - "
" + - "
"; - - return card; + "" + ); } /** @@ -1376,44 +1342,55 @@ export class Init { * Build footer after last post */ #buildFooter() { - let btnSeeMoreHTML = ""; - let btnReloadHTML = ""; + const { + btnSeeMore, + btnReload, + timelineType, + profileName, + hashtagName, + instanceUrl, + } = this.mtSettings; + let btnSeeMoreHTML = "", + btnReloadHTML = ""; // Create button to open Mastodon page - if (this.mtSettings.btnSeeMore) { + if (btnSeeMore) { let btnSeeMorePath = ""; - if (this.mtSettings.timelineType === "profile") { - if (this.mtSettings.profileName) { - btnSeeMorePath = this.mtSettings.profileName; - } else { - this.#showError( - "Please check your profileName value", - "⚠️" - ); - } - } else if (this.mtSettings.timelineType === "hashtag") { - btnSeeMorePath = "tags/" + this.mtSettings.hashtagName; - } else if (this.mtSettings.timelineType === "local") { - btnSeeMorePath = "public/local"; + switch (timelineType) { + case "profile": + if (profileName) { + btnSeeMorePath = profileName; + } else { + this.#showError( + "Please check your profileName value", + "⚠️" + ); + } + break; + case "hashtag": + btnSeeMorePath = "tags/" + hashtagName; + break; + case "local": + btnSeeMorePath = "public/local"; + break; } - btnSeeMoreHTML = ` - - ${this.mtSettings.btnSeeMore} - `; + btnSeeMoreHTML = + '' + + btnSeeMore + + ""; } // Create button to refresh the timeline - if (this.mtSettings.btnReload) { - btnReloadHTML = ` - `; + if (btnReload) { + btnReloadHTML = + '"; } // Add footer container @@ -1423,12 +1400,11 @@ export class Init { ); // Add event listener to the button "Refresh" - if (this.mtSettings.btnReload) { - const reloadBtn = - this.mtContainerNode.getElementsByClassName("btn-refresh")[0]; - reloadBtn.addEventListener("click", () => { - this.mtUpdate(); - }); + if (btnReload) { + const reloadBtn = this.mtContainerNode.querySelector(".btn-refresh"); + if (reloadBtn) { + reloadBtn.addEventListener("click", () => this.mtUpdate()); + } } } @@ -1453,12 +1429,12 @@ export class Init { // Check if spoiler text button was clicked if (target.classList.contains("mt-btn-spoiler-txt")) { - this.#toogleTxtSpoiler(e); + this.#toggleTxtSpoiler(e); } // Check if spoiler media button was clicked if (target.classList.contains("mt-btn-spoiler-media")) { - this.#toogleMediaSpoiler(e); + this.#toggleMediaSpoiler(e); } // Check if image in post was clicked