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'; 'use strict';
var html_blocks = {};
[ module.exports = [
'address',
'article', 'article',
'aside', 'aside',
'button', 'base',
'basefont',
'blockquote', 'blockquote',
'body', 'body',
'canvas',
'caption', 'caption',
'center',
'col', 'col',
'colgroup', 'colgroup',
'dd', 'dd',
'details',
'dialog',
'dir',
'div', 'div',
'dl', 'dl',
'dt', 'dt',
'embed',
'fieldset', 'fieldset',
'figcaption', 'figcaption',
'figure', 'figure',
'footer', 'footer',
'form', 'form',
'frame',
'frameset',
'h1', 'h1',
'h2', 'head',
'h3',
'h4',
'h5',
'h6',
'header', 'header',
'hgroup',
'hr', 'hr',
'iframe', 'html',
'legend',
'li', 'li',
'map', 'link',
'object', 'main',
'menu',
'menuitem',
'meta',
'nav',
'noframes',
'ol', 'ol',
'output', 'optgroup',
'option',
'p', 'p',
'param',
'pre', 'pre',
'progress',
'script',
'section', 'section',
'style', 'source',
'title',
'summary',
'table', 'table',
'tbody', 'tbody',
'td', 'td',
'textarea',
'tfoot', 'tfoot',
'th', 'th',
'tr',
'thead', 'thead',
'ul', 'title',
'video' 'tr',
].forEach(function (name) { html_blocks[name] = true; }); 'track',
'ul'
];
module.exports = html_blocks;

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 + var HTML_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + '|' + comment +
'|' + processing + '|' + declaration + '|' + cdata + ')'); '|' + 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_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 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) { module.exports = function html_block(state, startLine, endLine, silent) {
var ch, match, nextLine, token, var i, nextLine, token, lineText,
pos = state.bMarks[startLine], pos = state.bMarks[startLine] + state.tShift[startLine],
max = state.eMarks[startLine], max = state.eMarks[startLine];
shift = state.tShift[startLine];
pos += shift;
if (!state.md.options.html) { return false; } if (!state.md.options.html) { return false; }
if (shift > 3 || pos + 2 >= max) { return false; }
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { 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/* ? */) { for (i = 0; i < HTML_SEQUENCES.length; i++) {
// Directive start / comment start / processing instruction start if (HTML_SEQUENCES[i][0].test(lineText)) { break; }
if (silent) { return true; } }
} else if (ch === 0x2F/* / */ || isLetter(ch)) { if (i === HTML_SEQUENCES.length) { return false; }
// Probably start or end of tag if (silent) {
if (ch === 0x2F/* \ */) { // true if this sequence can be a terminator, false otherwise
// closing tag return HTML_SEQUENCES[i][2];
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 { nextLine = startLine + 1;
return false;
}
// If we are here - we detected HTML block. // If we are here - we detected HTML block.
// Let's roll down till empty line (block end). // Let's roll down till block end.
nextLine = startLine + 1; if (!HTML_SEQUENCES[i][1].test(lineText)) {
while (nextLine < state.lineMax && !state.isEmpty(nextLine)) { for (; nextLine < endLine; nextLine++) {
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; state.line = nextLine;
token = state.push('html_block', '', 0); token = state.push('html_block', '', 0);
token.map = [ startLine, state.line ]; token.map = [ startLine, nextLine ];
token.content = state.getLines(startLine, nextLine, 0, true); token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
return true; return true;
}; };

Loading…
Cancel
Save