diff --git a/CHANGELOG b/CHANGELOG
index 50d9bb8..b201496 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,4 @@
-v4.4.1 - 04/04/2024
+v4.4.2 - 04/04/2024
- Fix render emojos in warning/spoiler text
- Sanitize post content before rendering
- Add custom title for play video button
diff --git a/README.md b/README.md
index ca5bb1e..5cc95db 100644
--- a/README.md
+++ b/README.md
@@ -65,11 +65,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/dist/mastodon-timeline.esm.js b/dist/mastodon-timeline.esm.js
index eec777d..2a41636 100644
--- a/dist/mastodon-timeline.esm.js
+++ b/dist/mastodon-timeline.esm.js
@@ -1,8 +1,8 @@
/**
* Mastodon embed timeline
* @author idotj
- * @version 4.4.1
+ * @version 4.4.2
* @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,txtMaxLines:"",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){let e={};return"profile"===this.mtSettings.timelineType?this.mtSettings.userId?(e.timeline=`${t}accounts/${this.mtSettings.userId}/statuses?limit=${this.mtSettings.maxNbPostFetch}`,this.mtSettings.hidePinnedPosts||(e.pinned=`${t}accounts/${this.mtSettings.userId}/statuses?pinned=true`)):this.#n("Please check your userId value","⚠️"):"hashtag"===this.mtSettings.timelineType?this.mtSettings.hashtagName?e.timeline=`${t}timelines/tag/${this.mtSettings.hashtagName}?limit=${this.mtSettings.maxNbPostFetch}`:this.#n("Please check your hashtagName value","⚠️"):"local"===this.mtSettings.timelineType?e.timeline=`${t}timelines/public?local=true&limit=${this.mtSettings.maxNbPostFetch}`:this.#n("Please check your timelineType value","⚠️"),this.mtSettings.hideEmojos||(e.emojos=`${t}custom_emojis`),e}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 e=this.fetchedData.timeline;let i=0;if(this.mtBodyNode.replaceChildren(),e.forEach((t=>{const e="public"===t.visibility||!this.mtSettings.hideUnlisted&&"unlisted"===t.visibility,s=this.mtSettings.hideReblog&&t.reblog,a=this.mtSettings.hideReplies&&t.in_reply_to_id;!e||s||a||i${e?.length||0} posts have been fetched from the serverThis 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
"}let g=[];if(t.media_attachments.length>0)for(let e in t.media_attachments)g.push(this.#L(t.media_attachments[e],t.sensitive));if(t.reblog&&t.reblog.media_attachments.length>0)for(let e in t.reblog.media_attachments)g.push(this.#L(t.reblog.media_attachments[e],t.reblog.sensitive));g=`
${g.join("")}
`;let u="";!this.mtSettings.hidePreviewLink&&t.card&&(u=this.#T(t.card));let v="";if(t.poll){let e="";for(let i in t.poll.options)e+="
`,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",dateLocale:"en-GB",dateOptions:{day:"2-digit",month:"short",year:"numeric"},hideUnlisted:!1,hideReblog:!1,hideReplies:!1,hidePinnedPosts:!1,hideUserAccount:!1,txtMaxLines:"",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){let e={};return"profile"===this.mtSettings.timelineType?this.mtSettings.userId?(e.timeline=`${t}accounts/${this.mtSettings.userId}/statuses?limit=${this.mtSettings.maxNbPostFetch}`,this.mtSettings.hidePinnedPosts||(e.pinned=`${t}accounts/${this.mtSettings.userId}/statuses?pinned=true`)):this.#n("Please check your userId value","⚠️"):"hashtag"===this.mtSettings.timelineType?this.mtSettings.hashtagName?e.timeline=`${t}timelines/tag/${this.mtSettings.hashtagName}?limit=${this.mtSettings.maxNbPostFetch}`:this.#n("Please check your hashtagName value","⚠️"):"local"===this.mtSettings.timelineType?e.timeline=`${t}timelines/public?local=true&limit=${this.mtSettings.maxNbPostFetch}`:this.#n("Please check your timelineType value","⚠️"),this.mtSettings.hideEmojos||(e.emojos=`${t}custom_emojis`),e}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 e=this.fetchedData.timeline;let i=0;if(this.mtBodyNode.replaceChildren(),e.forEach((t=>{const e="public"===t.visibility||!this.mtSettings.hideUnlisted&&"unlisted"===t.visibility,s=this.mtSettings.hideReblog&&t.reblog,a=this.mtSettings.hideReplies&&t.in_reply_to_id;!e||s||a||i${e?.length||0} posts have been fetched from the serverThis 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
"}let g=[];if(t.media_attachments.length>0)for(let e in t.media_attachments)g.push(this.#L(t.media_attachments[e],t.sensitive));if(t.reblog&&t.reblog.media_attachments.length>0)for(let e in t.reblog.media_attachments)g.push(this.#L(t.reblog.media_attachments[e],t.reblog.sensitive));g=`
${g.join("")}
`;let u="";!this.mtSettings.hidePreviewLink&&t.card&&(u=this.#T(t.card));let v="";if(t.poll){let e="";for(let i in t.poll.options)e+="
`,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.umd.js b/dist/mastodon-timeline.umd.js
index 6046f1b..55a307d 100644
--- a/dist/mastodon-timeline.umd.js
+++ b/dist/mastodon-timeline.umd.js
@@ -2,7 +2,7 @@
/**
* Mastodon embed timeline
* @author idotj
- * @version 4.4.1
+ * @version 4.4.2
* @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",dateLocale:"en-GB",dateOptions:{day:"2-digit",month:"short",year:"numeric"},hideUnlisted:!1,hideReblog:!1,hideReplies:!1,hidePinnedPosts:!1,hideUserAccount:!1,txtMaxLines:"",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){let e={};return"profile"===this.mtSettings.timelineType?this.mtSettings.userId?(e.timeline=`${t}accounts/${this.mtSettings.userId}/statuses?limit=${this.mtSettings.maxNbPostFetch}`,this.mtSettings.hidePinnedPosts||(e.pinned=`${t}accounts/${this.mtSettings.userId}/statuses?pinned=true`)):this.#n("Please check your userId value","⚠️"):"hashtag"===this.mtSettings.timelineType?this.mtSettings.hashtagName?e.timeline=`${t}timelines/tag/${this.mtSettings.hashtagName}?limit=${this.mtSettings.maxNbPostFetch}`:this.#n("Please check your hashtagName value","⚠️"):"local"===this.mtSettings.timelineType?e.timeline=`${t}timelines/public?local=true&limit=${this.mtSettings.maxNbPostFetch}`:this.#n("Please check your timelineType value","⚠️"),this.mtSettings.hideEmojos||(e.emojos=`${t}custom_emojis`),e}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 e=this.fetchedData.timeline;let i=0;if(this.mtBodyNode.replaceChildren(),e.forEach((t=>{const e="public"===t.visibility||!this.mtSettings.hideUnlisted&&"unlisted"===t.visibility,s=this.mtSettings.hideReblog&&t.reblog,a=this.mtSettings.hideReplies&&t.in_reply_to_id;!e||s||a||i${e?.length||0} posts have been fetched from the serverThis 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
"}let g=[];if(t.media_attachments.length>0)for(let e in t.media_attachments)g.push(this.#L(t.media_attachments[e],t.sensitive));if(t.reblog&&t.reblog.media_attachments.length>0)for(let e in t.reblog.media_attachments)g.push(this.#L(t.reblog.media_attachments[e],t.reblog.sensitive));g=`
${g.join("")}
`;let u="";!this.mtSettings.hidePreviewLink&&t.card&&(u=this.#T(t.card));let v="";if(t.poll){let e="";for(let i in t.poll.options)e+="
`,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",dateLocale:"en-GB",dateOptions:{day:"2-digit",month:"short",year:"numeric"},hideUnlisted:!1,hideReblog:!1,hideReplies:!1,hidePinnedPosts:!1,hideUserAccount:!1,txtMaxLines:"",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){let e={};return"profile"===this.mtSettings.timelineType?this.mtSettings.userId?(e.timeline=`${t}accounts/${this.mtSettings.userId}/statuses?limit=${this.mtSettings.maxNbPostFetch}`,this.mtSettings.hidePinnedPosts||(e.pinned=`${t}accounts/${this.mtSettings.userId}/statuses?pinned=true`)):this.#n("Please check your userId value","⚠️"):"hashtag"===this.mtSettings.timelineType?this.mtSettings.hashtagName?e.timeline=`${t}timelines/tag/${this.mtSettings.hashtagName}?limit=${this.mtSettings.maxNbPostFetch}`:this.#n("Please check your hashtagName value","⚠️"):"local"===this.mtSettings.timelineType?e.timeline=`${t}timelines/public?local=true&limit=${this.mtSettings.maxNbPostFetch}`:this.#n("Please check your timelineType value","⚠️"),this.mtSettings.hideEmojos||(e.emojos=`${t}custom_emojis`),e}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 e=this.fetchedData.timeline;let i=0;if(this.mtBodyNode.replaceChildren(),e.forEach((t=>{const e="public"===t.visibility||!this.mtSettings.hideUnlisted&&"unlisted"===t.visibility,s=this.mtSettings.hideReblog&&t.reblog,a=this.mtSettings.hideReplies&&t.in_reply_to_id;!e||s||a||i${e?.length||0} posts have been fetched from the serverThis 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
"}let g=[];if(t.media_attachments.length>0)for(let e in t.media_attachments)g.push(this.#L(t.media_attachments[e],t.sensitive));if(t.reblog&&t.reblog.media_attachments.length>0)for(let e in t.reblog.media_attachments)g.push(this.#L(t.reblog.media_attachments[e],t.reblog.sensitive));g=`
${g.join("")}
`;let u="";!this.mtSettings.hidePreviewLink&&t.card&&(u=this.#T(t.card));let v="";if(t.poll){let e="";for(let i in t.poll.options)e+="