'use strict'; var jsx_inline = require('./lib/jsx_inline'); var escape_code = require('./lib/escape_code'); module.exports = function jsx_plugin(md) { md.set({ xhtmlOut: true }); // JSX should entirely replace embedded HTML. md.inline.ruler.before('html_inline', 'jsx_inline', jsx_inline); md.disable('html_inline'); // We'll parse blocks as inline and then strip the surrounding paragraph at the end; it's easier. md.disable('html_block'); md.core.ruler.push('jsx_blockify', function(state) { // Look for things like

...

and strip the

,

there. // FIXME Quadratic time in worst case, I think? var paragraphTokensToRemove = []; var lastInlineTokenSeen; for (var blkIdx = 0; blkIdx < state.tokens.length; blkIdx++) { if (state.tokens[blkIdx].type !== 'paragraph_open') { continue; } var nextBlkToken = state.tokens[blkIdx + 1]; if (nextBlkToken.type !== 'inline' || nextBlkToken.children[0].type !== 'jsx_inline') { continue; } // FIXME Incorrect and a hack: //

...

will also get stripped. var paragraphOpens = 0; for (var i = blkIdx + 1; i < state.tokens.length; i++) { if (state.tokens[i].type === 'paragraph_open') { paragraphOpens++; continue; } else if (state.tokens[i].type !== 'paragraph_close') { continue; } if (paragraphOpens > 0) { paragraphOpens--; continue; } // OK, this is the paragraph_close matching the open we started on. // What came right before here? var prevBlkToken = state.tokens[i - 1]; if (prevBlkToken.type !== 'inline') { break; } var prevInlineToken = prevBlkToken.children[prevBlkToken.children.length - 1]; if (prevInlineToken.type !== 'jsx_inline') { break; } // If we got this far, we're stripping the surrounding paragraph. // FIXME Also a hack. The 'inline' JSX that's inside the paragraph should // now get a linebreak after it in the generated HTML. Easier to test // and looks better in the HTML. prevInlineToken.content += '\n'; paragraphTokensToRemove.push( blkIdx, i ); break; } } state.tokens = state.tokens.filter(function(blkToken, idx) { return paragraphTokensToRemove.indexOf(idx) === -1; }); }); md.renderer.rules.fence = escape_code(md.renderer.rules.fence); md.renderer.rules.code_inline = escape_code(md.renderer.rules.code_inline); md.renderer.rules.code_block = escape_code(md.renderer.rules.code_block); md.renderer.rules['jsx_inline'] = function(tokens, idx) { // If the span is JSX, just pass the original source for the span // through to output. return tokens[idx].content; }; };