/** * Mastodon embed timeline * @author idotj * @version 4.3.5 * @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",dateLocale:"en-GB",dateOptions:{day:"2-digit",month:"short",year:"numeric"},hideUnlisted:!1,hideReblog:!1,hideReplies:!1,hidePinnedPosts:!1,hideUserAccount:!1,hideEmojos:!1,hideVideoPreview:!1,hidePreviewLink:!1,hideCounterBar:!1,markdownBlockquote:!1,disableCarousel:!1,carouselCloseTxt:"Close carousel",carouselPrevTxt:"Previous media item",carouselNextTxt:"Next media item",txtMaxLines:"0",btnShowMore:"SHOW MORE",btnShowLess:"SHOW LESS",btnShowContent:"SHOW CONTENT",btnSeeMore:"See more posts at Mastodon",btnReload:"Refresh",insistSearchContainer:!1,insistSearchContainerTime:"3000"},this.mtSettings={...this.defaultSettings,...t},this.mtContainerNode="",this.mtBodyNode="",this.fetchedData={},this.#t((()=>{this.#e()}))}#t(t){"undefined"!=typeof document&&"complete"===document.readyState?t():"undefined"!=typeof document&&"complete"!==document.readyState&&document.addEventListener("DOMContentLoaded",t())}#e(){const t=()=>{this.mtContainerNode=document.getElementById(this.mtSettings.mtContainerId),this.mtBodyNode=this.mtContainerNode.getElementsByClassName("mt-body")[0],this.#i(),this.#s("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.#t((()=>{this.mtBodyNode.replaceChildren(),this.mtBodyNode.insertAdjacentHTML("afterbegin",'
'),this.#s("updateTimeline")}))}mtColorTheme(t){this.#t((()=>{this.mtContainerNode.setAttribute("data-theme",t)}))}#i(){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)}#a(){return new Promise(((t,e)=>{const i=`${this.mtSettings.instanceUrl}/api/v1/`;let s={};this.mtSettings.instanceUrl?"profile"===this.mtSettings.timelineType?this.mtSettings.userId?(s.timeline=`${i}accounts/${this.mtSettings.userId}/statuses?limit=${this.mtSettings.maxNbPostFetch}`,this.mtSettings.hidePinnedPosts||(s.pinned=`${i}accounts/${this.mtSettings.userId}/statuses?pinned=true`)):this.#o("Please check your userId value","⚠️"):"hashtag"===this.mtSettings.timelineType?this.mtSettings.hashtagName?s.timeline=`${i}timelines/tag/${this.mtSettings.hashtagName}?limit=${this.mtSettings.maxNbPostFetch}`:this.#o("Please check your hashtagName value","⚠️"):"local"===this.mtSettings.timelineType?s.timeline=`${i}timelines/public?local=true&limit=${this.mtSettings.maxNbPostFetch}`:this.#o("Please check your timelineType value","⚠️"):this.#o("Please check your instanceUrl value","⚠️"),this.mtSettings.hideEmojos||(s.emojos=`${i}custom_emojis`);const a=Object.entries(s).map((([t,i])=>this.#n(i).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((e=>{this.fetchedData=e.reduce(((t,e)=>({...t,...e})),{}),t()}))}))}async#n(t){const e=await fetch(t);if(!e.ok)throw new Error(`\n Failed to fetch the following Url:
${t}
Error status: ${e.status}
Error message: ${e.statusText}\n `);return await e.json()}async#s(t){let e;if(await this.#a(),this.mtSettings.hidePinnedPosts||void 0===this.fetchedData.pinned?.length||0===this.fetchedData.pinned.length)e=this.fetchedData.timeline;else{e=[...this.fetchedData.pinned.map((t=>({...t,pinned:!0}))),...this.fetchedData.timeline]}this.mtBodyNode.replaceChildren();let i=0;for(let t in e)("public"==e[t].visibility||!this.mtSettings.hideUnlisted&&"unlisted"==e[t].visibility)&&(this.mtSettings.hideReblog&&e[t].reblog||this.mtSettings.hideReplies&&e[t].in_reply_to_id||i${e?.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,"📭")}else"newTimeline"===t?(this.#l(),this.#d(),this.#m()):"updateTimeline"===t?this.#l():this.#o("The function buildTimeline() was expecting a param")}#r(t,e){this.mtBodyNode.insertAdjacentHTML("beforeend",this.#h(t,e))}#h(t,e){let i,s,a,o,n,r,l,d,m,h;t.reblog?(n=t.reblog.url,i='
'+this.#c(t.reblog.account.username)+' avatar
'+this.#c(t.account.username)+' avatar
',a=!this.mtSettings.hideEmojos&&t.reblog.account.display_name?this.#p(t.reblog.account.display_name,t.reblog.account.emojis):t.reblog.account.display_name?t.reblog.account.display_name:t.reblog.account.username,o=this.mtSettings.hideUserAccount?"":'
",s='
'+a+""+o+"
",r=t.reblog.created_at,h=t.reblog.replies_count,m=t.reblog.reblogs_count,d=t.reblog.favourites_count):(n=t.url,i='
'+this.#c(t.account.username)+' avatar
',a=!this.mtSettings.hideEmojos&&t.account.display_name?this.#p(t.account.display_name,t.account.emojis):t.account.display_name?t.account.display_name:t.account.username,o=this.mtSettings.hideUserAccount?"":'
",s='
'+a+""+o+"
",r=t.created_at,h=t.replies_count,m=t.reblogs_count,d=t.favourites_count),l=this.#g(r);const c=`\n
\n ${t.pinned?'':""}\n \n \n ${t.edited_at?" *":""}\n \n
`;let p="";"0"!==this.mtSettings.txtMaxLines&&(p=" truncate",this.mtBodyNode.parentNode.style.setProperty("--mt-txt-max-lines",this.mtSettings.txtMaxLines));let g="";g=""!==t.spoiler_text?'
'+t.spoiler_text+'
'+this.#u(t.content)+"
":t.reblog&&""!==t.reblog.content&&""!==t.reblog.spoiler_text?'
'+t.reblog.spoiler_text+'
'+this.#u(t.reblog.content)+"
":t.reblog&&""!==t.reblog.content&&""===t.reblog.spoiler_text?'
'+this.#u(t.reblog.content)+"
":'
'+this.#u(t.content)+"
";let u=[];if(t.media_attachments.length>0)for(let e in t.media_attachments)u.push(this.#v(t.media_attachments[e],t.sensitive));if(t.reblog&&t.reblog.media_attachments.length>0)for(let e in t.reblog.media_attachments)u.push(this.#v(t.reblog.media_attachments[e],t.reblog.sensitive));u=`
${u.join("")}
`;let v="";!this.mtSettings.hidePreviewLink&&t.card&&(v=this.#b(t.card));let b="";if(t.poll){let e="";for(let i in t.poll.options)e+="
  • "+t.poll.options[i].title+"
  • ";b='
      '+e+"
    "}let w="";if(!this.mtSettings.hideCounterBar){w='
    '+('
    '+h+"
    ")+('
    '+m+"
    ")+('
    '+d+"
    ")+"
    "}return'
    '+i+s+c+"
    "+g+u+v+b+w+"
    "}#u(t){let e=t;return e=this.#w(e),this.mtSettings.hideEmojos||(e=this.#p(e,this.fetchedData.emojos)),this.mtSettings.markdownBlockquote&&(e=this.#f(e,"

    >","

    ","

    ","

    ")),e}#w(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}#f(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}#c(t){return(t??"").replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}#p(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}#g(t){const e=new Date(t);return new Intl.DateTimeFormat(this.mtSettings.dateLocale,this.mtSettings.dateOptions).format(e)}#v(t,e){const i=e||!1,s=t.type;let a="";return"image"===s&&(a='
    '+(i?'":"")+''+(t.description?this.#c(t.description):
    '),"audio"===s&&(a=t.preview_url?'
    '+(i?'":"")+''+(t.description?this.#c(t.description):
    ':'
    '+(i?'":"")+'
    '),"video"!==s&&"gifv"!==s||(a=this.mtSettings.hideVideoPreview?'
    '+(i?'":"")+'
    ':'
    '+(i?'":"")+''+(t.description?this.#c(t.description):
    '),a}#S(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)}))}#y(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.#S("mt-carousel",a),s.length>=2&&this.#x(e.length,i)}#x(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)}}#L(t){const e=t.target.closest("[data-media-type]"),i=e.dataset.mediaUrlHd;e.replaceChildren(),e.innerHTML=``}#N(t){const e=t.target,i=e.nextSibling;"img"===i.localName||"audio"===i.localName||"video"===i.localName?(e.parentNode.classList.remove("mt-post-media-spoiler"),e.style.display="none"):(i.classList.contains("spoiler-txt-hidden")||i.classList.contains("spoiler-txt-visible"))&&(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))}#b(t){return''+(t.image?'
    '+this.#c(t.image_description)+'
    ':'
    📄
    ')+'
    '+(t.provider_name?''+this.#T(t.provider_name)+"":"")+''+t.title+""+(t.author_name?''+this.#T(t.author_name)+"":"")+"
    "}#T(t){return(new DOMParser).parseFromString(t,"text/html").body.textContent}#m(){if(this.mtSettings.btnSeeMore||this.mtSettings.btnReload){this.mtBodyNode.parentNode.insertAdjacentHTML("beforeend",'');const t=this.mtContainerNode.getElementsByClassName("mt-footer")[0];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");const i=`\n \n ${this.mtSettings.btnSeeMore}\n `;t.insertAdjacentHTML("beforeend",i)}if(this.mtSettings.btnReload){const e=`\n `;t.insertAdjacentHTML("beforeend",e);this.mtContainerNode.getElementsByClassName("btn-refresh")[0].addEventListener("click",(()=>{this.mtUpdate()}))}}}#d(){this.mtBodyNode.addEventListener("click",(t=>{const e=t.target,i=e.localName,s=e.parentNode;("article"==i||"article"==e.offsetParent?.localName||"img"==i&&this.mtSettings.disableCarousel&&"video"!==s.getAttribute("data-media-type")&&"gifv"!==s.getAttribute("data-media-type"))&&this.#C(t),"button"==i&&e.classList.contains("mt-btn-spoiler")&&this.#N(t),"img"!=i||this.mtSettings.disableCarousel||"video"===s.getAttribute("data-media-type")||"gifv"===s.getAttribute("data-media-type")||this.#y(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.#L(t)})),this.mtBodyNode.addEventListener("keydown",(t=>{const e=t.target.localName;"Enter"===t.key&&"article"==e&&this.#C(t)}))}#C(t){const e=t.target.closest(".mt-post").dataset.location;"a"!==t.target.localName&&"span"!==t.target.localName&&"button"!==t.target.localName&&"bdi"!==t.target.localName&&"time"!==t.target.localName&&!t.target.classList.contains("mt-post-media-spoiler")&&"mt-post-preview-noImage"!==t.target.className&&"mt-post-avatar-image-big"!==t.target.parentNode.className&&"mt-post-avatar-image-small"!==t.target.parentNode.className&&"mt-post-preview-image"!==t.target.parentNode.className&&"mt-post-preview"!==t.target.parentNode.className&&e&&window.open(e,"_blank","noopener")}#l(){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};