Browse Source

Implement new html block algorithm from 0.21

pull/135/head
Alex Kocharin 10 years ago
parent
commit
643d9f75a0
  1. 57
      lib/common/html_blocks.js
  2. 2
      lib/common/html_re.js
  3. 85
      lib/rules_block/html_block.js

57
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'
];

2
lib/common/html_re.js

@ -22,5 +22,7 @@ var cdata = '<!\\[CDATA\\[[\\s\\S]*?\\]\\]>';
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;

85
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 ],
[ /^<![A-Z]/, />/, true ],
[ /^<!\[CDATA\[/, /\]\]>/, 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; }
if (silent) {
// true if this sequence can be a terminator, false otherwise
return HTML_SEQUENCES[i][2];
}
// Make sure tag name is valid
if (block_names[match[1].toLowerCase()] !== true) { return false; }
if (silent) { return true; }
} else {
return false;
}
nextLine = startLine + 1;
// 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++;
// 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;
};

Loading…
Cancel
Save