From f5c4ab057359120d16a540e8c03c0075656b756a Mon Sep 17 00:00:00 2001
From: Penar Musaraj <pmusaraj@gmail.com>
Date: Wed, 19 Dec 2018 04:26:09 -0500
Subject: [PATCH] Add category link renderer to plugin API (#6787)

* Add category link renderer to plugin API

- lets themes/plugins override the category link display

- planning to use this in a "category icons" theme component

* small code review fix

* Code review refactor
---
 .../discourse/helpers/category-link.js.es6    | 76 +++++++++++--------
 .../discourse/lib/plugin-api.js.es6           | 17 ++++-
 2 files changed, 59 insertions(+), 34 deletions(-)

diff --git a/app/assets/javascripts/discourse/helpers/category-link.js.es6 b/app/assets/javascripts/discourse/helpers/category-link.js.es6
index 2ae0d9f7c0a..bf3df520f5a 100644
--- a/app/assets/javascripts/discourse/helpers/category-link.js.es6
+++ b/app/assets/javascripts/discourse/helpers/category-link.js.es6
@@ -5,6 +5,12 @@ import { iconHTML } from "discourse-common/lib/icon-library";
 var get = Em.get,
   escapeExpression = Handlebars.Utils.escapeExpression;
 
+let _renderer = defaultCategoryLinkRenderer;
+
+export function replaceCategoryLinkRenderer(fn) {
+  _renderer = fn;
+}
+
 function categoryStripe(color, classes) {
   var style = color ? "style='background-color: #" + color + ";'" : "";
   return "<span class='" + classes + "' " + style + "></span>";
@@ -32,6 +38,43 @@ export function categoryBadgeHTML(category, opts) {
   )
     return "";
 
+  return _renderer(category, opts);
+}
+
+export function categoryLinkHTML(category, options) {
+  var categoryOptions = {};
+
+  // TODO: This is a compatibility layer with the old helper structure.
+  // Can be removed once we migrate to `registerUnbound` fully
+  if (options && options.hash) {
+    options = options.hash;
+  }
+
+  if (options) {
+    if (options.allowUncategorized) {
+      categoryOptions.allowUncategorized = true;
+    }
+    if (options.link !== undefined) {
+      categoryOptions.link = options.link;
+    }
+    if (options.extraClasses) {
+      categoryOptions.extraClasses = options.extraClasses;
+    }
+    if (options.hideParent) {
+      categoryOptions.hideParent = true;
+    }
+    if (options.categoryStyle) {
+      categoryOptions.categoryStyle = options.categoryStyle;
+    }
+  }
+  return new Handlebars.SafeString(
+    categoryBadgeHTML(category, categoryOptions)
+  );
+}
+
+registerUnbound("category-link", categoryLinkHTML);
+
+function defaultCategoryLinkRenderer(category, opts) {
   let description = get(category, "description_text");
   let restricted = get(category, "read_restricted");
   let url = opts.url
@@ -103,36 +146,3 @@ export function categoryBadgeHTML(category, opts) {
   extraClasses = categoryStyle ? categoryStyle + extraClasses : extraClasses;
   return `<${tagName} class="badge-wrapper ${extraClasses}" ${href}>${html}</${tagName}>`;
 }
-
-export function categoryLinkHTML(category, options) {
-  var categoryOptions = {};
-
-  // TODO: This is a compatibility layer with the old helper structure.
-  // Can be removed once we migrate to `registerUnbound` fully
-  if (options && options.hash) {
-    options = options.hash;
-  }
-
-  if (options) {
-    if (options.allowUncategorized) {
-      categoryOptions.allowUncategorized = true;
-    }
-    if (options.link !== undefined) {
-      categoryOptions.link = options.link;
-    }
-    if (options.extraClasses) {
-      categoryOptions.extraClasses = options.extraClasses;
-    }
-    if (options.hideParent) {
-      categoryOptions.hideParent = true;
-    }
-    if (options.categoryStyle) {
-      categoryOptions.categoryStyle = options.categoryStyle;
-    }
-  }
-  return new Handlebars.SafeString(
-    categoryBadgeHTML(category, categoryOptions)
-  );
-}
-
-registerUnbound("category-link", categoryLinkHTML);
diff --git a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 b/app/assets/javascripts/discourse/lib/plugin-api.js.es6
index 685ae3d6250..ba10a5c2d9e 100644
--- a/app/assets/javascripts/discourse/lib/plugin-api.js.es6
+++ b/app/assets/javascripts/discourse/lib/plugin-api.js.es6
@@ -28,6 +28,7 @@ import {
   registerIconRenderer,
   replaceIcon
 } from "discourse-common/lib/icon-library";
+import { replaceCategoryLinkRenderer } from "discourse/helpers/category-link";
 import { addNavItem } from "discourse/models/nav-item";
 import { replaceFormatter } from "discourse/lib/utilities";
 import { modifySelectKit } from "select-kit/mixins/plugin-api";
@@ -39,7 +40,7 @@ import Sharing from "discourse/lib/sharing";
 import { addComposerUploadHandler } from "discourse/components/composer-editor";
 
 // If you add any methods to the API ensure you bump up this number
-const PLUGIN_API_VERSION = "0.8.25";
+const PLUGIN_API_VERSION = "0.8.26";
 
 class PluginApi {
   constructor(version, container) {
@@ -775,6 +776,20 @@ class PluginApi {
   addComposerUploadHandler(extensions, method) {
     addComposerUploadHandler(extensions, method);
   }
+
+  /**
+   * Registers a renderer that overrides the display of category links.
+   *
+   * Example:
+   *
+   * function testReplaceRenderer(category, opts) {
+   *   return "Hello World";
+   * }
+   * api.replaceCategoryLinkRenderer(categoryIconsRenderer);
+   **/
+  replaceCategoryLinkRenderer(fn) {
+    replaceCategoryLinkRenderer(fn);
+  }
 }
 
 let _pluginv01;