Переглянути джерело

chore(all): code style change

Estevão Soares dos Santos 10 роки тому
батько
коміт
8b000b134a
60 змінених файлів з 1280 додано та 1309 видалено
  1. 1 1
      Gruntfile.js
  2. 127 127
      src/angular.js
  3. 28 22
      src/helpers.js
  4. 5 5
      src/loader.js
  5. 95 92
      src/showdown.js
  6. 123 124
      src/subParsers/anchors.js
  7. 20 22
      src/subParsers/autoLinks.js
  8. 17 17
      src/subParsers/blockGamut.js
  9. 41 44
      src/subParsers/blockQuotes.js
  10. 37 39
      src/subParsers/codeBlocks.js
  11. 21 22
      src/subParsers/codeSpans.js
  12. 18 21
      src/subParsers/detab.js
  13. 7 7
      src/subParsers/encodeAmpsAndAngles.js
  14. 4 4
      src/subParsers/encodeBackslashEscapes.js
  15. 16 16
      src/subParsers/encodeCode.js
  16. 33 38
      src/subParsers/encodeEmailAddress.js
  17. 10 10
      src/subParsers/escapeSpecialCharsWithinTagAttributes.js
  18. 17 21
      src/subParsers/githubCodeBlocks.js
  19. 3 3
      src/subParsers/hashBlock.js
  20. 12 12
      src/subParsers/hashElement.js
  21. 130 124
      src/subParsers/hashHTMLBlocks.js
  22. 60 60
      src/subParsers/headers.js
  23. 87 95
      src/subParsers/images.js
  24. 5 7
      src/subParsers/italicsAndBold.js
  25. 132 136
      src/subParsers/lists.js
  26. 7 7
      src/subParsers/outdent.js
  27. 28 30
      src/subParsers/paragraphs.js
  28. 17 18
      src/subParsers/spanGamut.js
  29. 2 2
      src/subParsers/stripBlankLines.js
  30. 21 21
      src/subParsers/stripLinkDefinitions.js
  31. 6 8
      src/subParsers/unescapeSpecialChars.js
  32. 3 3
      test/cases/anchors-by-reference.html
  33. 6 6
      test/cases/blockquote-nested-markdown.html
  34. 2 2
      test/cases/blockquote.html
  35. 2 2
      test/cases/doubline-list.html
  36. 1 1
      test/cases/emphasis.html
  37. 1 1
      test/cases/escaped-number-period.html
  38. 2 2
      test/cases/github-style-at-start.html
  39. 2 2
      test/cases/github-style-codeblock.html
  40. 1 1
      test/cases/github-style-linebreaks.html
  41. 5 5
      test/cases/horizontal-rules.html
  42. 3 2
      test/cases/html5-strutural-tags.html
  43. 3 3
      test/cases/images.html
  44. 2 1
      test/cases/implicit-anchors.html
  45. 1 1
      test/cases/inline-escaped-chars.html
  46. 3 1
      test/cases/inline-style-tag.html
  47. 2 2
      test/cases/lazy-blockquote.html
  48. 4 3
      test/cases/list-with-blockquote.html
  49. 3 2
      test/cases/list-with-code.html
  50. 2 2
      test/cases/multi-paragraph-list.html
  51. 4 3
      test/cases/multiline-unordered-list.html
  52. 5 5
      test/cases/nested-blockquote.html
  53. 3 3
      test/cases/ordered-list-same-number.html
  54. 3 3
      test/cases/ordered-list-wrong-numbers.html
  55. 3 3
      test/cases/ordered-list.html
  56. 3 3
      test/cases/unordered-list-asterisk.html
  57. 3 3
      test/cases/unordered-list-minus.html
  58. 3 3
      test/cases/unordered-list-plus.html
  59. 2 1
      test/cases/url-with-parenthesis.html
  60. 73 85
      test/node/Container/testMakeHtml.js

+ 1 - 1
Gruntfile.js

@@ -10,7 +10,7 @@ module.exports = function (grunt) {
         concat: {
             options: {
                 sourceMap: true,
-                banner: ";/*! <%= pkg.name %> <%= grunt.template.today('dd-mm-yyyy') %> */\n(function(){\n 'use strict';\n",
+                banner: ";/*! <%= pkg.name %> <%= grunt.template.today('dd-mm-yyyy') %> */\n(function(){\n",
                 footer: "}).call(this)"
             },
             dist: {

+ 127 - 127
src/angular.js

@@ -6,145 +6,145 @@
 //Check if AngularJs and Showdown is defined and only load ng-Showdown if both are present
 if (typeof angular !== 'undefined' && typeof showdown !== 'undefined') {
 
-    (function (module, showdown) {
-        'use strict';
+  (function (module, showdown) {
+    'use strict';
+
+    module.provider('$showdown', provider).directive('sdModelToHtml',
+                                                     ['$showdown', markdownToHtmlDirective]).filter('sdStripHtml',
+                                                                                                    stripHtmlFilter);
+
+    /**
+     * Angular Provider
+     * Enables configuration of showdown via angular.config and Dependency Injection into controllers, views
+     * directives, etc... This assures the directives and filters provided by the library itself stay consistent
+     * with the user configurations.
+     * If the user wants to use a different configuration in a determined context, he can use the "classic" Showdown
+     * object instead.
+     */
+    function provider() {
+
+      // Configuration parameters for Showdown
+      var config = {
+        extensions: [],
+        stripHtml:  true
+      };
+
+      /**
+       * Sets a configuration option
+       *
+       * @param {string} key Config parameter key
+       * @param {string} value Config parameter value
+       */
+      /* jshint validthis: true */
+      this.setOption = function (key, value) {
+        config[key] = value;
+
+        return this;
+      };
+
+      /**
+       * Gets the value of the configuration parameter specified by key
+       *
+       * @param {string} key The config parameter key
+       * @returns {string|null} Returns the value of the config parameter. (or null if the config parameter is not set)
+       */
+      this.getOption = function (key) {
+        if (config.hasOwnProperty(key)) {
+          return config.key;
+        } else {
+          return null;
+        }
+      };
 
-        module
-            .provider('$showdown', provider)
-            .directive('sdModelToHtml', ['$showdown', markdownToHtmlDirective])
-            .filter('sdStripHtml', stripHtmlFilter);
+      /**
+       * Loads a Showdown Extension
+       *
+       * @param {string} extensionName The name of the extension to load
+       */
+      this.loadExtension = function (extensionName) {
+        config.extensions.push(extensionName);
 
-        /**
-         * Angular Provider
-         * Enables configuration of showdown via angular.config and Dependency Injection into controllers, views
-         * directives, etc... This assures the directives and filters provided by the library itself stay consistent
-         * with the user configurations.
-         * If the user wants to use a different configuration in a determined context, he can use the "classic" Showdown
-         * object instead.
-         */
-        function provider() {
-
-            // Configuration parameters for Showdown
-            var config = {
-                extensions: [],
-                stripHtml: true
-            };
-
-            /**
-             * Sets a configuration option
-             *
-             * @param {string} key Config parameter key
-             * @param {string} value Config parameter value
-             */ /* jshint validthis: true */
-            this.setOption = function (key, value) {
-                config[key] = value;
-
-                return this;
-            };
-
-            /**
-             * Gets the value of the configuration parameter specified by key
-             *
-             * @param {string} key The config parameter key
-             * @returns {string|null} Returns the value of the config parameter. (or null if the config parameter is not set)
-             */
-            this.getOption = function (key) {
-                if (config.hasOwnProperty(key)) {
-                    return config.key;
-                } else {
-                    return null;
-                }
-            };
-
-            /**
-             * Loads a Showdown Extension
-             *
-             * @param {string} extensionName The name of the extension to load
-             */
-            this.loadExtension = function (extensionName) {
-                config.extensions.push(extensionName);
-
-                return this;
-            };
-
-            function SDObject() {
-                var converter = new showdown.Converter(config);
-
-                /**
-                 * Converts a markdown text into HTML
-                 *
-                 * @param {string} markdown The markdown string to be converted to HTML
-                 * @returns {string} The converted HTML
-                 */
-                this.makeHtml = function (markdown) {
-                    return converter.makeHtml(markdown);
-                };
-
-                /**
-                 * Strips a text of it's HTML tags
-                 *
-                 * @param {string} text
-                 * @returns {string}
-                 */
-                this.stripHtml = function (text) {
-                    return String(text).replace(/<[^>]+>/gm, '');
-                };
-            }
-
-            // The object returned by service provider
-            this.$get = function () {
-                return new SDObject();
-            };
-        }
+        return this;
+      };
+
+      function SDObject() {
+        var converter = new showdown.Converter(config);
 
         /**
-         * AngularJS Directive to Md to HTML transformation
-         *
-         * Usage example:
-         * <div sd-md-to-html-model="markdownText" ></div>
+         * Converts a markdown text into HTML
          *
-         * @param $showdown
-         * @returns {*}
+         * @param {string} markdown The markdown string to be converted to HTML
+         * @returns {string} The converted HTML
          */
-        function markdownToHtmlDirective($showdown) {
-
-            var link = function (scope, element) {
-                scope.$watch('model', function (newValue) {
-                    var val;
-                    if (typeof newValue === 'string') {
-                        val = $showdown.makeHtml(newValue);
-                    } else {
-                        val = typeof newValue;
-                    }
-                    element.html(val);
-                });
-            };
-
-            return {
-                restrict: 'A',
-                link: link,
-                scope: {
-                    model: '=sdModelToHtml'
-                }
-            };
-        }
+        this.makeHtml = function (markdown) {
+          return converter.makeHtml(markdown);
+        };
 
         /**
-         * AngularJS Filter to Strip HTML tags from text
+         * Strips a text of it's HTML tags
          *
-         * @returns {Function}
+         * @param {string} text
+         * @returns {string}
          */
-        function stripHtmlFilter() {
-            return function (text) {
-                return String(text).replace(/<[^>]+>/gm, '');
-            };
+        this.stripHtml = function (text) {
+          return String(text).replace(/<[^>]+>/gm, '');
+        };
+      }
+
+      // The object returned by service provider
+      this.$get = function () {
+        return new SDObject();
+      };
+    }
+
+    /**
+     * AngularJS Directive to Md to HTML transformation
+     *
+     * Usage example:
+     * <div sd-md-to-html-model="markdownText" ></div>
+     *
+     * @param $showdown
+     * @returns {*}
+     */
+    function markdownToHtmlDirective($showdown) {
+
+      var link = function (scope, element) {
+        scope.$watch('model', function (newValue) {
+          var val;
+          if (typeof newValue === 'string') {
+            val = $showdown.makeHtml(newValue);
+          } else {
+            val = typeof newValue;
+          }
+          element.html(val);
+        });
+      };
+
+      return {
+        restrict: 'A',
+        link:     link,
+        scope:    {
+          model: '=sdModelToHtml'
         }
-
-    })(angular.module('showdown', []), showdown);
+      };
+    }
+
+    /**
+     * AngularJS Filter to Strip HTML tags from text
+     *
+     * @returns {Function}
+     */
+    function stripHtmlFilter() {
+      return function (text) {
+        return String(text).replace(/<[^>]+>/gm, '');
+      };
+    }
+
+  })(angular.module('showdown', []), showdown);
 
 } else {
 
-    /** TODO Since this library is opt out, maybe we should not throw an error so we can concatenate this
-     script with the main lib */
-    // throw new Error("ng-showdown was not loaded because one of it's dependencies (AngularJS or Showdown) wasn't met");
+  /** TODO Since this library is opt out, maybe we should not throw an error so we can concatenate this
+   script with the main lib */
+  // throw new Error("ng-showdown was not loaded because one of it's dependencies (AngularJS or Showdown) wasn't met");
 }

+ 28 - 22
src/helpers.js

@@ -3,50 +3,56 @@
  */
 
 function isString(a) {
-    return (typeof a === 'string' || a instanceof String);
+  'use strict';
+  return (typeof a === 'string' || a instanceof String);
 }
 
 function forEach(obj, callback) {
-    if (typeof obj.forEach === 'function') {
-        obj.forEach(callback);
-    } else {
-        var i, len = obj.length;
-        for (i = 0; i < len; i++) {
-            callback(obj[i], i, obj);
-        }
+  'use strict';
+  if (typeof obj.forEach === 'function') {
+    obj.forEach(callback);
+  } else {
+    var i, len = obj.length;
+    for (i = 0; i < len; i++) {
+      callback(obj[i], i, obj);
     }
+  }
 }
 
 function isArray(a) {
-    return a.constructor === Array;
+  'use strict';
+  return a.constructor === Array;
 }
 
 function isUndefined(value) {
-    return typeof value === 'undefined';
+  'use strict';
+  return typeof value === 'undefined';
 }
 
 var escapeCharactersCallback = function (wholeMatch, m1) {
-    var charCodeToEscape = m1.charCodeAt(0);
-    return '~E' + charCodeToEscape + 'E';
+  'use strict';
+  var charCodeToEscape = m1.charCodeAt(0);
+  return '~E' + charCodeToEscape + 'E';
 };
 
 var escapeCharacters = function (text, charsToEscape, afterBackslash) {
-    // First we have to escape the escape characters so that
-    // we can build a character class out of them
-    var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
+  'use strict';
+  // First we have to escape the escape characters so that
+  // we can build a character class out of them
+  var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
 
-    if (afterBackslash) {
-        regexString = '\\\\' + regexString;
-    }
+  if (afterBackslash) {
+    regexString = '\\\\' + regexString;
+  }
 
-    var regex = new RegExp(regexString, 'g');
-    text = text.replace(regex, escapeCharactersCallback);
+  var regex = new RegExp(regexString, 'g');
+  text = text.replace(regex, escapeCharactersCallback);
 
-    return text;
+  return text;
 };
 
 if (!showdown.hasOwnProperty('helper')) {
-    showdown.helper = {};
+  showdown.helper = {};
 }
 
 /**

+ 5 - 5
src/loader.js

@@ -6,15 +6,15 @@ var root = this;
 
 // CommonJS/nodeJS Loader
 if (typeof module !== 'undefined' && module.exports) {
-    module.exports = showdown;
+  module.exports = showdown;
 }
 // AMD Loader
 else if (typeof define === 'function' && define.amd) {
-    define('showdown', function () {
-        return showdown;
-    });
+  define('showdown', function () {
+    return showdown;
+  });
 }
 // Regular Browser loader
 else {
-    root.showdown = showdown;
+  root.showdown = showdown;
 }

+ 95 - 92
src/showdown.js

@@ -6,8 +6,8 @@
 var showdown = {},
     parsers = {},
     globalOptions = {
-        omitExtraWLInCodeBlocks: false,
-        prefixHeaderId: false
+      omitExtraWLInCodeBlocks: false,
+      prefixHeaderId:          false
     };
 
 ///////////////////////////////////////////////////////////////////////////
@@ -19,7 +19,6 @@ var showdown = {},
  */
 showdown.helper = {};
 
-
 ///////////////////////////////////////////////////////////////////////////
 // API
 //
@@ -29,16 +28,19 @@ showdown.extensions = {};
 
 //Public methods
 showdown.setOption = function (key, value) {
-    globalOptions[key] = value;
-    return this;
+  'use strict';
+  globalOptions[key] = value;
+  return this;
 };
 
 showdown.getOption = function (key) {
-    return globalOptions[key];
+  'use strict';
+  return globalOptions[key];
 };
 
 showdown.getOptions = function () {
-    return globalOptions;
+  'use strict';
+  return globalOptions;
 };
 
 /**
@@ -51,17 +53,18 @@ showdown.getOptions = function () {
  * @returns {*}
  */
 showdown.subParser = function (name, func) {
-    if (showdown.helper.isString(name)) {
-        if (typeof func !== 'undefined') {
-            parsers[name] = func;
-        } else {
-            if (parsers.hasOwnProperty(name)) {
-                return parsers[name];
-            } else {
-                throw Error('SubParser named ' + name + ' not registered!');
-            }
-        }
+  'use strict';
+  if (showdown.helper.isString(name)) {
+    if (typeof func !== 'undefined') {
+      parsers[name] = func;
+    } else {
+      if (parsers.hasOwnProperty(name)) {
+        return parsers[name];
+      } else {
+        throw Error('SubParser named ' + name + ' not registered!');
+      }
     }
+  }
 };
 
 /**
@@ -70,85 +73,85 @@ showdown.subParser = function (name, func) {
  * @returns {{makeHtml: Function}}
  */
 showdown.Converter = function (converterOptions) {
+  'use strict';
+
+  converterOptions = converterOptions || {};
+
+  var options = globalOptions,
+      parserOrder = [
+        'detab',
+        'stripBlankLines',
+        //runLanguageExtensions,
+        'githubCodeBlocks',
+        'hashHTMLBlocks',
+        'stripLinkDefinitions',
+        'blockGamut',
+        'unescapeSpecialChars'
+      ];
+
+  // Merge options
+  if (typeof converterOptions === 'object') {
+    for (var opt in converterOptions) {
+      if (converterOptions.hasOwnProperty(opt)) {
+        options[opt] = converterOptions[opt];
+      }
+    }
+  }
 
-    converterOptions = converterOptions || {};
-
-    var options = globalOptions,
-        parserOrder = [
-            'detab',
-            'stripBlankLines',
-            //runLanguageExtensions,
-            'githubCodeBlocks',
-            'hashHTMLBlocks',
-            'stripLinkDefinitions',
-            'blockGamut',
-            'unescapeSpecialChars'
-        ];
-
-    // Merge options
-    if (typeof converterOptions === 'object') {
-        for (var opt in converterOptions) {
-            if (converterOptions.hasOwnProperty(opt)) {
-                options[opt] = converterOptions[opt];
-            }
-        }
+  var makeHtml = function (text) {
+
+    //check if text is not falsy
+    if (!text) {
+      return text;
     }
 
-    var makeHtml = function (text) {
-
-        //check if text is not falsy
-        if (!text) {
-            return text;
-        }
-
-        var globals = {
-            gHtmlBlocks: [],
-            gUrls: {},
-            gTitles: {},
-            gListLevel: 0,
-            hashLinkCounts: {}
-        };
-
-        // attacklab: Replace ~ with ~T
-        // This lets us use tilde as an escape char to avoid md5 hashes
-        // The choice of character is arbitrary; anything that isn't
-        // magic in Markdown will work.
-        text = text.replace(/~/g, '~T');
-
-        // attacklab: Replace $ with ~D
-        // RegExp interprets $ as a special character
-        // when it's in a replacement string
-        text = text.replace(/\$/g, '~D');
-
-        // Standardize line endings
-        text = text.replace(/\r\n/g, '\n'); // DOS to Unix
-        text = text.replace(/\r/g, '\n'); // Mac to Unix
-
-        // Make sure text begins and ends with a couple of newlines:
-        text = '\n\n' + text + '\n\n';
-
-        // Run all registered parsers
-        for (var i = 0; i < parserOrder.length; ++i) {
-            var name = parserOrder[i];
-            text = parsers[name](text, options, globals);
-        }
-
-        // attacklab: Restore dollar signs
-        text = text.replace(/~D/g, '$$');
-
-        // attacklab: Restore tildes
-        text = text.replace(/~T/g, '~');
-
-        // Run output modifiers
-        //showdown.forEach(g_output_modifiers, function (x) {
-        //    text = _ExecuteExtension(x, text);
-        //});
-
-        return text;
+    var globals = {
+      gHtmlBlocks:    [],
+      gUrls:          {},
+      gTitles:        {},
+      gListLevel:     0,
+      hashLinkCounts: {}
     };
 
+    // attacklab: Replace ~ with ~T
+    // This lets us use tilde as an escape char to avoid md5 hashes
+    // The choice of character is arbitrary; anything that isn't
+    // magic in Markdown will work.
+    text = text.replace(/~/g, '~T');
 
-    return {
-        makeHtml: makeHtml
-    };
+    // attacklab: Replace $ with ~D
+    // RegExp interprets $ as a special character
+    // when it's in a replacement string
+    text = text.replace(/\$/g, '~D');
+
+    // Standardize line endings
+    text = text.replace(/\r\n/g, '\n'); // DOS to Unix
+    text = text.replace(/\r/g, '\n'); // Mac to Unix
+
+    // Make sure text begins and ends with a couple of newlines:
+    text = '\n\n' + text + '\n\n';
+
+    // Run all registered parsers
+    for (var i = 0; i < parserOrder.length; ++i) {
+      var name = parserOrder[i];
+      text = parsers[name](text, options, globals);
+    }
+
+    // attacklab: Restore dollar signs
+    text = text.replace(/~D/g, '$$');
+
+    // attacklab: Restore tildes
+    text = text.replace(/~T/g, '~');
+
+    // Run output modifiers
+    //showdown.forEach(g_output_modifiers, function (x) {
+    //    text = _ExecuteExtension(x, text);
+    //});
+
+    return text;
+  };
+
+  return {
+    makeHtml: makeHtml
+  };
 };

+ 123 - 124
src/subParsers/anchors.js

@@ -6,131 +6,130 @@
  * Turn Markdown link shortcuts into XHTML <a> tags.
  */
 showdown.subParser('anchors', function (text, config, globals) {
-    'use strict';
-
-    var writeAnchorTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
-        if (showdown.helper.isUndefined(m7)) {
-            m7 = '';
-        }
-        wholeMatch = m1;
-        var linkText = m2,
-            linkId = m3.toLowerCase(),
-            url = m4,
-            title = m7;
-
-        if (!url) {
-            if (!linkId) {
-                // lower-case and turn embedded newlines into spaces
-                linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
-            }
-            url = '#' + linkId;
-
-            if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
-                url = globals.gUrls[linkId];
-                if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
-                    title = globals.gTitles[linkId];
-                }
-            }
-            else {
-                if (wholeMatch.search(/\(\s*\)$/m) > -1) {
-                    // Special case for explicit empty url
-                    url = '';
-                } else {
-                    return wholeMatch;
-                }
-            }
+  'use strict';
+
+  var writeAnchorTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
+    if (showdown.helper.isUndefined(m7)) {
+      m7 = '';
+    }
+    wholeMatch = m1;
+    var linkText = m2,
+        linkId = m3.toLowerCase(),
+        url = m4,
+        title = m7;
+
+    if (!url) {
+      if (!linkId) {
+        // lower-case and turn embedded newlines into spaces
+        linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
+      }
+      url = '#' + linkId;
+
+      if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
+        url = globals.gUrls[linkId];
+        if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
+          title = globals.gTitles[linkId];
         }
-
-        url = showdown.helper.escapeCharacters(url, '*_');
-        var result = '<a href="' + url + '"';
-
-        if (title !== '' && title !== null) {
-            title = title.replace(/"/g, '&quot;');
-            title = showdown.helper.escapeCharacters(title, '*_');
-            result += ' title="' + title + '"';
+      } else {
+        if (wholeMatch.search(/\(\s*\)$/m) > -1) {
+          // Special case for explicit empty url
+          url = '';
+        } else {
+          return wholeMatch;
         }
-
-        result += '>' + linkText + '</a>';
-
-        return result;
-    };
-
-    // First, handle reference-style links: [link text] [id]
-    /*
-     text = text.replace(/
-     (							// wrap whole match in $1
-     \[
-     (
-     (?:
-     \[[^\]]*\]		// allow brackets nested one level
-     |
-     [^\[]			// or anything else
-     )*
-     )
-     \]
-
-     [ ]?					// one optional space
-     (?:\n[ ]*)?				// one optional newline followed by spaces
-
-     \[
-     (.*?)					// id = $3
-     \]
-     )()()()()					// pad remaining backreferences
-     /g,_DoAnchors_callback);
-     */
-    text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
-
-    //
-    // Next, inline-style links: [link text](url "optional title")
-    //
-
-    /*
-     text = text.replace(/
-     (						// wrap whole match in $1
-     \[
-     (
-     (?:
-     \[[^\]]*\]	// allow brackets nested one level
-     |
-     [^\[\]]			// or anything else
-     )
-     )
-     \]
-     \(						// literal paren
-     [ \t]*
-     ()						// no id, so leave $3 empty
-     <?(.*?)>?				// href = $4
-     [ \t]*
-     (						// $5
-     (['"])				// quote char = $6
-     (.*?)				// Title = $7
-     \6					// matching quote
-     [ \t]*				// ignore any spaces/tabs between closing quote and )
-     )?						// title is optional
-     \)
-     )
-     /g,writeAnchorTag);
-     */
-    text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);
-
-    //
-    // Last, handle reference-style shortcuts: [link text]
-    // These must come last in case you've also got [link test][1]
-    // or [link test](/foo)
-    //
-
-    /*
-     text = text.replace(/
-     (		 					// wrap whole match in $1
-     \[
-     ([^\[\]]+)				// link text = $2; can't contain '[' or ']'
-     \]
-     )()()()()()					// pad rest of backreferences
-     /g, writeAnchorTag);
-     */
-    text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
-
-    return text;
-
+      }
+    }
+
+    url = showdown.helper.escapeCharacters(url, '*_');
+    var result = '<a href="' + url + '"';
+
+    if (title !== '' && title !== null) {
+      title = title.replace(/"/g, '&quot;');
+      title = showdown.helper.escapeCharacters(title, '*_');
+      result += ' title="' + title + '"';
+    }
+
+    result += '>' + linkText + '</a>';
+
+    return result;
+  };
+
+  // First, handle reference-style links: [link text] [id]
+  /*
+   text = text.replace(/
+   (							// wrap whole match in $1
+   \[
+   (
+   (?:
+   \[[^\]]*\]		// allow brackets nested one level
+   |
+   [^\[]			// or anything else
+   )*
+   )
+   \]
+
+   [ ]?					// one optional space
+   (?:\n[ ]*)?				// one optional newline followed by spaces
+
+   \[
+   (.*?)					// id = $3
+   \]
+   )()()()()					// pad remaining backreferences
+   /g,_DoAnchors_callback);
+   */
+  text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
+
+  //
+  // Next, inline-style links: [link text](url "optional title")
+  //
+
+  /*
+   text = text.replace(/
+   (						// wrap whole match in $1
+   \[
+   (
+   (?:
+   \[[^\]]*\]	// allow brackets nested one level
+   |
+   [^\[\]]			// or anything else
+   )
+   )
+   \]
+   \(						// literal paren
+   [ \t]*
+   ()						// no id, so leave $3 empty
+   <?(.*?)>?				// href = $4
+   [ \t]*
+   (						// $5
+   (['"])				// quote char = $6
+   (.*?)				// Title = $7
+   \6					// matching quote
+   [ \t]*				// ignore any spaces/tabs between closing quote and )
+   )?						// title is optional
+   \)
+   )
+   /g,writeAnchorTag);
+   */
+  text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,
+                      writeAnchorTag);
+
+  //
+  // Last, handle reference-style shortcuts: [link text]
+  // These must come last in case you've also got [link test][1]
+  // or [link test](/foo)
+  //
+
+  /*
+   text = text.replace(/
+   (		 					// wrap whole match in $1
+   \[
+   ([^\[\]]+)				// link text = $2; can't contain '[' or ']'
+   \]
+   )()()()()()					// pad rest of backreferences
+   /g, writeAnchorTag);
+   */
+  text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
+
+  return text;
 
 });

+ 20 - 22
src/subParsers/autoLinks.js

@@ -3,31 +3,29 @@
  */
 
 showdown.subParser('autoLinks', function (text) {
-    'use strict';
+  'use strict';
 
-    text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, "<a href=\"$1\">$1</a>");
+  text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, "<a href=\"$1\">$1</a>");
 
-    // Email addresses: <address@domain.foo>
+  // Email addresses: <address@domain.foo>
 
-    /*
-     text = text.replace(/
-     <
-     (?:mailto:)?
-     (
-     [-.\w]+
-     \@
-     [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
-     )
-     >
-     /gi, _DoAutoLinks_callback());
-     */
-    text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
-        function (wholeMatch, m1) {
-            var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
-            return showdown.subParser('encodeEmailAddress')(unescapedStr);
-        }
-    );
+  /*
+   text = text.replace(/
+   <
+   (?:mailto:)?
+   (
+   [-.\w]+
+   \@
+   [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
+   )
+   >
+   /gi, _DoAutoLinks_callback());
+   */
+  text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, function (wholeMatch, m1) {
+    var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
+    return showdown.subParser('encodeEmailAddress')(unescapedStr);
+  });
 
-    return text;
+  return text;
 
 });

+ 17 - 17
src/subParsers/blockGamut.js

@@ -7,27 +7,27 @@
  * tags like paragraphs, headers, and list items.
  */
 showdown.subParser('blockGamut', function (text, options, globals) {
-    'use strict';
+  'use strict';
 
-    text = showdown.subParser('headers')(text, options, globals);
+  text = showdown.subParser('headers')(text, options, globals);
 
-    // Do Horizontal Rules:
-    var key = showdown.subParser('hashBlock')('<hr />', options, globals);
-    text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, key);
-    text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, key);
-    text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm, key);
+  // Do Horizontal Rules:
+  var key = showdown.subParser('hashBlock')('<hr />', options, globals);
+  text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, key);
+  text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, key);
+  text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm, key);
 
-    text = showdown.subParser('lists')(text, options, globals);
-    text = showdown.subParser('codeBlocks')(text, options, globals);
-    text = showdown.subParser('blockQuotes')(text, options, globals);
+  text = showdown.subParser('lists')(text, options, globals);
+  text = showdown.subParser('codeBlocks')(text, options, globals);
+  text = showdown.subParser('blockQuotes')(text, options, globals);
 
-    // We already ran _HashHTMLBlocks() before, in Markdown(), but that
-    // was to escape raw HTML in the original Markdown source. This time,
-    // we're escaping the markup we've just created, so that we don't wrap
-    // <p> tags around block-level tags.
-    text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
-    text = showdown.subParser('paragraphs')(text, options, globals);
+  // We already ran _HashHTMLBlocks() before, in Markdown(), but that
+  // was to escape raw HTML in the original Markdown source. This time,
+  // we're escaping the markup we've just created, so that we don't wrap
+  // <p> tags around block-level tags.
+  text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
+  text = showdown.subParser('paragraphs')(text, options, globals);
 
-    return text;
+  return text;
 });
 

+ 41 - 44
src/subParsers/blockQuotes.js

@@ -3,48 +3,45 @@
  */
 
 showdown.subParser('blockQuotes', function (text, options, globals) {
-    'use strict';
-
-    /*
-     text = text.replace(/
-     (								// Wrap whole match in $1
-     (
-     ^[ \t]*>[ \t]?			// '>' at the start of a line
-     .+\n					// rest of the first line
-     (.+\n)*					// subsequent consecutive lines
-     \n*						// blanks
-     )+
-     )
-     /gm, function(){...});
-     */
-
-    text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
-        function (wholeMatch, m1) {
-            var bq = m1;
-
-            // attacklab: hack around Konqueror 3.5.4 bug:
-            // "----------bug".replace(/^-/g,"") == "bug"
-            bq = bq.replace(/^[ \t]*>[ \t]?/gm, '~0'); // trim one level of quoting
-
-            // attacklab: clean up hack
-            bq = bq.replace(/~0/g, '');
-
-            bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
-            bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
-
-            bq = bq.replace(/(^|\n)/g, '$1  ');
-            // These leading spaces screw with <pre> content, so we need to fix that:
-            bq = bq.replace(
-                /(\s*<pre>[^\r]+?<\/pre>)/gm,
-                function (wholeMatch, m1) {
-                    var pre = m1;
-                    // attacklab: hack around Konqueror 3.5.4 bug:
-                    pre = pre.replace(/^  /mg, '~0');
-                    pre = pre.replace(/~0/g, '');
-                    return pre;
-                });
-
-            return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
-        });
-    return text;
+  'use strict';
+
+  /*
+   text = text.replace(/
+   (								// Wrap whole match in $1
+   (
+   ^[ \t]*>[ \t]?			// '>' at the start of a line
+   .+\n					// rest of the first line
+   (.+\n)*					// subsequent consecutive lines
+   \n*						// blanks
+   )+
+   )
+   /gm, function(){...});
+   */
+
+  text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, function (wholeMatch, m1) {
+    var bq = m1;
+
+    // attacklab: hack around Konqueror 3.5.4 bug:
+    // "----------bug".replace(/^-/g,"") == "bug"
+    bq = bq.replace(/^[ \t]*>[ \t]?/gm, '~0'); // trim one level of quoting
+
+    // attacklab: clean up hack
+    bq = bq.replace(/~0/g, '');
+
+    bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
+    bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
+
+    bq = bq.replace(/(^|\n)/g, '$1  ');
+    // These leading spaces screw with <pre> content, so we need to fix that:
+    bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
+      var pre = m1;
+      // attacklab: hack around Konqueror 3.5.4 bug:
+      pre = pre.replace(/^  /mg, '~0');
+      pre = pre.replace(/~0/g, '');
+      return pre;
+    });
+
+    return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
+  });
+  return text;
 });

+ 37 - 39
src/subParsers/codeBlocks.js

@@ -6,43 +6,41 @@
  * Process Markdown `<pre><code>` blocks.
  */
 showdown.subParser('codeBlocks', function (text, options, globals) {
-    'use strict';
-
-    /*
-     text = text.replace(text,
-     /(?:\n\n|^)
-     (								// $1 = the code block -- one or more lines, starting with a space/tab
-     (?:
-     (?:[ ]{4}|\t)			// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
-     .*\n+
-     )+
-     )
-     (\n*[ ]{0,3}[^ \t\n]|(?=~0))	// attacklab: g_tab_width
-     /g,function(){...});
-     */
-
-    // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
-    text += '~0';
-
-    text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
-        function (wholeMatch, m1, m2) {
-            var codeblock = m1,
-                nextChar = m2;
-
-            codeblock = showdown.subParser('outdent')(codeblock);
-            codeblock = showdown.subParser('encodeCode')(codeblock);
-            codeblock = showdown.subParser('detab')(codeblock);
-            codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
-            codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
-
-            codeblock = '<pre><code>' + codeblock + '\n</code></pre>';
-
-            return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
-        }
-    );
-
-    // attacklab: strip sentinel
-    text = text.replace(/~0/, '');
-
-    return text;
+  'use strict';
+
+  /*
+   text = text.replace(text,
+   /(?:\n\n|^)
+   (								// $1 = the code block -- one or more lines, starting with a space/tab
+   (?:
+   (?:[ ]{4}|\t)			// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
+   .*\n+
+   )+
+   )
+   (\n*[ ]{0,3}[^ \t\n]|(?=~0))	// attacklab: g_tab_width
+   /g,function(){...});
+   */
+
+  // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+  text += '~0';
+
+  text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
+                      function (wholeMatch, m1, m2) {
+                        var codeblock = m1, nextChar = m2;
+
+                        codeblock = showdown.subParser('outdent')(codeblock);
+                        codeblock = showdown.subParser('encodeCode')(codeblock);
+                        codeblock = showdown.subParser('detab')(codeblock);
+                        codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
+                        codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
+
+                        codeblock = '<pre><code>' + codeblock + '\n</code></pre>';
+
+                        return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
+                      });
+
+  // attacklab: strip sentinel
+  text = text.replace(/~0/, '');
+
+  return text;
 });

+ 21 - 22
src/subParsers/codeSpans.js

@@ -28,30 +28,29 @@
  *         ... type <code>`bar`</code> ...
  */
 showdown.subParser('codeSpans', function (text) {
-    'use strict';
+  'use strict';
 
-    /*
-     text = text.replace(/
-     (^|[^\\])					// Character before opening ` can't be a backslash
-     (`+)						// $2 = Opening run of `
-     (							// $3 = The code block
-     [^\r]*?
-     [^`]					// attacklab: work around lack of lookbehind
-     )
-     \2							// Matching closer
-     (?!`)
-     /gm, function(){...});
-     */
+  /*
+   text = text.replace(/
+   (^|[^\\])					// Character before opening ` can't be a backslash
+   (`+)						// $2 = Opening run of `
+   (							// $3 = The code block
+   [^\r]*?
+   [^`]					// attacklab: work around lack of lookbehind
+   )
+   \2							// Matching closer
+   (?!`)
+   /gm, function(){...});
+   */
 
-    text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
-        function (wholeMatch, m1, m2, m3) {
-            var c = m3;
-            c = c.replace(/^([ \t]*)/g, '');	// leading whitespace
-            c = c.replace(/[ \t]*$/g, '');	// trailing whitespace
-            c = showdown.subParser('encodeCode')(c);
-            return m1 + '<code>' + c + '</code>';
-        });
+  text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, function (wholeMatch, m1, m2, m3) {
+    var c = m3;
+    c = c.replace(/^([ \t]*)/g, '');	// leading whitespace
+    c = c.replace(/[ \t]*$/g, '');	// trailing whitespace
+    c = showdown.subParser('encodeCode')(c);
+    return m1 + '<code>' + c + '</code>';
+  });
 
-    return text;
+  return text;
 
 });

+ 18 - 21
src/subParsers/detab.js

@@ -6,33 +6,30 @@
  * Convert all tabs to spaces
  */
 showdown.subParser('detab', function (text) {
-    'use strict';
+  'use strict';
 
-    // expand first n-1 tabs
-    text = text.replace(/\t(?=\t)/g, '    '); // g_tab_width
+  // expand first n-1 tabs
+  text = text.replace(/\t(?=\t)/g, '    '); // g_tab_width
 
-    // replace the nth with two sentinels
-    text = text.replace(/\t/g, '~A~B');
+  // replace the nth with two sentinels
+  text = text.replace(/\t/g, '~A~B');
 
-    // use the sentinel to anchor our regex so it doesn't explode
-    text = text.replace(/~B(.+?)~A/g,
-        function (wholeMatch, m1) {
-            var leadingText = m1,
-                numSpaces = 4 - leadingText.length % 4;  // g_tab_width
+  // use the sentinel to anchor our regex so it doesn't explode
+  text = text.replace(/~B(.+?)~A/g, function (wholeMatch, m1) {
+    var leadingText = m1, numSpaces = 4 - leadingText.length % 4;  // g_tab_width
 
-            // there *must* be a better way to do this:
-            for (var i = 0; i < numSpaces; i++) {
-                leadingText += ' ';
-            }
+    // there *must* be a better way to do this:
+    for (var i = 0; i < numSpaces; i++) {
+      leadingText += ' ';
+    }
 
-            return leadingText;
-        }
-    );
+    return leadingText;
+  });
 
-    // clean up sentinels
-    text = text.replace(/~A/g, '    ');  // g_tab_width
-    text = text.replace(/~B/g, '');
+  // clean up sentinels
+  text = text.replace(/~A/g, '    ');  // g_tab_width
+  text = text.replace(/~B/g, '');
 
-    return text;
+  return text;
 
 });

+ 7 - 7
src/subParsers/encodeAmpsAndAngles.js

@@ -6,13 +6,13 @@
  * Smart processing for ampersands and angle brackets that need to be encoded.
  */
 showdown.subParser('encodeAmpsAndAngles', function (text) {
-    'use strict';
-    // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
-    // http://bumppo.net/projects/amputator/
-    text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
+  'use strict';
+  // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
+  // http://bumppo.net/projects/amputator/
+  text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
 
-    // Encode naked <'s
-    text = text.replace(/<(?![a-z\/?\$!])/gi, '&lt;');
+  // Encode naked <'s
+  text = text.replace(/<(?![a-z\/?\$!])/gi, '&lt;');
 
-    return text;
+  return text;
 });

+ 4 - 4
src/subParsers/encodeBackslashEscapes.js

@@ -14,8 +14,8 @@
  * as an optimization for Firefox.  This function gets called a LOT.
  */
 showdown.subParser('encodeBackslashEscapes', function (text) {
-    'use strict';
-    text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
-    text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, showdown.helper.escapeCharactersCallback);
-    return text;
+  'use strict';
+  text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
+  text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, showdown.helper.escapeCharactersCallback);
+  return text;
 });

+ 16 - 16
src/subParsers/encodeCode.js

@@ -8,26 +8,26 @@
  * and lose their special Markdown meanings.
  */
 showdown.subParser('encodeCode', function (text) {
-    'use strict';
+  'use strict';
 
-    // Encode all ampersands; HTML entities are not
-    // entities within a Markdown code span.
-    text = text.replace(/&/g, '&amp;');
+  // Encode all ampersands; HTML entities are not
+  // entities within a Markdown code span.
+  text = text.replace(/&/g, '&amp;');
 
-    // Do the angle bracket song and dance:
-    text = text.replace(/</g, '&lt;');
-    text = text.replace(/>/g, '&gt;');
+  // Do the angle bracket song and dance:
+  text = text.replace(/</g, '&lt;');
+  text = text.replace(/>/g, '&gt;');
 
-    // Now, escape characters that are magic in Markdown:
-    text = showdown.helper.escapeCharacters(text, '*_{}[]\\', false);
+  // Now, escape characters that are magic in Markdown:
+  text = showdown.helper.escapeCharacters(text, '*_{}[]\\', false);
 
-    // jj the line above breaks this:
-    //---
-    //* Item
-    //   1. Subitem
-    //            special char: *
-    // ---
+  // jj the line above breaks this:
+  //---
+  //* Item
+  //   1. Subitem
+  //            special char: *
+  // ---
 
-    return text;
+  return text;
 
 });

+ 33 - 38
src/subParsers/encodeEmailAddress.js

@@ -2,7 +2,6 @@
  * Created by Estevao on 12-01-2015.
  */
 
-
 /**
  *  Input: an email address, e.g. "foo@example.com"
  *
@@ -19,42 +18,38 @@
  *
  */
 showdown.subParser('encodeEmailAddress', function (addr) {
-    'use strict';
-
-    var encode = [
-        function (ch) {
-            return '&#' + ch.charCodeAt(0) + ';';
-        },
-        function (ch) {
-            return '&#x' + ch.charCodeAt(0).toString(16) + ';';
-        },
-        function (ch) {
-            return ch;
-        }
-    ];
-
-    addr = 'mailto:' + addr;
-
-    addr = addr.replace(/./g, function (ch) {
-        if (ch === '@') {
-            // this *must* be encoded. I insist.
-            ch = encode[Math.floor(Math.random() * 2)](ch);
-        } else if (ch !== ':') {
-            // leave ':' alone (to spot mailto: later)
-            var r = Math.random();
-            // roughly 10% raw, 45% hex, 45% dec
-            ch = (
-                r > 0.9 ? encode[2](ch) :
-                    r > 0.45 ? encode[1](ch) :
-                        encode[0](ch)
-            );
-        }
-        return ch;
-    });
-
-    addr = '<a href="' + addr + '">' + addr + '</a>';
-    addr = addr.replace(/">.+:/g, '">'); // strip the mailto: from the visible part
-
-    return addr;
+  'use strict';
+
+  var encode = [
+    function (ch) {
+      return '&#' + ch.charCodeAt(0) + ';';
+    }, function (ch) {
+      return '&#x' + ch.charCodeAt(0).toString(16) + ';';
+    }, function (ch) {
+      return ch;
+    }
+  ];
+
+  addr = 'mailto:' + addr;
+
+  addr = addr.replace(/./g, function (ch) {
+    if (ch === '@') {
+      // this *must* be encoded. I insist.
+      ch = encode[Math.floor(Math.random() * 2)](ch);
+    } else if (ch !== ':') {
+      // leave ':' alone (to spot mailto: later)
+      var r = Math.random();
+      // roughly 10% raw, 45% hex, 45% dec
+      ch = (
+        r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
+      );
+    }
+    return ch;
+  });
+
+  addr = '<a href="' + addr + '">' + addr + '</a>';
+  addr = addr.replace(/">.+:/g, '">'); // strip the mailto: from the visible part
+
+  return addr;
 
 });

+ 10 - 10
src/subParsers/escapeSpecialCharsWithinTagAttributes.js

@@ -7,17 +7,17 @@
  * don't conflict with their use in Markdown for code, italics and strong.
  */
 showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text) {
-    'use strict';
+  'use strict';
 
-    // Build a regex to find HTML tags and comments.  See Friedl's
-    // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
-    var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
+  // Build a regex to find HTML tags and comments.  See Friedl's
+  // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
+  var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
 
-    text = text.replace(regex, function (wholeMatch) {
-        var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, '$1`');
-        tag = showdown.helper.escapeCharacters(tag, '\\`*_');
-        return tag;
-    });
+  text = text.replace(regex, function (wholeMatch) {
+    var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, '$1`');
+    tag = showdown.helper.escapeCharacters(tag, '\\`*_');
+    return tag;
+  });
 
-    return text;
+  return text;
 });

+ 17 - 21
src/subParsers/githubCodeBlocks.js

@@ -13,34 +13,30 @@
  * ```
  */
 showdown.subParser('githubCodeBlocks', function (text, options, globals) {
-    'use strict';
+  'use strict';
 
-    text += '~0';
+  text += '~0';
 
-    text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,
-        function (wholeMatch, m1, m2) {
-            var language = m1,
-                codeblock = m2,
-                end = '\n';
+  text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g, function (wholeMatch, m1, m2) {
+    var language = m1, codeblock = m2, end = '\n';
 
-            if (options.omitExtraWLInCodeBlocks) {
-                end = '';
-            }
+    if (options.omitExtraWLInCodeBlocks) {
+      end = '';
+    }
 
-            codeblock = showdown.subParser('encodeCode')(codeblock);
-            codeblock = showdown.subParser('detab')(codeblock);
-            codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
-            codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
+    codeblock = showdown.subParser('encodeCode')(codeblock);
+    codeblock = showdown.subParser('detab')(codeblock);
+    codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
+    codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
 
-            codeblock = '<pre><code' + (language ? ' class="' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
+    codeblock = '<pre><code' + (language ? ' class="' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
 
-            return showdown.subParser('hashBlock')(codeblock, options, globals);
-        }
-    );
+    return showdown.subParser('hashBlock')(codeblock, options, globals);
+  });
 
-    // attacklab: strip sentinel
-    text = text.replace(/~0/, '');
+  // attacklab: strip sentinel
+  text = text.replace(/~0/, '');
 
-    return text;
+  return text;
 
 });

+ 3 - 3
src/subParsers/hashBlock.js

@@ -3,7 +3,7 @@
  */
 
 showdown.subParser('hashBlock', function (text, options, globals) {
-    'use strict';
-    text = text.replace(/(^\n+|\n+$)/g, '');
-    return '\n\n~K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
+  'use strict';
+  text = text.replace(/(^\n+|\n+$)/g, '');
+  return '\n\n~K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
 });

+ 12 - 12
src/subParsers/hashElement.js

@@ -3,21 +3,21 @@
  */
 
 showdown.subParser('hashElement', function (text, options, globals) {
-    'use strict';
+  'use strict';
 
-    return function (wholeMatch, m1) {
-        var blockText = m1;
+  return function (wholeMatch, m1) {
+    var blockText = m1;
 
-        // Undo double lines
-        blockText = blockText.replace(/\n\n/g, '\n');
-        blockText = blockText.replace(/^\n/, '');
+    // Undo double lines
+    blockText = blockText.replace(/\n\n/g, '\n');
+    blockText = blockText.replace(/^\n/, '');
 
-        // strip trailing blank lines
-        blockText = blockText.replace(/\n+$/g, '');
+    // strip trailing blank lines
+    blockText = blockText.replace(/\n+$/g, '');
 
-        // Replace the element text with a marker ("~KxK" where x is its key)
-        blockText = '\n\n~K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
+    // Replace the element text with a marker ("~KxK" where x is its key)
+    blockText = '\n\n~K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
 
-        return blockText;
-    };
+    return blockText;
+  };
 });

+ 130 - 124
src/subParsers/hashHTMLBlocks.js

@@ -3,129 +3,135 @@
  */
 
 showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
-    'use strict';
-
-    // attacklab: Double up blank lines to reduce lookaround
-    text = text.replace(/\n/g, '\n\n');
-
-    // Hashify HTML blocks:
-    // We only want to do this for block-level HTML tags, such as headers,
-    // lists, and tables. That's because we still want to wrap <p>s around
-    // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
-    // phrase emphasis, and spans. The list of tags we're looking for is
-    // hard-coded:
-    //var block_tags_a = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside';
-    //var block_tags_b = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside';
-
-    // First, look for nested blocks, e.g.:
-    //   <div>
-    //     <div>
-    //     tags for inner block must be indented.
-    //     </div>
-    //   </div>
-    //
-    // The outermost tags must start at the left margin for this to match, and
-    // the inner nested divs must be indented.
-    // We need to do this before the next, more liberal match, because the next
-    // match will start at the first `<div>` and stop at the first `</div>`.
-
-    // attacklab: This regex can be expensive when it fails.
-    /*
-     var text = text.replace(/
-     (						// save in $1
-     ^					// start of line  (with /m)
-     <($block_tags_a)	// start tag = $2
-     \b					// word break
-     // attacklab: hack around khtml/pcre bug...
-     [^\r]*?\n			// any number of lines, minimally matching
-     </\2>				// the matching end tag
-     [ \t]*				// trailing spaces/tabs
-     (?=\n+)				// followed by a newline
-     )						// attacklab: there are sentinel newlines at end of document
-     /gm,function(){...}};
-     */
-    text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, showdown.subParser('hashElement')(text, options, globals));
-
-    //
-    // Now match more liberally, simply from `\n<tag>` to `</tag>\n`
-    //
-
-    /*
-     var text = text.replace(/
-     (						// save in $1
-     ^					// start of line  (with /m)
-     <($block_tags_b)	// start tag = $2
-     \b					// word break
-     // attacklab: hack around khtml/pcre bug...
-     [^\r]*?				// any number of lines, minimally matching
-     </\2>				// the matching end tag
-     [ \t]*				// trailing spaces/tabs
-     (?=\n+)				// followed by a newline
-     )						// attacklab: there are sentinel newlines at end of document
-     /gm,function(){...}};
-     */
-    text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm, showdown.subParser('hashElement')(text, options, globals));
-
-    // Special case just for <hr />. It was easier to make a special case than
-    // to make the other regex more complicated.
-
-    /*
-     text = text.replace(/
-     (						// save in $1
-     \n\n				// Starting after a blank line
-     [ ]{0,3}
-     (<(hr)				// start tag = $2
-     \b					// word break
-     ([^<>])*?			//
-     \/?>)				// the matching end tag
-     [ \t]*
-     (?=\n{2,})			// followed by a blank line
-     )
-     /g,showdown.subParser('hashElement')(text, options, globals));
-     */
-    text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, showdown.subParser('hashElement')(text, options, globals));
-
-    // Special case for standalone HTML comments:
-
-    /*
-     text = text.replace(/
-     (						// save in $1
-     \n\n				// Starting after a blank line
-     [ ]{0,3}			// attacklab: g_tab_width - 1
-     <!
-     (--[^\r]*?--\s*)+
-     >
-     [ \t]*
-     (?=\n{2,})			// followed by a blank line
-     )
-     /g,showdown.subParser('hashElement')(text, options, globals));
-     */
-    text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g, showdown.subParser('hashElement')(text, options, globals));
-
-    // PHP and ASP-style processor instructions (<?...?> and <%...%>)
-
-    /*
-     text = text.replace(/
-     (?:
-     \n\n				// Starting after a blank line
-     )
-     (						// save in $1
-     [ ]{0,3}			// attacklab: g_tab_width - 1
-     (?:
-     <([?%])			// $2
-     [^\r]*?
-     \2>
-     )
-     [ \t]*
-     (?=\n{2,})			// followed by a blank line
-     )
-     /g,showdown.subParser('hashElement')(text, options, globals));
-     */
-    text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, showdown.subParser('hashElement')(text, options, globals));
-
-    // attacklab: Undo double lines (see comment at top of this function)
-    text = text.replace(/\n\n/g, '\n');
-    return text;
-
+  'use strict';
+
+  // attacklab: Double up blank lines to reduce lookaround
+  text = text.replace(/\n/g, '\n\n');
+
+  // Hashify HTML blocks:
+  // We only want to do this for block-level HTML tags, such as headers,
+  // lists, and tables. That's because we still want to wrap <p>s around
+  // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+  // phrase emphasis, and spans. The list of tags we're looking for is
+  // hard-coded:
+  //var block_tags_a =
+  // 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside';
+  // var block_tags_b =
+  // 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside';
+
+  // First, look for nested blocks, e.g.:
+  //   <div>
+  //     <div>
+  //     tags for inner block must be indented.
+  //     </div>
+  //   </div>
+  //
+  // The outermost tags must start at the left margin for this to match, and
+  // the inner nested divs must be indented.
+  // We need to do this before the next, more liberal match, because the next
+  // match will start at the first `<div>` and stop at the first `</div>`.
+
+  // attacklab: This regex can be expensive when it fails.
+  /*
+   var text = text.replace(/
+   (						// save in $1
+   ^					// start of line  (with /m)
+   <($block_tags_a)	// start tag = $2
+   \b					// word break
+   // attacklab: hack around khtml/pcre bug...
+   [^\r]*?\n			// any number of lines, minimally matching
+   </\2>				// the matching end tag
+   [ \t]*				// trailing spaces/tabs
+   (?=\n+)				// followed by a newline
+   )						// attacklab: there are sentinel newlines at end of document
+   /gm,function(){...}};
+   */
+  text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,
+                      showdown.subParser('hashElement')(text, options, globals));
+
+  //
+  // Now match more liberally, simply from `\n<tag>` to `</tag>\n`
+  //
+
+  /*
+   var text = text.replace(/
+   (						// save in $1
+   ^					// start of line  (with /m)
+   <($block_tags_b)	// start tag = $2
+   \b					// word break
+   // attacklab: hack around khtml/pcre bug...
+   [^\r]*?				// any number of lines, minimally matching
+   </\2>				// the matching end tag
+   [ \t]*				// trailing spaces/tabs
+   (?=\n+)				// followed by a newline
+   )						// attacklab: there are sentinel newlines at end of document
+   /gm,function(){...}};
+   */
+  text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm,
+                      showdown.subParser('hashElement')(text, options, globals));
+
+  // Special case just for <hr />. It was easier to make a special case than
+  // to make the other regex more complicated.
+
+  /*
+   text = text.replace(/
+   (						// save in $1
+   \n\n				// Starting after a blank line
+   [ ]{0,3}
+   (<(hr)				// start tag = $2
+   \b					// word break
+   ([^<>])*?			//
+   \/?>)				// the matching end tag
+   [ \t]*
+   (?=\n{2,})			// followed by a blank line
+   )
+   /g,showdown.subParser('hashElement')(text, options, globals));
+   */
+  text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
+                      showdown.subParser('hashElement')(text, options, globals));
+
+  // Special case for standalone HTML comments:
+
+  /*
+   text = text.replace(/
+   (						// save in $1
+   \n\n				// Starting after a blank line
+   [ ]{0,3}			// attacklab: g_tab_width - 1
+   <!
+   (--[^\r]*?--\s*)+
+   >
+   [ \t]*
+   (?=\n{2,})			// followed by a blank line
+   )
+   /g,showdown.subParser('hashElement')(text, options, globals));
+   */
+  text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,
+                      showdown.subParser('hashElement')(text, options, globals));
+
+  // PHP and ASP-style processor instructions (<?...?> and <%...%>)
+
+  /*
+   text = text.replace(/
+   (?:
+   \n\n				// Starting after a blank line
+   )
+   (						// save in $1
+   [ ]{0,3}			// attacklab: g_tab_width - 1
+   (?:
+   <([?%])			// $2
+   [^\r]*?
+   \2>
+   )
+   [ \t]*
+   (?=\n{2,})			// followed by a blank line
+   )
+   /g,showdown.subParser('hashElement')(text, options, globals));
+   */
+  text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
+                      showdown.subParser('hashElement')(text, options, globals));
+
+  // attacklab: Undo double lines (see comment at top of this function)
+  text = text.replace(/\n\n/g, '\n');
+  return text;
 
 });

+ 60 - 60
src/subParsers/headers.js

@@ -3,77 +3,77 @@
  */
 
 showdown.subParser('headers', function (text, options, globals) {
-    'use strict';
+  'use strict';
 
-    var prefixHeader = options.prefixHeaderId;
+  var prefixHeader = options.prefixHeaderId;
 
-    // Set text-style headers:
-    //	Header 1
-    //	========
-    //
-    //	Header 2
-    //	--------
-    //
-    text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
-        function (wholeMatch, m1) {
-            return showdown.subParser('hashBlock')('<h1 id="' + headerId(m1) + '">' +
-            showdown.subParser('spanGamut')(m1, options, globals) + '</h1>', options, globals);
-        });
+  // Set text-style headers:
+  //	Header 1
+  //	========
+  //
+  //	Header 2
+  //	--------
+  //
+  text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm, function (wholeMatch, m1) {
+    return showdown.subParser('hashBlock')('<h1 id="' + headerId(m1) + '">' + showdown.subParser('spanGamut')(m1,
+                                                                                                              options,
+                                                                                                              globals) + '</h1>',
+                                           options, globals);
+  });
 
-    text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
-        function (matchFound, m1) {
-            return showdown.subParser('hashBlock')('<h2 id="' + headerId(m1) + '">' +
-            showdown.subParser('spanGamut')(m1, options, globals) + '</h2>', options, globals);
-        });
+  text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm, function (matchFound, m1) {
+    return showdown.subParser('hashBlock')('<h2 id="' + headerId(m1) + '">' + showdown.subParser('spanGamut')(m1,
+                                                                                                              options,
+                                                                                                              globals) + '</h2>',
+                                           options, globals);
+  });
 
-    // atx-style headers:
-    //  # Header 1
-    //  ## Header 2
-    //  ## Header 2 with closing hashes ##
-    //  ...
-    //  ###### Header 6
-    //
+  // atx-style headers:
+  //  # Header 1
+  //  ## Header 2
+  //  ## Header 2 with closing hashes ##
+  //  ...
+  //  ###### Header 6
+  //
 
-    /*
-     text = text.replace(/
-     ^(\#{1,6})				// $1 = string of #'s
-     [ \t]*
-     (.+?)					// $2 = Header text
-     [ \t]*
-     \#*						// optional closing #'s (not counted)
-     \n+
-     /gm, function() {...});
-     */
+  /*
+   text = text.replace(/
+   ^(\#{1,6})				// $1 = string of #'s
+   [ \t]*
+   (.+?)					// $2 = Header text
+   [ \t]*
+   \#*						// optional closing #'s (not counted)
+   \n+
+   /gm, function() {...});
+   */
 
-    text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
-        function (wholeMatch, m1, m2) {
-            var span = showdown.subParser('spanGamut')(m2, options, globals),
-                header = '<h' + m1.length + ' id="' + headerId(m2) + '">' + span + '</h' + m1.length + '>';
+  text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm, function (wholeMatch, m1, m2) {
+    var span = showdown.subParser('spanGamut')(m2, options,
+                                               globals), header = '<h' + m1.length + ' id="' + headerId(m2) + '">' + span + '</h' + m1.length + '>';
 
-            return showdown.subParser('hashBlock')(header, options, globals);
-        });
+    return showdown.subParser('hashBlock')(header, options, globals);
+  });
 
-    function headerId(m) {
-        var title,
-            escapedId = m.replace(/[^\w]/g, '').toLowerCase();
+  function headerId(m) {
+    var title, escapedId = m.replace(/[^\w]/g, '').toLowerCase();
 
-        if (globals.hashLinkCounts[escapedId]) {
-            title = escapedId + '-' + (globals.hashLinkCounts[escapedId]++);
-        } else {
-            title = escapedId;
-            globals.hashLinkCounts[escapedId] = 1;
-        }
+    if (globals.hashLinkCounts[escapedId]) {
+      title = escapedId + '-' + (globals.hashLinkCounts[escapedId]++);
+    } else {
+      title = escapedId;
+      globals.hashLinkCounts[escapedId] = 1;
+    }
 
-        // Prefix id to prevent causing inadvertent pre-existing style matches.
-        if (prefixHeader === true) {
-            prefixHeader = 'section';
-        }
+    // Prefix id to prevent causing inadvertent pre-existing style matches.
+    if (prefixHeader === true) {
+      prefixHeader = 'section';
+    }
 
-        if (showdown.helper.isString(prefixHeader)) {
-            return prefixHeader + title;
-        }
-        return title;
+    if (showdown.helper.isString(prefixHeader)) {
+      return prefixHeader + title;
     }
+    return title;
+  }
 
-    return text;
+  return text;
 });

+ 87 - 95
src/subParsers/images.js

@@ -2,108 +2,100 @@
  * Created by Estevao on 11-01-2015.
  */
 
-
 /**
  * Turn Markdown image shortcuts into <img> tags.
  */
 showdown.subParser('images', function (text, options, globals) {
-    'use strict';
+  'use strict';
 
-    var writeImageTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
+  var writeImageTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
 
-        wholeMatch = m1;
-        var altText = m2,
-            linkId = m3.toLowerCase(),
-            url = m4,
-            title = m7,
-            gUrls = globals.gUrls,
-            gTitles = globals.gTitles;
+    wholeMatch = m1;
+    var altText = m2, linkId = m3.toLowerCase(), url = m4, title = m7, gUrls = globals.gUrls, gTitles = globals.gTitles;
 
-        if (!title) {
-            title = '';
-        }
+    if (!title) {
+      title = '';
+    }
 
-        if (url === '' || url === null) {
-            if (linkId === '' || linkId === null) {
-                // lower-case and turn embedded newlines into spaces
-                linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
-            }
-            url = '#' + linkId;
-
-            if (typeof gUrls[linkId] !== 'undefined') {
-                url = gUrls[linkId];
-                if (typeof gTitles[linkId] !== 'undefined') {
-                    title = gTitles[linkId];
-                }
-            }
-            else {
-                return wholeMatch;
-            }
-        }
+    if (url === '' || url === null) {
+      if (linkId === '' || linkId === null) {
+        // lower-case and turn embedded newlines into spaces
+        linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
+      }
+      url = '#' + linkId;
 
-        altText = altText.replace(/"/g, '&quot;');
-        url = showdown.helper.escapeCharacters(url, '*_');
-        var result = '<img src="' + url + '" alt="' + altText + '"';
-
-        // attacklab: Markdown.pl adds empty title attributes to images.
-        // Replicate this bug.
-
-        //if (title != "") {
-        title = title.replace(/"/g, '&quot;');
-        title = escapeCharacters(title, '*_');
-        result += ' title="' + title + '"';
-        //}
-
-        result += ' />';
-
-        return result;
-    };
-
-
-    // First, handle reference-style labeled images: ![alt text][id]
-    /*
-     text = text.replace(/
-     (						// wrap whole match in $1
-     !\[
-     (.*?)				// alt text = $2
-     \]
-
-     [ ]?				// one optional space
-     (?:\n[ ]*)?			// one optional newline followed by spaces
-
-     \[
-     (.*?)				// id = $3
-     \]
-     )()()()()				// pad rest of backreferences
-     /g,writeImageTag);
-     */
-    text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
-
-    // Next, handle inline images:  ![alt text](url "optional title")
-    // Don't forget: encode * and _
-    /*
-     text = text.replace(/
-     (						// wrap whole match in $1
-     !\[
-     (.*?)				// alt text = $2
-     \]
-     \s?					// One optional whitespace character
-     \(					// literal paren
-     [ \t]*
-     ()					// no id, so leave $3 empty
-     <?(\S+?)>?			// src url = $4
-     [ \t]*
-     (					// $5
-     (['"])			// quote char = $6
-     (.*?)			// title = $7
-     \6				// matching quote
-     [ \t]*
-     )?					// title is optional
-     \)
-     )
-     /g,writeImageTag);
-     */
-    text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
-
-    return text;
+      if (typeof gUrls[linkId] !== 'undefined') {
+        url = gUrls[linkId];
+        if (typeof gTitles[linkId] !== 'undefined') {
+          title = gTitles[linkId];
+        }
+      } else {
+        return wholeMatch;
+      }
+    }
+
+    altText = altText.replace(/"/g, '&quot;');
+    url = showdown.helper.escapeCharacters(url, '*_');
+    var result = '<img src="' + url + '" alt="' + altText + '"';
+
+    // attacklab: Markdown.pl adds empty title attributes to images.
+    // Replicate this bug.
+
+    //if (title != "") {
+    title = title.replace(/"/g, '&quot;');
+    title = escapeCharacters(title, '*_');
+    result += ' title="' + title + '"';
+    //}
+
+    result += ' />';
+
+    return result;
+  };
+
+  // First, handle reference-style labeled images: ![alt text][id]
+  /*
+   text = text.replace(/
+   (						// wrap whole match in $1
+   !\[
+   (.*?)				// alt text = $2
+   \]
+
+   [ ]?				// one optional space
+   (?:\n[ ]*)?			// one optional newline followed by spaces
+
+   \[
+   (.*?)				// id = $3
+   \]
+   )()()()()				// pad rest of backreferences
+   /g,writeImageTag);
+   */
+  text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
+
+  // Next, handle inline images:  ![alt text](url "optional title")
+  // Don't forget: encode * and _
+  /*
+   text = text.replace(/
+   (						// wrap whole match in $1
+   !\[
+   (.*?)				// alt text = $2
+   \]
+   \s?					// One optional whitespace character
+   \(					// literal paren
+   [ \t]*
+   ()					// no id, so leave $3 empty
+   <?(\S+?)>?			// src url = $4
+   [ \t]*
+   (					// $5
+   (['"])			// quote char = $6
+   (.*?)			// title = $7
+   \6				// matching quote
+   [ \t]*
+   )?					// title is optional
+   \)
+   )
+   /g,writeImageTag);
+   */
+  text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
+
+  return text;
 });

+ 5 - 7
src/subParsers/italicsAndBold.js

@@ -3,13 +3,11 @@
  */
 
 showdown.subParser('italicsAndBold', function (text) {
-    'use strict';
-    // <strong> must go first:
-    text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
-        '<strong>$2</strong>');
+  'use strict';
+  // <strong> must go first:
+  text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, '<strong>$2</strong>');
 
-    text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
-        '<em>$2</em>');
+  text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>');
 
-    return text;
+  return text;
 });

+ 132 - 136
src/subParsers/lists.js

@@ -6,145 +6,141 @@
  * Form HTML ordered (numbered) and unordered (bulleted) lists.
  */
 showdown.subParser('lists', function (text, options, globals) {
-    'use strict';
-
-    /**
-     * Process the contents of a single ordered or unordered list, splitting it
-     * into individual list items.
-     * @param listStr
-     * @returns {string|*}
-     */
-    var processListItems = function (listStr) {
-        // The $g_list_level global keeps track of when we're inside a list.
-        // Each time we enter a list, we increment it; when we leave a list,
-        // we decrement. If it's zero, we're not in a list anymore.
-        //
-        // We do this because when we're not inside a list, we want to treat
-        // something like this:
-        //
-        //    I recommend upgrading to version
-        //    8. Oops, now this line is treated
-        //    as a sub-list.
-        //
-        // As a single paragraph, despite the fact that the second line starts
-        // with a digit-period-space sequence.
-        //
-        // Whereas when we're inside a list (or sub-list), that line will be
-        // treated as the start of a sub-list. What a kludge, huh? This is
-        // an aspect of Markdown's syntax that's hard to parse perfectly
-        // without resorting to mind-reading. Perhaps the solution is to
-        // change the syntax rules such that sub-lists must start with a
-        // starting cardinal number; e.g. "1." or "a.".
-
-        globals.gListLevel++;
-
-        // trim trailing blank lines:
-        listStr = listStr.replace(/\n{2,}$/, '\n');
-
-        // attacklab: add sentinel to emulate \z
-        listStr += '~0';
-
-        /*
-         list_str = list_str.replace(/
-         (\n)?							// leading line = $1
-         (^[ \t]*)						// leading whitespace = $2
-         ([*+-]|\d+[.]) [ \t]+			// list marker = $3
-         ([^\r]+?						// list item text   = $4
-         (\n{1,2}))
-         (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
-         /gm, function(){...});
-         */
-        listStr = listStr.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
-            function (wholeMatch, m1, m2, m3, m4) {
-                var item = showdown.subParser('outdent')(m4, options, globals);
-                //m1 - LeadingLine
-
-                if (m1 || (item.search(/\n{2,}/) > -1)) {
-                    item = showdown.subParser('blockGamut')(item, options, globals);
-                } else {
-                    // Recursion for sub-lists:
-                    item = showdown.subParser('lists')(item, options, globals);
-                    item = item.replace(/\n$/, ''); // chomp(item)
-                    item = showdown.subParser('spanGamut')(item, options, globals);
-                }
-
-                return '<li>' + item + '</li>\n';
-            }
-        );
-
-        // attacklab: strip sentinel
-        listStr = listStr.replace(/~0/g, '');
-
-        globals.gListLevel--;
-        return listStr;
-    };
-
-
-    // attacklab: add sentinel to hack around khtml/safari bug:
-    // http://bugs.webkit.org/show_bug.cgi?id=11231
-    text += '~0';
-
-    // Re-usable pattern to match any entirel ul or ol list:
+  'use strict';
+
+  /**
+   * Process the contents of a single ordered or unordered list, splitting it
+   * into individual list items.
+   * @param listStr
+   * @returns {string|*}
+   */
+  var processListItems = function (listStr) {
+    // The $g_list_level global keeps track of when we're inside a list.
+    // Each time we enter a list, we increment it; when we leave a list,
+    // we decrement. If it's zero, we're not in a list anymore.
+    //
+    // We do this because when we're not inside a list, we want to treat
+    // something like this:
+    //
+    //    I recommend upgrading to version
+    //    8. Oops, now this line is treated
+    //    as a sub-list.
+    //
+    // As a single paragraph, despite the fact that the second line starts
+    // with a digit-period-space sequence.
+    //
+    // Whereas when we're inside a list (or sub-list), that line will be
+    // treated as the start of a sub-list. What a kludge, huh? This is
+    // an aspect of Markdown's syntax that's hard to parse perfectly
+    // without resorting to mind-reading. Perhaps the solution is to
+    // change the syntax rules such that sub-lists must start with a
+    // starting cardinal number; e.g. "1." or "a.".
+
+    globals.gListLevel++;
+
+    // trim trailing blank lines:
+    listStr = listStr.replace(/\n{2,}$/, '\n');
+
+    // attacklab: add sentinel to emulate \z
+    listStr += '~0';
 
     /*
-     var whole_list = /
-     (									// $1 = whole list
-     (								// $2
-     [ ]{0,3}					// attacklab: g_tab_width - 1
-     ([*+-]|\d+[.])				// $3 = first list item marker
-     [ \t]+
-     )
-     [^\r]+?
-     (								// $4
-     ~0							// sentinel for workaround; should be $
-     |
-     \n{2,}
-     (?=\S)
-     (?!							// Negative lookahead for another list item marker
-     [ \t]*
-     (?:[*+-]|\d+[.])[ \t]+
-     )
-     )
-     )/g
+     list_str = list_str.replace(/
+     (\n)?							// leading line = $1
+     (^[ \t]*)						// leading whitespace = $2
+     ([*+-]|\d+[.]) [ \t]+			// list marker = $3
+     ([^\r]+?						// list item text   = $4
+     (\n{1,2}))
+     (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
+     /gm, function(){...});
      */
-    var wholeList = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
-
-    if (globals.gListLevel) {
-        text = text.replace(wholeList, function (wholeMatch, m1, m2) {
-            var list = m1,
-                listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
-
-            // Turn double returns into triple returns, so that we can make a
-            // paragraph for the last item in a list, if necessary:
-            list = list.replace(/\n{2,}/g, '\n\n\n');
-
-            var result = processListItems(list);
-
-            // Trim any trailing whitespace, to put the closing `</$list_type>`
-            // up on the preceding line, to get it past the current stupid
-            // HTML block parser. This is a hack to work around the terrible
-            // hack that is the HTML block parser.
-            result = result.replace(/\s+$/, '');
-            result = '<' + listType + '>' + result + '</' + listType + '>\n';
-            return result;
-        });
-    } else {
-        wholeList = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
-
-        text = text.replace(wholeList, function(wholeMatch,m1,m2,m3) {
-
-                // Turn double returns into triple returns, so that we can make a
-                // paragraph for the last item in a list, if necessary:
-            var list = m2.replace(/\n{2,}/g, '\n\n\n'),
-                listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol',
-                result = processListItems(list);
-
-            return m1 + '<' + listType + '>\n' + result + '</' + listType + '>\n';
-        });
-    }
+    listStr = listStr.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
+                              function (wholeMatch, m1, m2, m3, m4) {
+                                var item = showdown.subParser('outdent')(m4, options, globals);
+                                //m1 - LeadingLine
+
+                                if (m1 || (item.search(/\n{2,}/) > -1)) {
+                                  item = showdown.subParser('blockGamut')(item, options, globals);
+                                } else {
+                                  // Recursion for sub-lists:
+                                  item = showdown.subParser('lists')(item, options, globals);
+                                  item = item.replace(/\n$/, ''); // chomp(item)
+                                  item = showdown.subParser('spanGamut')(item, options, globals);
+                                }
+
+                                return '<li>' + item + '</li>\n';
+                              });
 
     // attacklab: strip sentinel
-    text = text.replace(/~0/, '');
-
-    return text;
+    listStr = listStr.replace(/~0/g, '');
+
+    globals.gListLevel--;
+    return listStr;
+  };
+
+  // attacklab: add sentinel to hack around khtml/safari bug:
+  // http://bugs.webkit.org/show_bug.cgi?id=11231
+  text += '~0';
+
+  // Re-usable pattern to match any entirel ul or ol list:
+
+  /*
+   var whole_list = /
+   (									// $1 = whole list
+   (								// $2
+   [ ]{0,3}					// attacklab: g_tab_width - 1
+   ([*+-]|\d+[.])				// $3 = first list item marker
+   [ \t]+
+   )
+   [^\r]+?
+   (								// $4
+   ~0							// sentinel for workaround; should be $
+   |
+   \n{2,}
+   (?=\S)
+   (?!							// Negative lookahead for another list item marker
+   [ \t]*
+   (?:[*+-]|\d+[.])[ \t]+
+   )
+   )
+   )/g
+   */
+  var wholeList = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
+
+  if (globals.gListLevel) {
+    text = text.replace(wholeList, function (wholeMatch, m1, m2) {
+      var list = m1, listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
+
+      // Turn double returns into triple returns, so that we can make a
+      // paragraph for the last item in a list, if necessary:
+      list = list.replace(/\n{2,}/g, '\n\n\n');
+
+      var result = processListItems(list);
+
+      // Trim any trailing whitespace, to put the closing `</$list_type>`
+      // up on the preceding line, to get it past the current stupid
+      // HTML block parser. This is a hack to work around the terrible
+      // hack that is the HTML block parser.
+      result = result.replace(/\s+$/, '');
+      result = '<' + listType + '>' + result + '</' + listType + '>\n';
+      return result;
+    });
+  } else {
+    wholeList = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
+
+    text = text.replace(wholeList, function (wholeMatch, m1, m2, m3) {
+
+      // Turn double returns into triple returns, so that we can make a
+      // paragraph for the last item in a list, if necessary:
+      var list = m2.replace(/\n{2,}/g,
+                            '\n\n\n'), listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol', result = processListItems(list);
+
+      return m1 + '<' + listType + '>\n' + result + '</' + listType + '>\n';
+    });
+  }
+
+  // attacklab: strip sentinel
+  text = text.replace(/~0/, '');
+
+  return text;
 });

+ 7 - 7
src/subParsers/outdent.js

@@ -6,14 +6,14 @@
  * Remove one level of line-leading tabs or spaces
  */
 showdown.subParser('outdent', function (text) {
-    'use strict';
+  'use strict';
 
-    // attacklab: hack around Konqueror 3.5.4 bug:
-    // "----------bug".replace(/^-/g,"") == "bug"
-    text = text.replace(/^(\t|[ ]{1,4})/gm, '~0'); // attacklab: g_tab_width
+  // attacklab: hack around Konqueror 3.5.4 bug:
+  // "----------bug".replace(/^-/g,"") == "bug"
+  text = text.replace(/^(\t|[ ]{1,4})/gm, '~0'); // attacklab: g_tab_width
 
-    // attacklab: clean up hack
-    text = text.replace(/~0/g, '');
+  // attacklab: clean up hack
+  text = text.replace(/~0/g, '');
 
-    return text;
+  return text;
 });

+ 28 - 30
src/subParsers/paragraphs.js

@@ -6,42 +6,40 @@
  *
  */
 showdown.subParser('paragraphs', function (text, options, globals) {
-    'use strict';
+  'use strict';
 
-    // Strip leading and trailing lines:
-    text = text.replace(/^\n+/g, '');
-    text = text.replace(/\n+$/g, '');
+  // Strip leading and trailing lines:
+  text = text.replace(/^\n+/g, '');
+  text = text.replace(/\n+$/g, '');
 
-    var grafs = text.split(/\n{2,}/g),
-        grafsOut = [];
+  var grafs = text.split(/\n{2,}/g), grafsOut = [];
 
-    /** Wrap <p> tags. */
-    var end = grafs.length;
-    for (var i = 0; i < end; i++) {
-        var str = grafs[i];
+  /** Wrap <p> tags. */
+  var end = grafs.length;
+  for (var i = 0; i < end; i++) {
+    var str = grafs[i];
 
-        // if this is an HTML marker, copy it
-        if (str.search(/~K(\d+)K/g) >= 0) {
-            grafsOut.push(str);
-        }
-        else if (str.search(/\S/) >= 0) {
-            str = showdown.subParser('spanGamut')(str, options, globals);
-            str = str.replace(/^([ \t]*)/g, '<p>');
-            str += '</p>';
-            grafsOut.push(str);
-        }
+    // if this is an HTML marker, copy it
+    if (str.search(/~K(\d+)K/g) >= 0) {
+      grafsOut.push(str);
+    } else if (str.search(/\S/) >= 0) {
+      str = showdown.subParser('spanGamut')(str, options, globals);
+      str = str.replace(/^([ \t]*)/g, '<p>');
+      str += '</p>';
+      grafsOut.push(str);
     }
+  }
 
-    /** Unhashify HTML blocks */
-    end = grafsOut.length;
-    for (i = 0; i < end; i++) {
-        // if this is a marker for an html block...
-        while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
-            var blockText = globals.gHtmlBlocks[RegExp.$1];
-            blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
-            grafsOut[i] = grafsOut[i].replace(/~K\d+K/, blockText);
-        }
+  /** Unhashify HTML blocks */
+  end = grafsOut.length;
+  for (i = 0; i < end; i++) {
+    // if this is a marker for an html block...
+    while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
+      var blockText = globals.gHtmlBlocks[RegExp.$1];
+      blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
+      grafsOut[i] = grafsOut[i].replace(/~K\d+K/, blockText);
     }
+  }
 
-    return grafsOut.join('\n\n');
+  return grafsOut.join('\n\n');
 });

+ 17 - 18
src/subParsers/spanGamut.js

@@ -7,28 +7,27 @@
  * tags like paragraphs, headers, and list items.
  */
 showdown.subParser('spanGamut', function (text, options, globals) {
-    'use strict';
+  'use strict';
 
+  text = showdown.subParser('codeSpans')(text, options, globals);
+  text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
+  text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
 
-    text = showdown.subParser('codeSpans')(text, options, globals);
-    text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
-    text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
+  // Process anchor and image tags. Images must come first,
+  // because ![foo][f] looks like an anchor.
+  text = showdown.subParser('images')(text, options, globals);
+  text = showdown.subParser('anchors')(text, options, globals);
 
-    // Process anchor and image tags. Images must come first,
-    // because ![foo][f] looks like an anchor.
-    text = showdown.subParser('images')(text, options, globals);
-    text = showdown.subParser('anchors')(text, options, globals);
+  // Make links out of things like `<http://example.com/>`
+  // Must come after _DoAnchors(), because you can use < and >
+  // delimiters in inline links like [this](<url>).
+  text = showdown.subParser('autoLinks')(text, options, globals);
+  text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
+  text = showdown.subParser('italicsAndBold')(text, options, globals);
 
-    // Make links out of things like `<http://example.com/>`
-    // Must come after _DoAnchors(), because you can use < and >
-    // delimiters in inline links like [this](<url>).
-    text = showdown.subParser('autoLinks')(text, options, globals);
-    text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
-    text = showdown.subParser('italicsAndBold')(text, options, globals);
+  // Do hard breaks:
+  text = text.replace(/  +\n/g, ' <br />\n');
 
-    // Do hard breaks:
-    text = text.replace(/  +\n/g, ' <br />\n');
-
-    return text;
+  return text;
 
 });

+ 2 - 2
src/subParsers/stripBlankLines.js

@@ -9,6 +9,6 @@
  * contorted like /[ \t]*\n+/
  */
 showdown.subParser('stripBlankLines', function (text) {
-    'use strict';
-    return text.replace(/^[ \t]+$/mg, '');
+  'use strict';
+  return text.replace(/^[ \t]+$/mg, '');
 });

+ 21 - 21
src/subParsers/stripLinkDefinitions.js

@@ -28,30 +28,30 @@
  *
  */
 showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
-    'use strict';
+  'use strict';
 
-    // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
-    text += '~0';
+  // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+  text += '~0';
 
-    text = text.replace(/^[ ]{0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,
-        function (wholeMatch, m1, m2, m3, m4) {
-            m1 = m1.toLowerCase();
-            globals.gUrls[m1] = showdown.subParser('encodeAmpsAndAngles')(m2);  // Link IDs are case-insensitive
-            if (m3) {
-                // Oops, found blank lines, so it's not a title.
-                // Put back the parenthetical statement we stole.
-                return m3 + m4;
-            } else if (m4) {
-                globals.gTitles[m1] = m4.replace(/"/g, '&quot;');
-            }
+  text = text.replace(/^[ ]{0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,
+                      function (wholeMatch, m1, m2, m3, m4) {
+                        m1 = m1.toLowerCase();
+                        globals.gUrls[m1] = showdown.subParser('encodeAmpsAndAngles')(m2);  // Link IDs are
+                                                                                            // case-insensitive
+                        if (m3) {
+                          // Oops, found blank lines, so it's not a title.
+                          // Put back the parenthetical statement we stole.
+                          return m3 + m4;
+                        } else if (m4) {
+                          globals.gTitles[m1] = m4.replace(/"/g, '&quot;');
+                        }
 
-            // Completely remove the definition from the text
-            return '';
-        }
-    );
+                        // Completely remove the definition from the text
+                        return '';
+                      });
 
-    // attacklab: strip sentinel
-    text = text.replace(/~0/, '');
+  // attacklab: strip sentinel
+  text = text.replace(/~0/, '');
 
-    return text;
+  return text;
 });

+ 6 - 8
src/subParsers/unescapeSpecialChars.js

@@ -6,13 +6,11 @@
  * Swap back in all the special characters we've hidden.
  */
 showdown.subParser('unescapeSpecialChars', function (text) {
-    'use strict';
+  'use strict';
 
-    text = text.replace(/~E(\d+)E/g,
-        function (wholeMatch, m1) {
-            var charCodeToReplace = parseInt(m1);
-            return String.fromCharCode(charCodeToReplace);
-        }
-    );
-    return text;
+  text = text.replace(/~E(\d+)E/g, function (wholeMatch, m1) {
+    var charCodeToReplace = parseInt(m1);
+    return String.fromCharCode(charCodeToReplace);
+  });
+  return text;
 });

+ 3 - 3
test/cases/anchors-by-reference.html

@@ -1,4 +1,4 @@
 <p>This is <a href="http://example.com/" title="Optional Title Here">an example</a> reference-style link.
-This is <a href="http://example.com/" title="Optional Title Here">another</a> reference-style link.
-This is <a href="http://example.com/" title="Optional Title Here">a third</a> reference-style link.
-This is <a href="http://example.com/" title="Optional Title Here">a fourth</a> reference-style link.</p>
+  This is <a href="http://example.com/" title="Optional Title Here">another</a> reference-style link.
+  This is <a href="http://example.com/" title="Optional Title Here">a third</a> reference-style link.
+  This is <a href="http://example.com/" title="Optional Title Here">a fourth</a> reference-style link.</p>

+ 6 - 6
test/cases/blockquote-nested-markdown.html

@@ -1,12 +1,12 @@
 <blockquote>
-    <h2 id="thisisaheader">This is a header.</h2>
+  <h2 id="thisisaheader">This is a header.</h2>
 
-    <ol>
-        <li>This is the first list item.</li>
-        <li>This is the second list item.</li>
-    </ol>
+  <ol>
+    <li>This is the first list item.</li>
+    <li>This is the second list item.</li>
+  </ol>
 
-    <p>Here's some example code:</p>
+  <p>Here's some example code:</p>
 
     <pre><code>return shell_exec("echo $input | $markdown_script");
     </code></pre>

+ 2 - 2
test/cases/blockquote.html

@@ -1,5 +1,5 @@
 <blockquote>
-	<p>This is a multi line blockquote test</p>
+  <p>This is a multi line blockquote test</p>
 
-	<p>With more than one line.</p>
+  <p>With more than one line.</p>
 </blockquote>

+ 2 - 2
test/cases/doubline-list.html

@@ -1,4 +1,4 @@
 <ul>
-    <li><p>Bird</p></li>
-    <li><p>Magic</p></li>
+  <li><p>Bird</p></li>
+  <li><p>Magic</p></li>
 </ul>

+ 1 - 1
test/cases/emphasis.html

@@ -11,7 +11,7 @@
 <p>text <strong>with bold sentence</strong> in middle</p>
 
 <p>text with <strong>bold text that
-spans across multiple</strong> lines</p>
+  spans across multiple</strong> lines</p>
 
 <p>underscored_word</p>
 

+ 1 - 1
test/cases/escaped-number-period.html

@@ -1 +1 @@
-<p>It happened in 1986.  What a great season.</p>
+<p>It happened in 1986. What a great season.</p>

+ 2 - 2
test/cases/github-style-at-start.html

@@ -1,6 +1,6 @@
 <pre><code>function MyFunc(a) {
-    // ...
-}
+  // ...
+  }
 </code></pre>
 
 <p>That is some code!</p>

+ 2 - 2
test/cases/github-style-codeblock.html

@@ -1,8 +1,8 @@
 <p>Define a function in javascript:</p>
 
 <pre><code>function MyFunc(a) {
-    var s = '`';
-}
+  var s = '`';
+  }
 </code></pre>
 
 <p>And some HTML</p>

+ 1 - 1
test/cases/github-style-linebreaks.html

@@ -1,3 +1,3 @@
 <pre><code>code can go here
-this is rendered on a second line
+  this is rendered on a second line
 </code></pre>

+ 5 - 5
test/cases/horizontal-rules.html

@@ -1,9 +1,9 @@
-<hr />
+<hr/>
 
-<hr />
+<hr/>
 
-<hr />
+<hr/>
 
-<hr />
+<hr/>
 
-<hr />
+<hr/>

+ 3 - 2
test/cases/html5-strutural-tags.html

@@ -13,10 +13,11 @@
 <aside>ignore me</aside>
 
 <article>read
-me</article>
+  me
+</article>
 
 <aside>
-ignore me
+  ignore me
 </aside>
 
 <p>the end</p>

+ 3 - 3
test/cases/images.html

@@ -1,5 +1,5 @@
-<p><img src="/path/to/img.jpg" alt="Alt text" title="" /></p>
+<p><img src="/path/to/img.jpg" alt="Alt text" title=""/></p>
 
-<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title" /></p>
+<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title"/></p>
 
-<p><img src="url/to/image" alt="Alt text" title="Optional title attribute" /></p>
+<p><img src="url/to/image" alt="Alt text" title="Optional title attribute"/></p>

+ 2 - 1
test/cases/implicit-anchors.html

@@ -1 +1,2 @@
-<p>Search the web at <a href="http://google.com/">Google</a> or <a href="http://daringfireball.net/">Daring Fireball</a>.</p>
+<p>Search the web at <a href="http://google.com/">Google</a> or <a href="http://daringfireball.net/">Daring Fireball</a>.
+</p>

+ 1 - 1
test/cases/inline-escaped-chars.html

@@ -1,2 +1,2 @@
 <p>Hello.this_is_a_variable
-and.this.is.another_one</p>
+  and.this.is.another_one</p>

+ 3 - 1
test/cases/inline-style-tag.html

@@ -1,5 +1,7 @@
 <style>
-    p { line-height: 20px; }
+  p {
+    line-height: 20px;
+  }
 </style>
 
 <p>An exciting sentence.</p>

+ 2 - 2
test/cases/lazy-blockquote.html

@@ -1,5 +1,5 @@
 <blockquote>
-	<p>This is a multi line blockquote test</p>
+  <p>This is a multi line blockquote test</p>
 
-	<p>With more than one line.</p>
+  <p>With more than one line.</p>
 </blockquote>

+ 4 - 3
test/cases/list-with-blockquote.html

@@ -1,8 +1,9 @@
 <ul>
-    <li><p>A list item with a blockquote:</p>
+  <li><p>A list item with a blockquote:</p>
 
     <blockquote>
-        <p>This is a blockquote
+      <p>This is a blockquote
         inside a list item.</p>
-    </blockquote></li>
+    </blockquote>
+  </li>
 </ul>

+ 3 - 2
test/cases/list-with-code.html

@@ -1,6 +1,7 @@
 <ul>
-    <li><p>A list item with code:</p>
+  <li><p>A list item with code:</p>
 
     <pre><code>alert('Hello world!');
-    </code></pre></li>
+    </code></pre>
+  </li>
 </ul>

+ 2 - 2
test/cases/multi-paragraph-list.html

@@ -1,6 +1,6 @@
 <ol>
-    <li><p>This is a major bullet point.</p>
+  <li><p>This is a major bullet point.</p>
 
     <p>That contains multiple paragraphs.</p></li>
-    <li><p>And another line</p></li>
+  <li><p>And another line</p></li>
 </ol>

+ 4 - 3
test/cases/multiline-unordered-list.html

@@ -1,5 +1,6 @@
 <ul>
-    <li>This line spans
- more than one line and is lazy</li>
-    <li>Similar to this line</li>
+  <li>This line spans
+    more than one line and is lazy
+  </li>
+  <li>Similar to this line</li>
 </ul>

+ 5 - 5
test/cases/nested-blockquote.html

@@ -1,9 +1,9 @@
 <blockquote>
-	<p>This is a multi line blockquote test</p>
+  <p>This is a multi line blockquote test</p>
 
-    <blockquote>
-        <p>And nesting!</p>
-    </blockquote>
+  <blockquote>
+    <p>And nesting!</p>
+  </blockquote>
 
-	<p>With more than one line.</p>
+  <p>With more than one line.</p>
 </blockquote>

+ 3 - 3
test/cases/ordered-list-same-number.html

@@ -1,5 +1,5 @@
 <ol>
-    <li>Red</li>
-    <li>Green</li>
-    <li>Blue</li>
+  <li>Red</li>
+  <li>Green</li>
+  <li>Blue</li>
 </ol>

+ 3 - 3
test/cases/ordered-list-wrong-numbers.html

@@ -1,5 +1,5 @@
 <ol>
-    <li>Red</li>
-    <li>Green</li>
-    <li>Blue</li>
+  <li>Red</li>
+  <li>Green</li>
+  <li>Blue</li>
 </ol>

+ 3 - 3
test/cases/ordered-list.html

@@ -1,5 +1,5 @@
 <ol>
-    <li>Red</li>
-    <li>Green</li>
-    <li>Blue</li>
+  <li>Red</li>
+  <li>Green</li>
+  <li>Blue</li>
 </ol>

+ 3 - 3
test/cases/unordered-list-asterisk.html

@@ -1,5 +1,5 @@
 <ul>
-    <li>Red</li>
-    <li>Green</li>
-    <li>Blue</li>
+  <li>Red</li>
+  <li>Green</li>
+  <li>Blue</li>
 </ul>

+ 3 - 3
test/cases/unordered-list-minus.html

@@ -1,5 +1,5 @@
 <ul>
-    <li>Red</li>
-    <li>Green</li>
-    <li>Blue</li>
+  <li>Red</li>
+  <li>Green</li>
+  <li>Blue</li>
 </ul>

+ 3 - 3
test/cases/unordered-list-plus.html

@@ -1,5 +1,5 @@
 <ul>
-    <li>Red</li>
-    <li>Green</li>
-    <li>Blue</li>
+  <li>Red</li>
+  <li>Green</li>
+  <li>Blue</li>
 </ul>

+ 2 - 1
test/cases/url-with-parenthesis.html

@@ -1 +1,2 @@
-<p>There's an <a href="http://en.memory-alpha.org/wiki/Darmok_(episode)">episode</a> of Star Trek: The Next Generation</p>
+<p>There's an <a href="http://en.memory-alpha.org/wiki/Darmok_(episode)">episode</a> of Star Trek: The Next Generation
+</p>

+ 73 - 85
test/node/Container/testMakeHtml.js

@@ -3,95 +3,83 @@
  */
 
 (function () {
-    'use strict';
-
-    require('source-map-support').install();
-    require('chai').should();
-
-    var fs        = require('fs'),
-        showdown  = require('../../../dist/showdown.js'),
-        converter = new showdown.Converter(),
-        cases     = fs
-            .readdirSync('test/cases/')
-            .filter(filter())
-            .map(map('test/cases/')),
-        issues    = fs
-            .readdirSync('test/issues/')
-            .filter(filter())
-            .map(map('test/issues/'));
-
-    //Tests
-    describe('Converter.makeHtml() simple testcases', function () {
-        for (var i = 0; i < cases.length; ++i) {
-            it(cases[i].name, assertion(cases[i]));
-        }
-    });
-
-    describe('Converter.makeHtml() issues testcase', function () {
-        for (var i = 0; i < issues.length; ++i) {
-            it(issues[i].name, assertion(issues[i]));
-        }
-    });
-
-
-    function filter() {
-        return function(file) {
-            var ext = file.slice(-3);
-            return (ext === '.md');
-        };
-    }
-
-    function map(dir) {
-        return function(file) {
-            var name = file.replace('.md', ''),
-                htmlPath = dir + name + '.html',
-                html = fs.readFileSync(htmlPath, 'utf8'),
-                mdPath = dir + name + '.md',
-                md = fs.readFileSync(mdPath, 'utf8');
-
-            return {
-                name: name,
-                input: md,
-                expected: html
-            };
-        };
-    }
-
-    //Normalize input/output
-    function normalize(testCase) {
+  'use strict';
 
-        // Normalize line returns
-        testCase.expected = testCase.expected.replace(/\r/g, '');
-        testCase.actual = testCase.actual.replace(/\r/g, '');
+  require('source-map-support').install();
+  require('chai').should();
 
-        // Ignore all leading/trailing whitespace
-        testCase.expected = testCase.expected.split('\n').map(function (x) {
-            return x.trim();
-        }).join('\n');
-        testCase.actual = testCase.actual.split('\n').map(function (x) {
-            return x.trim();
-        }).join('\n');
-
-        // Remove extra lines
-        testCase.expected = testCase.expected.trim();
-
-        // Convert whitespace to a visible character so that it shows up on error reports
-        testCase.expected = testCase.expected.replace(/ /g, '·');
-        testCase.expected = testCase.expected.replace(/\n/g, '•\n');
-        testCase.actual = testCase.actual.replace(/ /g, '·');
-        testCase.actual = testCase.actual.replace(/\n/g, '•\n');
-
-        return testCase;
+  var fs = require('fs'), showdown = require('../../../dist/showdown.js'), converter = new showdown.Converter(), cases = fs.readdirSync('test/cases/').filter(filter()).map(map('test/cases/')), issues = fs.readdirSync('test/issues/').filter(filter()).map(map('test/issues/'));
 
+  //Tests
+  describe('Converter.makeHtml() simple testcases', function () {
+    for (var i = 0; i < cases.length; ++i) {
+      it(cases[i].name, assertion(cases[i]));
     }
+  });
 
-    function assertion(testCase) {
-        return function () {
-            testCase.actual = converter.makeHtml(testCase.input);
-            testCase = normalize(testCase);
-
-            // Compare
-            testCase.actual.should.equal(testCase.expected);
-        };
+  describe('Converter.makeHtml() issues testcase', function () {
+    for (var i = 0; i < issues.length; ++i) {
+      it(issues[i].name, assertion(issues[i]));
     }
+  });
+
+
+  function filter() {
+    return function (file) {
+      var ext = file.slice(-3);
+      return (ext === '.md');
+    };
+  }
+
+  function map(dir) {
+    return function (file) {
+      var name = file.replace('.md', ''), htmlPath = dir + name + '.html', html = fs.readFileSync(htmlPath,
+                                                                                                  'utf8'), mdPath = dir + name + '.md', md = fs.readFileSync(mdPath,
+                                                                                                                                                             'utf8');
+
+      return {
+        name:     name,
+        input:    md,
+        expected: html
+      };
+    };
+  }
+
+  //Normalize input/output
+  function normalize(testCase) {
+
+    // Normalize line returns
+    testCase.expected = testCase.expected.replace(/\r/g, '');
+    testCase.actual = testCase.actual.replace(/\r/g, '');
+
+    // Ignore all leading/trailing whitespace
+    testCase.expected = testCase.expected.split('\n').map(function (x) {
+      return x.trim();
+    }).join('\n');
+    testCase.actual = testCase.actual.split('\n').map(function (x) {
+      return x.trim();
+    }).join('\n');
+
+    // Remove extra lines
+    testCase.expected = testCase.expected.trim();
+
+    // Convert whitespace to a visible character so that it shows up on error reports
+    testCase.expected = testCase.expected.replace(/ /g, '·');
+    testCase.expected = testCase.expected.replace(/\n/g, '•\n');
+    testCase.actual = testCase.actual.replace(/ /g, '·');
+    testCase.actual = testCase.actual.replace(/\n/g, '•\n');
+
+    return testCase;
+
+  }
+
+  function assertion(testCase) {
+    return function () {
+      testCase.actual = converter.makeHtml(testCase.input);
+      testCase = normalize(testCase);
+
+      // Compare
+      testCase.actual.should.equal(testCase.expected);
+    };
+  }
 })();