text: (function(addon) {
  
      if (typeof define == "function" && define.amd) { // AMD
          define("uikit-markdownarea", ["uikit"], function(){
              return jQuery.UIkit.markdownarea || addon(window, window.jQuery, window.jQuery.UIkit);
          });
      }
  
      if(window && window.jQuery && window.jQuery.UIkit) {
          addon(window, window.jQuery, window.jQuery.UIkit);
      }
  
  })(function(global, $, UI){
  
      var Markdownarea = function(element, options){
  
          var $element = $(element);
  
          if($element.data("markdownarea")) return;
  
          this.element = $element;
          this.options = $.extend({}, Markdownarea.defaults, options);
  
          this.marked     = this.options.marked || marked;
          this.CodeMirror = this.options.CodeMirror || CodeMirror;
  
          this.marked.setOptions({
            gfm           : true,
            tables        : true,
            breaks        : true,
            pedantic      : true,
            sanitize      : false,
            smartLists    : true,
            smartypants   : false,
            langPrefix    : 'lang-'
          });
  
          this.init();
  
          this.element.data("markdownarea", this);
      };
  
      $.extend(Markdownarea.prototype, {
  
          init: function(){
  
              var $this = this, tpl = Markdownarea.template;
  
              tpl = tpl.replace(/\{\:lblPreview\}/g, this.options.lblPreview);
              tpl = tpl.replace(/\{\:lblCodeview\}/g, this.options.lblCodeview);
  
              this.markdownarea = $(tpl);
              this.content      = this.markdownarea.find(".uk-markdownarea-content");
              this.toolbar      = this.markdownarea.find(".uk-markdownarea-toolbar");
              this.preview      = this.markdownarea.find(".uk-markdownarea-preview").children().eq(0);
              this.code         = this.markdownarea.find(".uk-markdownarea-code");
  
              this.element.before(this.markdownarea).appendTo(this.code);
  
              this.editor = this.CodeMirror.fromTextArea(this.element[0], this.options.codemirror);
  
              this.editor.markdownarea = this;
  
              this.editor.on("change", (function(){
                  var render = function(){
  
                      var value   = $this.editor.getValue();
  
                      $this.currentvalue  = String(value);
  
                      $this.element.trigger("markdownarea-before", [$this]);
  
                      $this.applyPlugins();
  
                      $this.marked($this.currentvalue, function (err, markdown) {
  
                        if (err) throw err;
  
                        $this.preview.html(markdown);
                        $this.element.val($this.editor.getValue()).trigger("markdownarea-update", [$this]);
                      });
                  };
                  render();
                  return UI.Utils.debounce(render, 150);
              })());
  
              this.code.find(".CodeMirror").css("height", this.options.height);
  
              this._buildtoolbar();
              this.fit();
  
              $(window).on("resize", UI.Utils.debounce(function(){
                  $this.fit();
              }, 200));
  
  
              var previewContainer = $this.preview.parent(),
                  codeContent      = this.code.find('.CodeMirror-sizer'),
                  codeScroll       = this.code.find('.CodeMirror-scroll').on('scroll',UI.Utils.debounce(function() {
  
                      if($this.markdownarea.attr("data-mode")=="tab") return;
  
                      // calc position
                      var codeHeight       = codeContent.height()   - codeScroll.height(),
                          previewHeight    = previewContainer[0].scrollHeight - previewContainer.height(),
                          ratio            = previewHeight / codeHeight,
                          previewPostition = codeScroll.scrollTop() * ratio;
  
                      // apply new scroll
                      previewContainer.scrollTop(previewPostition);
              }, 10));
  
              this.markdownarea.on("click", ".uk-markdown-button-markdown, .uk-markdown-button-preview", function(e){
  
                  e.preventDefault();
  
                  if($this.markdownarea.attr("data-mode")=="tab") {
  
                      $this.markdownarea.find(".uk-markdown-button-markdown, .uk-markdown-button-preview").removeClass("uk-active").filter(this).addClass("uk-active");
  
                      $this.activetab = $(this).hasClass("uk-markdown-button-markdown") ? "code":"preview";
                      $this.markdownarea.attr("data-active-tab", $this.activetab);
                  }
              });
  
              this.preview.parent().css("height", this.code.height());
          },
  
          applyPlugins: function(){
  
              var $this   = this,
                  plugins = Object.keys(Markdownarea.plugins),
                  plgs    = Markdownarea.plugins;
  
              this.markers = {};
  
              if(plugins.length) {
  
                  var lines = this.currentvalue.split("\n");
  
                  plugins.forEach(function(name){
                      this.markers[name] = [];
                  }, this);
  
                  for(var line=0,max=lines.length;line<max;line++) {
  
                      (function(line){
                          plugins.forEach(function(name){
  
                              var i = 0;
  
                              lines[line] = lines[line].replace(plgs[name].identifier, function(){
  
                                  var replacement =  plgs[name].cb({
                                      "area" : $this,
                                      "found": arguments,
                                      "line" : line,
                                      "pos"  : i++,
                                      "uid"  : [name, line, i, (new Date().getTime())+"RAND"+(Math.ceil(Math.random() *100000))].join('-'),
                                      "replace": function(strwith){
                                          var src   = this.area.editor.getLine(this.line),
                                              start = src.indexOf(this.found[0]);
                                              end   = start + this.found[0].length;
  
                                          this.area.editor.replaceRange(strwith, {"line": this.line, "ch":start}, {"line": this.line, "ch":end} );
                                      }
                                  });
  
                                  return replacement;
                              });
                          });
                      })(line);
                  }
  
                  this.currentvalue = lines.join("\n");
  
              }
          },
  
          _buildtoolbar: function(){
  
              if(!(this.options.toolbar && this.options.toolbar.length)) return;
  
              var $this = this, bar = [];
  
              this.options.toolbar.forEach(function(cmd){
                  if(Markdownarea.commands[cmd]) {
  
                     var title = Markdownarea.commands[cmd].title ? Markdownarea.commands[cmd].title : cmd;
  
                     bar.push('<li><a data-markdownarea-cmd="'+cmd+'" title="'+title+'" data-uk-tooltip>'+Markdownarea.commands[cmd].label+'</a></li>');
  
                     if(Markdownarea.commands[cmd].shortcut) {
                         $this.registerShortcut(Markdownarea.commands[cmd].shortcut, Markdownarea.commands[cmd].action);
                     }
                  }
              });
  
              this.toolbar.html(bar.join("\n"));
  
              this.markdownarea.on("click", "a[data-markdownarea-cmd]", function(){
                  var cmd = $(this).data("markdownareaCmd");
  
                  if(cmd && Markdownarea.commands[cmd] && (!$this.activetab || $this.activetab=="code" || cmd=="fullscreen")) {
                      Markdownarea.commands[cmd].action.apply($this, [$this.editor])
                  }
  
              });
          },
  
          fit: function() {
  
              var mode = this.options.mode;
  
              if(mode=="split" && this.markdownarea.width() < this.options.maxsplitsize) {
                  mode = "tab";
              }
  
              if(mode=="tab") {
  
                  if(!this.activetab) {
                      this.activetab = "code";
                      this.markdownarea.attr("data-active-tab", this.activetab);
                  }
  
                  this.markdownarea.find(".uk-markdown-button-markdown, .uk-markdown-button-preview").removeClass("uk-active")
                                   .filter(this.activetab=="code" ? '.uk-markdown-button-markdown':'.uk-markdown-button-preview').addClass("uk-active");
  
              }
  
              this.editor.refresh();
              this.preview.parent().css("height", this.code.height());
  
              this.markdownarea.attr("data-mode", mode);
          },
  
          registerShortcut: function(combination, callback){
  
              var $this = this;
  
              combination = $.isArray(combination) ? combination : [combination];
  
              for(var i=0,max=combination.length;i < max;i++) {
                  var map = {};
  
                  map[combination[i]] = function(){
                      callback.apply($this, [$this.editor]);
                  };
  
                  $this.editor.addKeyMap(map);
              }
          },
  
          getMode: function(){
              var pos = this.editor.getDoc().getCursor();
  
              return this.editor.getTokenAt(pos).state.base.htmlState ? 'html':'markdown';
          }
      });
  
      //jQuery plugin
  
      $.fn.markdownarea = function(options){
  
          return this.each(function(){
  
              var ele = $(this);
  
              if(!ele.data("markdownarea")) {
                  var obj = new Markdownarea(ele, options);
              }
          });
      };
  
      var baseReplacer = function(replace, editor){
          var text     = editor.getSelection(),
              markdown = replace.replace('$1', text);
  
          editor.replaceSelection(markdown, 'end');
      };
  
      Markdownarea.commands = {
          "fullscreen": {
              "title"  : 'Fullscreen',
              "label"  : '<i class="uk-icon-expand"></i>',
              "action" : function(editor){
  
                  editor.markdownarea.markdownarea.toggleClass("uk-markdownarea-fullscreen");
  
                  var wrap = editor.getWrapperElement();
  
                  if(editor.markdownarea.markdownarea.hasClass("uk-markdownarea-fullscreen")) {
  
                      editor.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset, width: wrap.style.width, height: wrap.style.height};
                      wrap.style.width  = "";
                      wrap.style.height = editor.markdownarea.content.height()+"px";
                      document.documentElement.style.overflow = "hidden";
  
                  } else {
  
                      document.documentElement.style.overflow = "";
                      var info = editor.state.fullScreenRestore;
                      wrap.style.width = info.width; wrap.style.height = info.height;
                      window.scrollTo(info.scrollLeft, info.scrollTop);
                  }
  
                  editor.refresh();
                  editor.markdownarea.preview.parent().css("height", editor.markdownarea.code.height());
              }
          },
  
          "bold" : {
              "title"  : "Bold",
              "label"  : '<i class="uk-icon-bold"></i>',
              "shortcut": ['Ctrl-B', 'Cmd-B'],
              "action" : function(editor){
                  baseReplacer(this.getMode() == 'html' ? "<strong>$1</strong>":"**$1**", editor);
              }
          },
          "italic" : {
              "title"  : "Italic",
              "label"  : '<i class="uk-icon-italic"></i>',
              "action" : function(editor){
                  baseReplacer(this.getMode() == 'html' ? "<em>$1</em>":"*$1*", editor);
              }
          },
          "strike" : {
              "title"  : "Strikethrough",
              "label"  : '<i class="uk-icon-strikethrough"></i>',
              "action" : function(editor){
                  baseReplacer(this.getMode() == 'html' ? "<del>$1</del>":"~~$1~~", editor);
              }
          },
          "blockquote" : {
              "title"  : "Blockquote",
              "label"  : '<i class="uk-icon-quote-right"></i>',
              "action" : function(editor){
                  baseReplacer(this.getMode() == 'html' ? "<blockquote><p>$1</p></blockquote>":"> $1", editor);
              }
          },
          "link" : {
              "title"  : "Link",
              "label"  : '<i class="uk-icon-link"></i>',
              "action" : function(editor){
                  baseReplacer(this.getMode() == 'html' ? '<a href="http://">$1</a>':"[$1](http://)", editor);
              }
          },
          "picture" : {
              "title"  : "Picture",
              "label"  : '<i class="uk-icon-picture-o"></i>',
              "action" : function(editor){
                  baseReplacer(this.getMode() == 'html' ? '<img src="http://" alt="$1">':"![$1](http://)", editor);
              }
          },
          "listUl" : {
              "title"  : "Unordered List",
              "label"  : '<i class="uk-icon-list-ul"></i>',
              "action" : function(editor){
                  if(this.getMode() == 'markdown') baseReplacer("* $1", editor);
              }
          },
          "listOl" : {
              "title"  : "Ordered List",
              "label"  : '<i class="uk-icon-list-ol"></i>',
              "action" : function(editor){
                  if(this.getMode() == 'markdown') baseReplacer("1. $1", editor);
              }
          }
      }
  
      Markdownarea.defaults = {
          "mode"         : "split",
          "height"       : 500,
          "maxsplitsize" : 1000,
          "codemirror"   : { mode: 'gfm', tabMode: 'indent', tabindex: "2", lineWrapping: true, dragDrop: false, autoCloseTags: true, matchTags: true },
          "toolbar"      : [ "bold", "italic", "strike", "link", "picture", "blockquote", "listUl", "listOl" ],
          "lblPreview"   : "Preview",
          "lblCodeview"  : "Markdown"
      };
  
      Markdownarea.template = '<div class="uk-markdownarea uk-clearfix" data-mode="split">' +
                                  '<div class="uk-markdownarea-navbar">' +
                                      '<ul class="uk-markdownarea-navbar-nav uk-markdownarea-toolbar"></ul>' +
                                      '<div class="uk-markdownarea-navbar-flip">' +
                                          '<ul class="uk-markdownarea-navbar-nav">' +
                                              '<li class="uk-markdown-button-markdown"><a>{:lblCodeview}</a></li>' +
                                              '<li class="uk-markdown-button-preview"><a>{:lblPreview}</a></li>' +
                                              '<li><a data-markdownarea-cmd="fullscreen"><i class="uk-icon-expand"></i></a></li>' +
                                          '</ul>' +
                                      '</div>' +
                                  '</div>' +
                                  '<div class="uk-markdownarea-content">' +
                                      '<div class="uk-markdownarea-code"></div>' +
                                      '<div class="uk-markdownarea-preview"><div></div></div>' +
                                  '</div>' +
                              '</div>';
  
      Markdownarea.plugins   = {};
      Markdownarea.addPlugin = function(name, identifier, callback) {
          Markdownarea.plugins[name] = {"identifier":identifier, "cb":callback};
      };
  
      UI["markdownarea"] = Markdownarea;
  
      // init code
      $(function() {
  
          $("textarea[data-uk-markdownarea]").each(function() {
              var area = $(this), obj;
  
              if (!area.data("markdownarea")) {
                  obj = new Markdownarea(area, UI.Utils.options(area.attr("data-uk-markdownarea")));
              }
          });
      });
  
      return Markdownarea;
  });