Skip to content

Creating an Extension

Jeon Sang Wan edited this page Mar 24, 2020 · 3 revisions

Example 1: Custom video extension

This is a simple example of creating a custom markdown element. The extension is actually replacing some markdown text with a custom directive. The directive is <video video-data="someVar"></video>. The extension assumes that someVar already exists on the page that the markdown is running on.

Here's the code:

(function () {

  var videoHTML = '<video video-data="someAngularVarriableLocalToThisPage"></video>';

  function video() {
    var replace = function () {
      return videoHTML;
    };
    return [
      // Inline style
      {
        type: 'lang',
        regex: '\\[\\s*?!\\[[^()]*\\([^\\(]*\\s*?\\(.* "video"\\)',
        replace: replace
      }];
  }

  // Client-side export
  if (showdown && showdown.extensions) {
    showdown.extensions.video = video;
  }
})();

To load this into ng-showdown, you can reference it like so.

 angular
    .module('example')
    .config(function ($showdownProvider) {
      $showdownProvider.loadExtension('video');
     });

Example 2: Complete Control

Taken from @jspizziri. See Issue #28 for more details.

JsFiddle

I created my own markdown directive as an alternative to the mardown-to-html directive:

// directive/markdown/markdown.js
'use strict';

angular.module('myApp')
  .directive('markdown', function($showdown, $sanitize, $sce) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        scope.$watch('model', function (newValue) {
          var showdownHTML;
          if (typeof newValue === 'string') {
            showdownHTML = $showdown.makeHtml(newValue);
            scope.trustedHtml = ($showdown.getOption('sanitize')) ? $sanitize(showdownHTML) : $sce.trustAsHtml(showdownHTML);
          } else {
            scope.trustedHtml = typeof newValue;
          }
        });
      },
      scope: {
        model: '=markdown'
      },
      template: '<div bind-html-compile="trustedHtml"></div>'
    };
  });

Please note that this is an exact copy of the markdown-to-html directive with the exception of this: template: '<div bind-html-compile="trustedHtml"></div>'.

With that being done, I created another directive bind-html-compile which compiled the html given to it which looks like so:

// directive/bindHtmlCompile/bindHtmlCompile.js
'use strict';

angular.module('myApp')
  .directive('bindHtmlCompile', function($compile) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        scope.$watch(function() {
          return scope.$eval(attrs.bindHtmlCompile);
        }, function(value) {
          element.html(value);
          $compile(element.contents())(scope);
        });
      }
    };
  });

Usage:

<!-- instead of this: -->
<div markdown-to-html="myMarkdown"></div>

<!-- use this: -->
<div markdown="myMarkdown"></div>

Voilà!

Additionally, to keep my organization a little cleaner, I created the showdown extensions as angular constants like so:

// constants/myExt.js
(function(){

  'use strict';

  angular.module('myApp')
    .constant('myExt',
      function myExt() {
        var myext1 = {
           type: 'lang',
           regex: /markdown/g,
           replace: 'showdown'
         };
         var myext2 = {
           /* extension code */
         };
         return [myext1, myext2];
      });

})();

And then injected and registered them in the config:

// app.js

  .config(function($showdownProvider, myExt) {
    $showdownProvider.setOption('tables', true);
    //...

    $showdownProvider.loadExtension(myExt);
    //...
  })
Clone this wiki locally