mirror of
				https://gitlab.com/idotj/mastodon-embed-timeline.git
				synced 2025-10-29 22:22:23 +00:00 
			
		
		
		
	Feature/emojo support
This commit is contained in:
		
							parent
							
								
									526d01f797
								
							
						
					
					
						commit
						da04faa369
					
				| @ -1,3 +1,7 @@ | |||||||
|  | v3.8.2 - xx/08/2023 | ||||||
|  | - Add support to customized emojis | ||||||
|  | - Javascript refactoring to allow multiple requests | ||||||
|  | 
 | ||||||
| v3.8.1 - 14/08/2023 | v3.8.1 - 14/08/2023 | ||||||
| - Show preview card from link, photo or video URL | - Show preview card from link, photo or video URL | ||||||
| - Add description for the ALT attribute in images | - Add description for the ALT attribute in images | ||||||
|  | |||||||
| @ -83,7 +83,10 @@ hide_replies: false, | |||||||
| // Hide preview for links. Default: don't hide | // Hide preview for links. Default: don't hide | ||||||
| hide_preview_link: false, | hide_preview_link: false, | ||||||
| 
 | 
 | ||||||
| // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag (default: don't apply) | // Show custom emojis available on the server. Default: show them | ||||||
|  | show_emojos: true, | ||||||
|  | 
 | ||||||
|  | // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag. Default: don't apply | ||||||
| markdown_blockquote: false, | markdown_blockquote: false, | ||||||
| 
 | 
 | ||||||
| // Limit the text content to a maximum number of lines. Default: 0 (unlimited) | // Limit the text content to a maximum number of lines. Default: 0 (unlimited) | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Mastodon embed feed timeline v3.8.1 */ | /* Mastodon embed feed timeline v3.8.2 */ | ||||||
| /* More info at: */ | /* More info at: */ | ||||||
| /* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ | /* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ | ||||||
| 
 | 
 | ||||||
| @ -97,14 +97,14 @@ html[data-theme="dark"] { | |||||||
| .mt-avatar { | .mt-avatar { | ||||||
|   position: absolute; |   position: absolute; | ||||||
|   top: 1rem; |   top: 1rem; | ||||||
|   left: 5px; |   left: 0.25rem; | ||||||
|   width: 3rem; |   width: 3rem; | ||||||
|   height: 3rem; |   height: 3rem; | ||||||
|   background-repeat: no-repeat; |   background-repeat: no-repeat; | ||||||
|   background-position: 50% 50%; |   background-position: 50% 50%; | ||||||
|   background-size: contain; |   background-size: contain; | ||||||
|   background-color: var(--bg-color); |   background-color: var(--bg-color); | ||||||
|   border-radius: 5px; |   border-radius: 0.25rem; | ||||||
| } | } | ||||||
| .mt-avatar-boosted { | .mt-avatar-boosted { | ||||||
|   width: 2.5rem; |   width: 2.5rem; | ||||||
| @ -145,11 +145,16 @@ html[data-theme="dark"] { | |||||||
| .toot-text:not(.truncate) .ellipsis::after { | .toot-text:not(.truncate) .ellipsis::after { | ||||||
|   content: "..."; |   content: "..."; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| .toot-text blockquote { | .toot-text blockquote { | ||||||
|   border-left: 4px solid var(--line-gray-color); |   border-left: 0.25rem solid var(--line-gray-color); | ||||||
|   margin-left: 0; |   margin-left: 0; | ||||||
|   padding-left: 8px; |   padding-left: 0.5rem; | ||||||
|  | } | ||||||
|  | .toot-text .custom-emoji { | ||||||
|  |   height: 1.5rem; | ||||||
|  |   min-width: 1.5rem; | ||||||
|  |   margin-bottom: -0.25rem; | ||||||
|  |   width: auto; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .mt-error { | .mt-error { | ||||||
| @ -164,13 +169,15 @@ html[data-theme="dark"] { | |||||||
|   padding: 0.75rem; |   padding: 0.75rem; | ||||||
|   text-align: center; |   text-align: center; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| .mt-error-icon { | .mt-error-icon { | ||||||
|   font-size: 2rem; |   font-size: 2rem; | ||||||
| } | } | ||||||
| .mt-error-message { | .mt-error-message { | ||||||
|   padding: 1rem 0; |   padding: 1rem 0; | ||||||
| } | } | ||||||
|  | .mt-error-message hr { | ||||||
|  |   color: var(--line-gray-color); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| /* Poll */ | /* Poll */ | ||||||
| .toot-poll { | .toot-poll { | ||||||
| @ -244,7 +251,7 @@ html[data-theme="dark"] { | |||||||
| .toot-preview-link { | .toot-preview-link { | ||||||
|   min-height: 4rem; |   min-height: 4rem; | ||||||
|   display: flex; |   display: flex; | ||||||
|   flex-direction: row;   |   flex-direction: row; | ||||||
| 
 | 
 | ||||||
|   border: 1px solid var(--line-gray-color); |   border: 1px solid var(--line-gray-color); | ||||||
|   border-radius: 0.5rem; |   border-radius: 0.5rem; | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Mastodon embed feed timeline v3.8.1 |  * Mastodon embed feed timeline v3.8.2 | ||||||
|  * More info at: |  * More info at: | ||||||
|  * https://gitlab.com/idotj/mastodon-embed-feed-timeline
 |  * https://gitlab.com/idotj/mastodon-embed-feed-timeline
 | ||||||
|  */ |  */ | ||||||
| @ -9,7 +9,7 @@ | |||||||
|  * Adjust these parameters to customize your timeline |  * Adjust these parameters to customize your timeline | ||||||
|  */ |  */ | ||||||
| window.addEventListener("load", () => { | window.addEventListener("load", () => { | ||||||
|   let mapi = new MastodonApi({ |   const customParams = new MastodonApi({ | ||||||
|     // Id of the <div> containing the timeline
 |     // Id of the <div> containing the timeline
 | ||||||
|     container_body_id: "mt-body", |     container_body_id: "mt-body", | ||||||
| 
 | 
 | ||||||
| @ -46,7 +46,10 @@ window.addEventListener("load", () => { | |||||||
|     // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide
 |     // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide
 | ||||||
|     hide_preview_link: false, |     hide_preview_link: false, | ||||||
| 
 | 
 | ||||||
|     // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag (default: don't apply)
 |     // Show custom emojis available on the server. Default: show them
 | ||||||
|  |     show_emojos: true, | ||||||
|  | 
 | ||||||
|  |     // Converts Markdown symbol ">" at the beginning of a paragraph into a blockquote HTML tag. Ddefault: don't apply
 | ||||||
|     markdown_blockquote: false, |     markdown_blockquote: false, | ||||||
| 
 | 
 | ||||||
|     // Limit the text content to a maximum number of lines. Default: 0 (unlimited)
 |     // Limit the text content to a maximum number of lines. Default: 0 (unlimited)
 | ||||||
| @ -60,7 +63,6 @@ window.addEventListener("load", () => { | |||||||
| /** | /** | ||||||
|  * Set all variables with customized values or use default ones |  * Set all variables with customized values or use default ones | ||||||
|  * @param {object} params_ User customized values |  * @param {object} params_ User customized values | ||||||
|  * Trigger color theme function |  | ||||||
|  * Trigger main function to build the timeline |  * Trigger main function to build the timeline | ||||||
|  */ |  */ | ||||||
| const MastodonApi = function (params_) { | const MastodonApi = function (params_) { | ||||||
| @ -83,149 +85,86 @@ const MastodonApi = function (params_) { | |||||||
|     typeof params_.hide_preview_link !== "undefined" |     typeof params_.hide_preview_link !== "undefined" | ||||||
|       ? params_.hide_preview_link |       ? params_.hide_preview_link | ||||||
|       : false; |       : false; | ||||||
|  |   this.SHOW_EMOJOS = | ||||||
|  |     typeof params_.show_emojos !== "undefined" ? params_.show_emojos : true; | ||||||
|   this.MARKDOWN_BLOCKQUOTE = |   this.MARKDOWN_BLOCKQUOTE = | ||||||
|     typeof params_.markdown_blockquote !== "undefined" |     typeof params_.markdown_blockquote !== "undefined" | ||||||
|       ? params_.markdown_blockquote |       ? params_.markdown_blockquote | ||||||
|       : false; |       : false; | ||||||
|   this.TEXT_MAX_LINES = params_.text_max_lines || "0"; |   this.TEXT_MAX_LINES = params_.text_max_lines || "0"; | ||||||
|   this.LINK_SEE_MORE = params_.link_see_more; |   this.LINK_SEE_MORE = params_.link_see_more; | ||||||
|  |   this.FETCHED_DATA = {}; | ||||||
| 
 | 
 | ||||||
|   this.mtBodyContainer = document.getElementById(params_.container_body_id); |   this.mtBodyContainer = document.getElementById(params_.container_body_id); | ||||||
| 
 | 
 | ||||||
|   this.setTheme(); |  | ||||||
| 
 |  | ||||||
|   this.buildTimeline(); |   this.buildTimeline(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Set the theme style choosen by user or browser/OS |  * Trigger functions and construct timeline | ||||||
|  */ |  */ | ||||||
| MastodonApi.prototype.setTheme = function () { | MastodonApi.prototype.buildTimeline = async function () { | ||||||
|   /** |   // Apply color theme
 | ||||||
|    * Set the theme value in the <html> tag using the attribute "data-theme" |   this.setTheme(); | ||||||
|    * @param {string} theme Type of theme to apply: dark or light |  | ||||||
|    */ |  | ||||||
|   const setTheme = function (theme) { |  | ||||||
|     document.documentElement.setAttribute("data-theme", theme); |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   if (this.DEFAULT_THEME === "auto") { |   // Get server data
 | ||||||
|     let systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); |   await this.getTimelineData(); | ||||||
|     systemTheme.matches ? setTheme("dark") : setTheme("light"); | 
 | ||||||
|     // Update the theme if user change browser/OS preference
 |   // Empty the <div> container
 | ||||||
|     systemTheme.addEventListener("change", (e) => { |   this.mtBodyContainer.innerHTML = ""; | ||||||
|       e.matches ? setTheme("dark") : setTheme("light"); | 
 | ||||||
|     }); |   for (let i in this.FETCHED_DATA.timeline) { | ||||||
|  |     // First filter (Public / Unlisted)
 | ||||||
|  |     if ( | ||||||
|  |       this.FETCHED_DATA.timeline[i].visibility == "public" || | ||||||
|  |       (!this.HIDE_UNLISTED && | ||||||
|  |         this.FETCHED_DATA.timeline[i].visibility == "unlisted") | ||||||
|  |     ) { | ||||||
|  |       // Second filter (Reblog / Replies)
 | ||||||
|  |       if ( | ||||||
|  |         (this.HIDE_REBLOG && this.FETCHED_DATA.timeline[i].reblog) || | ||||||
|  |         (this.HIDE_REPLIES && this.FETCHED_DATA.timeline[i].in_reply_to_id) | ||||||
|  |       ) { | ||||||
|  |         // Nothing here (Don't append toots)
 | ||||||
|  |       } else { | ||||||
|  |         // Append toots
 | ||||||
|  |         this.appendToot(this.FETCHED_DATA.timeline[i], Number(i)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Check if there are toots in the container (due to filters applied)
 | ||||||
|  |   if (this.mtBodyContainer.innerHTML === "") { | ||||||
|  |     this.mtBodyContainer.setAttribute("role", "none"); | ||||||
|  |     this.mtBodyContainer.innerHTML = | ||||||
|  |       '<div class="mt-error"><span class="mt-error-icon">📭</span><br/><strong>Sorry, no toots to show</strong><br/><div class="mt-error-message">Got ' + | ||||||
|  |       this.FETCHED_DATA.timeline.length + | ||||||
|  |       ' toots from the server but due to the "hide filters" applied, no toot is shown</div></div>'; | ||||||
|   } else { |   } else { | ||||||
|     setTheme(this.DEFAULT_THEME); |     // Insert link after last toot to visit Mastodon page
 | ||||||
|  |     if (this.LINK_SEE_MORE) { | ||||||
|  |       let linkSeeMorePath = ""; | ||||||
|  |       if (this.TIMELINE_TYPE === "profile") { | ||||||
|  |         linkSeeMorePath = this.PROFILE_NAME; | ||||||
|  |       } else if (this.TIMELINE_TYPE === "hashtag") { | ||||||
|  |         linkSeeMorePath = "tags/" + this.HASHTAG_NAME; | ||||||
|  |       } else if (this.TIMELINE_TYPE === "local") { | ||||||
|  |         linkSeeMorePath = "public/local"; | ||||||
|  |       } | ||||||
|  |       let linkSeeMore = | ||||||
|  |         '<div class="mt-footer"><a href="' + | ||||||
|  |         this.INSTANCE_URL + | ||||||
|  |         "/" + | ||||||
|  |         linkSeeMorePath + | ||||||
|  |         '" class="btn" target="_blank" rel="nofollow noopener noreferrer">' + | ||||||
|  |         this.LINK_SEE_MORE + | ||||||
|  |         "</a></div>"; | ||||||
|  |       this.mtBodyContainer.parentNode.insertAdjacentHTML( | ||||||
|  |         "beforeend", | ||||||
|  |         linkSeeMore | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Listing toots function |  | ||||||
|  */ |  | ||||||
| MastodonApi.prototype.buildTimeline = function () { |  | ||||||
|   let mapi = this; |  | ||||||
|   let requestURL = ""; |  | ||||||
| 
 |  | ||||||
|   // Get request
 |  | ||||||
|   if (this.TIMELINE_TYPE === "profile") { |  | ||||||
|     requestURL = `${this.INSTANCE_URL}/api/v1/accounts/${this.USER_ID}/statuses?limit=${this.TOOTS_LIMIT}`; |  | ||||||
|   } else if (this.TIMELINE_TYPE === "hashtag") { |  | ||||||
|     requestURL = `${this.INSTANCE_URL}/api/v1/timelines/tag/${this.HASHTAG_NAME}?limit=${this.TOOTS_LIMIT}`; |  | ||||||
|   } else if (this.TIMELINE_TYPE === "local") { |  | ||||||
|     requestURL = `${this.INSTANCE_URL}/api/v1/timelines/public?local=true&limit=${this.TOOTS_LIMIT}`; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   fetch(requestURL, { |  | ||||||
|     method: "get", |  | ||||||
|   }) |  | ||||||
|     .then((response) => { |  | ||||||
|       if (response.ok) { |  | ||||||
|         return response.json(); |  | ||||||
|       } else if (response.status === 404) { |  | ||||||
|         throw new Error("404 Not found", { cause: response }); |  | ||||||
|       } else { |  | ||||||
|         throw new Error(response.status); |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|     .then((jsonData) => { |  | ||||||
|       // console.log("jsonData: ", jsonData);
 |  | ||||||
| 
 |  | ||||||
|       // Empty the <div> container
 |  | ||||||
|       this.mtBodyContainer.innerHTML = ""; |  | ||||||
| 
 |  | ||||||
|       for (let i in jsonData) { |  | ||||||
|         // First filter (Public / Unlisted)
 |  | ||||||
|         if ( |  | ||||||
|           jsonData[i].visibility == "public" || |  | ||||||
|           (!this.HIDE_UNLISTED && jsonData[i].visibility == "unlisted") |  | ||||||
|         ) { |  | ||||||
|           // Second filter (Reblog / Replies)
 |  | ||||||
|           if ( |  | ||||||
|             (mapi.HIDE_REBLOG && jsonData[i].reblog) || |  | ||||||
|             (mapi.HIDE_REPLIES && jsonData[i].in_reply_to_id) |  | ||||||
|           ) { |  | ||||||
|             // Nothing here (Don't append toots)
 |  | ||||||
|           } else { |  | ||||||
|             // Format and append toots
 |  | ||||||
|             appendToot.call(mapi, jsonData[i], Number(i)); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       // Check if there are toots in the container (due to filters applied)
 |  | ||||||
|       if (this.mtBodyContainer.innerHTML === "") { |  | ||||||
|         this.mtBodyContainer.setAttribute("role", "none"); |  | ||||||
|         this.mtBodyContainer.innerHTML = |  | ||||||
|           '<div class="mt-error"><span class="mt-error-icon">📭</span><br/><strong>Sorry, no toots to show</strong><br/><div class="mt-error-message">Got ' + |  | ||||||
|           jsonData.length + |  | ||||||
|           ' toots from the server but due to the "hide filters" applied, no toot is shown</div></div>'; |  | ||||||
|       } else { |  | ||||||
|         // Insert link after last toot to visit Mastodon page
 |  | ||||||
|         if (mapi.LINK_SEE_MORE) { |  | ||||||
|           let linkSeeMorePath = ""; |  | ||||||
|           if (this.TIMELINE_TYPE === "profile") { |  | ||||||
|             linkSeeMorePath = mapi.PROFILE_NAME; |  | ||||||
|           } else if (this.TIMELINE_TYPE === "hashtag") { |  | ||||||
|             linkSeeMorePath = "tags/" + this.HASHTAG_NAME; |  | ||||||
|           } else if (this.TIMELINE_TYPE === "local") { |  | ||||||
|             linkSeeMorePath = "public/local"; |  | ||||||
|           } |  | ||||||
|           let linkSeeMore = |  | ||||||
|             '<div class="mt-footer"><a href="' + |  | ||||||
|             mapi.INSTANCE_URL + |  | ||||||
|             "/" + |  | ||||||
|             linkSeeMorePath + |  | ||||||
|             '" class="btn" target="_blank" rel="nofollow noopener noreferrer">' + |  | ||||||
|             mapi.LINK_SEE_MORE + |  | ||||||
|             "</a></div>"; |  | ||||||
|           this.mtBodyContainer.parentNode.insertAdjacentHTML( |  | ||||||
|             "beforeend", |  | ||||||
|             linkSeeMore |  | ||||||
|           ); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|     .catch((err) => { |  | ||||||
|       this.mtBodyContainer.innerHTML = |  | ||||||
|         '<div class="mt-error"><span class="mt-error-icon">❌</span><br/><strong>Sorry, request failed:</strong><br/><div class="mt-error-message">' + |  | ||||||
|         err + |  | ||||||
|         "</div></div>"; |  | ||||||
|       this.mtBodyContainer.setAttribute("role", "none"); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|   /** |  | ||||||
|    * Inner function to add each toot in timeline container |  | ||||||
|    * @param {object} c Toot content |  | ||||||
|    * @param {number} i Index of toot |  | ||||||
|    */ |  | ||||||
|   const appendToot = function (c, i) { |  | ||||||
|     this.mtBodyContainer.insertAdjacentHTML( |  | ||||||
|       "beforeend", |  | ||||||
|       this.assambleToot(c, i) |  | ||||||
|     ); |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   // Toot interactions
 |   // Toot interactions
 | ||||||
|   this.mtBodyContainer.addEventListener("click", function (e) { |   this.mtBodyContainer.addEventListener("click", function (e) { | ||||||
| @ -297,6 +236,108 @@ MastodonApi.prototype.buildTimeline = function () { | |||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Set the theme style chosen by the user or by the browser/OS | ||||||
|  |  */ | ||||||
|  | MastodonApi.prototype.setTheme = function () { | ||||||
|  |   /** | ||||||
|  |    * Set the theme value in the <html> tag using the attribute "data-theme" | ||||||
|  |    * @param {string} theme Type of theme to apply: dark or light | ||||||
|  |    */ | ||||||
|  |   const setTheme = function (theme) { | ||||||
|  |     document.documentElement.setAttribute("data-theme", theme); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   if (this.DEFAULT_THEME === "auto") { | ||||||
|  |     let systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); | ||||||
|  |     systemTheme.matches ? setTheme("dark") : setTheme("light"); | ||||||
|  |     // Update the theme if user change browser/OS preference
 | ||||||
|  |     systemTheme.addEventListener("change", (e) => { | ||||||
|  |       e.matches ? setTheme("dark") : setTheme("light"); | ||||||
|  |     }); | ||||||
|  |   } else { | ||||||
|  |     setTheme(this.DEFAULT_THEME); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Requests to the server to get all the data | ||||||
|  |  */ | ||||||
|  | MastodonApi.prototype.getTimelineData = async function () { | ||||||
|  |   return new Promise((resolve, reject) => { | ||||||
|  |     /** | ||||||
|  |      * Fetch data from server | ||||||
|  |      * @param {string} url address to fetch | ||||||
|  |      * @returns {object} List of objects | ||||||
|  |      */ | ||||||
|  |     async function fetchData(url) { | ||||||
|  |       const response = await fetch(url); | ||||||
|  | 
 | ||||||
|  |       if (!response.ok) { | ||||||
|  |         throw new Error( | ||||||
|  |           "Failed to fetch the following URL: " + | ||||||
|  |             url + | ||||||
|  |             "<hr>" + | ||||||
|  |             "Error status: " + | ||||||
|  |             response.status + | ||||||
|  |             "<hr>" + | ||||||
|  |             "Error message: " + | ||||||
|  |             response.statusText | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       const data = await response.json(); | ||||||
|  |       return data; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // URLs to fetch
 | ||||||
|  |     let urls = {}; | ||||||
|  |     if (this.TIMELINE_TYPE === "profile") { | ||||||
|  |       urls.timeline = `${this.INSTANCE_URL}/api/v1/accounts/${this.USER_ID}/statuses?limit=${this.TOOTS_LIMIT}`; | ||||||
|  |     } else if (this.TIMELINE_TYPE === "hashtag") { | ||||||
|  |       urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/tag/${this.HASHTAG_NAME}?limit=${this.TOOTS_LIMIT}`; | ||||||
|  |     } else if (this.TIMELINE_TYPE === "local") { | ||||||
|  |       urls.timeline = `${this.INSTANCE_URL}/api/v1/timelines/public?local=true&limit=${this.TOOTS_LIMIT}`; | ||||||
|  |     } | ||||||
|  |     if (this.SHOW_EMOJOS) { | ||||||
|  |       urls.emojos = this.INSTANCE_URL + "/api/v1/custom_emojis"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const urlsPromises = Object.entries(urls).map(([key, url]) => { | ||||||
|  |       return fetchData(url) | ||||||
|  |         .then((data) => ({ [key]: data })) | ||||||
|  |         .catch((error) => { | ||||||
|  |           reject(new Error("Something went wrong fetching data")); | ||||||
|  |           this.mtBodyContainer.innerHTML = | ||||||
|  |             '<div class="mt-error"><span class="mt-error-icon">❌</span><br/><strong>Sorry, request failed:</strong><br/><div class="mt-error-message">' + | ||||||
|  |             error.message + | ||||||
|  |             "</div></div>"; | ||||||
|  |           this.mtBodyContainer.setAttribute("role", "none"); | ||||||
|  |           return { [key]: [] }; | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     // Fetch all urls simultaneously
 | ||||||
|  |     Promise.all(urlsPromises).then((dataObjects) => { | ||||||
|  |       this.FETCHED_DATA = dataObjects.reduce((result, dataItem) => { | ||||||
|  |         return { ...result, ...dataItem }; | ||||||
|  |       }, {}); | ||||||
|  | 
 | ||||||
|  |       // console.log("Timeline data: ", this.FETCHED_DATA);
 | ||||||
|  |       resolve(); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Inner function to add each toot in timeline container | ||||||
|  |  * @param {object} c Toot content | ||||||
|  |  * @param {number} i Index of toot | ||||||
|  |  */ | ||||||
|  | MastodonApi.prototype.appendToot = function (c, i) { | ||||||
|  |   this.mtBodyContainer.insertAdjacentHTML("beforeend", this.assambleToot(c, i)); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Build toot structure |  * Build toot structure | ||||||
|  * @param {object} c Toot content |  * @param {object} c Toot content | ||||||
| @ -503,6 +544,11 @@ MastodonApi.prototype.formatTootText = function (c) { | |||||||
|   // Format hashtags and mentions
 |   // Format hashtags and mentions
 | ||||||
|   content = this.addTarget2hashtagMention(content); |   content = this.addTarget2hashtagMention(content); | ||||||
| 
 | 
 | ||||||
|  |   // Convert emojos shortcode into images
 | ||||||
|  |   if (this.SHOW_EMOJOS) { | ||||||
|  |     content = this.showEmojos(content, this.FETCHED_DATA.emojos); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   // Convert markdown styles into HTML
 |   // Convert markdown styles into HTML
 | ||||||
|   if (this.MARKDOWN_BLOCKQUOTE) { |   if (this.MARKDOWN_BLOCKQUOTE) { | ||||||
|     content = this.replaceHTMLtag( |     content = this.replaceHTMLtag( | ||||||
| @ -532,6 +578,28 @@ MastodonApi.prototype.addTarget2hashtagMention = function (c) { | |||||||
|   return content; |   return content; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Find all custom emojis shortcode and replace by image | ||||||
|  |  * @param {string} c Text content | ||||||
|  |  * @param {array} e List with all custom emojis | ||||||
|  |  * @returns {string} Text content modified | ||||||
|  |  */ | ||||||
|  | MastodonApi.prototype.showEmojos = function (c, e) { | ||||||
|  |   if (c.includes(":")) { | ||||||
|  |     for (const emojo of e) { | ||||||
|  |       const regex = new RegExp(`\\:${emojo.shortcode}\\:`, "g"); | ||||||
|  |       c = c.replace( | ||||||
|  |         regex, | ||||||
|  |         `<img src="${emojo.url}" class="custom-emoji" alt="Emoji ${emojo.shortcode}" />` | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return c; | ||||||
|  |   } else { | ||||||
|  |     return c; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Find all start/end <tags> and replace them by another start/end <tags> |  * Find all start/end <tags> and replace them by another start/end <tags> | ||||||
|  * @param {string} c Text content |  * @param {string} c Text content | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								src/mastodon-timeline.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/mastodon-timeline.min.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								src/mastodon-timeline.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/mastodon-timeline.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 i.j
						i.j