diff --git a/README.md b/README.md
index 3d6e856..95f2e2d 100644
--- a/README.md
+++ b/README.md
@@ -198,7 +198,7 @@ var defaultOptions = showdown.getDefaultOptions();
* **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.
+ * **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
@@ -328,7 +328,9 @@ var defaultOptions = showdown.getDefaultOptions();
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 `` tags)
+ * **openLinksInNewWindow**: (boolean) [default false] Open all links in new windows (by adding the attribute `target="_blank"` to `` tags) (since v1.7.0)
+
+ * **backslashEscapesHTMLTags**: (boolean) [default false] Support for HTML Tag escaping. ex: `\foo\
` (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.
diff --git a/dist/showdown.js b/dist/showdown.js
index fd063a4..75874b3 100644
Binary files a/dist/showdown.js and b/dist/showdown.js differ
diff --git a/dist/showdown.js.map b/dist/showdown.js.map
index 213e449..507224d 100644
Binary files a/dist/showdown.js.map and b/dist/showdown.js.map differ
diff --git a/dist/showdown.min.js b/dist/showdown.min.js
index 88e9000..cdcbe50 100644
Binary files a/dist/showdown.min.js and b/dist/showdown.min.js differ
diff --git a/dist/showdown.min.js.map b/dist/showdown.min.js.map
index 3b8a1ef..276717b 100644
Binary files a/dist/showdown.min.js.map and b/dist/showdown.min.js.map differ
diff --git a/src/options.js b/src/options.js
index efe8c6a..70c5f7e 100644
--- a/src/options.js
+++ b/src/options.js
@@ -125,6 +125,11 @@ function getDefaultOpts (simple) {
defaultValue: false,
description: 'Open all links in new windows',
type: 'boolean'
+ },
+ backslashEscapesHTMLTags: {
+ defaultValue: false,
+ description: 'Support for HTML Tag escaping. ex: \foo\
',
+ type: 'boolean'
}
};
if (simple === false) {
diff --git a/src/subParsers/anchors.js b/src/subParsers/anchors.js
index 5779368..49676ea 100644
--- a/src/subParsers/anchors.js
+++ b/src/subParsers/anchors.js
@@ -82,8 +82,12 @@ showdown.subParser('anchors', function (text, options, globals) {
if (!showdown.helper.isString(options.ghMentionsLink)) {
throw new Error('ghMentionsLink option must be a string');
}
- var lnk = options.ghMentionsLink.replace(/\{u}/g, username);
- return st + '' + mentions + '';
+ var lnk = options.ghMentionsLink.replace(/\{u}/g, username),
+ target = '';
+ if (options.openLinksInNewWindow) {
+ target = ' target="¨E95Eblank"';
+ }
+ return st + '' + mentions + '';
});
}
diff --git a/src/subParsers/hashHTMLBlocks.js b/src/subParsers/hashHTMLBlocks.js
index 74b4284..b16b103 100644
--- a/src/subParsers/hashHTMLBlocks.js
+++ b/src/subParsers/hashHTMLBlocks.js
@@ -48,14 +48,26 @@ showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
};
+ if (options.backslashEscapesHTMLTags) {
+ // encode backslash escaped HTML tags
+ text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) {
+ return '<' + inside + '>';
+ });
+ }
+
+ // hash HTML Blocks
for (var i = 0; i < blockTags.length; ++i) {
var opTagPos,
- rgx1 = new RegExp('^ {0,3}<' + blockTags[i] + '\\b[^>]*>', 'im'),
+ rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'),
patLeft = '<' + blockTags[i] + '\\b[^>]*>',
patRight = '' + blockTags[i] + '>';
// 1. Look for the first position of the first opening HTML tag in the text
while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) {
+
+ // if the HTML tag is \ escaped, we need to escape it and break
+
+
//2. Split the text in that position
var subTexts = showdown.helper.splitAtIndex(text, opTagPos),
//3. Match recursively
diff --git a/src/subParsers/lists.js b/src/subParsers/lists.js
index 8118714..1b2c07d 100644
--- a/src/subParsers/lists.js
+++ b/src/subParsers/lists.js
@@ -93,16 +93,14 @@ showdown.subParser('lists', function (text, options, globals) {
item = showdown.subParser('lists')(item, options, globals);
item = item.replace(/\n$/, ''); // chomp(item)
item = showdown.subParser('hashHTMLBlocks')(item, options, globals);
+
// Colapse double linebreaks
item = item.replace(/\n\n+/g, '\n\n');
- // replace double linebreaks with a placeholder
- item = item.replace(/\n\n/g, '¨B');
if (isParagraphed) {
item = showdown.subParser('paragraphs')(item, options, globals);
} else {
item = showdown.subParser('spanGamut')(item, options, globals);
}
- item = item.replace(/¨B/g, '\n\n');
}
// now we need to remove the marker (¨A)
diff --git a/src/subParsers/spanGamut.js b/src/subParsers/spanGamut.js
index b829ba4..489907c 100644
--- a/src/subParsers/spanGamut.js
+++ b/src/subParsers/spanGamut.js
@@ -32,7 +32,10 @@ showdown.subParser('spanGamut', function (text, options, globals) {
// Do hard breaks
if (options.simpleLineBreaks) {
// GFM style hard breaks
- text = text.replace(/\n/g, '
\n');
+ // only add line breaks if the text does not contain a block (special case for lists)
+ if (!/\n\n¨K/.test(text)) {
+ text = text.replace(/\n+/g, '
\n');
+ }
} else {
// Vanilla hard breaks
text = text.replace(/ +\n/g, '
\n');
diff --git a/src/subParsers/tables.js b/src/subParsers/tables.js
index dcd74c9..6ce7bc6 100644
--- a/src/subParsers/tables.js
+++ b/src/subParsers/tables.js
@@ -22,7 +22,8 @@ showdown.subParser('tables', function (text, options, globals) {
function parseHeaders (header, style) {
var id = '';
header = header.trim();
- if (options.tableHeaderId) {
+ // support both tablesHeaderId and tableHeaderId due to error in documention so we don't break backwards compatibility
+ if (options.tablesHeaderId || options.tableHeaderId) {
id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
}
header = showdown.subParser('spanGamut')(header, options, globals);
diff --git a/test/features/#374.escape-html-tags.html b/test/features/#374.escape-html-tags.html
new file mode 100644
index 0000000..25126a6
--- /dev/null
+++ b/test/features/#374.escape-html-tags.html
@@ -0,0 +1 @@
+
<div>foo</div>
\ No newline at end of file
diff --git a/test/features/#374.escape-html-tags.md b/test/features/#374.escape-html-tags.md
new file mode 100644
index 0000000..07d5f92
--- /dev/null
+++ b/test/features/#374.escape-html-tags.md
@@ -0,0 +1 @@
+\foo\
diff --git a/test/issues/#397.unordered-list-strange-behavior.html b/test/issues/#397.unordered-list-strange-behavior.html
new file mode 100644
index 0000000..bab378d
--- /dev/null
+++ b/test/issues/#397.unordered-list-strange-behavior.html
@@ -0,0 +1,14 @@
+
diff --git a/test/issues/#397.unordered-list-strange-behavior.md b/test/issues/#397.unordered-list-strange-behavior.md
new file mode 100644
index 0000000..59bc46b
--- /dev/null
+++ b/test/issues/#397.unordered-list-strange-behavior.md
@@ -0,0 +1,11 @@
+- **Customer** – Opens the Customer List. Refer to the document “Customer Management”.
+ - Customer List
+ - New Customer
+ - Customer Prices
+ - Appointments
+
+- **Designer** - Opens the Designer List. Refer to the document “Designer Commissions”.
+ - Designer List
+ - New Designer
+ - Designer Payment List
+ - New Designer Payment
\ No newline at end of file
diff --git a/test/node/testsuite.features.js b/test/node/testsuite.features.js
index 25907eb..b4234ad 100644
--- a/test/node/testsuite.features.js
+++ b/test/node/testsuite.features.js
@@ -80,6 +80,8 @@ describe('makeHtml() features testsuite', function () {
converter = new showdown.Converter({customizedHeaderId: true});
} else if (testsuite[i].name === '#378.simplifiedAutoLinks-with-excludeTrailingPunctuationFromURLs') {
converter = new showdown.Converter({simplifiedAutoLink: true, excludeTrailingPunctuationFromURLs: true});
+ } else if (testsuite[i].name === '#374.escape-html-tags') {
+ converter = new showdown.Converter({backslashEscapesHTMLTags: true});
} else if (testsuite[i].name === '#379.openLinksInNewWindow-breaks-em-markdup') {
converter = new showdown.Converter({openLinksInNewWindow: true});
} else {
@@ -95,7 +97,7 @@ describe('makeHtml() features testsuite', function () {
suite = tableSuite;
for (var i = 0; i < suite.length; ++i) {
if (suite[i].name === 'basic-with-header-ids') {
- converter = new showdown.Converter({tables: true, tableHeaderId: true});
+ converter = new showdown.Converter({tables: true, tablesHeaderId: true});
} else if (suite[i].name === '#179.parse-md-in-table-ths') {
converter = new showdown.Converter({tables: true, strikethrough: true});
} else {