# -*- coding: utf-8 -*-##--# Copyright (C) 2009-2013 Thomas Leitner <t_leitner@gmx.at>## This file is part of kramdown which is licensed under the MIT.#++#require'kramdown/parser/html'moduleKramdownmoduleParserclassKramdownincludeKramdown::Parser::Html::Parser# Mapping of markdown attribute value to content model. I.e. :raw when "0", :default when "1"# (use default content model for the HTML element), :span when "span", :block when block and# for everything else +nil+ is returned.HTML_MARKDOWN_ATTR_MAP={"0"=>:raw,"1"=>:default,"span"=>:span,"block"=>:block}TRAILING_WHITESPACE=/[ \t]*\n/defhandle_kramdown_html_tag(el,closed,handle_body)el.options[:ial]=@block_ialif@block_ialcontent_model=if@tree.type!=:html_element||@tree.options[:content_model]!=:raw(@options[:parse_block_html]?HTML_CONTENT_MODEL[el.value]::raw)else:rawendifval=HTML_MARKDOWN_ATTR_MAP[el.attr.delete('markdown')]content_model=(val==:default?HTML_CONTENT_MODEL[el.value]:val)end@src.scan(TRAILING_WHITESPACE)ifcontent_model==:blockel.options[:content_model]=content_modelel.options[:is_closed]=closedif!closed&&handle_bodyifcontent_model==:blockif!parse_blocks(el)warning("Found no end tag for '#{el.value}' - auto-closing it")endelsifcontent_model==:spancurpos=@src.posif@src.scan_until(/(?=<\/#{el.value}\s*>)/mi)add_text(extract_string(curpos...@src.pos,@src),el)@src.scan(HTML_TAG_CLOSE_RE)elseadd_text(@src.rest,el)@src.terminatewarning("Found no end tag for '#{el.value}' - auto-closing it")endelseparse_raw_html(el,&method(:handle_kramdown_html_tag))end@src.scan(TRAILING_WHITESPACE)unless(@tree.type==:html_element&&@tree.options[:content_model]==:raw)endendHTML_BLOCK_START=/^#{OPT_SPACE}<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/# Parse the HTML at the current position as block-level HTML.defparse_block_htmlifresult=@src.scan(HTML_COMMENT_RE)@tree.children<<Element.new(:xml_comment,result,nil,:category=>:block)@src.scan(TRAILING_WHITESPACE)trueelsifresult=@src.scan(HTML_INSTRUCTION_RE)@tree.children<<Element.new(:xml_pi,result,nil,:category=>:block)@src.scan(TRAILING_WHITESPACE)trueelseifresult=@src.check(/^#{OPT_SPACE}#{HTML_TAG_RE}/)&&!HTML_SPAN_ELEMENTS.include?(@src[1].downcase)@src.pos+=@src.matched_sizehandle_html_start_tag(&method(:handle_kramdown_html_tag))Kramdown::Parser::Html::ElementConverter.convert(@root,@tree.children.last)if@options[:html_to_native]trueelsifresult=@src.check(/^#{OPT_SPACE}#{HTML_TAG_CLOSE_RE}/)&&!HTML_SPAN_ELEMENTS.include?(@src[1].downcase)name=@src[1].downcaseif@tree.type==:html_element&&@tree.value==name@src.pos+=@src.matched_sizethrow:stop_block_parsing,:foundelsefalseendelsefalseendendenddefine_parser(:block_html,HTML_BLOCK_START)HTML_SPAN_START=/<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/# Parse the HTML at the current position as span-level HTML.defparse_span_htmlifresult=@src.scan(HTML_COMMENT_RE)@tree.children<<Element.new(:xml_comment,result,nil,:category=>:span)elsifresult=@src.scan(HTML_INSTRUCTION_RE)@tree.children<<Element.new(:xml_pi,result,nil,:category=>:span)elsifresult=@src.scan(HTML_TAG_CLOSE_RE)warning("Found invalidly used HTML closing tag for '#{@src[1]}'")add_text(result)elsifresult=@src.scan(HTML_TAG_RE)tag_name=@src[1].downcaseifHTML_BLOCK_ELEMENTS.include?(tag_name)warning("Found block HTML tag '#{tag_name}' in span-level text")add_text(result)returnendattrs=Utils::OrderedHash.new@src[2].scan(HTML_ATTRIBUTE_RE).each{|name,sep,val|attrs[name.downcase]=(val||'').gsub(/\n+/,' ')}do_parsing=(HTML_CONTENT_MODEL[tag_name]==:raw||@tree.options[:content_model]==:raw?false:@options[:parse_span_html])ifval=HTML_MARKDOWN_ATTR_MAP[attrs.delete('markdown')]ifval==:blockwarning("Cannot use block-level parsing in span-level HTML tag - using default mode")elsifval==:spando_parsing=trueelsifval==:defaultdo_parsing=HTML_CONTENT_MODEL[tag_name]!=:rawelsifval==:rawdo_parsing=falseendendel=Element.new(:html_element,tag_name,attrs,:category=>:span,:content_model=>(do_parsing?:span::raw),:is_closed=>!!@src[4])@tree.children<<elstop_re=/<\/#{Regexp.escape(tag_name)}\s*>/iif!@src[4]&&HTML_ELEMENTS_WITHOUT_BODY.include?(el.value)warning("The HTML tag '#{el.value}' cannot have any content - auto-closing it")elsif!@src[4]ifparse_spans(el,stop_re,(do_parsing?nil:[:span_html]))@src.scan(stop_re)elsewarning("Found no end tag for '#{el.value}' - auto-closing it")add_text(@src.rest,el)@src.terminateendendKramdown::Parser::Html::ElementConverter.convert(@root,el)if@options[:html_to_native]elseadd_text(@src.getch)endenddefine_parser(:span_html,HTML_SPAN_START,'<')endendend