diff --git a/lib/common/html_blocks.js b/lib/common/html_blocks.js
index 96848e0..d13c17d 100644
--- a/lib/common/html_blocks.js
+++ b/lib/common/html_blocks.js
@@ -3,60 +3,65 @@
'use strict';
-var html_blocks = {};
-[
+module.exports = [
+ 'address',
'article',
'aside',
- 'button',
+ 'base',
+ 'basefont',
'blockquote',
'body',
- 'canvas',
'caption',
+ 'center',
'col',
'colgroup',
'dd',
+ 'details',
+ 'dialog',
+ 'dir',
'div',
'dl',
'dt',
- 'embed',
'fieldset',
'figcaption',
'figure',
'footer',
'form',
+ 'frame',
+ 'frameset',
'h1',
- 'h2',
- 'h3',
- 'h4',
- 'h5',
- 'h6',
+ 'head',
'header',
- 'hgroup',
'hr',
- 'iframe',
+ 'html',
+ 'legend',
'li',
- 'map',
- 'object',
+ 'link',
+ 'main',
+ 'menu',
+ 'menuitem',
+ 'meta',
+ 'nav',
+ 'noframes',
'ol',
- 'output',
+ 'optgroup',
+ 'option',
'p',
+ 'param',
'pre',
- 'progress',
- 'script',
'section',
- 'style',
+ 'source',
+ 'title',
+ 'summary',
'table',
'tbody',
'td',
- 'textarea',
'tfoot',
'th',
- 'tr',
'thead',
- 'ul',
- 'video'
-].forEach(function (name) { html_blocks[name] = true; });
-
-
-module.exports = html_blocks;
+ 'title',
+ 'tr',
+ 'track',
+ 'ul'
+];
diff --git a/lib/common/html_re.js b/lib/common/html_re.js
index 2d33f68..4fd9369 100644
--- a/lib/common/html_re.js
+++ b/lib/common/html_re.js
@@ -22,5 +22,7 @@ var cdata = '';
var HTML_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + '|' + comment +
'|' + processing + '|' + declaration + '|' + cdata + ')');
+var HTML_OPEN_CLOSE_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + ')');
module.exports.HTML_TAG_RE = HTML_TAG_RE;
+module.exports.HTML_OPEN_CLOSE_TAG_RE = HTML_OPEN_CLOSE_TAG_RE;
diff --git a/lib/rules_block/html_block.js b/lib/rules_block/html_block.js
index cc69596..0d9426b 100644
--- a/lib/rules_block/html_block.js
+++ b/lib/rules_block/html_block.js
@@ -4,69 +4,68 @@
var block_names = require('../common/html_blocks');
+var HTML_OPEN_CLOSE_TAG_RE = require('../common/html_re').HTML_OPEN_CLOSE_TAG_RE;
+
+// An array of opening and corresponding closing sequences for html tags,
+// last argument defines whether it can terminate a paragraph or not
+//
+var HTML_SEQUENCES = [
+ [ /^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true ],
+ [ /^/, true ],
+ [ /^<\?/, /\?>/, true ],
+ [ /^/, true ],
+ [ /^/, true ],
+ [ new RegExp('^?(' + block_names.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true ],
+ [ new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false ]
+];
-var HTML_TAG_OPEN_RE = /^<([a-zA-Z][a-zA-Z0-9]{0,14})[\s\/>]/;
-var HTML_TAG_CLOSE_RE = /^<\/([a-zA-Z][a-zA-Z0-9]{0,14})[\s>]/;
-
-function isLetter(ch) {
- /*eslint no-bitwise:0*/
- var lc = ch | 0x20; // to lower case
- return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */);
-}
-
module.exports = function html_block(state, startLine, endLine, silent) {
- var ch, match, nextLine, token,
- pos = state.bMarks[startLine],
- max = state.eMarks[startLine],
- shift = state.tShift[startLine];
-
- pos += shift;
+ var i, nextLine, token, lineText,
+ pos = state.bMarks[startLine] + state.tShift[startLine],
+ max = state.eMarks[startLine];
if (!state.md.options.html) { return false; }
- if (shift > 3 || pos + 2 >= max) { return false; }
-
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
- ch = state.src.charCodeAt(pos + 1);
+ lineText = state.src.slice(pos, max);
- if (ch === 0x21/* ! */ || ch === 0x3F/* ? */) {
- // Directive start / comment start / processing instruction start
- if (silent) { return true; }
+ for (i = 0; i < HTML_SEQUENCES.length; i++) {
+ if (HTML_SEQUENCES[i][0].test(lineText)) { break; }
+ }
- } else if (ch === 0x2F/* / */ || isLetter(ch)) {
+ if (i === HTML_SEQUENCES.length) { return false; }
- // Probably start or end of tag
- if (ch === 0x2F/* \ */) {
- // closing tag
- match = state.src.slice(pos, max).match(HTML_TAG_CLOSE_RE);
- if (!match) { return false; }
- } else {
- // opening tag
- match = state.src.slice(pos, max).match(HTML_TAG_OPEN_RE);
- if (!match) { return false; }
- }
- // Make sure tag name is valid
- if (block_names[match[1].toLowerCase()] !== true) { return false; }
- if (silent) { return true; }
-
- } else {
- return false;
+ if (silent) {
+ // true if this sequence can be a terminator, false otherwise
+ return HTML_SEQUENCES[i][2];
}
- // If we are here - we detected HTML block.
- // Let's roll down till empty line (block end).
nextLine = startLine + 1;
- while (nextLine < state.lineMax && !state.isEmpty(nextLine)) {
- nextLine++;
+
+ // If we are here - we detected HTML block.
+ // Let's roll down till block end.
+ if (!HTML_SEQUENCES[i][1].test(lineText)) {
+ for (; nextLine < endLine; nextLine++) {
+ if (state.tShift[nextLine] < state.blkIndent) { break; }
+
+ pos = state.bMarks[nextLine] + state.tShift[nextLine];
+ max = state.eMarks[nextLine];
+ lineText = state.src.slice(pos, max);
+
+ if (HTML_SEQUENCES[i][1].test(lineText)) {
+ if (lineText.length !== 0) { nextLine++; }
+ break;
+ }
+ }
}
state.line = nextLine;
token = state.push('html_block', '', 0);
- token.map = [ startLine, state.line ];
- token.content = state.getLines(startLine, nextLine, 0, true);
+ token.map = [ startLine, nextLine ];
+ token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
return true;
};