From 829c332e13c8e463278e0a8b205bddc1b67e583a Mon Sep 17 00:00:00 2001
From: chylex <contact@chylex.com>
Date: Sat, 5 May 2018 11:47:19 +0200
Subject: [PATCH] Add a global function for mustache injection & fix broken
 clear-columns mustache

---
 Resources/Plugins/clear-columns/browser.js  | 15 +++------
 Resources/Plugins/emoji-keyboard/browser.js |  2 +-
 Resources/Plugins/templates/browser.js      |  2 +-
 Resources/Scripts/code.js                   | 35 +++++++++++++++++++--
 Resources/Scripts/plugins.browser.js        |  1 +
 5 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/Resources/Plugins/clear-columns/browser.js b/Resources/Plugins/clear-columns/browser.js
index 56c16271..b4833248 100644
--- a/Resources/Plugins/clear-columns/browser.js
+++ b/Resources/Plugins/clear-columns/browser.js
@@ -21,10 +21,6 @@ enabled(){
     Object.keys(TD.controller.columnManager.getAll()).forEach(func);
   };
   
-  var replaceMustache = (key, search, replace) => {
-    TD.mustaches[key] = TD.mustaches[key].replace(search, replace);
-  };
-  
   var wasShiftPressed = false;
   
   var updateShiftState = (pressed) => {
@@ -86,22 +82,21 @@ enabled(){
 </a>`;
   
   // add column buttons and keyboard shortcut info to UI
-  replaceMustache("column/column_header.mustache", "</header>", `
+  window.TDPF_injectMustache("column/column_header.mustache", "prepend", "</header>", `
 {{^isTemporary}}
   <a class="column-header-link td-clear-column-shortcut" href="#" data-action="td-clearcolumns-dosingle" style="right:34px">
     <i class="icon icon-clear-timeline js-show-tip" data-placement="bottom" data-original-title="Clear column (hold Shift to restore)"></i>
   </a>
-{{/isTemporary}}
-</header>`);
+{{/isTemporary}}`);
   
-  replaceMustache("keyboard_shortcut_list.mustache", "</dl>  <dl", `
+  window.TDPF_injectMustache("keyboard_shortcut_list.mustache", "prepend", "</dl> <dl", `
 <dd class="keyboard-shortcut-definition" style="white-space:nowrap">
   <span class="text-like-keyboard-key">1</span> … <span class="text-like-keyboard-key">9</span> + <span class="text-like-keyboard-key">Del</span> Clear column 1-9
 </dd><dd class="keyboard-shortcut-definition">
   <span class="text-like-keyboard-key">Alt</span> + <span class="text-like-keyboard-key">Del</span> Clear all columns
-</dd></dl><dl`);
+</dd>`);
   
-  replaceMustache("menus/column_nav_menu.mustache", "{{_i}}Add column{{/i}}</div> </a> </div>", `{{_i}}Add column{{/i}}</div></a>${this.btnClearAllHTML}</div>`)
+  window.TDPF_injectMustache("menus/column_nav_menu.mustache", "replace", "{{_i}}Add column{{/i}}</div> </a> </div>", `{{_i}}Add column{{/i}}</div></a>${this.btnClearAllHTML}</div>`)
   
   // load custom style
   var css = window.TDPF_createCustomStyle(this);
diff --git a/Resources/Plugins/emoji-keyboard/browser.js b/Resources/Plugins/emoji-keyboard/browser.js
index a9ab7088..6984017a 100644
--- a/Resources/Plugins/emoji-keyboard/browser.js
+++ b/Resources/Plugins/emoji-keyboard/browser.js
@@ -54,7 +54,7 @@ enabled(){
   var buttonHTML = '<button class="needsclick btn btn-on-blue txt-left padding-v--6 padding-h--8 emoji-keyboard-popup-btn"><i class="icon icon-heart"></i></button>';
   
   this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
-  TD.mustaches["compose/docked_compose.mustache"] = TD.mustaches["compose/docked_compose.mustache"].replace('<div class="cf margin-t--12 margin-b--30">', '<div class="cf margin-t--12 margin-b--30">'+buttonHTML);
+  window.TDPF_injectMustache("compose/docked_compose.mustache", "append", '<div class="cf margin-t--12 margin-b--30">', buttonHTML);
   
   var maybeDockedComposePanel = $(".js-docked-compose");
   
diff --git a/Resources/Plugins/templates/browser.js b/Resources/Plugins/templates/browser.js
index e1f26f11..450179bc 100644
--- a/Resources/Plugins/templates/browser.js
+++ b/Resources/Plugins/templates/browser.js
@@ -37,7 +37,7 @@ enabled(){
   var buttonHTML = '<button class="manage-templates-btn needsclick btn btn-on-blue full-width txt-left margin-b--12 padding-v--6 padding-h--12"><i class="icon icon-bookmark"></i><span class="label padding-ls">Manage templates</span></button>';
   
   this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
-  TD.mustaches["compose/docked_compose.mustache"] = TD.mustaches["compose/docked_compose.mustache"].replace('<div class="js-tweet-type-button">', buttonHTML+'<div class="js-tweet-type-button">');
+  window.TDPF_injectMustache("compose/docked_compose.mustache", "prepend", '<div class="js-tweet-type-button">', buttonHTML);
   
   var dockedComposePanel = $(".js-docked-compose");
   
diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js
index dfdea8fd..086cc401 100644
--- a/Resources/Scripts/code.js
+++ b/Resources/Scripts/code.js
@@ -1003,10 +1003,40 @@
     };
   })();
   
+  //
+  // Block: Setup global function to inject custom HTML into mustache templates.
+  //
+  window.TDGF_injectMustache = function(name, operation, search, custom){
+    let replacement;
+    
+    switch(operation){
+      case "replace": replacement = custom; break;
+      case "append": replacement = search+custom; break;
+      case "prepend": replacement = custom+search; break;
+      default: throw "Invalid mustache injection operation. Only 'replace', 'append', 'prepend' are supported.";
+    }
+    
+    let prev = TD.mustaches[name];
+    
+    if (!prev){
+      $TD.crashDebug("Mustache injection is referencing an invalid mustache: "+name);
+      return false;
+    }
+    
+    TD.mustaches[name] = prev.replace(search, replacement);
+    
+    if (prev === TD.mustaches[name]){
+      $TD.crashDebug("Mustache injection had no effect: "+name);
+      return false;
+    }
+    
+    return true;
+  };
+  
   //
   // Block: Let's make retweets lowercase again.
   //
-  TD.mustaches["status/tweet_single.mustache"] = TD.mustaches["status/tweet_single.mustache"].replace("{{_i}} Retweeted{{/i}}", "{{_i}} retweeted{{/i}}");
+  window.TDGF_injectMustache("status/tweet_single.mustache", "replace", "{{_i}} Retweeted{{/i}}", "{{_i}} retweeted{{/i}}");
   
   if (ensurePropertyExists(TD, "services", "TwitterActionRetweet", "prototype", "generateText")){
     TD.services.TwitterActionRetweet.prototype.generateText = appendToFunction(TD.services.TwitterActionRetweet.prototype.generateText, function(){
@@ -1075,7 +1105,8 @@
       }
     });
     
-    TD.mustaches["status/media_thumb.mustache"] = TD.mustaches["status/media_thumb.mustache"].replace("is-gif", "is-gif is-paused");
+    window.TDGF_injectMustache("status/media_thumb.mustache", "append", "is-gif", " is-paused");
+    
     TD.mustaches["media/native_video.mustache"] = '<div class="js-media-gif-container media-item nbfc is-video" style="background-image:url({{imageSrc}})"><video class="js-media-gif media-item-gif full-width block {{#isPossiblySensitive}}is-invisible{{/isPossiblySensitive}}" loop src="{{videoUrl}}"></video><a class="js-gif-play pin-all is-actionable">{{> media/video_overlay}}</a></div>';
     
     if (!ensurePropertyExists(TD, "components", "MediaGallery", "prototype", "_loadTweet") ||
diff --git a/Resources/Scripts/plugins.browser.js b/Resources/Scripts/plugins.browser.js
index 1d48f58d..747a7661 100644
--- a/Resources/Scripts/plugins.browser.js
+++ b/Resources/Scripts/plugins.browser.js
@@ -121,4 +121,5 @@
   window.TDPF_playVideo = window.TDGF_playVideo;
   window.TDPF_reloadColumns = window.TDGF_reloadColumns;
   window.TDPF_prioritizeNewestEvent = window.TDGF_prioritizeNewestEvent;
+  window.TDPF_injectMustache = window.TDGF_injectMustache;
 })();