Estevao Soares dos Santos преди 8 години
родител
ревизия
cb2ef8a93c

+ 45 - 22
README.md

@@ -10,7 +10,8 @@
 
 ------
 
-Showdown is a Javascript Markdown to HTML converter, based on the original works by John Gruber. Showdown can be used client side (in the browser) or server side (with NodeJs).
+Showdown is a Javascript Markdown to HTML converter, based on the original works by John Gruber.
+Showdown can be used client side (in the browser) or server side (with NodeJs).
 
 ## Live DEMO
 
@@ -28,7 +29,8 @@ Check a live Demo here http://showdownjs.github.io/demo/
 
 ## Donate [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/tiviesantos)
 
-We're currently looking to improve showdown with automated tests in all browsers and a proper domain and webpage. [If you like our work, please donate!!](https://www.paypal.me/tiviesantos) Your contribution will be greatly appreciated.
+We're currently looking to improve showdown with automated tests in all browsers and a proper domain and webpage.
+[If you like our work, please donate!!](https://www.paypal.me/tiviesantos) Your contribution will be greatly appreciated.
 
 ## Installation
 
@@ -75,7 +77,8 @@ Showdown has been tested successfully with:
   * Netscape 8.1.2
   * Konqueror 3.5.4
 
-In theory, Showdown will work in any browser that supports ECMA 262 3rd Edition (JavaScript 1.5).  The converter itself might even work in things that aren't web browsers, like Acrobat.  No promises.
+In theory, Showdown will work in any browser that supports ECMA 262 3rd Edition (JavaScript 1.5).
+The converter itself might even work in things that aren't web browsers, like Acrobat.  No promises.
 
 
 ## Node compatibility
@@ -196,17 +199,27 @@ var defaultOptions = showdown.getDefaultOptions();
     <code><pre>var foo = 'bar';</pre></code>
     ```
 
- * **noHeaderId**: (boolean) [default false] Disable the automatic generation of header ids. Setting to true overrides **prefixHeaderId**
+ * **noHeaderId**: (boolean) [default false] Disable the automatic generation of header ids.
+   Setting to true overrides **prefixHeaderId**
 
- * **customizedHeaderId**: (boolean) [default false] Use text in curly braces as header id. (since v1.7.0)
+ * **customizedHeaderId**: (boolean) [default false] Use text in curly braces as header id. **(since v1.7.0)**
    Example:
    ```
    ## Sample header {real-id}     will use real-id as id
    ```
 
- * **ghCompatibleHeaderId**: (boolean) [default false] Generate header ids compatible with github style (spaces are replaced with dashes and a bunch of non alphanumeric chars are removed) (since v1.5.5)
+ * **ghCompatibleHeaderId**: (boolean) [default false] Generate header ids compatible with github style
+   (spaces are replaced with dashes and a bunch of non alphanumeric chars are removed) **(since v1.5.5)**
 
- * **prefixHeaderId**: (string/boolean) [default false] Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to `true` will add a generic 'section' prefix.
+ * **prefixHeaderId**: (string/boolean) [default false] Add a prefix to the generated header ids.
+   Passing a string will prefix that string to the header id. Setting to `true` will add a generic 'section' prefix.
+
+ * **rawPrefixHeaderId**: (boolean) [default false] Setting this option to true will prevent showdown from modifying the prefix.
+   This might result in malformed IDs (if, for instance, the " char is used in the prefix).
+   Has no effect if prefixHeaderId is set to false. **(since v 1.7.3)**
+
+ * **rawHeaderId**: (boolean) [default false] Remove only spaces, ' and " from generated header ids (including prefixes),
+    replacing them with dashes (-). WARNING: This might result in malformed ids **(since v1.7.3)**
  
  * **parseImgDimensions**: (boolean) [default false] Enable support for setting image dimensions from within markdown syntax.
    Examples:
@@ -227,7 +240,8 @@ var defaultOptions = showdown.getDefaultOptions();
     <h3>foo</h3>
     ```
 
- * **simplifiedAutoLink**: (boolean) [default false] Turning this option on will enable automatic linking to urls. This means that 
+ * **simplifiedAutoLink**: (boolean) [default false] Turning this option on will enable automatic linking to urls.
+   This means that:
 
    ```md
    some text www.google.com
@@ -248,7 +262,8 @@ var defaultOptions = showdown.getDefaultOptions();
    <p>check this link <a href="www.google.com">www.google.com</a>!</p>
    ```
    
- * **literalMidWordUnderscores**: (boolean) [default false] Turning this on will stop showdown from interpreting underscores in the middle of words as `<em>` and `<strong>` and instead treat them as literal underscores. 
+ * **literalMidWordUnderscores**: (boolean) [default false] Turning this on will stop showdown from interpreting
+   underscores in the middle of words as `<em>` and `<strong>` and instead treat them as literal underscores.
 
    Example:
    
@@ -260,7 +275,8 @@ var defaultOptions = showdown.getDefaultOptions();
    <p>some text with__underscores__in middle</p>
    ```
 
- * **literalMidWordAsterisks**: (boolean) [default false] Turning this on will stop showdown from interpreting asterisks in the middle of words as `<em>` and `<strong>` and instead treat them as literal asterisks. 
+ * **literalMidWordAsterisks**: (boolean) [default false] Turning this on will stop showdown from interpreting asterisks
+   in the middle of words as `<em>` and `<strong>` and instead treat them as literal asterisks.
 
    Example:
 
@@ -298,12 +314,15 @@ var defaultOptions = showdown.getDefaultOptions();
    ```
  * **smoothLivePreview**: (boolean) [default false] Prevents weird effects in live previews due to incomplete input
  
- * **smartIndentationFix**: (boolean) [default false] Tries to smartly fix indentation problems related to es6 template strings in the midst of indented code.
+ * **smartIndentationFix**: (boolean) [default false] Tries to smartly fix indentation problems related to es6 template
+   strings in the midst of indented code.
 
- * **disableForced4SpacesIndentedSublists**: (boolean) [default false] Disables the requirement of indenting sublists by 4 spaces for them to be nested, 
- effectively reverting to the old behavior where 2 or 3 spaces were enough. (since v1.5.0)
+ * **disableForced4SpacesIndentedSublists**: (boolean) [default false] Disables the requirement of indenting sublists
+   by 4 spaces for them to be nested, effectively reverting to the old behavior where 2 or 3 spaces were enough.
+   **(since v1.5.0)**
  
- * **simpleLineBreaks**: (boolean) [default false] Parses line breaks as <br> like GitHub does, without needing 2 spaces at the end of the line (since v1.5.1)
+ * **simpleLineBreaks**: (boolean) [default false] Parses line breaks as <br> like GitHub does, without
+   needing 2 spaces at the end of the line **(since v1.5.1)**
  
    ```md
    a line
@@ -317,22 +336,24 @@ var defaultOptions = showdown.getDefaultOptions();
    wrapped in two</p>
    ```
 
- * **requireSpaceBeforeHeadingText**: (boolean) [default false] Makes adding a space between `#` and the header text mandatory (since v1.5.3)
+ * **requireSpaceBeforeHeadingText**: (boolean) [default false] Makes adding a space between `#` and the header text mandatory **(since v1.5.3)**
  
- * **ghMentions**: (boolean) [default false] Enables github @mentions, which link to the username mentioned (since v1.6.0) 
+ * **ghMentions**: (boolean) [default false] Enables github @mentions, which link to the username mentioned **(since v1.6.0)**
  
- * **ghMentionsLink**: (string) [default `https://github.com/{u}`] Changes the link generated by @mentions. Showdown will replace `{u}` with the username. Only applies if ghMentions option is enabled.
+ * **ghMentionsLink**: (string) [default `https://github.com/{u}`] Changes the link generated by @mentions.
+   Showdown will replace `{u}` with the username. Only applies if ghMentions option is enabled.
    Example: `@tivie` with ghMentionsOption set to `//mysite.com/{u}/profile` will result in `<a href="//mysite.com/tivie/profile">@tivie</a>`
  
  * **encodeEmails**: (boolean) [default true] Enables e-mail addresses encoding through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities. (since v1.6.1)
 
    NOTE: Prior to version 1.6.1, emails would always be obfuscated through dec and hex encoding.
 
- * **openLinksInNewWindow**: (boolean) [default false] Open all links in new windows (by adding the attribute `target="_blank"` to `<a>` tags) (since v1.7.0)
+ * **openLinksInNewWindow**: (boolean) [default false] Open all links in new windows
+   (by adding the attribute `target="_blank"` to `<a>` tags) **(since v1.7.0)**
 
- * **backslashEscapesHTMLTags**: (boolean) [default false] Support for HTML Tag escaping. ex: `\<div>foo\</div>` (since v1.7.2)
+ * **backslashEscapesHTMLTags**: (boolean) [default false] Support for HTML Tag escaping. ex: `\<div>foo\</div>` **(since v1.7.2)**
 
-**NOTE**: Please note that until version 1.6.0, all of these options are ***DISABLED*** by default in the cli tool.
+**NOTE**: Please note that until **version 1.6.0**, all of these options are ***DISABLED*** by default in the cli tool.
  
 ## Flavors
 
@@ -405,7 +426,8 @@ var showdown    = require('showdown'),
 
 ## Tests
 
-A suite of tests is available which require node.js.  Once node is installed, run the following command from the project root to install the dependencies:
+A suite of tests is available which require node.js.  Once node is installed, run the following command from
+the project root to install the dependencies:
 
     npm install
 
@@ -413,7 +435,8 @@ Once installed the tests can be run from the project root using:
 
     npm test
 
-New test cases can easily be added.  Create a markdown file (ending in `.md`) which contains the markdown to test.  Create a `.html` file of the exact same name.  It will automatically be tested when the tests are executed with `mocha`.
+New test cases can easily be added.  Create a markdown file (ending in `.md`) which contains the markdown to test.
+Create a `.html` file of the exact same name.  It will automatically be tested when the tests are executed with `mocha`.
 
 ## Contributing
 

+ 62 - 25
dist/showdown.js

@@ -1,4 +1,4 @@
-;/*! showdown 05-08-2017 */
+;/*! showdown 23-08-2017 */
 (function(){
 /**
  * Created by Tivie on 13-07-2015.
@@ -20,14 +20,24 @@ function getDefaultOpts (simple) {
     },
     prefixHeaderId: {
       defaultValue: false,
-      describe: 'Specify a prefix to generated header ids',
+      describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix',
       type: 'string'
     },
+    rawPrefixHeaderId: {
+      defaultValue: false,
+      describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',
+      type: 'boolean'
+    },
     ghCompatibleHeaderId: {
       defaultValue: false,
       describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
       type: 'boolean'
     },
+    rawHeaderId: {
+      defaultValue: false,
+      describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
+      type: 'boolean'
+    },
     headerLevelStart: {
       defaultValue: false,
       describe: 'The header blocks level start',
@@ -183,7 +193,8 @@ var showdown = {},
         simpleLineBreaks:                     true,
         requireSpaceBeforeHeadingText:        true,
         ghCompatibleHeaderId:                 true,
-        ghMentions:                           true
+        ghMentions:                           true,
+        backslashEscapesHTMLTags:             true
       },
       original: {
         noHeaderId:                           true,
@@ -2088,7 +2099,6 @@ showdown.subParser('headers', function (text, options, globals) {
   text = globals.converter._dispatch('headers.before', text, options, globals);
 
   var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
-      ghHeaderId = options.ghCompatibleHeaderId,
 
   // Set text-style headers:
   //	Header 1
@@ -2141,7 +2151,8 @@ showdown.subParser('headers', function (text, options, globals) {
   });
 
   function headerId (m) {
-    var title;
+    var title,
+        prefix;
 
     // It is separate from other options to allow combining prefix and customized
     if (options.customizedHeaderId) {
@@ -2151,16 +2162,22 @@ showdown.subParser('headers', function (text, options, globals) {
       }
     }
 
+    title = m;
+
     // Prefix id to prevent causing inadvertent pre-existing style matches.
     if (showdown.helper.isString(options.prefixHeaderId)) {
-      title = options.prefixHeaderId + m;
+      prefix = options.prefixHeaderId;
     } else if (options.prefixHeaderId === true) {
-      title = 'section ' + m;
+      prefix = 'section-';
     } else {
-      title = m;
+      prefix = '';
     }
 
-    if (ghHeaderId) {
+    if (!options.rawPrefixHeaderId) {
+      title = prefix + title;
+    }
+
+    if (options.ghCompatibleHeaderId) {
       title = title
         .replace(/ /g, '-')
         // replace previously escaped chars (&, ¨ and $)
@@ -2171,12 +2188,26 @@ showdown.subParser('headers', function (text, options, globals) {
         // borrowed from github's redcarpet (some they should produce similar results)
         .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
         .toLowerCase();
+    } else if (options.rawHeaderId) {
+      title = title
+        .replace(/ /g, '-')
+        // replace previously escaped chars (&, ¨ and $)
+        .replace(/&amp;/g, '&')
+        .replace(/¨T/g, '¨')
+        .replace(/¨D/g, '$')
+        // replace " and '
+        .replace(/["']/g, '-')
+        .toLowerCase();
     } else {
       title = title
         .replace(/[^\w]/g, '')
         .toLowerCase();
     }
 
+    if (options.rawPrefixHeaderId) {
+      title = prefix + title;
+    }
+
     if (globals.hashLinkCounts[title]) {
       title = title + '-' + (globals.hashLinkCounts[title]++);
     } else {
@@ -2342,14 +2373,14 @@ showdown.subParser('italicsAndBold', function (text, options, globals) {
 
   // Now parse asterisks
   if (options.literalMidWordAsterisks) {
-    text = text.trim().replace(/(?:^| +)\*{3}(\S[\s\S]*?)\*{3}(?: +|$)/g, function (wm, txt) {
-      return parseInside (txt, ' <strong><em>', '</em></strong> ');
+    text = text.trim().replace(/(^| )\*{3}(\S[\s\S]*?)\*{3}([ ,;!?.]|$)/g, function (wm, lead, txt, trail) {
+      return parseInside (txt, lead + '<strong><em>', '</em></strong>' + trail);
     });
-    text = text.trim().replace(/(?:^| +)\*{2}(\S[\s\S]*?)\*{2}(?: +|$)/g, function (wm, txt) {
-      return parseInside (txt, ' <strong>', '</strong> ');
+    text = text.trim().replace(/(^| )\*{2}(\S[\s\S]*?)\*{2}([ ,;!?.]|$)/g, function (wm, lead, txt, trail) {
+      return parseInside (txt, lead + '<strong>', '</strong>' + trail);
     });
-    text = text.trim().replace(/(?:^| +)\*{1}(\S[\s\S]*?)\*{1}(?: +|$)/g, function (wm, txt) {
-      return parseInside (txt, ' <em>', '</em>' + (wm.slice(-1) === ' ' ? ' ' : ''));
+    text = text.trim().replace(/(^| )\*(\S[\s\S]*?)\*([ ,;!?.]|$)/g, function (wm, lead, txt, trail) {
+      return parseInside (txt, lead + '<em>', '</em>' + trail);
     });
   } else {
     text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {
@@ -2785,7 +2816,9 @@ showdown.subParser('tables', function (text, options, globals) {
     return text;
   }
 
-  var tableRgx = /^ {0,3}\|?.+\|.+\n[ \t]{0,3}\|?[ \t]*:?[ \t]*(?:-|=){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:-|=){2,}[\s\S]+?(?:\n\n|¨0)/gm;
+  var tableRgx       = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
+    //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
+      singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|\n( {0,3}\|.+\|\n)*(?:\n|¨0)/gm;
 
   function parseStyles (sLine) {
     if (/^:[ \t]*--*$/.test(sLine)) {
@@ -2836,14 +2869,7 @@ showdown.subParser('tables', function (text, options, globals) {
     return tb;
   }
 
-  text = globals.converter._dispatch('tables.before', text, options, globals);
-
-  // find escaped pipe characters
-  text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
-
-  // parse tables
-  text = text.replace(tableRgx, function (rawTable) {
-
+  function parseTable (rawTable) {
     var i, tableLines = rawTable.split('\n');
 
     // strip wrong first and last column if wrapped tables are used
@@ -2906,7 +2932,18 @@ showdown.subParser('tables', function (text, options, globals) {
     }
 
     return buildTable(headers, cells);
-  });
+  }
+
+  text = globals.converter._dispatch('tables.before', text, options, globals);
+
+  // find escaped pipe characters
+  text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
+
+  // parse multi column tables
+  text = text.replace(tableRgx, parseTable);
+
+  // parse one column tables
+  text = text.replace(singeColTblRgx, parseTable);
 
   text = globals.converter._dispatch('tables.after', text, options, globals);
 

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/showdown.js.map


Файловите разлики са ограничени, защото са твърде много
+ 1 - 1
dist/showdown.min.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/showdown.min.js.map


+ 11 - 1
src/options.js

@@ -18,14 +18,24 @@ function getDefaultOpts (simple) {
     },
     prefixHeaderId: {
       defaultValue: false,
-      describe: 'Specify a prefix to generated header ids',
+      describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix',
       type: 'string'
     },
+    rawPrefixHeaderId: {
+      defaultValue: false,
+      describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',
+      type: 'boolean'
+    },
     ghCompatibleHeaderId: {
       defaultValue: false,
       describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
       type: 'boolean'
     },
+    rawHeaderId: {
+      defaultValue: false,
+      describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
+      type: 'boolean'
+    },
     headerLevelStart: {
       defaultValue: false,
       describe: 'The header blocks level start',

+ 2 - 1
src/showdown.js

@@ -23,7 +23,8 @@ var showdown = {},
         simpleLineBreaks:                     true,
         requireSpaceBeforeHeadingText:        true,
         ghCompatibleHeaderId:                 true,
-        ghMentions:                           true
+        ghMentions:                           true,
+        backslashEscapesHTMLTags:             true
       },
       original: {
         noHeaderId:                           true,

+ 26 - 6
src/subParsers/headers.js

@@ -4,7 +4,6 @@ showdown.subParser('headers', function (text, options, globals) {
   text = globals.converter._dispatch('headers.before', text, options, globals);
 
   var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
-      ghHeaderId = options.ghCompatibleHeaderId,
 
   // Set text-style headers:
   //	Header 1
@@ -57,7 +56,8 @@ showdown.subParser('headers', function (text, options, globals) {
   });
 
   function headerId (m) {
-    var title;
+    var title,
+        prefix;
 
     // It is separate from other options to allow combining prefix and customized
     if (options.customizedHeaderId) {
@@ -67,16 +67,22 @@ showdown.subParser('headers', function (text, options, globals) {
       }
     }
 
+    title = m;
+
     // Prefix id to prevent causing inadvertent pre-existing style matches.
     if (showdown.helper.isString(options.prefixHeaderId)) {
-      title = options.prefixHeaderId + m;
+      prefix = options.prefixHeaderId;
     } else if (options.prefixHeaderId === true) {
-      title = 'section ' + m;
+      prefix = 'section-';
     } else {
-      title = m;
+      prefix = '';
+    }
+
+    if (!options.rawPrefixHeaderId) {
+      title = prefix + title;
     }
 
-    if (ghHeaderId) {
+    if (options.ghCompatibleHeaderId) {
       title = title
         .replace(/ /g, '-')
         // replace previously escaped chars (&, ¨ and $)
@@ -87,12 +93,26 @@ showdown.subParser('headers', function (text, options, globals) {
         // borrowed from github's redcarpet (some they should produce similar results)
         .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
         .toLowerCase();
+    } else if (options.rawHeaderId) {
+      title = title
+        .replace(/ /g, '-')
+        // replace previously escaped chars (&, ¨ and $)
+        .replace(/&amp;/g, '&')
+        .replace(/¨T/g, '¨')
+        .replace(/¨D/g, '$')
+        // replace " and '
+        .replace(/["']/g, '-')
+        .toLowerCase();
     } else {
       title = title
         .replace(/[^\w]/g, '')
         .toLowerCase();
     }
 
+    if (options.rawPrefixHeaderId) {
+      title = prefix + title;
+    }
+
     if (globals.hashLinkCounts[title]) {
       title = title + '-' + (globals.hashLinkCounts[title]++);
     } else {

+ 6 - 6
src/subParsers/italicsAndBold.js

@@ -40,14 +40,14 @@ showdown.subParser('italicsAndBold', function (text, options, globals) {
 
   // Now parse asterisks
   if (options.literalMidWordAsterisks) {
-    text = text.trim().replace(/(?:^| +)\*{3}(\S[\s\S]*?)\*{3}(?: +|$)/g, function (wm, txt) {
-      return parseInside (txt, ' <strong><em>', '</em></strong> ');
+    text = text.trim().replace(/(^| )\*{3}(\S[\s\S]*?)\*{3}([ ,;!?.]|$)/g, function (wm, lead, txt, trail) {
+      return parseInside (txt, lead + '<strong><em>', '</em></strong>' + trail);
     });
-    text = text.trim().replace(/(?:^| +)\*{2}(\S[\s\S]*?)\*{2}(?: +|$)/g, function (wm, txt) {
-      return parseInside (txt, ' <strong>', '</strong> ');
+    text = text.trim().replace(/(^| )\*{2}(\S[\s\S]*?)\*{2}([ ,;!?.]|$)/g, function (wm, lead, txt, trail) {
+      return parseInside (txt, lead + '<strong>', '</strong>' + trail);
     });
-    text = text.trim().replace(/(?:^| +)\*{1}(\S[\s\S]*?)\*{1}(?: +|$)/g, function (wm, txt) {
-      return parseInside (txt, ' <em>', '</em>' + (wm.slice(-1) === ' ' ? ' ' : ''));
+    text = text.trim().replace(/(^| )\*(\S[\s\S]*?)\*([ ,;!?.]|$)/g, function (wm, lead, txt, trail) {
+      return parseInside (txt, lead + '<em>', '</em>' + trail);
     });
   } else {
     text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {

+ 16 - 10
src/subParsers/tables.js

@@ -5,7 +5,9 @@ showdown.subParser('tables', function (text, options, globals) {
     return text;
   }
 
-  var tableRgx = /^ {0,3}\|?.+\|.+\n[ \t]{0,3}\|?[ \t]*:?[ \t]*(?:-|=){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:-|=){2,}[\s\S]+?(?:\n\n|¨0)/gm;
+  var tableRgx       = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
+    //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
+      singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|\n( {0,3}\|.+\|\n)*(?:\n|¨0)/gm;
 
   function parseStyles (sLine) {
     if (/^:[ \t]*--*$/.test(sLine)) {
@@ -56,14 +58,7 @@ showdown.subParser('tables', function (text, options, globals) {
     return tb;
   }
 
-  text = globals.converter._dispatch('tables.before', text, options, globals);
-
-  // find escaped pipe characters
-  text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
-
-  // parse tables
-  text = text.replace(tableRgx, function (rawTable) {
-
+  function parseTable (rawTable) {
     var i, tableLines = rawTable.split('\n');
 
     // strip wrong first and last column if wrapped tables are used
@@ -126,7 +121,18 @@ showdown.subParser('tables', function (text, options, globals) {
     }
 
     return buildTable(headers, cells);
-  });
+  }
+
+  text = globals.converter._dispatch('tables.before', text, options, globals);
+
+  // find escaped pipe characters
+  text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
+
+  // parse multi column tables
+  text = text.replace(tableRgx, parseTable);
+
+  // parse one column tables
+  text = text.replace(singeColTblRgx, parseTable);
 
   text = globals.converter._dispatch('tables.after', text, options, globals);
 

+ 1 - 0
test/features/#398.literalMidWordAsterisks-treats-non-word-characters-as-characters.html

@@ -0,0 +1 @@
+<p>strippers, <strong>hitler</strong>, and stalin</p>

+ 1 - 0
test/features/#398.literalMidWordAsterisks-treats-non-word-characters-as-characters.md

@@ -0,0 +1 @@
+strippers, **hitler**, and stalin

+ 9 - 0
test/features/literalMidWordUnderscores.html

@@ -0,0 +1,9 @@
+<p>some <em>foo</em> yeah</p>
+<p>some <strong>foo</strong> yeah</p>
+<p>some <strong><em>foo</em></strong> yeah</p>
+<p>some word_foo_yeah</p>
+<p>some word__foo__yeah</p>
+<p>some word___foo___yeah</p>
+<p>strippers, <em>hitler</em>, and stalin</p>
+<p>strippers, <strong>hitler</strong>, and stalin</p>
+<p>strippers, <strong><em>hitler</em></strong>, and stalin</p>

+ 17 - 0
test/features/literalMidWordUnderscores.md

@@ -0,0 +1,17 @@
+some _foo_ yeah
+
+some __foo__ yeah
+
+some ___foo___ yeah
+
+some word_foo_yeah
+
+some word__foo__yeah
+
+some word___foo___yeah
+
+strippers, _hitler_, and stalin
+
+strippers, __hitler__, and stalin
+
+strippers, ___hitler___, and stalin

+ 1 - 0
test/features/rawHeaderId/simple.html

@@ -0,0 +1 @@
+<h1 id="123-my#very/-strange-\header*`^ªº-_.,-yeah">123 My#very/ strange \header*`^ªº-_., yeah</h1>

+ 1 - 0
test/features/rawHeaderId/simple.md

@@ -0,0 +1 @@
+# 123 My#very/ strange \header*`^ªº-_., yeah

+ 2 - 0
test/features/rawHeaderId/with-prefixHeaderId.html

@@ -0,0 +1,2 @@
+<h1 id="/prefix/some-header">some header</h1>
+<h1 id="/prefix/another-!-#$%&/()=?»@£§{[]}«--header">another !"#$%&amp;/()=?»@£§{[]}«' header</h1>

+ 3 - 0
test/features/rawHeaderId/with-prefixHeaderId.md

@@ -0,0 +1,3 @@
+# some header
+
+# another !"#$%&/()=?»@£§{[]}«' header

+ 1 - 0
test/features/rawPrefixHeaderId/simple-with-prefixHeaderId.html

@@ -0,0 +1 @@
+<h1 id="/prefix/someheaderfoo">some header &amp;/) foo</h1>

+ 1 - 0
test/features/rawPrefixHeaderId/simple-with-prefixHeaderId.md

@@ -0,0 +1 @@
+# some header &/) foo

+ 81 - 0
test/features/tables/#406.does-not-render-one-column-tables.html

@@ -0,0 +1,81 @@
+<table>
+    <thead>
+    <tr>
+        <th>some header</th>
+    </tr>
+    </thead>
+    <tbody>
+    <tr>
+        <td>some content</td>
+    </tr>
+    </tbody>
+</table>
+<table>
+    <thead>
+    <tr>
+        <th>some header</th>
+    </tr>
+    </thead>
+    <tbody>
+    </tbody>
+</table>
+<table>
+    <thead>
+    <tr>
+        <th>some header</th>
+    </tr>
+    </thead>
+    <tbody>
+    <tr>
+        <td>some content</td>
+    </tr>
+    <tr>
+        <td>some content</td>
+    </tr>
+    <tr>
+        <td>some content</td>
+    </tr>
+    <tr>
+        <td>some content</td>
+    </tr>
+    <tr>
+        <td>some content</td>
+    </tr>
+    </tbody>
+</table>
+<table>
+    <thead>
+    <tr>
+        <th style="text-align:left;">some header</th>
+    </tr>
+    </thead>
+    <tbody>
+    <tr>
+        <td style="text-align:left;">some content</td>
+    </tr>
+    </tbody>
+</table>
+<table>
+    <thead>
+    <tr>
+        <th style="text-align:right;">some header</th>
+    </tr>
+    </thead>
+    <tbody>
+    <tr>
+        <td style="text-align:right;">some content</td>
+    </tr>
+    </tbody>
+</table>
+<table>
+    <thead>
+    <tr>
+        <th style="text-align:center;">some header</th>
+    </tr>
+    </thead>
+    <tbody>
+    <tr>
+        <td style="text-align:center;">some content</td>
+    </tr>
+    </tbody>
+</table>

+ 26 - 0
test/features/tables/#406.does-not-render-one-column-tables.md

@@ -0,0 +1,26 @@
+|some header |
+|------------|
+|some content|
+
+|some header |
+|------------|
+
+|some header |
+|------------|
+|some content|
+|some content|
+|some content|
+|some content|
+|some content|
+
+|some header |
+|:-----------|
+|some content|
+
+|some header |
+|-----------:|
+|some content|
+
+|some header |
+|:----------:|
+|some content|

+ 31 - 1
test/node/testsuite.features.js

@@ -8,7 +8,9 @@ var bootstrap = require('../bootstrap.js'),
     tableSuite = bootstrap.getTestSuite('test/features/tables/'),
     simplifiedAutoLinkSuite = bootstrap.getTestSuite('test/features/simplifiedAutoLink/'),
     openLinksInNewWindowSuite = bootstrap.getTestSuite('test/features/openLinksInNewWindow/'),
-    disableForced4SpacesIndentedSublistsSuite = bootstrap.getTestSuite('test/features/disableForced4SpacesIndentedSublists/');
+    disableForced4SpacesIndentedSublistsSuite = bootstrap.getTestSuite('test/features/disableForced4SpacesIndentedSublists/'),
+    rawHeaderIdSuite = bootstrap.getTestSuite('test/features/rawHeaderId/'),
+    rawPrefixHeaderIdSuite = bootstrap.getTestSuite('test/features/rawPrefixHeaderId/');
 
 describe('makeHtml() features testsuite', function () {
   'use strict';
@@ -22,6 +24,8 @@ describe('makeHtml() features testsuite', function () {
         converter = new showdown.Converter({headerLevelStart: 3});
       } else if (testsuite[i].name === '#164.1.simple-autolink' || testsuite[i].name === '#204.certain-links-with-at-and-dot-break-url') {
         converter = new showdown.Converter({simplifiedAutoLink: true});
+      } else if (testsuite[i].name === 'literalMidWordUnderscores') {
+        converter = new showdown.Converter({literalMidWordUnderscores: true});
       } else if (testsuite[i].name === '#164.2.disallow-underscore-emphasis-mid-word') {
         converter = new showdown.Converter({literalMidWordUnderscores: true});
       } else if (testsuite[i].name === '#164.3.strikethrough' || testsuite[i].name === '#214.escaped-markdown-chars-break-strikethrough') {
@@ -84,6 +88,8 @@ describe('makeHtml() features testsuite', function () {
         converter = new showdown.Converter({backslashEscapesHTMLTags: true});
       } else if (testsuite[i].name === '#379.openLinksInNewWindow-breaks-em-markdup') {
         converter = new showdown.Converter({openLinksInNewWindow: true});
+      } else if (testsuite[i].name === '#398.literalMidWordAsterisks-treats-non-word-characters-as-characters') {
+        converter = new showdown.Converter({literalMidWordAsterisks: true});
       } else {
         converter = new showdown.Converter();
       }
@@ -148,4 +154,28 @@ describe('makeHtml() features testsuite', function () {
       it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
     }
   });
+
+  // test rawHeaderId support
+  describe('rawHeaderId support', function () {
+    var converter,
+        suite = rawHeaderIdSuite;
+    for (var i = 0; i < suite.length; ++i) {
+      if (suite[i].name === 'with-prefixHeaderId') {
+        converter = new showdown.Converter({rawHeaderId: true, prefixHeaderId: '/prefix/'});
+      } else {
+        converter = new showdown.Converter({rawHeaderId: true});
+      }
+      it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
+    }
+  });
+
+  // test rawPrefixHeaderId support
+  describe('rawPrefixHeaderId support', function () {
+    var converter,
+        suite = rawPrefixHeaderIdSuite;
+    for (var i = 0; i < suite.length; ++i) {
+      converter = new showdown.Converter({rawPrefixHeaderId: true, prefixHeaderId: '/prefix/'});
+      it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
+    }
+  });
 });

Някои файлове не бяха показани, защото твърде много файлове са промени